Closed CaffreySun closed 1 year ago
看到报错信息中libRbtBezier.so路径是错的,错误的路径为第2步 CMakeList.txt中的绝对路径。
不要指定绝对路径,走 links linkdirs 。
或者全用 xmake.lua ,jni 也是。。xmake 有提供 gradle 插件,自动编译 jni 和打包
我在网上查了一下-Wl,-soname
:
-Wl选项告诉编译器将后面的参数传递给链接器。 -soname则指定了动态库的soname(短名,Short for shared object name) -Wl 表示后面的参数也就是-soname,libhello.so.1直接传给连接器ld进行处理。每一个库都有一个soname,当连接器发现程序库(如:libhello_v1.so)中有soname (libhello.so),连接器便会将soname (libhello.so)嵌入要连接的二进制文件内,而不是库文件的实际文件名(libhello_v1.so)。在程序执行期间,程序会查找拥有 soname名字(libhello.so)的文件,而不是库的文件名,换句话说,soname是库的区分标志。
我这两天又查了一下如何解决我遇到问题:
CMake 用 add_library(XXX SHARED IMPORTED) 并通过 IMPORTED_LOCATION 指定库的本地路径导入so编译。会先看这个 so 有没有 SONAME,如果有的话就把路径截断并通过 -L/path/libtest.so -ltest来链接,如果没有的话就会用全路径 -l/path/libtest.so 来链接。这会导致在链接生成的文件里面 NEEDED 字段一个是 so,一个是全路径so。全路径的 libtest.so 显然是没法在我们设置的 LD_LIBRARY_PATH 里面找到的,所以会报个 not found 的错误,这就是加载不到so的原因了。
之前提到的add_shflags("-Wl,-soname,libRbtBezier.so")
是一种方案,这样CMake就可以使用soname正确的链接。
另一种方案时CMakeList.txt中增加set_property(TARGET test PROPERTY IMPORTED_NO_SONAME 1)
,设置 IMPORTED_NO_SONAME 变量,显式的告诉 CMake 始终都把 lib full path 截断。
xmake是否需要同CMake一样在编译jni 动态库时添加动态库链接选项-Wl,-soname,
,这样就方便编译出来的so库使用。
不考虑,你可以自己设置。。add_shflags("-Wl,-soname,libRbtBezier.so")
。。另外,我刚说了。你 cmakelists 不去设置 绝对路径来 link 不走 IMPORTED_LOCATION 设置,也就没这个问题。。
我这也经常用于 android so库,从没有这种问题。
Xmake 版本
v2.7.8+20230406
操作系统版本和架构
Ubuntu 22.04.2 LTS
描述问题
我在编译一个名为RbtBezier的C++库,
xmake f -p android
->xmake b
target_include_directories(RbtBezierAdapter PRIVATE ${CMAKE_SOURCE_DIR}/includes)
add_library(RbtBezier SHARED IMPORTED) set_target_properties(RbtBezier PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}/libRbtBezier.so)
find_library( log-lib log)
target_link_libraries( RbtBezierAdapter RbtBezier ${log-lib})
Caused by: java.lang.UnsatisfiedLinkError: dlopen failed: library "/Volumes/SHW_APFS/WorkHome/Robot/Robot_Android/SDK/RobotPen_Android/robotpenmodel/src/main/cpp/../jniLibs/arm64-v8a/libRbtBezier.so" not found: needed by /data/app/~~fRYfb56I_uFC1H8fCeCE_w==/cn.robotdemo.d7.chanxian-ajzOiR8gFraQkGviBzSqVA==/lib/arm64/libRbtBezierAdapter.so in namespace classloader-namespace at java.lang.Runtime.loadLibrary0(Runtime.java:1077) at java.lang.Runtime.loadLibrary0(Runtime.java:998) at java.lang.System.loadLibrary(System.java:1661) at cn.robotpen.views.adapter.RbtBezierAdapter.(SourceFile:14)