android-rs-glue icon indicating copy to clipboard operation
android-rs-glue copied to clipboard

Building a native library

Open torkleyy opened this issue 7 years ago • 19 comments

How can I use a native library I've built for Android? More specifically, I'd like to build rust-sdl2, however it seems cargo-apk cannot find the built SDL2 libraries.

torkleyy avatar Apr 26 '17 12:04 torkleyy

In theory this should work as in any non-Android platform: http://doc.crates.io/build-script.html#overriding-build-scripts

tomaka avatar Apr 26 '17 12:04 tomaka

I'm trying to build a ggez based app, which uses SDL2.

 = note: /usr/local/android-ndk-r15b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld: error: cannot find -lSDL2
          collect2: error: ld returned 1 exit status
          Error while executing gcc

What steps should I do to fix that problem? Should I create an updated docker image, which will install SDL2 before running cargo apk build?

UPD. I installed into docker image libsdl2-dev libsdl2-2.0 and it didn't help, I'm getting the same error.

TatriX avatar Oct 05 '17 07:10 TatriX

I installed into docker image libsdl2-dev libsdl2-2.0 and it didn't help

That's because these packages contain a libsdl2 that targets your current platform, while you need a libsdl2 that targets Android.

tomaka avatar Oct 05 '17 11:10 tomaka

Could you please point me to the docs on how I can do it?

TatriX avatar Oct 05 '17 14:10 TatriX

If I have libSDL2.so built for android, where should I place it so ld could find it?

TatriX avatar Oct 09 '17 10:10 TatriX

See the docs here: http://doc.crates.io/build-script.html#overriding-build-scripts

Put a .cargo/config file somewhere (or in your HOME), and put something like this inside:

[target.arm-linux-androideabi.SDL2]   # refers to this line: https://github.com/Rust-SDL2/rust-sdl2/blob/master/sdl2-sys/Cargo.toml#L11
rustc-link-search = ["/some/path"]
rustc-link-lib = ["SDL2"]   # name of the file, with `lib` and `.so` removed

tomaka avatar Oct 09 '17 12:10 tomaka

Ok, I did a custom build.rs. cargo apk build produced the apk, and I installed it to the device with adb. But app crashes with

java.lang.UnsatisfiedLinkError: dlopen failed: "/data/app/rust.bomber-2/lib/arm/libSDL2.so" has unexpected e_machine: 3

TatriX avatar Oct 09 '17 14:10 TatriX

That means that libSDL2.so is not compiled for the right architecture (ARM vs x86, I guess)

tomaka avatar Oct 09 '17 14:10 tomaka

There are 4 libs like so

.
├── arm64-v8a
│   └── libSDL2.so
├── armeabi-v7a
│   └── libSDL2.so
├── x86
│   └── libSDL2.so
└── x86_64
    └── libSDL2.so

build.rs looks like this:

        println!("cargo:rustc-flags=-L sdl2/arm64-v8a",);
        println!("cargo:rustc-flags=-L sdl2/armeabi",);
        println!("cargo:rustc-flags=-L sdl2/armeabi-v7a",);
        println!("cargo:rustc-flags=-L sdl2/x86",);

Is is possible that cargo apk uses wrong lib?

TatriX avatar Oct 09 '17 14:10 TatriX

arm64-v8a/libSDL2.so:   ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, BuildID[sha1]=678e6ed427ba01e71cc6e675ac376b713c387dd7, with debug_info, not stripped
armeabi-v7a/libSDL2.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=0b70b55f875a58a784cbe1ecd8837a2fb7e3550a, with debug_info, not stripped
x86_64/libSDL2.so:      ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=07c38370c2ed4f9c712bcbab0c579801989f8730, with debug_info, not stripped
x86/libSDL2.so:         ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, BuildID[sha1]=b7e7fd5aac2e0459b609f2b16a650adec042da5f, with debug_info, not stripped

TatriX avatar Oct 09 '17 14:10 TatriX

Well, try using only one to see if it works.

tomaka avatar Oct 09 '17 15:10 tomaka

I linked arm64-v8a/libSDL2.so statically, and the next error :) is

java.lang.IllegalArgumentException: Requested window android.view.ViewRootImpl$W@b091df3 does not exist

TatriX avatar Oct 09 '17 15:10 TatriX

Hm, probably it's not related. But it still crashes.

TatriX avatar Oct 09 '17 15:10 TatriX

Now I'm trying to build exactly one target. In Cargo.toml:

[package.metadata.android]
build_targets = [ "aarch64-linux-android" ]

then cargo apk build gives

Compiling android_native_app_glue.c
/usr/local/android-ndk-r15b/sources/android/native_app_glue/android_native_app_glue.c:18:17: fatal error: jni.h: No such file or directory
 #include <jni.h>
                 ^
compilation terminated.
error: process didn't exit successfully: `/usr/local/android-ndk-r15b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-gcc /usr/local/android-ndk-r15b/sources/android/native_app_glue/android_native_app_glue.c -c -o /root/src/target/android-artifacts/aarch64-linux-android/android_native_app_glue.o --sysroot /usr/local/android-ndk-r15b/platforms/android-18/arch-arm64` (exit code: 1)

TatriX avatar Oct 09 '17 15:10 TatriX

ok, I finally did it. android_version = 21 did the trick

TatriX avatar Oct 09 '17 15:10 TatriX

Got the same jni.h not found trying to compile current example:

 ~  cargo apk build
Compiling android_native_app_glue.c
/home/marcos.cabral/Android/Sdk/ndk/android-ndk-r18b/sources/android/native_app_glue/android_native_app_glue.c:18:10: fatal error:
      'jni.h' file not found
#include <jni.h>
         ^~~~~~~
1 error generated.
error: process didn't exit successfully: `/home/marcos.cabral/Android/Sdk/ndk/android-ndk-r18b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc /home/marcos.cabral/Android/Sdk/ndk/android-ndk-r18b/sources/android/native_app_glue/android_native_app_glue.c -c -o /home/marcos.cabral/_w/android-rs-glue/examples/advanced/target/android-artifacts/armv7-linux-androideabi/android_native_app_glue.o --sysroot /home/marcos.cabral/Android/Sdk/ndk/android-ndk-r18b/platforms/android-29/arch-arm` (exit code: 1)

searching for jni.h found that it is present at:

Sdk/ndk-bundle/sysroot/usr/include/jni.h
Sdk/ndk/android-ndk-r18b/sysroot/usr/include/jni.h
Sdk/ndk/20.0.5594570/sysroot/usr/include/jni.h
Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/jni.h
Sdk/ndk/20.0.5594570/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/jni.h

So, for me it looks like cargo apk is pointing to the wrong sysroot

What am I missing ?

mmacedoeu avatar Oct 01 '19 20:10 mmacedoeu

Can you try things with the master version of cargo-apk? The build process has changed substantially. The current version isn't available on crates.io yet. Waiting for #221 to be resolved. The current master shouldn't have that issue. However, there is a known issue when linking to c++. The issue is discussed and has a workaround in #245.

philip-alldredge avatar Oct 01 '19 21:10 philip-alldredge

Thanks, building example basic and advanced works with master, looking forward to build something with a gui like conrod. If there is any project / example doing it already, could you please point me the url ?

mmacedoeu avatar Oct 02 '19 21:10 mmacedoeu

I am unaware of any examples that use a GUI.

philip-alldredge avatar Oct 02 '19 23:10 philip-alldredge