必须使用ndk内置android.toolchain.cmake,因其自动处理abi、api级别、sysroot、stl链接等关键联动逻辑,手动编写易出错;调用时须显式指定cmake_toolchain_file、android_abi、android_native_api_level和android_stl四个参数。

直接用 NDK 自带的 android.toolchain.cmake,别自己手写完整 toolchain 文件——NDK 从 r19 起就内置了稳定、兼容性好、参数可控的官方工具链,手动维护容易漏掉 ABI、sysroot、STL、API 级别等关键联动逻辑。
为什么必须用 android.toolchain.cmake 而不是自定义 toolchain
NDK 的 android.toolchain.cmake 不只是设置编译器路径,它会自动:
- 根据
-DANDROID_ABI=arm64-v8a推导CMAKE_SYSTEM_PROCESSOR和目标指令集 - 按
-DANDROID_NATIVE_API_LEVEL=21拉取对应 sysroot 和头文件,避免sys/types.h: No such file - 注入正确的 STL 链接逻辑(如
-lc++_shared),绕过undefined reference to __cxa_throw - 禁用 host 工具链误参与(如
find_program(ninja)不会去宿主机找)
自己写 toolchain 很容易只设了 CMAKE_C_COMPILER,却忘了 CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY,导致链接时混用 host 的 libstdc++.so,运行时报 cannot locate symbol 'std::string::_M_mutate'。
cmake 命令行必须传的四个参数
调用 cmake 时,以下参数缺一不可,顺序无关,但必须显式指定:
-
-DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake:指向 NDK 内置工具链($NDK是你 NDK 的绝对路径,如/home/user/Android/Sdk/ndk/25.2.9577136) -
-DANDROID_ABI=arm64-v8a:决定生成代码架构,可选值包括armeabi-v7a、x86_64;注意armeabi已废弃 -
-DANDROID_NATIVE_API_LEVEL=21:对应 Android 最低支持版本,不能低于minSdkVersion,否则logcat或pthread相关符号缺失 -
-DANDROID_STL=c++_shared:必须与 Java 层System.loadLibrary()加载顺序一致;若用c++_static,所有依赖库必须统一静态链接,否则double free
示例命令:
Android 开发调试技能,通过系统 ADB 工具操作 Android 设备。以下场景必须触发此技能:(1) 直接 ADB 操作——安装 APK、查看设备列表、抓取 logcat 日志、查看已安装应用、清除应用数据、截图、重启设备、拉取/推送文件、查看 CPU/内存/电池信息、adb shell 操作;(2)...
cmake -B build-arm64 \ -S . \ -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \ -DANDROID_ABI=arm64-v8a \ -DANDROID_NATIVE_API_LEVEL=21 \ -DANDROID_STL=c++_shared
常见错误现象和对应修复点
遇到构建失败,先盯住这三类日志线索:
-
CMake Error at .../android.toolchain.cmake:xxx (message): Unsupported NDK version:说明你用了太老或太新的 NDK;r21+ 官方支持,r10e 及更早已弃用;检查$NDK/source.properties中的Pkg.Revision -
fatal error: 'jni.h' file not found:没传-DANDROID_NATIVE_API_LEVEL,或传了但值太小(如设成 16);NDK 默认不暴露 JNI 头,需 API ≥ 19 才启用 -
undefined reference to 'AAssetManager_fromJava':漏加logcat或android这类系统库;在CMakeLists.txt中补上target_link_libraries(your_lib log android)
特别注意:CMAKE_SYSROOT 不要手动 set —— android.toolchain.cmake 会根据 ANDROID_NATIVE_API_LEVEL 和 ANDROID_ABI 自动算出并覆盖它;手动覆盖反而导致头文件路径错乱。
Gradle 中 externalNativeBuild 的等效配置
如果你用 Android Studio,build.gradle 里写的配置,实际就是翻译成上面那套 cmake 参数:
android {
ndkVersion "25.2.9577136"
defaultConfig {
minSdkVersion 21
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_shared"
abiFilters "arm64-v8a"
}
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
}
}
}
这里 ndkVersion 决定 CMAKE_TOOLCHAIN_FILE 路径,minSdkVersion 映射为 ANDROID_NATIVE_API_LEVEL,abiFilters 映射为 ANDROID_ABI。Gradle 会自动拼出完整命令,你不需要也不应该在 CMakeLists.txt 里再写 set(CMAKE_SYSTEM_NAME Android) —— 工具链文件已强制设为 Android,重复设置会触发 CMake 警告甚至失败。
真正容易被忽略的是:NDK 工具链对 C++ 标准的支持有隐含限制。比如 ANDROID_NATIVE_API_LEVEL=16 时,即使你写了 set(CMAKE_CXX_STANDARD 17),std::optional 依然不可用 —— 因为 sysroot 里没对应头文件。API 级别才是能力边界,C++ 标准只是语法糖开关。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










