rust-mobile / ndk

Rust bindings to the Android NDK
Apache License 2.0
1.11k stars 110 forks source link

Unable to load native library: /data/app-lib/*/lib*.so #446

Open p0ryae opened 9 months ago

p0ryae commented 9 months ago

I managed to compile, get the .so file, and then package an apk based on it. However, no matter what I try, I keep getting this error over and over again. It just can't load the native library, even though it's compiled based on the device's architecture (armv6). I use the arm-linux-androideabi target in order to get the final lib .so file.

I use ndk r16b, which is the last ndk to support armeabi.

For compilation of the .so file, I pass through the CARGO_TARGET_ARM_LINUX_ANDROIDEABI_LINKER flag with the value of /home/porya/Android/Sdk/ndk/android-ndk-r16b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ld. Furthermore, I also link the libraries in the build.rs:

fn main() {
    println!("cargo:rustc-link-search=/home/porya/Android/Sdk/ndk/android-ndk-r16b/platforms/android-19/arch-arm/usr/lib/");
}

The full error report in adb logcat:

E/AndroidRuntime( 3363): FATAL EXCEPTION: main
E/AndroidRuntime( 3363): Process: org.p0ryae.trs24, PID: 3363
E/AndroidRuntime( 3363): java.lang.RuntimeException: Unable to start activity ComponentInfo{org.p0ryae.trs24/android.app.NativeActivity}: java.lang.IllegalArgumentException: Unable to load native library: /data/app-lib/org.p0ryae.trs24-1/libtrs_24.so
E/AndroidRuntime( 3363):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2212)
E/AndroidRuntime( 3363):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2271)
E/AndroidRuntime( 3363):    at android.app.ActivityThread.access$800(ActivityThread.java:144)
E/AndroidRuntime( 3363):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1205)
E/AndroidRuntime( 3363):    at android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime( 3363):    at android.os.Looper.loop(Looper.java:136)
E/AndroidRuntime( 3363):    at android.app.ActivityThread.main(ActivityThread.java:5179)
E/AndroidRuntime( 3363):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 3363):    at java.lang.reflect.Method.invoke(Method.java:515)
E/AndroidRuntime( 3363):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:732)
E/AndroidRuntime( 3363):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:566)
E/AndroidRuntime( 3363):    at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime( 3363): Caused by: java.lang.IllegalArgumentException: Unable to load native library: /data/app-lib/org.p0ryae.trs24-1/libtrs_24.so
E/AndroidRuntime( 3363):    at android.app.NativeActivity.onCreate(NativeActivity.java:183)
E/AndroidRuntime( 3363):    at android.app.Activity.performCreate(Activity.java:5231)
E/AndroidRuntime( 3363):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
E/AndroidRuntime( 3363):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2169)
E/AndroidRuntime( 3363):    ... 11 more
W/ActivityManager( 2138):   Force finishing activity org.p0ryae.trs24/android.app.NativeActivity

I also tried checking the dependencies for libtrs_24.so using readelf and my android system has all of them.

Is there a way to find the root cause? Am I missing something? Any ideas on where to start is appreciated.

p0ryae commented 9 months ago

Update:

After hours and days of researching and going through hell, nothing helped to get anywhere...

UNTIL I decided to manually load the library via android studio (System.loadLibrary("trs_24");) and run it on my armv6 device. Turns out it can't locate the getifaddrs symbol. Full error log:

FATAL EXCEPTION: main
Process: com.example.myapplication, PID: 12794
java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "getifaddrs" referenced by "libtrs_24.so"...

getifaddrs function (or ifaddrs header) native support exists since android 7.0 (NDK >= 24). For NDKs below 24 (or androids below 7.0), I found this repo for the implementation:

https://github.com/morristech/android-ifaddrs

Not sure exactly how to go from here. Am I supposed to compile the custom c code in rust, so the final built .so file has it (using the cc crate)?

mrazorvin commented 7 months ago

Hi, I faced same problem,

I'm tried to create rust bindings for https://github.com/effekseer/Effekseer (c++ lib). I started with custom build.rs that compiles static lib with cc from sources (in the same way as luau-sys), it's perfectly works on Linux and Windows. But when I tried to compile my lib with NDK, I got dlopen failed: cannot locate symbol eglGetProcAdressess.

I investigated little bit more and know for sure that I can use following code to call this function inside my lib


#include <iostream>
#include <stdio.h>
#include <string>
#include <dlfcn.h>

using namespace std;

#define DLL_EXPORT extern "C"

typedef void (*GLFWglproc)(void);
typedef GLFWglproc(EGLAPIENTRY *PFN_eglGetProcAddress)(const char *);

struct Pointers
{
  PFN_eglGetProcAddress eglGetProcAddress;
};

DLL_EXPORT void effekseer_version()
{
  std::cout << "v1.0.0" << endl;

#if defined(__ANDROID__)
  auto handle = dlopen("libEGL.so", RTLD_LAZY | RTLD_LOCAL);
  auto ptrs = new Pointers;
  ptrs->eglGetProcAddress = (PFN_eglGetProcAddress)dlsym(handle, "eglGetProcAddress");
  if (ptrs->eglGetProcAddress("glDeleteBuffers") == nullptr)
  {
    std::cout << "glDeleteBuffers --- NOT FOUND ---" << endl;
  }
  else
  {
    std::cout << "glDeleteBuffers +++ FOUND +++" << endl;
    auto glFetString
  }

  std::cout << "Android extension v1.2.0" << endl;
#endif
}

So at this point I knows that only static linking don't work correctly. Also not sure where to move next I tried following:

mrazorvin commented 7 months ago

UPDATE

I forgot to link shared libraries

Following lines were missed in build.rs

println!(r"cargo:rustc-link-lib={}", "EGL");
println!(r"cargo:rustc-link-lib={}", "GLESv3");

*.so dependencies could be checked with xelfviewer (https://github.com/horsicq/XELFViewer)

image

For example on screenshot above GLES3 is missed

P.S

For GLES lib name is different from it namespace, correct lib name could be found there https://developer.android.com/ndk/guides/stable_apis