Rodolfo Rocco
Rodolfo Rocco

Reputation: 71

Linking shared library libGLES_mali.so causes dlopen failed: library "[email protected]" not found in Android >= 7.0

Since Android 7.0 it's not possible anymore to link against a non-ndk shared library (see NDK Apps Linking to Platform Libraries).

One possible workaround consists in including the library in the apk (See Update your app).

The library that you are trying to link against may depend on other non-ndk libraries. In that case you should include those libraries too.

In my case I've been developing an application which makes use of OpenCL. On ARM devices the library with the correct symbols is libGLES_mali.so. The application works fine on devices with Android < 7.0 but it crashes on devices with Android >= 7.0. The error that I can read in logcat is:

java.lang.UnsatisfiedLinkError: dlopen failed: library "[email protected]" not found

Using the command

readelf -d libGLES_mali.so | grep NEEDED

I can read the name of the libraries libGLES_mali.so depend on and predictably [email protected] is among them:

0x0000000000000001 (NEEDED)             Shared library: [[email protected]]
 0x0000000000000001 (NEEDED)             Shared library: [liblog.so]
 0x0000000000000001 (NEEDED)             Shared library: [libnativewindow.so]
 0x0000000000000001 (NEEDED)             Shared library: [libz.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc++.so]
 0x0000000000000001 (NEEDED)             Shared library: [libutils.so]
 0x0000000000000001 (NEEDED)             Shared library: [libcutils.so]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so]
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so]

I've tried including the aforementioned library in the apk but I get the same error. The weird thing is that the library is part of the VNDK-SP (see SP-HAL) and as such it is my understanding that private libraries may depend on it freely.

Any suggestion?

EDIT 31/01/2019: Tested devices running on Android >= 7.0 were all Huawei. Could it possibly be a vendor related problem?

Upvotes: 4

Views: 3681

Answers (2)

fakr00n
fakr00n

Reputation: 113

I have had a similar problem with libOpenCL.so library needing libcutils.so and I solved it in a slightly different way:

Instead of linking and including libOpenCL.so in the .apk, I chose to only link my c++ code to it and then use libOpenCL.so the library locally installed on the phone (it's the same file - No need to have it in 2 different locations).

This was much easier for me because by doing this I didn't have to rename and load libcutils as soon as my app started which (I had SW design constraints preventing me from doing this).

Here are the details:

  1. I created a lib dir in a location that Android Studio does not include when packaging the .apk file (ex: src/cpp/lib)
  2. I downloaded the 32-bit and 64-bit libOpenCL.so from my phone using "adb pull ..." and saved them to src/cpp/lib/armeabi-v7a and src/cpp/lib/arm64-v8a respectively (I guess you did a similar thing - see Does Android support OpenCL? for more details)
  3. I added the following 2 lines to my CMakeKists.txt:
add_library(OpenCL SHARED IMPORTED)
set_target_properties(OpenCL PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/cpp/lib/${ANDROID_ABI}/libOpenCL.so)

It's a bit sad but it seems to me that it's almost impossible to make an OpenCL app that works on all Android phones (the libs are called differently and are at different locations on different phones)... Please, let me know if you know of a way to do this :)

Upvotes: 2

Rodolfo Rocco
Rodolfo Rocco

Reputation: 71

Alex Cohn comment was right. In order to solve the problem I did the following:

1) Renamed [email protected] in libfoo.so

2) Added libfoo.so in CMakeLists.txt like this:

add_library( foo
         SHARED
         IMPORTED )
set_target_properties( foo
         PROPERTIES IMPORTED_LOCATION
         ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libfoo.so )

3) Target-linked MyLibrary, which contains the OpenCL calls, against libfoo.so (and, of course, libGLES_mali.so)

target_link_libraries (MyLibrary GLES_mali foo)

4) Loaded libfoo.so as soon as possible. To do so I created a static method in my MainActivity which I call as soon as the application enters onCreate().

private static void loadLibrary() {
    System.loadLibrary("foo");
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    loadLibrary();
    ...
}  

At this point the application crashes complaining that it couldn't find some libraries. Using the readelf command:

./readelf -d /Users/rodolforocco/AndroidProjects/OvermindClient/app/libs/arm64-v8a/android-27/libfoo.so | grep NEEDED

I was able to see that these were indeed the libraries that libfoo.so depended on. These libraries also depended on other libraries that could not be located. I copied them all from the folder /system/lib64/ in my device to the folder ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/, where libfoo.so was.

5) Finally, as before, I loaded MyLibrary when I needed it.

The application doesn't crash anymore and works as intended. Thanks a lot!

Upvotes: 3

Related Questions