2

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?

Ian Butler
  • 107
  • 1
  • 9
  • 1
    "libMySuperLib.so" was linked against "libjpeg.so.62". If you used `ndk-build`, this is quite unusual. But if you used the standalone toolchain with Unix-style makefiles, then such outcome would not be unexpected. In the latter case, you may need some editing to your make files or configure script. – Alex Cohn Aug 20 '14 at 06:10
  • 1
    @AlexCohn yes, we were using libjpeg-turbo's autotools and then standard makefiles. I'll have my colleague who fixed our issue submit an answer with details. Thanks! – Ian Butler Sep 07 '14 at 05:01

1 Answers1

1

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

senbrow
  • 588
  • 1
  • 4
  • 11