Android NDK下CMake ExternalProject超级构建未执行问题排查
解决Android Studio中CMake ExternalProject未自动构建的问题
你遇到的问题其实是Android Studio的CMake集成机制导致的——默认情况下,Gradle只会触发**直接关联到Android可识别目标(比如共享库.so)**的CMake构建流程,而你的顶层CMake配置里没有生成这样的目标,所以Gradle在完成CMake配置后就停住了,不会调用ninja执行实际的构建任务。
先梳理下现有配置的核心问题:
- 你的
ExternalProject_Add(main)只是定义了一个外部项目,但没有在顶层CMake中创建任何Gradle能识别的构建目标(比如add_library生成的共享库)。 - Gradle的Android插件会扫描CMake脚本中的
add_library输出,只有发现有需要打包到APK的库时,才会完整执行CMake构建流程。
修复步骤
1. 修改顶层CMakeLists.txt,添加触发构建的目标
你需要在顶层CMake中添加一个“占位”的共享库,让它依赖你的main外部项目,这样Gradle就会触发整个构建链。如果你的main项目本身生成了需要打包的.so,也可以直接引用它。
修改后的CMakeLists.txt:
cmake_minimum_required(VERSION 3.4.1) include(ExternalProject) if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install) endif () # 转发Android交叉编译参数到外部项目 set(ANDROID_CMAKE_ARGS -DANDROID_ABI=${ANDROID_ABI} -DANDROID_PLATFORM=${ANDROID_PLATFORM} -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DANDROID_NDK=${ANDROID_NDK} -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -G${CMAKE_GENERATOR}) # 构建Eigen依赖 ExternalProject_Add(eigen HG_REPOSITORY https://bitbucket.org/eigen/eigen HG_TAG 3.2.10 CMAKE_ARGS ${ANDROID_CMAKE_ARGS}) # 构建主项目,依赖Eigen ExternalProject_Add(main DEPENDS eigen SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/main CMAKE_ARGS ${ANDROID_CMAKE_ARGS} # 如果你的main项目不需要安装,可以留空INSTALL_COMMAND INSTALL_COMMAND "") # 关键:添加一个空的共享库,让Gradle识别到需要构建的目标 # 这个库会依赖main外部项目,从而触发整个构建流程 add_library(dummy SHARED dummy.cpp) add_dependencies(dummy main) # -------- 如果你的main项目生成了实际需要的库(比如libmain.so),可以用下面的配置替换上面的dummy部分 -------- # add_library(main SHARED IMPORTED) # set_target_properties(main PROPERTIES # IMPORTED_LOCATION ${CMAKE_INSTALL_PREFIX}/lib/libmain.so) # add_dependencies(main main)
注意:你需要在CMakeLists.txt同目录下创建一个空的dummy.cpp文件,内容可以是空的,或者简单写一行:
#include <jni.h>
2. 优化build.gradle配置(可选但推荐)
在defaultConfig的externalNativeBuild中明确指定ABI,避免Gradle默认只构建部分ABI:
apply plugin: 'com.android.application' android { compileSdkVersion 26 buildToolsVersion "26.0.2" defaultConfig { externalNativeBuild { cmake { cppFlags "-std=c++11 -frtti -fexceptions" // 明确指定需要构建的ABI abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' } } } externalNativeBuild { cmake { path "CMakeLists.txt" } } } dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) implementation 'com.android.support:appcompat-v7:26.+' implementation 'com.android.support.constraint:constraint-layout:1.0.2' testImplementation 'junit:junit:4.12' }
原理说明
Gradle的Android插件与CMake的集成逻辑是:只有当CMake脚本中存在add_library创建的共享库目标(因为Android需要打包.so到APK),插件才会调用ninja执行完整的构建。通过添加dummy库并依赖main外部项目,相当于给Gradle一个“信号”:这个库需要构建,而它依赖的所有外部项目也必须先完成构建,这样就会自动触发eigen和main的下载、编译流程了。
内容的提问来源于stack exchange,提问作者tac-eibmoz
相关产品推荐
相关产品推荐

