我有一个原生Android, SDK样式库,依赖于OpenCV。
为了避免当用户使用库和他们自己使用OpenCV时发生冲突,我想将OpenCV静态编译到我的库中并隐藏其符号。
我静态编译OpenCV (3.4.13world
模块)并使用它,以及它在我的库中的第三方库。
当我尝试使用我的库时,它抛出一个异常,即使该异常被用户捕获,SIGABRT
正在导致应用程序终止。
这是来自logcat
的堆栈跟踪
A/libc: Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 24115 (.test), pid 24115 (.test)
...
A/DEBUG: backtrace:
A/DEBUG: #00 pc 0000000000051948 /apex/com.android.runtime/lib64/bionic/libc.so (abort+168) (BuildId: 931371c1098ffd5adc489b9ff4da8e82)
A/DEBUG: #01 pc 00000000000b2ba0 /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libc++_shared.so (BuildId: ece72a2ebc3774a1be9fd21271258acd3bcdfaa7)
A/DEBUG: #02 pc 00000000000aec8c /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libc++_shared.so (__gxx_personality_v0+348) (BuildId: ece72a2ebc3774a1be9fd21271258acd3bcdfaa7)
A/DEBUG: #03 pc 00000000004dd2dc /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libmylib.so (BuildId: 790f2880373cb985055ab9b7b2efc48b1afb82fd)
A/DEBUG: #04 pc 00000000004dd7e4 /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libmylib.so (BuildId: 790f2880373cb985055ab9b7b2efc48b1afb82fd)
A/DEBUG: #05 pc 0000000000170600 /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libmylib.so (mylib::TestClass::TestClass(char const*, char const*)+908) (BuildId: 790f2880373cb985055ab9b7b2efc48b1afb82fd)
A/DEBUG: #06 pc 000000000000c5d0 /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libJnilibrary.so (BuildId: 7f3605ea8cb95dc87864e3df22f6b77b46c2e592)
A/DEBUG: #07 pc 000000000000c3b8 /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libJnilibrary.so (BuildId: 7f3605ea8cb95dc87864e3df22f6b77b46c2e592)
A/DEBUG: #08 pc 000000000000c308 /data/app/~~gc4ZOfzcr7C0hRfmsieCtQ==/com.example.test-sx2ESCfGCsi3lXPZWnk9nA==/base.apk!libJnilibrary.so (Java_com_example_lib_Engine_cxxInit+56) (BuildId: 7f3605ea8cb95dc87864e3df22f6b77b46c2e592)
A/DEBUG: #09 pc 00000000002d7644 /apex/com.android.art/lib64/libart.so (art_quick_generic_jni_trampoline+148) (BuildId: 2b417e2566f5eb686666666b6ee952ea)
(如果JNI库使用c++_static
,也会发生这种情况,但在这种情况下,它上面的__gxx_personality_v0
和1来自libJnilibrary.so
)
如果我将OpenCV编译为共享库并将我的库链接到它,那么一切都可以正常工作。
我以前在库中遇到过异常问题,参见我问的这个问题。我通过使用c++_static
STL编译一切来解决它。问题看起来类似于此,确实我错过了key function
,但即使在添加它之后,问题仍然发生。
我查看了使用llvm-readelf -CWs
的符号,并注意到当OpenCV动态链接时,除了OpenCV符号外,输出还包含一些ndk和cxxabi符号,这些符号在OpenCV静态使用时不存在。我不知道它们之间是否有联系但是例如
110: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::uncaught_exception()
...
201: 0000000000000000 0 OBJECT GLOBAL DEFAULT UND vtable for __cxxabiv1::__vmi_class_type_info
...
231: 0000000000000000 0 FUNC GLOBAL DEFAULT UND std::__ndk1::to_string(unsigned int)
(当使用静态构建的OpenCV时,所有这些都缺失)
我正在使用ndk版本21e
(我现在不能使用更高的版本,因为另一个库使用Bazel
,它目前只支持最多21)
OpenCV是用以下标志构建的
cmake -DCMAKE_BUILD_TYPE=Release -DINSTALL_ANDROID_EXAMPLES=OFF -DANDROID_EXAMPLES_WITH_LIBS=OFF -DANDROID_ABI="arm64-v8a"
-DBUILD_EXAMPLES=OFF -DBUILD_DOCS=OFF -DWITH_OPENCL=OFF -DBUILD_ANDROID_PROJECTS=OFF -DBUILD_ANDROID_EXAMPLES=OFF -DANDROID_ARM_NEON=1
-DANDROID_STL=c++_static -DANDROID_PLATFORM=android-21 -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake"
-DBUILD_SHARED_LIBS=OFF -DBUILD_FAT_JAVA_LIB=OFF -DBUILD_JAVA=OFF -DINSTALL_CREATE_DISTRIB=ON -DINSTALL_ANDROID_EXAMPLES=OFF -DBUILD_opencv_objdetect=OFF
-DBUILD_opencv_video=ON -DBUILD_opencv_videoio=ON -DBUILD_opencv_features2d=ON -DBUILD_opencv_flann=OFF -DBUILD_opencv_highgui=ON -DBUILD_opencv_ml=OFF
-DBUILD_opencv_photo=OFF -DBUILD_opencv_python=OFF -DBUILD_opencv_shape=OFF -DBUILD_opencv_stitching=OFF -DBUILD_opencv_superres=OFF -DBUILD_opencv_ts=OFF
-DBUILD_opencv_videostab=OFF -DBUILD_ANDROID_PROJECTS=OFF -DBUILD_opencv_world=ON -DBUILD_opencv_dnn=OFF -DBUILD_opencv_core=ON -DBUILD_opencv_imgcodecs=ON
-DBUILD_opencv_imgproc=ON -DBUILD_opencv_calib3d=ON -GNinja -DCMAKE_INSTALL_PREFIX=../install -DBUILD_ZLIB=1 -DWITH_PROTOBUF=OFF -DWITH_QUIRC=OFF ..
我的库是使用Gradle和Android Studio编译的,带有这些CMake标志
externalNativeBuild {
cmake {
cppFlags "-std=c++17 -static-openmp -fopenmp -fexceptions -frtti -Wno-unused-command-line-argument -Wl,-s"
cppFlags "-Wl,--exclude-libs,libc++_static.a -Wl,--exclude-libs,libc++abi.a"
arguments "-DANDROID_STL=c++_static", "-DANDROID_ARM_NEON=TRUE"
}
}
这个问题最终与第三方或任何类似的东西无关。
我使用NDK版本r21e
。升级NDK到r24
修复了这个问题。
似乎当链接OpenCV
作为共享对象时,它通过导入或包含一些缺失/有问题的符号来掩盖实际的NDK错误,当我们停止使用它时,错误出现了。