Android Studio中NDK构建共享库遇Gradle依赖问题求助
解决Gradle无法识别CMake ExternalProject_Add生成的共享库及软链接报错问题
我之前也踩过类似的坑,Gradle对jniLibs下的软链接兼容性很差,而且CMake的ExternalProject_Add因为是异步构建目标,Gradle的native同步流程根本识别不到它。下面给你两个更规范的解决方案,替代临时的虚拟可执行文件hack:
方案一:让CMake自动复制库到jniLibs目录
既然软链接行不通,我们可以让CMake在构建完成后,直接把生成的共享库复制到Gradle默认扫描的jniLibs对应架构目录下,这样Gradle看到的是实际文件,就不会有软链接的问题了。
在你的cpp/CMakeLists.txt里添加以下代码:
# 先获取ExternalProject_Add构建的libactual的输出目录 ExternalProject_Get_Property(libactual BINARY_DIR) # 假设生成的库路径是${BINARY_DIR}/libfoo.so,根据你的实际构建输出调整 set(LIBFOO_SOURCE_PATH "${BINARY_DIR}/libfoo.so") # 目标路径:app模块的jniLibs对应ABI目录 set(LIBFOO_TARGET_PATH "${CMAKE_SOURCE_DIR}/../app/src/main/jniLibs/${ANDROID_ABI}/libfoo.so") # 添加自定义构建后命令,复制库文件 add_custom_command( TARGET libactual POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${LIBFOO_SOURCE_PATH} ${LIBFOO_TARGET_PATH} COMMENT "Copying libfoo.so to app's jniLibs directory" )
这样每次libactual构建完成后,CMake都会自动把libfoo.so复制到对应ABI的jniLibs子目录,Gradle在扫描时就能正常识别并打包这个库了。
方案二:配置Gradle直接读取CMake构建输出目录
如果不想复制文件,也可以直接让Gradle从CMake的构建输出目录读取共享库,修改app模块的build.gradle:
android { // ... 你的其他配置 sourceSets { main { // 添加CMake构建输出目录到jniLibs的扫描路径 // 路径根据你的CMake实际输出调整,比如debug构建的话可能是下面这个路径 jniLibs.srcDirs += "${project.rootDir}/cpp/build/intermediates/cmake/debug/obj/${ANDROID_ABI}" } } externalNativeBuild { cmake { path "../cpp/CMakeLists.txt" } } }
这样Gradle会直接去CMake的构建产物目录找库,不需要额外的复制操作,也避开了软链接的问题。
为什么之前的方法行不通?
- 软链接报错:Gradle在构建初始化阶段会遍历jniLibs目录的所有文件,它的文件系统处理逻辑默认不跟随软链接,所以会抛出"Couldn't follow symbolic link"的错误。
- IMPORTED库不被Gradle识别:
ExternalProject_Add是在CMake的后期构建阶段执行的,而Gradle同步native项目时,这个库还没生成,所以Gradle无法识别你定义的IMPORTED目标,自然会报"Unexpected native build target"的错误。
临时的虚拟可执行文件方案虽然能让Gradle识别目标,但属于hack手段,上面的两种方法更符合Android项目的构建规范,也更稳定。
内容的提问来源于stack exchange,提问作者martinkunev




