cmake编译三方库运行找不到依赖库

最近在做的android studio jni 开发项目中需要依赖第三方库,通过cmake的方式打包编译。测试用遇到so库正常打包到apk,但是实际运行遇到,通过编译链接的方式找不到依赖库,但是通过dlopen的方式确实可以正常加载的问题。

so库的链接方式有两种:一种是通过dlopen,另一种是通过编译链接。

(1)创建工程后,创建依赖库目录:

 在libs下创建x86_64目录(这里abiFilters 只用x86_64),将我们libtest.so考到目录下面。

(2)build.gradle 修改

defaultConfig {
    applicationId "com.example.myapplication"
    minSdk 28
    targetSdk 33
    versionCode 1
    versionName "1.0"

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    externalNativeBuild {
        cmake {
             cppFlags ''
             abiFilters 'x86_64'
        }
    }
    ndk {
        abiFilters 'x86_64'
    }
}


    sourceSets {
    main {
        jni {
            srcDirs 'src\\main\\jni'
        }
        //jniLibs {
             // srcDirs 'libs' 
        //}
    }
}

 // (1)jniLibs 这里不需要带${ANDROID_ABI} 设置后会把libs下so打包到apk。
 // (2)通过编译依赖的方式可以不需要这个,否则编译会报2个so的错误

(3)方式一  camkelists.txt(正常加载到libtest.so)

set(my_lib_path ${CMAKE_SOURCE_DIR}/../../../libs/${ANDROID_ABI} )
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -L${my_lib_path}")
#重要:通过命令flags的方式指定依赖库的路径-L
#add_compile_options(-g -fPIC)
#link_directories(${my_lib_path})
#message("debug" ${CMAKE_INSTALL_PREFIX})

include_directories(${CMAKE_SOURCE_DIR}/../../../libs/include)
#指定头文件路径

target_link_libraries( # Specifies the target library.
        myapplication
        test
        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})
#将依赖的第三方库链接到libmyapplication.so

(4)方式二修改camkelists.txt(不能正常加载到libtest.so)

add_library( # Sets the name of the library.
        test
        SHARED
        IMPORTED#标示我们引入的是外部库,无需编译
        )

set_target_properties(
        test
        PROPERTIES IMPORTED_LOCATION
        ${CMAKE_SOURCE_DIR}/../../../libs/x86_64/libtest.so)

# set_property(TARGET test PROPERTY IMPORTED_NO_SONAME 1)
#需要这个否则readelf -d libmyapplication.so 查看依赖的libtestso是编译时候的全路径名
#会导致not found

target_link_libraries( # Specifies the target library.
        myapplication
        test
        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

这种方式的cmakelists首先我们确定了libtest.so已经打包到了apk中,但是apk启动还是挂掉,无法找到libtest.so。

通过命令查看readelf -d libmyapplication.so 依赖情况:

 发现依赖的so是全路径,显然是不对的,从路径看也就是我们set_target_properties中设置的路径。这是怎么情况呢??

原因说明:

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的原因了。

解决办法1 :

设置 IMPORTED_NO_SONAME 变量,显式的告诉 CMake 始终都把 lib full path 截断。以上面的 libxxx.so 为例:

set_property(TARGET test PROPERTY IMPORTED_NO_SONAME 1)

解决办法2 :

如果第三方so是我们自己编译的,也可以在编译命令中加上soname设置,保证生成的so有正确的soname :

-Wl,-soname,libtest.so 

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值