Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linking with versioned shared library in Android NDK

I am trying to load two shared libraries in my Android application through the loadLibrary call:

System.loadLibrary("mywrapper");
System.loadLibrary("crypto");

I keep running catching the `UnsatisfiedLinkError. Here is a more detailed version of the error.

Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1969]:
  130 could not load needed library 'libcrypto.so.1.0.0' for 
  'libmywrapper.so' (load_library[1111]: Library 'libcrypto.so.1.0.0' not found)

Any ideas?

After spending some time I found out that Android doesn't support versioned libraries. Has any one faced the same issue?

like image 988
feverDream Avatar asked Jul 15 '12 10:07

feverDream


People also ask

Can shared libraries be versioned?

In Linux you can have different versions of the same shared library in the same system. This allows you to add a newer version of the shared library which is not compatible with the older library interface without breaking the functionality of binaries which use the older library.

What is libc ++_ shared so?

Shared runtimesIf your application includes multiple shared libraries, you should use libc++_shared.so . On Android, the libc++ used by the NDK is not the same as the one that's part of the OS. This gives NDK users access to the latest libc++ features and bug fixes even when targeting old versions of Android.

Does Android have LIBC?

The Android platform uses libc++ for the C++ standard library (releases up to and including Lollipop used stlport).


2 Answers

I had the same problem on building libwebsockets for Android, which needs to link with OpenSSL. I use libssl.so as example. You should do the same for related .so files.

Before:
huiying@huiying-PORTEGE-R835:~$ objdump -p libssl.so | grep so
libssl.so:     file format elf32-little
  NEEDED               libcrypto.so.1.0.0
  NEEDED               libdl.so
  NEEDED               libc.so
  SONAME               libssl.so.1.0.0

After 
huiying@huiying-PORTEGE-R835:~$ rpl -R -e .so.1.0.0 "_1_0_0.so" libssl.so 
Replacing ".so.1.0.0" with "_1_0_0.so" (case sensitive) (partial words matched)
.
A Total of 2 matches replaced in 1 file searched.
huiying@huiying-PORTEGE-R835:~$ objdump -p libssl.so | grep so
libssl.so:     file format elf32-little
  NEEDED               libcrypto_1_0_0.so
  NEEDED               libdl.so
  NEEDED               libc.so
  SONAME               libssl_1_0_0.so

And don't forget to change file name "libssl.so" to "libssl_1_0_0.so".

The hack works. I have running Android app to prove it. See my rant at http://computervisionandjava.blogspot.com/2015/05/trouble-with-versioned-shared-libraries.html.

like image 180
user996042 Avatar answered Sep 17 '22 08:09

user996042


It seems android has an issue with loading versioned libraries.The issue at hand was because of library so-name in my case libcrypto.so.1.0.0. Even if you rename the library and try to load it as a prebuilt shared library in an android make file it fails.( It has to be because the library name is somehow embedded in the file. And any library that links with it expects to be linked with a library of with the same name )

I hope there are other ways out there when it comes to handling libraries with version names in android.

For now I am evading the problem all together by using static libraries of openssl and linking them with my own shared library.

like image 34
feverDream Avatar answered Sep 20 '22 08:09

feverDream