Windows平台基于Android NDK编译boost小记
前言
本文记录在 Windows 环境下,使用
android-ndk-r26d编译Boost 1.74Android 静态库的完整过程。
目标 ABI:
armeabi-v7aarm64-v8ax86x86_64
⚠️ 说明:较新的 NDK 已移除
armeabiABI,android-ndk-r26d同样不再支持它。本文仅涵盖 NDK r26d 所支持的 Android ABI。
1. 准备 Android NDK
下载并解压 Android NDK,本文以 android-ndk-r26d 为例,假设安装路径为:
D:/Installed_Files/android_ndk/android-ndk-r26d
NDK 自带的 Clang 包装脚本位于:
D:/Installed_Files/android_ndk/android-ndk-r26d/toolchains/llvm/prebuilt/windows-x86_64/bin
后续我们将直接使用这些 .cmd 编译器包装脚本,例如:
aarch64-linux-android21-clang++.cmd
armv7a-linux-androideabi21-clang++.cmd
i686-linux-android21-clang++.cmd
x86_64-linux-android21-clang++.cmd
💡 这些 wrapper 已经内置了目标架构与 Android API Level,因此无需再手动传递
--target=...和--sysroot=...。
2. 准备 Boost 1.74
下载并解压 Boost 1.74,例如解压到:
D:/workspace/boost_1_74_0
从开始菜单打开 VS20XX 的开发人员命令提示符(x86 或 x64 版本都可以):

切换到 Boost 源码根目录:
cd D:\workspace\boost_1_74_0
选一个对应的msvc版本(这里以vc142为例),生成 b2 构建工具:
.\bootstrap.bat vc142
执行成功后,根目录下会出现 b2.exe。
后续所有编译命令都在 Boost 根目录下执行。
3. 编辑 user-config.jam
在 Boost 根目录新建(或编辑) user-config.jam,内容如下:
import os ;
# 替换成你的 NDK 路径
androidNDKRoot = D:/Installed_Files/android_ndk/android-ndk-r26d ;
androidToolchain = $(androidNDKRoot)/toolchains/llvm/prebuilt/windows-x86_64 ;
androidBin = $(androidToolchain)/bin ;
androidSysroot = $(androidToolchain)/sysroot ;
# Android armeabi-v7a, API 21.
using clang : android_armv7 :
$(androidBin)/armv7a-linux-androideabi21-clang++.cmd
:
<compileflags>-fPIC
<compileflags>-mthumb
<cxxflags>-std=c++14
<cxxflags>-g
<cxxflags>-Wno-enum-constexpr-conversion
<linkflags>-mthumb
<archiver>$(androidBin)/llvm-ar.exe
<ranlib>$(androidBin)/llvm-ranlib.exe
;
# Android arm64-v8a, API 21.
using clang : android_arm64 :
$(androidBin)/aarch64-linux-android21-clang++.cmd
:
<compileflags>-fPIC
<cxxflags>-std=c++14
<cxxflags>-g
<cxxflags>-Wno-enum-constexpr-conversion
<archiver>$(androidBin)/llvm-ar.exe
<ranlib>$(androidBin)/llvm-ranlib.exe
;
# Android x86, API 21.
using clang : android_x86 :
$(androidBin)/i686-linux-android21-clang++.cmd
:
<compileflags>-fPIC
<cxxflags>-std=c++14
<cxxflags>-g
<cxxflags>-Wno-enum-constexpr-conversion
<archiver>$(androidBin)/llvm-ar.exe
<ranlib>$(androidBin)/llvm-ranlib.exe
;
# Android x86_64, API 21.
using clang : android_x86_64 :
$(androidBin)/x86_64-linux-android21-clang++.cmd
:
<compileflags>-fPIC
<cxxflags>-std=c++14
<cxxflags>-g
<cxxflags>-Wno-enum-constexpr-conversion
<archiver>$(androidBin)/llvm-ar.exe
<ranlib>$(androidBin)/llvm-ranlib.exe
;
⚠️ 特别注意:工具集版本名(如
android_armv7、android_arm64)请使用下划线_,不要写成android-armv7或android-x86_64。包含-的名称可能被 Boost.Build 解析为子特性,从而引发如下错误:error: "android" is not a known subfeature value of <toolset>clang
4. 编译 armeabi-v7a
在管理员 PowerShell 中,确保当前目录仍为 Boost 根目录,然后执行:
.\b2 -q -j8 -a -d+2 --debug-configuration `
--user-config=.\user-config.jam `
toolset=clang-android_armv7 `
target-os=android architecture=arm address-model=32 abi=aapcs binary-format=elf `
threadapi=pthread threading=multi link=static variant=release `
--without-python `
--stagedir=stage/android/armv7 stage `
2>&1 | Tee-Object -FilePath .\build-ndk-armv7-release.log
📁 编译产物目录:
stage/android/armv7/lib
5. 编译 arm64-v8a
.\b2 -q -j8 -a -d+2 --debug-configuration `
--user-config=.\user-config.jam `
toolset=clang-android_arm64 `
target-os=android architecture=arm address-model=64 abi=aapcs binary-format=elf `
threadapi=pthread threading=multi link=static variant=release `
--without-python `
--stagedir=stage/android/arm64 stage `
2>&1 | Tee-Object -FilePath .\build-ndk-arm64-release.log
📁 编译产物目录:
stage/android/arm64/lib
6. 编译 x86
.\b2 -q -j8 -a -d+2 --debug-configuration `
--user-config=.\user-config.jam `
toolset=clang-android_x86 `
target-os=android architecture=x86 address-model=32 abi=sysv binary-format=elf `
threadapi=pthread threading=multi link=static variant=release `
--without-python `
--stagedir=stage/android/x86 stage `
2>&1 | Tee-Object -FilePath .\build-ndk-x86-release.log
📁 编译产物目录:
stage/android/x86/lib
7. 编译 x86_64
.\b2 -q -j8 -a -d+2 --debug-configuration `
--user-config=.\user-config.jam `
toolset=clang-android_x86_64 `
target-os=android architecture=x86 address-model=64 abi=sysv binary-format=elf `
threadapi=pthread threading=multi link=static variant=release `
--without-python `
--stagedir=stage/android/x86_64 stage `
2>&1 | Tee-Object -FilePath .\build-ndk-x86_64-release.log
📁 编译产物目录:
stage/android/x86_64/lib
注意:
--stagedir=后应改为您希望输出库文件的目录路径。variant=后应改为你希望编译的模式(debug/release)address-model=后根据目标平台填写32(x86)或64(x64)。
8. 关于 --without-python
所有编译命令中都添加了 --without-python。
原因在于 bootstrap.bat 可能会自动探测到本机安装的 Python(例如 C:\Program Files\Python311\Include\pyconfig.h),交叉编译 Android 时若误用了 Windows 下的 Python 头文件,就会出现类似错误:
C:\Program Files\Python311\Include\pyconfig.h:59:10: fatal error: 'io.h' file not found
#include <io.h>
^~~~~~
io.h 属于 Windows C Runtime 头文件,Android NDK 的 sysroot 中并不存在它。
🔹 除非你确实需要编译 Android 版
Boost.Python,并且已准备好对应目标 ABI 的 Python 头文件与库,否则建议一律使用--without-python。
9. 获取编译制品
四个 ABI 的静态库分别位于:
stage/android/armv7/lib
stage/android/arm64/lib
stage/android/x86/lib
stage/android/x86_64/lib
建议按 Android 工程常见的 ABI 目录结构整理:
boost_1_74_0_android/
include/
boost/
lib/
armeabi-v7a/
arm64-v8a/
x86/
x86_64/
⚠️ Android 的
.a静态库不能像 macOS universal library 那样将多个 ABI 合并成一个.a。实际接入工程时,必须按 ABI 分目录存放,并在 CMake 中通过${ANDROID_ABI}选择对应目录。
CMake 集成示例:
set(BOOST_ROOT "${CMAKE_CURRENT_LIST_DIR}/third_party/boost_1_74_0_android")
set(BOOST_LIB_DIR "${BOOST_ROOT}/lib/${ANDROID_ABI}")
add_library(boost_system STATIC IMPORTED)
set_target_properties(boost_system PROPERTIES
IMPORTED_LOCATION "${BOOST_LIB_DIR}/libboost_system.a"
)
target_include_directories(your_target PRIVATE
"${BOOST_ROOT}/include"
)
target_link_libraries(your_target PRIVATE
boost_system
)
10. 常见问题
10.1 找不到 cstddef
fatal error: 'cstddef' file not found
通常是 NDK sysroot 或 target 未正确生效。本文使用 NDK 内置的 *-clang++.cmd wrapper,可避免手动配置 --target 与 --sysroot 带来的错误。
10.2 std::unary_function 报错
若使用 -std=c++17,Boost 1.74 可能遇到 std::unary_function 已被移除的问题。因此本文统一使用:
<cxxflags>-std=c++14
10.3 enum-constexpr-conversion 警告
新版 Clang 可能在 Boost.MPL 中报出此类警告。本文通过以下参数规避:
<cxxflags>-Wno-enum-constexpr-conversion
10.4 日志过多,难以定位错误
本文编译命令中使用了:
-d+2 --debug-configuration
这两个参数会输出更详细的编译命令与 Boost.Build 配置加载信息,便于排查 user-config.jam 是否生效、实际调用的编译器及参数。确认配置无误后,可将其移除以减少日志量。
同时,命令中的:
2>&1 | Tee-Object -FilePath $log
可以同时在控制台显示输出并保存完整日志到文件。
若错误日志仍然混乱,可临时将 -j8 改为 -j1,以单线程方式编译,更容易定位第一个编译错误。

浙公网安备 33010602011771号