how to compile and link rust code into an android apk packed application
Asked Answered
V

1

17

I'm trying to add Rust code to an android NDK sample (native-activity); Whenever I link Rust code (compiled as a .a) into the .so , it fails to run.

I went on information from here to get an android aware rust compiler and 'standalone toolchain' https://github.com/mozilla/rust/wiki/Doc-building-for-android

Someone was suggesting on the Rust IRC channel that I need to mention 'thumb' somewhere; is there an option to pass to rustc, or did I have to build it all differently in the first place?

I've certainly been able to call rust & c from eachother on desktop builds.

Is there a sample where someone has rust code working in a .apk; it would have to be simple.. its very hard to decipher makefiles for complex projects. (I think it would be very hard to figure this out from reading Servo source)

I've verified this process generates a useable package without adding rust; it only fails to run if I link unstripped rust code - even if it isn't reached (even though the linking doesn't tell me anything is wrong). If i remove the call to 'rusty_android()', it works. If i move the call to rusty_android to a point that isn't reached, it still doesn't work. I can verify with 'nm' that 'rusty_android' is in the .so ... unmangled.

This is my current build process: its taken from the android native-activity sample; i've added a rust source file with a single extern functin returning a value, and tried to debug print that from the samples' C main

ANDROID_CXX  = /opt/ndk_standalone/bin/arm-linux-androideabi-gcc

android:
    $(ANDROID_CXX) -I/home/ME/android-ndk-r9b/sources/android/native_app_glue -c jni/main.c  -o obj/local/armeabi/objs/native-activity/main.o
    rustc --target=arm-linux-androideabi hello_android.rs -C android-cross-path=/opt/ndk_standalone --crate-type=staticlib -o rusty_android.a
    $(ANDROID_CXX) -shared -o libs/armeabi/libnative-activity.so obj/local/armeabi/objs/native-activity/main.o obj/local/armeabi/libandroid_native_app_glue.a another.o rusty_android.a -llog -landroid -lEGL -lGLESv1_CM
   ant debug
   adb install -r bin/NativeActivity-debug.apk
   adb shell am start -n com.example.native_activity/android.app.NativeActivity




hello_android.rs:-

use std::libc;
#[no_mangle]
pub extern fn   rusty_android()->libc::c_int {
99 as libc::c_int
}

in main.c, inserted in android_main(..):-
    { extern int rusty_android(); LOGI("****rust says %d****", rusty_android()); }

The suspicion that something to specificy 'thumb' might be needed arose from comparing LLVM IR and asm sources, but it seems strange that it would be an additional option required over and above 'arm-linux-androideabi'

Volturno answered 5/3, 2014 at 14:29 Comment(1)
Have not tried anything using Android's NativeActivity, but I've got a working Android Studio NDK project that builds and links against a pre-built rust shared library and uses a C++ shim for interfacing between Java and Rust. I've just now updated the Rust Wiki with these changes, and wouldn't mind sharing the project if you're still in need...Renovate
V
7

Since I posted this, someone helped out and i've got this makefile that works..

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := rust-prebuilt
LOCAL_SRC_FILES := librusty_android.a

include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)

LOCAL_MODULE    := native-activity
LOCAL_SRC_FILES := main.c

LOCAL_LDLIBS    := -llog -landroid -lEGL -lGLESv1_CM 
LOCAL_STATIC_LIBRARIES +=  android_native_app_glue rust-prebuilt

include $(BUILD_SHARED_LIBRARY)

$(call import-module,android/native_app_glue)

So using this, one can link a prebuilt rust static library in the ndk samples' own link process.

So what is it doing behind the scenes, librusty_android-> rust-prebuilt .. does it just have different linker options I missed ? is it converting the libray somehow, or signing it ?

I can obviously make a single makefile to compile my rust code then call this as a final step but it would still be nice to simplify this out and find out why it works.

Volturno answered 7/3, 2014 at 14:56 Comment(3)
I am trying to follow this and github.com/rust-lang/rust/wiki/Doc-building-for-android, and I am getting errors: b SharedLibrary : libnative-activity.so /home/skligys/Work/Android/android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: jni/librust_android.a(r-compiler-rt-gcc_personality_v0.o): in function __gcc_personality_v0:/home/skligys/Temp/Rust/rust/src/compiler-rt/lib/builtins/gcc_personality_v0.c:206: error: undefined reference to '_Unwind_GetIP'Triplett
I have the exact same problem as @SkirmantasKligys. Did you resolve this somehow?Catnip
@Bastian: My first fix was to get unwind.c from Android NDK (which defined _Unwind_GetGR, _Unwind_SetGR, _Unwind_GetIP, _Unwind_SetIP) and link it. My second fix was to switch to github.com/tomaka/android-rs-glue, and that worked fine out of the box.Triplett

© 2022 - 2024 — McMap. All rights reserved.