Search code examples
javaandroidandroid-ndkloadlibrarylibjpeg-turbo

Android native linker wants file named libjpeg.so.62 specifically


I have a native library for my Android app that uses libjpeg-turbo. I am compiling the library and libjpeg-turbo using NDK. It all seems to be compiling and installing fine (I see all .so files on the phone in /data/data/com.company.app/lib ) and I am calling

System.loadLibrary("jpeg");
System.loadLibrary("zmq");
System.loadLibrary("MySuperLib");
System.loadLibrary("jnilibwrapper");

E/AndroidRuntime(8186): java.lang.UnsatisfiedLinkError: dlopen failed: could not load library "libMySuperLib.so" needed by "libjnilibrapper.so"; caused by could not load library "libjpeg.so.62" needed by "libMySuperLib.so"; caused by library "libjpeg.so.62" not found

I found this workaround, making a symlink of the lib like so gets me passed this error

root@klteatt:/data/data/com.company.app/lib # ln -s libjpeg.so libjpeg.so.62

but of course that is not a solution.

Where could we be going wrong? Why is it wanting libjpeg.so.62 specifically?


Solution

  • The issue is caused by MySuperLib being linked with libjpeg-turbo's versioned soname at compile time. Android's JNI runtime does not currently support versioned dynamic libraries, which is why it cannot "find" libjpeg.so, since it only expects an unversioned soname.

    One possible way to compile libjpeg-turbo without versioning information is to modify libjpeg-turbo's Makefile.am *LDFLAGS variable, which is passed to libtool. By changing the *LDFLAGS variable to contain libtool's -avoid-version flag, libtool will try to avoid creating libraries with the version information embedded. Creating unversioned shared libraries is usually a terrible idea, but since you can't actually "install" shared libraries on Android at this point, it is fairly safe since your MySuperLib library is the only one that will ever be using the unversioned libjpeg.so.

    Here is an example of a patch to libjpeg-turbo's Makefile.am that will produce an unversioned libjpeg.so:

    --- Makefile.am 2014-08-28 09:57:37.000000000 -0700
    +++ Makefile.am.patched 2014-08-28 09:57:20.000000000 -0700
    @@ -1,5 +1,5 @@
     lib_LTLIBRARIES = libjpeg.la
    -libjpeg_la_LDFLAGS = -version-info ${LIBTOOL_CURRENT}:${SO_MINOR_VERSION}:${SO_AGE} -no-undefined
    +libjpeg_la_LDFLAGS = -avoid-version -no-undefined
     include_HEADERS = jerror.h jmorecfg.h jpeglib.h
    
     if WITH_TURBOJPEG
    

    Here is a link to libtool's link-mode manual, for more options and information: http://www.gnu.org/software/libtool/manual/html_node/Link-mode.html