You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动