I've compiled a shared library with android-cmake and the NDK against libstdc++, and as per android-ndk-r7/docs/CPLUSPLUS-SUPPORT.html I'm trying to load gnustl_shared before loading my library:
static {
System.loadLibrary("gnustl_shared");
System.loadLibrary("MathTest");
}
I can see this being done for instance here but I get an exception:
01-03 20:02:42.307: E/AndroidRuntime(569): Caused by: java.lang.UnsatisfiedLinkError: Couldn't load gnustl_shared: findLibrary returned null
If I don't load gnustl_shared, it fails with this exception:
01-03 20:03:04.667: E/AndroidRuntime(603): Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1311]: 33 cannot locate '_ZNSo3putEc'...
I have tested on API levels 8 and 9 with the same issue. What am I doing wrong? I assume that the symbol it's looking for in the last exception is related to the STL and that loading it would solve the problem. Is this the case?
Edit:
I've now included the STL library as suggested by answers. The compile line that CMake produces is this (note that my project has three files, mother.c
(a copy of George Marsaliga's Mother of All Random Number Generator available here), Driver.cpp
which contains functions to test different math libraries and print out the function runtimes, and androidactivity.cpp
which contains the JNI glue and calls the test function from Driver.cpp
. The verbose Makefile output generated by CMake is as follows. I'm not sure if this is useful information but
[ 33%] Building CXX object CMakeFiles/MathTest.dir/src/Driver.cpp.o
/Users/martin/Android/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-g++ -DMathTest_EXPORTS -D__STDC_INT64__ --sysroot=/Users/martin/Android/android-ndk-r7/platforms/android-8/arch-arm -fPIC -DANDROID -Wno-psabi -fsigned-char -mthumb -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -fexceptions -fno-check-new -fno-common -fstrict-aliasing -Wno-variadic-macros -Wextra -pedantic -g0 -O2 -fPIC -isystem /Users/martin/Android/android-ndk-r7/sources/cxx-stl/gnu-libstdc++/include -isystem /Users/martin/Android/android-ndk-r7/sources/cxx-stl/gnu-libstdc++/libs/armeabi/include -I/Users/martin/Repositories/MathTest/lib/cml-1_0_2 -I/Users/martin/Repositories/MathTest/lib/eigen-eigen-13a11181fc5a -I/Users/martin/Repositories/MathTest/lib/glm-0.9.3.B -o CMakeFiles/MathTest.dir/src/Driver.cpp.o -c /Users/martin/Repositories/MathTest/src/Driver.cpp
"/Applications/CMake 2.8-4.app/Contents/bin/cmake" -E cmake_progress_report /Users/martin/Repositories/MathTest/build/android/CMakeFiles 2
[ 66%] Building C object CMakeFiles/MathTest.dir/src/mother.c.o
/Users/martin/Android/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-gcc -DMathTest_EXPORTS -D__STDC_INT64__ --sysroot=/Users/martin/Android/android-ndk-r7/platforms/android-8/arch-arm -fPIC -DANDROID -Wno-psabi -fsigned-char -mthumb -O3 -DNDEBUG -fPIC -I/Users/martin/Android/android-ndk-r7/sources/cxx-stl/gnu-libstdc++/include -I/Users/martin/Android/android-ndk-r7/sources/cxx-stl/gnu-libstdc++/libs/armeabi/include -I/Users/martin/Repositories/MathTest/lib/cml-1_0_2 -I/Users/martin/Repositories/MathTest/lib/eigen-eigen-13a11181fc5a -I/Users/martin/Repositories/MathTest/lib/glm-0.9.3.B -o CMakeFiles/MathTest.dir/src/mother.c.o -c /Users/martin/Repositories/MathTest/src/mother.c
"/Applications/CMake 2.8-4.app/Contents/bin/cmake" -E cmake_progress_report /Users/martin/Repositories/MathTest/build/android/CMakeFiles 3
[100%] Building CXX object CMakeFiles/MathTest.dir/src/androidactivity.cpp.o
/Users/martin/Android/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-g++ -DMathTest_EXPORTS -D__STDC_INT64__ --sysroot=/Users/martin/Android/android-ndk-r7/platforms/android-8/arch-arm -fPIC -DANDROID -Wno-psabi -fsigned-char -mthumb -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security -fexceptions -fno-check-new -fno-common -fstrict-aliasing -Wno-variadic-macros -Wextra -pedantic -g0 -O2 -fPIC -isystem /Users/martin/Android/android-ndk-r7/sources/cxx-stl/gnu-libstdc++/include -isystem /Users/martin/Android/android-ndk-r7/sources/cxx-stl/gnu-libstdc++/libs/armeabi/include -I/Users/martin/Repositories/MathTest/lib/cml-1_0_2 -I/Users/martin/Repositories/MathTest/lib/eigen-eigen-13a11181fc5a -I/Users/martin/Repositories/MathTest/lib/glm-0.9.3.B -o CMakeFiles/MathTest.dir/src/androidactivity.cpp.o -c /Users/martin/Repositories/MathTest/src/androidactivity.cpp
Linking CXX shared library ../../android/libs/armeabi/libMathTest.so
readelf
shows that my library depends on libstdc++
, libm
, libc
and libdl
, and as far as I know all of these except libstdc++
are available on the device as per android-ndk-r7/docs/STABLE-APIS.html
.
Martin-Foots-MacBook-Pro:android martin$ ~/Android/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-readelf -d ../../android/libs/armeabi/libMathTest.so
Dynamic section at offset 0x14b0 contains 25 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libstdc++.so]
0x00000001 (NEEDED) Shared library: [libm.so]
0x00000001 (NEEDED) Shared library: [libc.so]
0x00000001 (NEEDED) Shared library: [libdl.so]
0x0000000e (SONAME) Library soname: [libMathTest.so]
0x00000010 (SYMBOLIC) 0x0
0x00000019 (INIT_ARRAY) 0x9498
0x0000001b (INIT_ARRAYSZ) 12 (bytes)
0x0000001a (FINI_ARRAY) 0x94a4
0x0000001c (FINI_ARRAYSZ) 12 (bytes)
0x00000004 (HASH) 0xd4
0x00000005 (STRTAB) 0x544
0x00000006 (SYMTAB) 0x234
0x0000000a (STRSZ) 1033 (bytes)
0x0000000b (SYMENT) 16 (bytes)
0x00000003 (PLTGOT) 0x9598
0x00000002 (PLTRELSZ) 136 (bytes)
0x00000014 (PLTREL) REL
0x00000017 (JMPREL) 0x990
0x00000011 (REL) 0x950
0x00000012 (RELSZ) 64 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x00000016 (TEXTREL) 0x0
0x6ffffffa (RELCOUNT) 4
0x00000000 (NULL) 0x0
Does this information help? Is there a way I can tell where the unfound symbol comes from?
well, you need to load gnustl_shared before your own libraries, something like this :
static {
System.loadLibrary("gnustl_shared");
System.loadLibrary("myNativeLib1");
System.loadLibrary("myNativeLib2");
//.......
}
In my case the gnustl_shared library is really not on the device (running Android 2.3.6). When I link the gnustl statically , the NDK app runs fine on the device. my 2 cents
You probably need to add it in your Application.mk as well. The project you linked did this at least.
I believe you'll need to package the appropriate libgnustl_shared.so's (one for each ABI you intend to work with) in your APK libs/*. What this means exactly to your custom CMake build system I can't tell you.
APKs are just zip files -- you can open up yours and ensure it's present where expected.
You show the G++ commands that cmake generated. They look OK. But the linker produced the libMathTest.so based on the system STL library. Actually, it's a mixture of system STL and gnustl (some references to the latter probably came from cxx-stl/gnu-libstdc++/include).
It would help if you echo the actual command behind
Linking CXX shared library ../../android/libs/armeabi/libMathTest.so
But maybe your application can be satisfied with the system STL library? One important advantage is that libstdc++.so is preinstalled on all devices, just like libm.
I met the same problem, however I made a large build with 6 shared libraries, all depend on libgnustl_shared.so, and I made two abi builds: armeabi and armeabi-v7a All shared libraries were manually copied to the libs/(abi-name)/, inclusive libgnustl-shared.so. I made the System.load( "gnustl_shared" ) at the first place, but whenever the android activity tried to load lib, it excepted and said gnustl_shared not found. I tried with Androip-8, android-9 and android-14, all have the same error.
_HERE THE ANDROID.MK_
MYTOP_DIR := $(call my-dir)
LOCAL_PATH := $(MYTOP_DIR)
include $(CLEAR_VARS)
NDK_ROOT := /home/workspace/android-ndk-r7
RUNTIME_STL_PATH :=$(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++
# name of the module to be built
LOCAL_MODULE := MyMediaPlayer
LOCAL_SRC_FILES := MyMediaPlayer.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/libMediaClient/include
# rule definition
LOCAL_CPP_EXTENSION := .cxx .cpp .cc
LOCAL_CFLAGS += -I$(RUNTIME_STL_PATH)/include
LOCAL_CFLAGS += -I$(RUNTIME_STL_PATH)/libs/$(TARGET_ARCH_ABI)/include
LOCAL_LDLIBS += -llog
LOCAL_LDLIBS += -landroid
LOCAL_LDLIBS += -L$(RUNTIME_STL_PATH)/libs/$(TARGET_ARCH_ABI)
LOCAL_LDLIBS += -lgnustl_shared
LOCAL_LDLIBS += -L$(LOCAL_PATH)/libMediaClient/lib/android/$(TARGET_ARCH_ABI)
LOCAL_LDLIBS += -lMediaClient
LOCAL_LDLIBS += -ltools
include $(BUILD_SHARED_LIBRARY)
_HERE THE APPLICATION.MK_
APP_ABI := armeabi armeabi-v7a
APP_STL := gnustl_shared # this doesn't make any sense
APP_MODULES := MyMediaPlayer
I could understand if exception occurs by loading my own libs, but here the libgnustil_shared did come from ndk, what wrong here!!!
Steven
User contributions licensed under CC BY-SA 3.0