ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Windows下android-ndk-r26b手动配置与CMake集成

Windows下android-ndk-r26b手动配置与CMake集成 简介Android NDK r26b Windows版是Google提供的Android原生开发工具集适合需要编写C/C代码、追求高性能或复用既有库的Android工程师常用于图形渲染、音视频编解码、物理模拟与神经网络推理等模块。该压缩包共2000个文件约1969个.h头文件构成主体覆盖NDK API、JNI接口、OpenGL ES、神经网络、相机元数据等多类声明便于开发者查阅底层接口另有13个.py脚本、10个.md、7个.txt和1个.pdf文档提供构建辅助、使用说明与版本信息整体630.97MB解压后可作为Android Studio的NDK环境。目前已有730人学习下载。借助这套资源开发者可以系统理解NDK工具链的组织方式掌握JNI桥接、交叉编译、动态库/静态库配置、多架构支持等关键内容同时通过头文件直接定位原生符号减少配置与调试时间。由于包内含大量本地头文件无需联网即可查阅各类NDK接口定义适合从零搭建原生开发环境或需要深入底层的中高级开发者。1. 为什么在 Windows 上要手动处理 android-ndk-r26b 而不是依赖 IDE 自动下载做 Android 原生开发时NDK 版本失控比 Java 依赖冲突更难排查链接阶段的undefined reference、JNI 函数签名对不上、C STL 重复加载最后往往都指向同一个原因——编译用的 NDK 和运行时预期不是同一个版本。android-ndk-r26b-windows.zip这个包在 SDK 下载列表里一直存在但很多项目从不主动锁定它。r26b 对应的版本标识是26.1.10909125Clang 版本不过新AGP 和独立 CMake 的兼容性都已验证过对 Windows 这条线的开发和 CI 机器都相对友好。下面直接走一遍下载校验、环境变量、ndk-build编译最小 so、接入 Gradle/CMake最后给几个只有 Windows 会遇到的高频坑。2. 下载校验与解压 android-ndk-r26b-windows.zip2.1 文件命名与下载前确认文件名里的r26b是“release 26 point b”对应唯一的版本标识26.1.10909125。Google 的下载地址规则是android-ndk-r26b-windows.zip这个包只给 64 位 Windows 用Linux 和 macOS 是另一套命名。下载前先确认系统是 64 位否则打开压缩包会看到toolchains/llvm/prebuilt/windows-x86_64目录无法被识别。用 PowerShell 直接下载到这个文件时加-UseBasicParsing可以避免 Windows PowerShell 5.1 依赖 IE 引擎导致交互卡住。$url https://dl.google.com/android/repository/android-ndk-r26b-windows.zip $out $env:USERPROFILE\Downloads\android-ndk-r26b-windows.zip Invoke-WebRequest -Uri $url -OutFile $out -UseBasicParsing这里$out指定了下载绝对路径方便后面校验和解压引用同一个变量。如果没有走命令行下载从浏览器拿到同名 zip 也完全可以不需要重复下载。2.2 校验与解压压缩包是跨网络传输的不能只看文件大小就解压。官方下载页会提供 SHA-256 校验值下载完成后立刻比对不一致就直接删除避免后面排查半天发现是包本身坏了。Get-FileHash -Path .\android-ndk-r26b-windows.zip -Algorithm SHA256 Expand-Archive -Path .\android-ndk-r26b-windows.zip -DestinationPath C:\Android\ndk -Force-Algorithm SHA256指定哈希算法Expand-Archive的-Force表示目标目录已存在时覆盖文件。Expand-Archive在 PowerShell 5.1 里会先建索引接近 1 GB 的包耗时较长替换方案是用 Windows 10 自带的tar -xf它对 zip 的支持更稳定输出也更像 Linux 工具链习惯。解压完成后先确认这个关键目录结构路径或文件作用ndk-build.cmdWindows 下的构建入口可供命令行或老式 Android.mk 工程调用toolchains\llvm\prebuilt\windows-x86_64clang、llvm-readelf 等工具链本体宿主平台是 x86_64 Windowsbuild\cmake\android.toolchain.cmake给 CMake 用的工具链文件手工编译时必须显式指定sysrootAndroid 平台头文件与系统库编板级代码时依赖它source.properties记录版本号排查“装的是哪个 NDK”时最先看这里2.3 目录规划与路径避坑解压出来的顶层目录名是android-ndk-r26b所以-DestinationPath C:\Android\ndk最终得到的是C:\Android\ndk\android-ndk-r26b。这个位置是我建议的安装路径短、无空格、无中文。不要放进C:\Program Files也不要把常用目录挂到 OneDrive 同步盘。CMake 和 Gradle 在 Windows 上处理带空格路径时转义规则不一致常常在does not match the generator这类诡异报错里消耗时间。解压完立刻做一次路径自检Test-Path C:\Android\ndk\android-ndk-r26b\ndk-build.cmd返回True说明目录层级正确同时这个文件也是后续所有命令行编译的核心入口。3. 在 Windows 上配置 android-ndk 环境变量并用 ndk-build 快速验证3.1 设置 ANDROID_NDK_HOME 并加入 PATHGradle 本身不靠环境变量识别 NDK但命令行ndk-build.cmd、部分开源构建脚本和 CMake 辅助脚本会去读取ANDROID_NDK_HOME或ANDROID_NDK_ROOT。两个变量在不同工具里各有偏好实践上宁可都设成同一个值别赌某个工具默认不读它们。[Environment]::SetEnvironmentVariable(ANDROID_NDK_HOME, C:\Android\ndk\android-ndk-r26b, User) [Environment]::SetEnvironmentVariable(ANDROID_NDK_ROOT, C:\Android\ndk\android-ndk-r26b, User) $userPath [Environment]::GetEnvironmentVariable(Path, User) [Environment]::SetEnvironmentVariable(Path, $userPath;C:\Android\ndk\android-ndk-r26b, User)第三个参数User表示写入当前用户的环境变量注册表位置不污染系统级变量。新开的终端才能看到变化当前会话需要手动设置一次才能继续验证$env:ANDROID_NDK_HOME C:\Android\ndk\android-ndk-r26b $env:Path ;C:\Android\ndk\android-ndk-r26b ndk-build.cmd --version--version会输出 NDK 版本和构建号看到类似r26b的标识才算环境变量生效。不要在这个环节用setxsetx的Path有 1024 字符截断风险而且写入前会覆盖掉带%VAR%引用形式的已有值。环境变量的用途对比如下变量名主要消费者说明ANDROID_NDK_HOME独立 CMake 脚本、部分老式构建系统指向 NDK 根目录即可ANDROID_NDK_ROOTReact Native autolink、Gradle 插件里的自定义任务部分工具硬编码了这个名字漏设会静默走回旧路径PATH中的 NDK 目录ndk-build.cmd、llvm-readelf.exe等命令行工具便于手工调试 ABI 产物3.2 编写最小 Android.mk 编译第一个 so不接 Gradle先验证 NDK 能不能独立完成交叉编译最可靠的做法是用ndk-build编一个 JNI 动态库。先在工程目录建好jni子目录New-Item -ItemType Directory -Force C:\dev\ndk-hello\jni在jni下新建三个文件。hello.c定义一个最简 JNI 函数#include jni.h JNIEXPORT jstring JNICALL Java_com_example_ndkdemo_NativeLib_stringFromJNI(JNIEnv *env, jobject thiz) { return (*env)-NewStringUTF(env, hello from ndk r26b); }Android.mk声明模块名和源文件LOCAL_PATH : $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE : hello LOCAL_SRC_FILES : hello.c LOCAL_LDLIBS : -llog include $(BUILD_SHARED_LIBRARY)Application.mk控制要生成哪些 ABI 的产物APP_ABI : arm64-v8a x86_64 APP_STL : c_sharedLOCAL_MODULE是编译产物名最终会生成libhello.soLOCAL_LDLIBS : -llog链上 Android 的 log 库方便之后在 JNI 层打印日志。APP_ABI只保留arm64-v8a和x86_64Windows 模拟器通常需要 x86_64真机用 arm64-v8a如果不做模拟器留下arm64-v8a即可能省一半编译时间。接着执行构建cd C:\dev\ndk-hello ndk-build.cmd NDK_PROJECT_PATH. APP_BUILD_SCRIPTjni/Android.mk NDK_APPLICATION_MKjni/Application.mkNDK_PROJECT_PATH.告诉构建脚本当前目录是工程根APP_BUILD_SCRIPT显式指定Android.mkNDK_APPLICATION_MK指定Application.mk。文件都放在默认jni目录时直接输ndk-build.cmd也能工作但显式参数能减少误用其他工程jni目录的歧义。构建成功后查看 ELF 头确认产物确实是目标 ABIC:\Android\ndk\android-ndk-r26b\toolchains\llvm\prebuilt\windows-x86_64\bin\llvm-readelf.exe -h libs\arm64-v8a\libhello.so输出里Machine字段是AArch64就说明交叉编译链路是通的。3.3 关联 Android SDK 管理ndk-build命令行验证通过不代表 Gradle 也能找到 NDK。新版 AGP 默认去 SDK 目录下的ndk\26.1.10909125查找不读ANDROID_NDK_HOME。所以手动解压的包要么复制到 SDK 的ndk目录要么用sdkmanager重新安装一份。用 SDK 自带命令行安装最省事sdkmanager ndk;26.1.10909125这会装到%LOCALAPPDATA%\Android\Sdk\ndk\26.1.10909125。如果坚持用手动解压的 zip也可以把整个目录移过去但目录名必须改成版本号New-Item -ItemType Directory -Force $env:LOCALAPPDATA\Android\Sdk\ndk Move-Item C:\Android\ndk\android-ndk-r26b $env:LOCALAPPDATA\Android\Sdk\ndk\26.1.10909125Move-Item会在目标路径不存在时直接改名避免多包一层目录。移动前先确认目标盘剩余空间够用NDK 完整包一般在 3 GB 左右。4. 把 android-ndk-r26b 接进 Gradle 和 CMake参数设置与 Windows 避坑4.1 用 ndkVersion 锁定 r26b避免版本漂移项目里一旦写死ndkVersion 26.1.10909125不管开发者本机默认装了什么 r26c、r27都会被迫切到 r26b。这一点对 Windows 的多人协作特别重要因为 IDE 自动下载的版本在不同 Android Studio 版本里差异很大。android { ndkVersion 26.1.10909125 defaultConfig { externalNativeBuild { cmake { arguments -DANDROID_STLc_shared, -DANDROID_PLATFORMandroid-21 cFlags -O2 cppFlags -stdc17 } } ndk { abiFilters arm64-v8a, x86_64 } } externalNativeBuild { cmake { path src/main/cpp/CMakeLists.txt } } }ndkVersion使用的是唯一标识而不是r26b这种简写写错版本号 AGP 会直接去下载而不是静默回退。arguments里以-D开头的值会传给 CMake-DANDROID_STLc_shared决定 C 运行时动态链接方式-DANDROID_PLATFORMandroid-21指定工具链参考的平台级不必紧跟minSdk设得过大。abiFilters在 Windows 上最有用四个 ABI 全编会显著拖慢增量编译。4.2 手工用 CMake 和 Ninja 验证工具链Gradle 的externalNativeBuild内部会把 CMake 包一层报错时很难直接定位。独立跑一次 CMake可以把 NDK 工具链本身的问题和 Gradle 配置的问题分离。假设src/main/cpp/CMakeLists.txt是cmake_minimum_required(VERSION 3.22.1) project(ndk_r26b_demo C CXX) add_library(hello SHARED hello.c) target_link_libraries(hello log)在 PowerShell 里执行cmake -S . -B build -G Ninja -DANDROID_ABIarm64-v8a -DANDROID_NDKC:/Android/ndk/android-ndk-r26b -DCMAKE_TOOLCHAIN_FILEC:/Android/ndk/android-ndk-r26b/build/cmake/android.toolchain.cmake -DANDROID_PLATFORMandroid-21 cmake --build build反引号是 PowerShell 续行符用 cmd 时改成^。-DANDROID_NDK和-DCMAKE_TOOLCHAIN_FILE两个参数缺一不可前者给 CMake 提供 NDK 根路径后者指定 Android 交叉编译工具链定义。-G Ninja要求ninja.exe在 PATH 里找不到时就显式加一条-DCMAKE_MAKE_PROGRAMC:/Android/ndk/android-ndk-r26b/toolchains/llvm/prebuilt/windows-x86_64/bin/ninja.exeWindows 下写路径全部用正斜杠可以避免 CMake 把反斜杠当转义字符导致路径被拆散。4.3 三个 Windows 必调参数与踩坑实际操作里我一般只在下面四个位置做调整其余交给 AGP 默认值参数或配置类型作用与 Windows 注意点-DANDROID_STLc_sharedCMake argument避免多个 so 各带一份 STLWindows 上若用c_static链接期容易看到符号冲突难排查-DANDROID_PLATFORMandroid-21CMake argument控制平台库基准设得比minSdk高会留下运行时风险设低则编译期约束更松ndkVersion 26.1.10909125Gradle 属性固定 r26b避免 IDE 自动安装的新版把 ABI 生成规则改掉abiFilters arm64-v8a, x86_64Gradle ndk 块压缩 ABI 集合Windows 上交叉编译最吃 CPUABI 越少增量编译越快还有一个容易忽略的点Gradle 内部生成的 CMake 变量优先级比环境变量高所以不要在gradle.properties里用ANDROID_NDK_HOME这种全局注入来临时顶替否则换个项目会带着错误路径。手工 CMake 验证通过后回 Gradle 执行:app:assembleDebug如果仍报错再单独看build目录下的ninja.log报错点通常比 IDE 的 Output 面板更具体。5. 验证 r26b 安装与高频异常处理5.1 命令行确认 NDK 版本与工具链完整不要相信一次编译成功就万事大吉换机器或换终端后环境变量经常静默失效。我习惯先跑一组固定命令ndk-build.cmd --version Select-String -Path C:\Android\ndk\android-ndk-r26b\source.properties -Pattern Pkg.Revision where.exe ndk-build.cmdndk-build.cmd --version确认命令行入口可用第二行读到的Pkg.Revision 26.1.10909125才是包的真实版本如果显示的不是这个值说明下载到的 zip 根本不是 r26b第三行确认 PATH 里的ndk-build.cmd来自哪个目录避免旧版本 NDK 被排到前面。5.2 三个高频异常与修复先看运行到编译时报什么错Windows 上最常见到的三类如下第一类Unable to locate NDK或NDK not configured。新版 AGP 不读ANDROID_NDK_HOME只认 SDK 下的ndk/version目录。解决办法是确认ndkVersion与%LOCALAPPDATA%\Android\Sdk\ndk\26.1.10909125目录名一致不一致就按第 3.3 节移动或重装 SDK 包。第二类Ninja: error: loading build.ninja: No such file or directory。通常是手工 CMake 时生成的build目录里没有build.ninja说明 CMake 配置阶段提前失败先删掉build目录再执行一次配置把输出里的ANDROID_NDK路径和CMAKE_TOOLCHAIN_FILE打印出来核对。第三类undefined reference to __android_log_print。这是链接 log 库失败Android.mk 工程要在LOCAL_LDLIBS里加-llogCMake 工程要在CMakeLists.txt里写target_link_libraries(hello log)加在cFlags里是无效的。如果每次都要手工验证可以在 PowerShell 里把这四条命令存成Check-Ndk.ps1一键输出版本、路径和第一个 so 的 ELF 头部。本文还有配套的精品资源点击获取
返回列表