基于VS2019编译ARM版本boost小记(含踩坑记录)

前言

本文记录使用 Visual Studio 2019 / MSVC v142 编译 Boost Windows ARM64 静态库时遇到的问题与解决过程,目标场景是为 Windows on ARM 设备生成 .lib 静态库。

示例环境:

Boost 1.88.0
Visual Studio 2019 v142
Windows ARM64
link=static
runtime-link=static

1. 🎯 编译目标

需要生成 Windows ARM64 版本的 Boost 静态库,输出目录例如:

stage/win_arm64/lib

在 Boost.Build 中,ARM64 对应的关键参数为:

target-os=windows
architecture=arm
address-model=64
binary-format=pe
  • architecture=arm 表示 ARM 架构族。
  • address-model=64 表示 64 位,即 ARM64。
  • binary-format=pe 表示 Windows PE/COFF 目标格式。

2. ⚙️ 准备 VS2019 ARM64 编译环境

请确保 Visual Studio Installer 中已安装以下组件:

MSVC v142 - VS 2019 C++ ARM64 build tools
Windows 10/11 SDK
C++ build tools

⚠️ 如未安装 ARM64 build tools,b2 即使启动也可能找不到对应的 cl.exelink.exelib.exe

在开始菜单中,找到 Visual Studio 自带的构建环境快捷方式(通常位于 C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio 2019\Visual Studio Tools\VC),选择:

x64_arm64 Cross Tools Command Prompt for VS 2019

若找不到该快捷方式,可自行创建:复制已有的 x86_x64 Cross Tools Command Prompt for VS 2019 快捷方式,将其命令修改为:

%comspec% /k "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsamd64_arm64.bat"

💡 也可直接在 PowerShell 中通过 vcvarsall.bat 初始化环境:

& "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64_arm64

若安装的是 Community 或 Professional 版本,请将路径中的 Enterprise 替换为 CommunityProfessional


3. 📦 生成 b2

切换到 Boost 根目录,运行引导脚本:

cd D:\workspace\boost_1_88_0
.\bootstrap.bat vc142

执行成功后,根目录下会出现 b2.exe

注意:此处的 vc142 仅用于编译 b2.exe 本身(Windows 原生工具),与后续 macOS 交叉编译无关。


4. 📜 基础编译命令

初始使用的命令大致为:

b2 stage `
  --toolset=msvc-14.2 `
  --without-python `
  --stagedir="stage\win_arm64" `
  link=static runtime-link=static threading=multi `
  target-os=windows architecture=arm address-model=64 `
  debug release

该命令尝试同时编译 debug 与 release 两套 ARM64 静态库。

🔍 为便于定位错误,建议先单独编译一个变体并记录日志:

.\b2 stage -q -j8 -a -d+2 --debug-configuration `
  --user-config=.\user-config.jam `
  toolset=msvc-14.2 `
  --without-python `
  --stagedir="stage\win_arm64" `
  link=static runtime-link=static threading=multi `
  target-os=windows windows-api=desktop architecture=arm address-model=64 binary-format=pe `
  variant=release `
  2>&1 | Tee-Object -FilePath .\build-windows-msvc142-arm64-release.log

Release 编译通过后,再编译 Debug:

.\b2 stage -q -j8 -a -d+2 --debug-configuration `
  --user-config=.\user-config.jam `
  toolset=msvc-14.2 `
  --without-python `
  --stagedir="stage\win_arm64_debug" `
  link=static runtime-link=static threading=multi `
  target-os=windows windows-api=desktop architecture=arm address-model=64 binary-format=pe `
  variant=debug `
  2>&1 | Tee-Object -FilePath .\build-windows-msvc142-arm64-debug.log

5. ⚠️ 踩坑一:Windows SDK 10.0.28000.0 与 VS2019 v142 不兼容

编译 ARM64 时出现类似错误:

compile-c-c++ bin.v2\libs\locale\build\msvc-14.2\debug\arm_64\link-static\runtime-link-static\threadapi-win32\threading-multi\win32\numeric.obj
numeric.cpp
C:\Program Files (x86)\Windows Kits\10\include\10.0.28000.0\um\winnt.h(6461): error C3861: '_CountOneBits64': identifier not found

错误表面来自 Boost.Locale,实际根源是 Windows SDK 头文件 winnt.h10.0.28000.0 是较新的 SDK,与 VS2019 v142 的 ARM64 编译器组合时,可能出现该工具链无法正确识别的 intrinsic 或宏。

这一问题与 Stack Overflow 上的讨论 identifier not found while compiling for ARM64 with Visual Studio 2019 类似。新版本 Windows SDK(如 26100 系列)在 ARM64 桌面场景下更依赖 VS2022 工具链;如果必须使用 VS2019,可行的变通方法是固定使用 Windows SDK 22621。本文遇到的 10.0.28000.0 问题类型相同,处理思路同样是避免让 VS2019 v142 自动选用过新的 SDK。


6. 🔧 解决方案:固定使用较旧版 Windows SDK

核心思路是阻止 Boost.Build 自动探测最新 SDK,改为固定一个与 VS2019 v142 更匹配的版本,例如:

10.0.22621.0
10.0.22000.0
10.0.19041.0

查看本机已安装的 SDK 版本:

Get-ChildItem "${env:ProgramFiles(x86)}\Windows Kits\10\Include" -Directory |
  Select-Object -ExpandProperty Name

如果存在 10.0.22621.0,可优先尝试。


7. 📝 编写固定 SDK 的 vcvars 脚本

在 Boost 根目录下新建文件 vcvars-vs2019-arm64-sdk22621.bat

  • VS2019 Enterprise 版内容:

    @echo off
    call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64_arm64 10.0.22621.0 -vcvars_ver=14.29
    
  • Community 版:

    @echo off
    call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x64_arm64 10.0.22621.0 -vcvars_ver=14.29
    
  • BuildTools 版:

    @echo off
    call "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x64_arm64 10.0.22621.0 -vcvars_ver=14.29
    

参数说明:

  • x64_arm64:host 为 x64,target 为 ARM64。
  • 10.0.22621.0:指定使用的 SDK 版本。
  • -vcvars_ver=14.29:固定使用 VS2019 v142 后期工具链版本(可根据本机实际版本调整)。

8. 📄 配置 user-config.jam

在 Boost 根目录创建或编辑 user-config.jam,加入 MSVC v142 配置:

using msvc : 14.2 ;

若希望 Boost.Build 自动调用刚才编写的 ARM64 环境脚本,可写成:

using msvc : 14.2 :
    :
    <setup-arm64>D:/workspace/local/boost/boost_1_88_0/boost_1_88_0/vcvars-vs2019-arm64-sdk22621.bat
    <rewrite-setup-scripts>always
    ;

💡 Jam 文件中的路径建议使用正斜杠 /,避免 Windows 反斜杠 \

通过以下参数可确认配置是否被正确加载:

-d+2 --debug-configuration

日志中应能看到 Boost.Build 加载了你的 user-config.jam 并调用了对应脚本。


9. 🧹 清理旧缓存并重新编译

切换 SDK 后务必清理旧的构建缓存:

Remove-Item -Recurse -Force .\bin.v2, .\stage\win_arm64, .\stage\win_arm64_debug -ErrorAction SilentlyContinue

然后重新编译 Release:

.\b2 stage -q -j8 -a -d+2 --debug-configuration `
  --user-config=.\user-config.jam `
  toolset=msvc-14.2 `
  --without-python `
  --stagedir="stage\win_arm64" `
  link=static runtime-link=static threading=multi `
  target-os=windows windows-api=desktop architecture=arm address-model=64 binary-format=pe `
  variant=release `
  2>&1 | Tee-Object -FilePath .\build-windows-msvc142-arm64-release.log

若日志中出现 10.0.22621.0 而非 10.0.28000.0,即表示 SDK 固定成功。


10. ⚠️ 踩坑二:runtime-link=static 与主工程运行库不一致

命令中使用了 runtime-link=static,这表示 Boost 链接 MSVC 静态运行库(/MT/MTd)。对应关系:

runtime-link=static + variant=release → /MT
runtime-link=static + variant=debug   → /MTd
runtime-link=shared + variant=release → /MD
runtime-link=shared + variant=debug   → /MDd

若主工程使用 /MD,而 Boost 使用 /MT,链接时可能报错:

LNK2038: mismatch detected for 'RuntimeLibrary'

因此 Boost 的 runtime-link 应与主工程保持一致:

  • 主工程 /MT:Boost 使用 runtime-link=static
  • 主工程 /MD:Boost 使用 runtime-link=shared

例如 /MD 版本的编译命令:

& .\b2 stage -q -j8 -a `
  --user-config=.\user-config.jam `
  toolset=msvc-14.2 `
  --without-python `
  --stagedir="stage\win_arm64_md" `
  link=static runtime-link=shared threading=multi `
  target-os=windows windows-api=desktop architecture=arm address-model=64 binary-format=pe `
  variant=release

⚠️ 注意:link=staticruntime-link=static 含义不同。

  • link=static:生成 Boost 静态库 .lib
  • runtime-link=static:Boost 自身使用静态 MSVC Runtime。

11. ⚠️ 踩坑三:Boost.Python 交叉编译易误用主机 Python

本文所有命令均添加了 --without-python。原因是 bootstrap.bat 可能自动探测到主机(x64)上的 Python,编译 ARM64 目标时若错误使用了 x64 Python 的头文件与库,将导致架构或 ABI 不匹配。

🔹 除非确实需要 ARM64 版 Boost.Python 并已准备好 ARM64 Python 开发包,否则强烈建议加上 --without-python


12. 🩹 临时绕过:若不需要 Locale 就跳过 Boost.Locale

本次 _CountOneBits64 错误是在 Boost.Locale 中触发的,若项目不需要该库,可临时通过 --without-locale 绕过:

& .\b2 stage -q -j8 -a `
  --user-config=.\user-config.jam `
  toolset=msvc-14.2 `
  --without-python --without-locale `
  --stagedir="stage\win_arm64" `
  link=static runtime-link=static threading=multi `
  target-os=windows windows-api=desktop architecture=arm address-model=64 binary-format=pe `
  variant=release

📌 这仅绕过触发点,若仍使用不匹配的 SDK(如 10.0.28000.0),其他包含 Windows SDK 头文件的库仍可能报错。更推荐的做法仍是固定到兼容的旧版 SDK。


13. 🎯 只编译需要的 Boost 库

全量编译 Boost 容易因无关库引发额外问题。实际工程中建议按需编译,例如:

--with-atomic --with-chrono --with-date_time --with-filesystem --with-system --with-thread --with-regex

完整命令示例:

.\b2 stage -q -j8 -a -d+2 --debug-configuration `
  --user-config=.\user-config.jam `
  toolset=msvc-14.2 `
  --without-python `
  --with-atomic --with-chrono --with-date_time --with-filesystem --with-system --with-thread --with-regex `
  --stagedir="stage\win_arm64" `
  link=static runtime-link=static threading=multi `
  target-os=windows windows-api=desktop architecture=arm address-model=64 binary-format=pe `
  variant=release `
  2>&1 | Tee-Object -FilePath .\build-windows-msvc142-arm64-selected.log

14. 📂 检查输出产物

编译完成后,静态库默认位于:

stage/win_arm64/lib

典型文件名例如:

libboost_system-vc142-mt-s-a64-1_88.lib
libboost_thread-vc142-mt-s-a64-1_88.lib

标记含义一览:

  • vc142:Visual Studio 2019 v142 工具集
  • mt:多线程(multi-threading)
  • s:静态运行时(/MT
  • a64:ARM64 架构
  • 1_88:Boost 1.88

若使用 runtime-link=shared,文件名中的运行时标记会相应变化。


15. 📚 参考


16. 🎓 小结

  1. Boost 完全可以使用 VS2019 v142 编译 Windows ARM64 静态库。
  2. ARM64 对应的 Boost.Build 参数为:architecture=arm address-model=64
  3. VS2019 v142 + Windows SDK 10.0.28000.0 可能出现 _CountOneBits64 等 SDK 头文件错误。
  4. 推荐固定到较旧且稳定的 SDK,如 10.0.22621.010.0.22000.010.0.19041.0
  5. link=staticruntime-link=static 含义不同,后者需与主工程的 /MT/MD 一致。
  6. 不需要 Boost.Python 时建议添加 --without-python
  7. 避免全量编译,通过 --with-xxx 仅编译实际需要的库,可有效减少干扰。
  8. 条件允许时,升级到 VS2022 v144 + Windows SDK 10.0.28000.0 等更新版本的工具组合,有助于从根本上规避此类兼容性问题。# 🏗️ 使用 VS2019 编译 Boost Windows ARM64 静态库踩坑记录
posted @ 2026-08-06 15:46  倚剑问天  阅读(1)  评论(0)    收藏  举报