1 何为跨平台构建
跨平台构建是指:
- 在一个平台(Build)上生成另一个平台(Host)可运行的程序
- 有时还涉及为第三个平台(Target)生成代码(如交叉编译器)
1.1 Build、Host、Target 平台
跨平台构建的核心是区分平台角色:
| 角色 | 说明 | 典型示例 |
|---|---|---|
| Build 平台 | 执行构建工具(如 CMake、Conan、make)的系统 | Windows 开发机 |
| Host 平台 | 构建出来的程序 要运行的系统 | Android、iOS、Linux |
| Target 平台 | 构建出的程序生成的代码将运行在哪(通常是工具链的目标平台) | 通常用于交叉编译器,例如为 iOS 构建一个能生成 ARM64 代码的 Clang |
target是跨平台构建中最不常用但也最容易混淆的角色,它主要用于 构建编译器本身 或 工具链程序 时,指定这些工具将来要生成哪种平台的代码。 或者简单地理解,target 一般只适用与工具链相关的程序。
1.2 举例:Visual Studio BuildTools
如安装 Visual Studio BuildTools 后,用 VSCode 扫描工具链可以得到 4 个:
{
"name": "Visual Studio 生成工具 2022 Release - amd64",
"visualStudio": "5356875b",
"visualStudioArchitecture": "x64",
"isTrusted": true,
"preferredGenerator": {
"name": "Visual Studio 17 2022",
"platform": "x64",
"toolset": "host=x64"
}
},
{
"name": "Visual Studio 生成工具 2022 Release - amd64_x86",
"visualStudio": "5356875b",
"visualStudioArchitecture": "x64",
"isTrusted": true,
"preferredGenerator": {
"name": "Visual Studio 17 2022",
"platform": "win32",
"toolset": "host=x64"
}
},
{
"name": "Visual Studio 生成工具 2022 Release - x86",
"visualStudio": "5356875b",
"visualStudioArchitecture": "x86",
"isTrusted": true,
"preferredGenerator": {
"name": "Visual Studio 17 2022",
"platform": "win32",
"toolset": "host=x86"
}
},
{
"name": "Visual Studio 生成工具 2022 Release - x86_amd64",
"visualStudio": "5356875b",
"visualStudioArchitecture": "x86",
"isTrusted": true,
"preferredGenerator": {
"name": "Visual Studio 17 2022",
"platform": "x64",
"toolset": "host=x86"
}
}信息整理成如下表格:
| 配置名称 | 主机平台(Toolset) | 目标平台(Platform) | 说明 |
|---|---|---|---|
| Visual Studio 生成工具 2022 Release - amd64 | host=x64 | platform=x64 | 在 64 位系统上,用 64 位编译器构建 64 位程序(推荐 x64 构建) |
| Visual Studio 生成工具 2022 Release - amd64_x86 | host=x64 | platform=win32 | 在 64 位系统上,用 64 位编译器构建 32 位程序 |
| Visual Studio 生成工具 2022 Release - x86 | host=x86 | platform=win32 | 在 32 位工具链环境下构建 32 位程序(已过时,较少使用) |
| Visual Studio 生成工具 2022 Release - x86_amd64 | host=x86 | platform=x64 | 用 32 位工具链构建 64 位程序(交叉编译,用于兼容老工具) |
1.3 举例:GCC 的交叉构建流程
我们来看 GCC 交叉编译器的构建三种情况:
- 原生构建(Native)
你在 Ubuntu x86_64 上构建 GCC 供自己使用:
| build | host | target |
|---|---|---|
| x86_64-linux-gnu | x86_64-linux-gnu | x86_64-linux-gnu |
- 跨平台应用构建(普通开发者常用)
你在 Ubuntu 上为 ARM Linux 编译一个程序:
| build | host | target |
|---|---|---|
| x86_64-linux-gnu | arm-linux-gnueabihf | arm-linux-gnueabihf |
- 跨平台交叉工具链构建(仅工具链作者才需)
你在 Ubuntu 上构建一个 “为 Windows 上运行,并能生成 ARM Linux 程序” 的 GCC 编译器:
| build | host | target |
|---|---|---|
| x86_64-linux-gnu | x86_64-w64-mingw32 | arm-linux-gnueabihf |
这种场景就用到了 target:程序本身不是目标,而是它生成的程序的目标。
2 平台三元组(Triplet)与通用模型
在跨平台构建系统(特别是 GNU 工具链、LLVM、CMake 以及 Conan 等工具)中,平台三元组(Triplet) 是一种标准格式,用于明确描述一个目标平台。
基本形式为:
<architecture>-<vendor>-<operating_system>
有时会扩展为四元组,加上 ABI 信息:
<architecture>-<vendor>-<operating_system>-<abi>
这一模型广泛用于描述:
- 当前系统
- 编译目标系统(host/target)
- 工具链适用的系统
2.1 各组成部分解释
| 部分 | 含义 | 示例 |
|---|---|---|
architecture | CPU 架构(或 ISA) | x86_64, arm, aarch64, mips, riscv64 |
vendor | 硬件厂商或平台分发商(常无实际意义) | pc, apple, w64, unknown |
os | 操作系统或运行时环境 | linux, windows, darwin, android, none |
abi(可选) | ABI 规范、调用约定、C/C++ 运行库 | gnu, gnueabihf, musl, eabi, msvc |
2.2 举例解析
-
x86_64-pc-linux-gnux86_64: 64 位 x86 架构pc: 通用 PC 平台linux: 操作系统gnu: GNU ABI(默认运行时)
表示:运行于 GNU/Linux 上的 64 位 PC 平台的程序
-
arm-none-eabiarm: 32 位 ARM 架构none: 无操作系统(裸机)eabi: ARM Embedded ABI(用于嵌入式)
表示:为裸机嵌入式设备(无 OS)构建的程序
-
x86_64-w64-mingw32x86_64: 64 位 x86w64: Windows 64-bitmingw32: Windows MinGW 子系统
表示:MinGW 工具链用于构建 Windows x64 应用
-
aarch64-apple-darwinaarch64: ARM 64 位(苹果 M 系列)apple: Apple 公司darwin: macOS 内核系统
表示:Apple Silicon 上运行的 macOS 程序
2.3 特别说明:ABI 字段
当四元组出现时,ABI 字段表达了运行时细节,比如:
gnu:GNU libcmusl:轻量级 libcgnueabihf:GNU EABI,支持硬件浮点eabi:嵌入式 ARM 的 ABImsvc:Microsoft Visual C++ ABI
2.4 在各工具链中的使用场景
| 工具 | 用途 | 使用方式 |
|---|---|---|
| GCC / Clang | 指定编译目标 | --target=arm-none-eabi |
| CMake | 设置交叉编译 | CMAKE_SYSTEM_NAME, 自定义 toolchain 中设定 |
| Conan | 精确控制构建三元组 | 在 profile 中设置 os/arch/compiler |
| vcpkg | triplet 配置包平台 | x64-windows, arm64-linux 等 |
| Rust | 目标平台 | rustup target add riscv64gc-unknown-elf |
| Go | 编译环境变量 | GOOS=linux GOARCH=arm |
3 CMake 中的跨平台构建原理
3.1 默认行为(原生构建)
在默认情况下,CMake 假设:
- Build = Host = Target
- 使用本机编译器(如
cl,gcc,clang)
3.2 跨平台/交叉构建时,必须指定:
- Toolchain 文件(最关键!)
cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain.cmake ..- 目标平台设置(以变量控制)
| CMake 变量 | 用途 | 示例 |
|---|---|---|
CMAKE_SYSTEM_NAME | 目标操作系统 | Linux, Windows, Android |
CMAKE_SYSTEM_PROCESSOR | 目标架构 | armv7, x86_64, aarch64 |
CMAKE_C_COMPILER, CMAKE_CXX_COMPILER | 交叉编译器路径 | /usr/bin/arm-linux-gnueabihf-gcc |
CMAKE_FIND_ROOT_PATH | 交叉编译头文件、库搜索路径 | /opt/arm-sysroot/ |
CMAKE_SYSROOT | 设置目标系统根目录 | /opt/sysroot/arm-linux |
3.3 一个典型的 toolchain-arm-linux.cmake:
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
set(CMAKE_SYSROOT /opt/arm-sysroot)
set(CMAKE_FIND_ROOT_PATH /opt/arm-sysroot)
# 只在目标路径中查找 include/lib
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)4 Conan 中的跨平台构建设置
Conan 通过 .profile 文件(或 settings.yml)建模平台三角色:
| Conan 设置项 | 含义 | 对应 CMake |
|---|---|---|
os_build / arch_build | 构建机平台(本机) | 无直接变量,CMake 自动检测 |
os / arch | 目标平台(Host) | CMAKE_SYSTEM_NAME, CMAKE_SYSTEM_PROCESSOR |
compiler, version, libcxx, cppstd | 编译器配置 | CMAKE_C_COMPILER, CMAKE_CXX_COMPILER 等 |
build_type | 构建类型 | CMAKE_BUILD_TYPE |
os_target, arch_target | 仅用于工具链构建的目标平台 | CMake 很少使用(除非构建编译器本身) |
4.1 示例 Conan Profile:
[settings]
os=Android
arch=armv8
compiler=clang
compiler.version=14
compiler.libcxx=libc++
build_type=Release
[env]
CONAN_CMAKE_TOOLCHAIN_FILE=/path/to/android.toolchain.cmakeConan 可以自动生成 toolchain 文件并传递给 CMake。
5 CMake + Conan 联合使用时的流程
-
Conan 读取 profile,解析
os/arch/compiler等设置 -
Conan 根据目标平台生成一个 CMake toolchain file(如
conan_toolchain.cmake) -
CMake 使用这个 toolchain 文件设置交叉构建参数
-
项目使用正确的交叉编译器与 sysroot 构建出目标平台可运行的程序
6 CMake 与 Conan 的概念对照表
| 语义 | Conan | CMake |
|---|---|---|
| 构建平台 | os_build, arch_build | 自动检测(不需配置) |
| 运行目标平台 | os, arch | CMAKE_SYSTEM_NAME, CMAKE_SYSTEM_PROCESSOR |
| 工具链配置 | compiler, version, libcxx | CMAKE_C_COMPILER, CMAKE_CXX_COMPILER, toolchain 文件 |
| 构建类型 | build_type | CMAKE_BUILD_TYPE |
| C++ 标准 | compiler.cppstd | CMAKE_CXX_STANDARD |
| 系统根路径 | 无 | CMAKE_SYSROOT, CMAKE_FIND_ROOT_PATH |
| 动态库选择(libcxx) | libstdc++, libc++, etc. | 与编译器默认相关 |
7 CMake 跨平台构建典型用例
7.1 Windows → Linux ARM 交叉编译:
- 使用 MinGW-w64 或 ARM Linux 工具链
- 编写
toolchain-arm.cmake并使用-DCMAKE_TOOLCHAIN_FILE
7.2 Linux → Android/iOS 交叉构建:
- 配合 Android NDK / Xcode SDK
- 使用官方提供的 CMake toolchain 文件
7.3 Windows → Emscripten(WebAssembly)
emcmake cmake -B build -DCMAKE_BUILD_TYPE=Release .Emscripten 提供了自己的 emcmake 和 toolchain 文件。
8 小结
| 内容 | CMake 实现 | Conan 设置 |
|---|---|---|
| 设置目标平台 | CMAKE_SYSTEM_NAME, PROCESSOR | os, arch |
| 指定交叉编译器 | CMAKE_C_COMPILER, etc. | compiler, version |
| 设置头文件/库路径 | CMAKE_SYSROOT, FIND_ROOT_PATH | env + toolchain 文件 |
| 控制构建类型/标准 | CMAKE_BUILD_TYPE, CXX_STANDARD | build_type, cppstd |
跨平台构建的核心在于明确平台角色,并为 CMake 配置合适的交叉工具链。Conan 的 profile 只是围绕 CMake 的变量做了一层抽象包装,最终还得通过 toolchain.cmake 执行构建。