为什么 C++ 可执行文件在 Android 设备上找不到动态库
Why C++ executable cannot find dynamic library when it is put on Android device
我正在使用 NDK 为 android 构建一个 C++ 可执行文件。可执行(./main)源文件main.c非常简单:
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Hello World\n");
return 0;
}
我可以用 cmake 和 android-cmake-toolchain 构建它。之后我把它放在 Android 设备上:
# this script is used to put binary to the device
import subprocess
output_executable = 'libs/armeabi-v7a/main /data/local/tmp/main'
# step 1: push
push_cmd = 'adb push '+output_executable
subprocess.check_call(push_cmd,stderr=subprocess.STDOUT, shell=True)
# step 2: change mode
mod_cmd = 'adb shell chmod 777 '+output_executable
subprocess.check_call(mod_cmd,stderr=subprocess.STDOUT, shell=True)
# step 3: run the program
run_cmd = 'adb shell '+output_executable
subprocess.check_call(run_cmd,stderr=subprocess.STDOUT, shell=True)
一切正常。但是,如果我只是把main.c改成main.cpp,然后照着做,编译就没问题了。但是当它放在 Android 设备上时,我收到以下错误消息:
soinfo_link_image(linker.cpp:1635): could not load library "libgnustl_shared.so" needed by "/data/local/tmp/main"; ....
我觉得应该根据报错信息指出stl库在Android平台的位置。任何想法将不胜感激。
.cpp
扩展使 NDK build
可以使用 c++ 编译器并 link 可以使用一些 c++ 库。您应该使用 -nodefaultlibs
选项并将库明确定义为 link with.
另外,看看SO: g++, static initialization and -nostdlib。
更新。
添加了日志(针对非信徒)。
当文件具有 .c
扩展名时:
C:\Dev\Projects\NdkTest\jni>ndk-build -B V=1
[armeabi] Compile thumb : hello-jni <= main.c
C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre
built/windows-x86_64/bin/arm-linux-androideabi-gcc -MMD -MP -MF
C:\Dev\Projects\NdkTest/ob j/local/armeabi/objs/hello-jni/main.o.d
-fpic -ffunction-sections -funwind-tables -fstack-protector
-no-canonical-prefixes -march=armv5te -mtune=xscale -msoft-f loat
-mthumb -Os -g -DNDEBUG -fomit-frame-pointer -fno-strict-aliasing
-finline-limit=64 -IC:\Dev\Projects\NdkTest/jni -DANDROID
-Wa,--noexecstack -Wformat -We rror=format-security
-IC:/Dev/Tools/Android/ndk-r10d/platforms/android-3/arch-arm/usr/inclu
de -c C:\Dev\Projects\NdkTest/jni/main.c -o C:\Dev\Projects\NdkTe
st/obj/local/armeabi/objs/hello-jni/main.o
[armeabi] Executable : hello-jni
C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre
built/windows-x86_64/bin/arm-linux-androideabi-g++ -Wl,--gc-sections
-Wl,-z,nocopyreloc --
sysroot=C:/Dev/Tools/Android/ndk-r10d/platforms/android-3/arch-arm
-Wl,-rpath-link=C:/Dev/Tools/Android/ndk-r10d/platforms/android-3/arch
-arm/usr/lib -Wl,-rpath
-link=C:\Dev\Projects\NdkTest/obj/local/armeabi
C:\Dev\Projects\NdkTest/obj/local/armeabi/objs/hello-jni/main.o -lgcc
-no-canonical-prefixes -Wl,--no-undefined -Wl,-z,noexecstack
-Wl,-z,relro -Wl,-z,now -mthumb -lc -lm -o
C:\Dev\Projects\NdkTest/obj/local/armeabi/hello-jni
[armeabi] Install : hello-jni => libs/armeabi/hello-jni
copy /b/y "C:\Dev\Projects\NdkTest\obj\local\armeabi\hello-jni"
"C:\Dev\Projects\NdkTest\libs\armeabi\hello-jni" > NUL
C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre
built/windows-x86_64/bin/arm-linux-androideabi-strip --strip-unneeded
C:\Dev\Projects\Ndk Test/libs/armeabi/hello-jni
当文件有 .cpp
扩展名时:
C:\Dev\Projects\NdkTest\jni>ndk-build -B V=1
[armeabi] Compile++ thumb: hello-jni <= main.cpp
C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre
built/windows-x86_64/bin/arm-linux-androideabi-g++ -MMD -MP -MF
C:\Dev\Projects\NdkTest/ob j/local/armeabi/objs/hello-jni/main.o.d
-fpic -ffunction-sections -funwind-tables -fstack-protector
-no-canonical-prefixes -march=armv5te -mtune=xscale -msoft-f loat
-fno-exceptions -fno-rtti -mthumb -Os -g -DNDEBUG -fomit-frame-pointer
-fno-strict-aliasing -finline-limit=64
-IC:/Dev/Tools/Android/ndk-r10d/sources/cxx-s tl/system/include
-IC:\Dev\Projects\NdkTest/jni -DANDROID -Wa,--noexecstack -Wformat
-Werror=format-security -IC:/Dev/Tools/Android/ndk-r10d/platforms/and
roid-3/arch-arm/usr/include -c C:\Dev\Projects\NdkTest/jni/main.cpp -o
C:\Dev\Projects\NdkTest/obj/local/armeabi/objs/hello-jni/main.o
[armeabi] StaticLibrary : libstdc++.a
C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre
built/windows-x86_64/bin/arm-linux-androideabi-gcc-ar crsD
C:\Dev\Projects\NdkTest/obj/loc al/armeabi/libstdc++.a
[armeabi] Executable : hello-jni
C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre
built/windows-x86_64/bin/arm-linux-androideabi-g++ -Wl,--gc-sections
-Wl,-z,nocopyreloc --
sysroot=C:/Dev/Tools/Android/ndk-r10d/platforms/android-3/arch-arm
-Wl,-rpath-link=C:/Dev/Tools/Android/ndk-r10d/platforms/android-3/arch
-arm/usr/lib -Wl,-rpath
-link=C:\Dev\Projects\NdkTest/obj/local/armeabi
C:\Dev\Projects\NdkTest/obj/local/armeabi/objs/hello-jni/main.o
C:\Dev\Projects\NdkTest/obj/local/armeabi/libstd c++.a -lgcc
-no-canonical-prefixes -Wl,--no-undefined -Wl,-z,noexecstack
-Wl,-z,relro -Wl,-z,now -mthumb
-LC:/Dev/Tools/Android/ndk-r10d/platforms/android-3/a rch-arm/usr/lib
-lstdc++ -lc -lm -o
C:\Dev\Projects\NdkTest/obj/local/armeabi/hello-jni
[armeabi] Install : hello-jni => libs/armeabi/hello-jni
copy /b/y "C:\Dev\Projects\NdkTest\obj\local\armeabi\hello-jni"
"C:\Dev\Projects\NdkTest\libs\armeabi\hello-jni" > NUL
C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre
built/windows-x86_64/bin/arm-linux-androideabi-strip --strip-unneeded
C:\Dev\Projects\Ndk Test/libs/armeabi/hello-jni
如您所见,将文件扩展名重命名为 .cpp
使 ndk-build
使用不同的编译器并 link 使用额外的库。
更新 2.
1) 如果您不需要 gnustl_shared
,请更新您的 Android.mk
LOCAL_CXXFLAGS += -nostdinc++ -I...
LOCAL_LDFLAGS += -nodefaultlibs -L...
LOCAL_LDLIBS += lc -lm -ldl -l...
2) 如果您确实需要 gnustl_shared
,请更新您的部署脚本
import subprocess
output_dir = 'libs/armeabi-v7a/'
output_files = ['main', 'libgnustl_shared.so']
target_dir = '/data/local/tmp/'
target_executable = target_dir+'main'
# step 1: push
for f in output_files:
push_cmd = 'adb push '+output_dir+f+' '+target_dir+f
subprocess.check_call(push_cmd,stderr=subprocess.STDOUT, shell=True)
# step 2: change mode
mod_cmd = 'adb shell chmod 777 '+target_executable
subprocess.check_call(mod_cmd,stderr=subprocess.STDOUT, shell=True)
# step 3: run the program
run_cmd = 'adb shell LD_LIBRARY_PATH='+target_dir.rstrip('/')+':$LD_LIBRARY_PATH '+target_executable
subprocess.check_call(run_cmd,stderr=subprocess.STDOUT, shell=True)
为什么要更新 LD_LIBRARY_PATH
请参阅 SO: Android – how to load shared library?
我正在使用 NDK 为 android 构建一个 C++ 可执行文件。可执行(./main)源文件main.c非常简单:
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Hello World\n");
return 0;
}
我可以用 cmake 和 android-cmake-toolchain 构建它。之后我把它放在 Android 设备上:
# this script is used to put binary to the device
import subprocess
output_executable = 'libs/armeabi-v7a/main /data/local/tmp/main'
# step 1: push
push_cmd = 'adb push '+output_executable
subprocess.check_call(push_cmd,stderr=subprocess.STDOUT, shell=True)
# step 2: change mode
mod_cmd = 'adb shell chmod 777 '+output_executable
subprocess.check_call(mod_cmd,stderr=subprocess.STDOUT, shell=True)
# step 3: run the program
run_cmd = 'adb shell '+output_executable
subprocess.check_call(run_cmd,stderr=subprocess.STDOUT, shell=True)
一切正常。但是,如果我只是把main.c改成main.cpp,然后照着做,编译就没问题了。但是当它放在 Android 设备上时,我收到以下错误消息:
soinfo_link_image(linker.cpp:1635): could not load library "libgnustl_shared.so" needed by "/data/local/tmp/main"; ....
我觉得应该根据报错信息指出stl库在Android平台的位置。任何想法将不胜感激。
.cpp
扩展使 NDK build
可以使用 c++ 编译器并 link 可以使用一些 c++ 库。您应该使用 -nodefaultlibs
选项并将库明确定义为 link with.
另外,看看SO: g++, static initialization and -nostdlib。
更新。
添加了日志(针对非信徒)。
当文件具有 .c
扩展名时:
C:\Dev\Projects\NdkTest\jni>ndk-build -B V=1
[armeabi] Compile thumb : hello-jni <= main.c
C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre
built/windows-x86_64/bin/arm-linux-androideabi-gcc -MMD -MP -MF
C:\Dev\Projects\NdkTest/ob j/local/armeabi/objs/hello-jni/main.o.d
-fpic -ffunction-sections -funwind-tables -fstack-protector
-no-canonical-prefixes -march=armv5te -mtune=xscale -msoft-f loat
-mthumb -Os -g -DNDEBUG -fomit-frame-pointer -fno-strict-aliasing
-finline-limit=64 -IC:\Dev\Projects\NdkTest/jni -DANDROID
-Wa,--noexecstack -Wformat -We rror=format-security
-IC:/Dev/Tools/Android/ndk-r10d/platforms/android-3/arch-arm/usr/inclu
de -c C:\Dev\Projects\NdkTest/jni/main.c -o C:\Dev\Projects\NdkTe
st/obj/local/armeabi/objs/hello-jni/main.o
[armeabi] Executable : hello-jni
C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre
built/windows-x86_64/bin/arm-linux-androideabi-g++ -Wl,--gc-sections
-Wl,-z,nocopyreloc --
sysroot=C:/Dev/Tools/Android/ndk-r10d/platforms/android-3/arch-arm
-Wl,-rpath-link=C:/Dev/Tools/Android/ndk-r10d/platforms/android-3/arch
-arm/usr/lib -Wl,-rpath
-link=C:\Dev\Projects\NdkTest/obj/local/armeabi
C:\Dev\Projects\NdkTest/obj/local/armeabi/objs/hello-jni/main.o -lgcc
-no-canonical-prefixes -Wl,--no-undefined -Wl,-z,noexecstack
-Wl,-z,relro -Wl,-z,now -mthumb -lc -lm -o
C:\Dev\Projects\NdkTest/obj/local/armeabi/hello-jni
[armeabi] Install : hello-jni => libs/armeabi/hello-jni
copy /b/y "C:\Dev\Projects\NdkTest\obj\local\armeabi\hello-jni"
"C:\Dev\Projects\NdkTest\libs\armeabi\hello-jni" > NUL
C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre
built/windows-x86_64/bin/arm-linux-androideabi-strip --strip-unneeded
C:\Dev\Projects\Ndk Test/libs/armeabi/hello-jni
当文件有 .cpp
扩展名时:
C:\Dev\Projects\NdkTest\jni>ndk-build -B V=1
[armeabi] Compile++ thumb: hello-jni <= main.cpp
C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre
built/windows-x86_64/bin/arm-linux-androideabi-g++ -MMD -MP -MF
C:\Dev\Projects\NdkTest/ob j/local/armeabi/objs/hello-jni/main.o.d
-fpic -ffunction-sections -funwind-tables -fstack-protector
-no-canonical-prefixes -march=armv5te -mtune=xscale -msoft-f loat
-fno-exceptions -fno-rtti -mthumb -Os -g -DNDEBUG -fomit-frame-pointer
-fno-strict-aliasing -finline-limit=64
-IC:/Dev/Tools/Android/ndk-r10d/sources/cxx-s tl/system/include
-IC:\Dev\Projects\NdkTest/jni -DANDROID -Wa,--noexecstack -Wformat
-Werror=format-security -IC:/Dev/Tools/Android/ndk-r10d/platforms/and
roid-3/arch-arm/usr/include -c C:\Dev\Projects\NdkTest/jni/main.cpp -o
C:\Dev\Projects\NdkTest/obj/local/armeabi/objs/hello-jni/main.o
[armeabi] StaticLibrary : libstdc++.a
C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre
built/windows-x86_64/bin/arm-linux-androideabi-gcc-ar crsD
C:\Dev\Projects\NdkTest/obj/loc al/armeabi/libstdc++.a
[armeabi] Executable : hello-jni
C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre
built/windows-x86_64/bin/arm-linux-androideabi-g++ -Wl,--gc-sections
-Wl,-z,nocopyreloc --
sysroot=C:/Dev/Tools/Android/ndk-r10d/platforms/android-3/arch-arm
-Wl,-rpath-link=C:/Dev/Tools/Android/ndk-r10d/platforms/android-3/arch
-arm/usr/lib -Wl,-rpath
-link=C:\Dev\Projects\NdkTest/obj/local/armeabi
C:\Dev\Projects\NdkTest/obj/local/armeabi/objs/hello-jni/main.o
C:\Dev\Projects\NdkTest/obj/local/armeabi/libstd c++.a -lgcc
-no-canonical-prefixes -Wl,--no-undefined -Wl,-z,noexecstack
-Wl,-z,relro -Wl,-z,now -mthumb
-LC:/Dev/Tools/Android/ndk-r10d/platforms/android-3/a rch-arm/usr/lib
-lstdc++ -lc -lm -o
C:\Dev\Projects\NdkTest/obj/local/armeabi/hello-jni
[armeabi] Install : hello-jni => libs/armeabi/hello-jni
copy /b/y "C:\Dev\Projects\NdkTest\obj\local\armeabi\hello-jni"
"C:\Dev\Projects\NdkTest\libs\armeabi\hello-jni" > NUL
C:/Dev/Tools/Android/ndk-r10d/toolchains/arm-linux-androideabi-4.8/pre
built/windows-x86_64/bin/arm-linux-androideabi-strip --strip-unneeded
C:\Dev\Projects\Ndk Test/libs/armeabi/hello-jni
如您所见,将文件扩展名重命名为 .cpp
使 ndk-build
使用不同的编译器并 link 使用额外的库。
更新 2.
1) 如果您不需要 gnustl_shared
,请更新您的 Android.mk
LOCAL_CXXFLAGS += -nostdinc++ -I...
LOCAL_LDFLAGS += -nodefaultlibs -L...
LOCAL_LDLIBS += lc -lm -ldl -l...
2) 如果您确实需要 gnustl_shared
,请更新您的部署脚本
import subprocess
output_dir = 'libs/armeabi-v7a/'
output_files = ['main', 'libgnustl_shared.so']
target_dir = '/data/local/tmp/'
target_executable = target_dir+'main'
# step 1: push
for f in output_files:
push_cmd = 'adb push '+output_dir+f+' '+target_dir+f
subprocess.check_call(push_cmd,stderr=subprocess.STDOUT, shell=True)
# step 2: change mode
mod_cmd = 'adb shell chmod 777 '+target_executable
subprocess.check_call(mod_cmd,stderr=subprocess.STDOUT, shell=True)
# step 3: run the program
run_cmd = 'adb shell LD_LIBRARY_PATH='+target_dir.rstrip('/')+':$LD_LIBRARY_PATH '+target_executable
subprocess.check_call(run_cmd,stderr=subprocess.STDOUT, shell=True)
为什么要更新 LD_LIBRARY_PATH
请参阅 SO: Android – how to load shared library?