news 2026/10/7 21:06:45

CMake 工具链与交叉编译完全指南:从 Toolchain File 到各平台实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CMake 工具链与交叉编译完全指南:从 Toolchain File 到各平台实战
  • 构建工具
  • 开发工具
  • CLI

【免费下载链接】CMake

Mirror of CMake upstream repository

项目地址:https://gitcode.com/gh_mirrors/cm/CMake
点击查看免费下载

导读

工具链(Toolchain)是 CMake 构建系统的基石:它决定了编译、链接、归档等全部构建动作由哪一组工具完成。本指南以 CMake 官方手册 cmake-toolchains(7) 为骨架,系统讲解语言启用机制、编译器相关变量与属性、try_compile能力探测,以及面向 Linux、Cray、Clang、QNX、Windows CE/Store/Phone、ADSP、Android、Apple 平台、Emscripten 与 Renesas 等十余类交叉编译场景的 Toolchain File 编写方法。读完本文,你将能够独立编写一份可用的 Toolchain File,理解CMAKE_FIND_ROOT_PATH_MODE_*等搜索规则的底层行为,并能针对具体嵌入式与移动平台完成配置。

引言:什么是 CMake 工具链

CMake 使用一组工具(Toolchain)来完成编译、库链接、归档创建等构建任务。这组工具由启用的语言决定:例如启用了 C 语言,就需要 C 编译器;启用了 Fortran,就需要 Fortran 编译器与对应的归档工具。工具链的获取方式分为两种:

  • 本机构建(host build):CMake 通过系统内省(system introspection)与默认值自动探测编译器路径和配套工具,无需人工指定;
  • 交叉编译(cross-compiling):通过Toolchain File(工具链文件)显式提供编译器与工具路径等信息。

从 CMake 3.19 起,还可以通过 cmake-presets(7) 指定 Toolchain File(preset 中的toolchainFile字段)。在源码层面,Source/cmake.cxx 中定义了命令行参数--toolchain <file>(见 Source/cmake.cxx#L310),并在 Source/cmake.cxx#L2150-L2153 处将 preset 展开后的ToolchainFile写入CMAKE_TOOLCHAIN_FILE缓存变量;Source/cmake.cxx#L2693-L2696 还支持从环境变量CMAKE_TOOLCHAIN_FILE读取该值。

关键事实:Toolchain File 本身是在配置阶段早期被加载的普通 CMake 脚本(set(...)赋值即生效),它并非一个被include()的普通模块,而是在检测编译器之前由cmake主流程注入,因此其中的变量赋值会直接作用于后续的编译器探测。

语言启用机制

语言由 project() 命令启用。调用project()时,CMake 会设置该语言相关的内建变量,例如 CMAKE_CXX_COMPILER、CMAKE_CXX_COMPILER_ID 等。若顶层 CMakeLists.txt 中没有project()命令,CMake 会隐式生成一个。默认启用C和CXX两种语言。

只启用 C 语言:

project(C_Only C)

不启用任何语言(可用于纯数据/配置项目):

project(MyProject NONE)

在project()之后通过 enable_language() 追加启用语言:

enable_language(CXX)

启用一种语言时,CMake 会为该语言查找编译器,并探测其供应商(vendor)与版本、目标架构与位宽、配套工具位置等信息。当前已启用的语言集合记录在 ENABLED_LANGUAGES 全局属性中。

从源码实现看,project()触发语言启用后,cmGlobalGenerator::EnableLanguages会加载对应的Modules/CMakeDetermine*Compiler.cmake与Modules/Platform/<Platform>-<Compiler>.cmake,例如Modules/CMakeDetermineCCompiler.cmake、Modules/Platform/Linux-GNU.cmake等,这些文件共同完成编译器 ID、版本和 ABI 探测。

与工具链相关的变量与属性

语言级编译器变量

以下变量与当前启用的语言一一对应,<LANG>可替换为C、CXX、Fortran、ASM、CUDA等:

变量含义
CMAKE_ _COMPILER用于<LANG>的编译器完整路径
CMAKE_ _COMPILER_IDCMake 使用的编译器标识(如GNU、Clang、MSVC、AppleClang)
CMAKE_ _COMPILER_VERSION编译器版本
CMAKE_ _FLAGS会附加到该语言所有编译与链接调用的标志(含各配置对应的CMAKE_<LANG>_FLAGS_<CONFIG>,如CMAKE_C_FLAGS_RELEASE)
CMAKE_ _LINK_FLAGS4.3 新增;仅附加到由该语言驱动链接的调用(同样存在配置化等价变量)

注意CMAKE_<LANG>_FLAGS同时作用于编译与链接驱动调用,而CMAKE_<LANG>_LINK_FLAGS(4.3 起)只作用于链接驱动,二者在链接阶段的语义差异是排查“链接时标志被吞”的关键。

链接语言的选择

CMake 需要决定用哪个编译器来驱动链接器。规则如下:

  • 由目标(target)中各源文件的 LANGUAGE 属性决定;
  • 对静态库,还参考其依赖库的LANGUAGE;
  • 可通过 LINKER_LANGUAGE 目标属性覆盖默认选择。

典型场景:一个项目同时包含 C 与 Fortran 源文件时,链接通常应交给 Fortran 编译器驱动(以引入其运行时库),此时可显式设置set_target_properties(mylib PROPERTIES LINKER_LANGUAGE Fortran)。

工具链能力探测

CMake 提供 try_compile() 命令与多个模块,用于测试工具链的特定能力与可用性:

  • CheckSourceCompiles(以及CheckCSourceCompiles、CheckCXXSourceCompiles、CheckFortranSourceCompiles等)
  • CheckCXXSymbolExists
  • CheckIncludeFile

这些 API 会以某种方式测试工具链,并将结果缓存(Cache 变量),避免下次运行 CMake 时重复探测。这也是为什么更换工具链后常常需要清理 CMakeCache.txt——缓存中的能力结论可能已失效。

部分工具链特性由 CMake 内建处理,无需编译测试:

  • POSITION_INDEPENDENT_CODE:指定目标构建为位置无关代码(-fPIC等),前提是编译器支持;
  • _VISIBILITY_PRESET与 VISIBILITY_INLINES_HIDDEN:在编译器支持时添加隐藏可见性标志。

从实现上看,try_compile会生成一个临时项目并在独立目录中执行编译(见 Source/cmTryCompileCommand.cxx)。这也是手册强调“Toolchain File 中不要依赖CMAKE_SOURCE_DIR/CMAKE_BINARY_DIR”的原因:在try_compile的上下文中,这些变量会被重定向到临时项目,取值不可预期;应优先使用始终有确定值的 CMAKE_CURRENT_LIST_DIR 来解析路径。

交叉编译概述:加载 Toolchain File

若以命令行参数--toolchain path/to/file或-DCMAKE_TOOLCHAIN_FILE=path/to/file调用 cmake(1),该文件会在早期被加载以设置编译器相关值。当 CMake 处于交叉编译时,CMAKE_CROSSCOMPILING 变量被置为true。

典型的交叉编译配置流程为:

$ cmake ../src -DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain.cmake

在源码层面,toolchain 文件路径会写入缓存;Source/cmGlobalGenerator.cxx#L717-L739 显示:配置阶段会读取构建目录下的CMakeSystem.cmake,若检测到CMAKE_TOOLCHAIN_FILE与本次输入值不一致,会将该变量标记为需要删除的缓存变更并重新配置,因为“toolchain 文件变化会使内省结果失效”。

Toolchain File 编写注意事项:

  • 不要使用CMAKE_SOURCE_DIR或CMAKE_BINARY_DIR:它们在try_compile等不同上下文中取值不同;应使用 CMAKE_CURRENT_LIST_DIR 定位 Toolchain File 同目录下的工具,它始终具有明确、可预期的值。

通用 Toolchain File 骨架

综合多平台场景,一份通用 Toolchain File 通常包含:

# 目标平台与架构(CMake 标识符) set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) # 交叉根文件系统与安装暂存路径(均可选) set(CMAKE_SYSROOT /path/to/rootfs) set(CMAKE_STAGING_PREFIX /path/to/stage) # 编译器(完整路径或可搜索的名字) set(CMAKE_C_COMPILER /path/to/arm-gcc) set(CMAKE_CXX_COMPILER /path/to/arm-g++) set(CMAKE_ASM_COMPILER /path/to/arm-as) # 如启用 ASM # 查找规则:程序只在宿主上找,库/头/包只在目标上找 set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

关键变量语义:

变量说明
CMAKE_SYSTEM_NAME目标平台的 CMake 标识符(Linux、Android、WindowsCE、QNX等),也是触发交叉编译的关键开关
CMAKE_SYSTEM_PROCESSOR目标架构的 CMake 标识符(如arm、aarch64)
CMAKE_SYSROOT可选;sysroot 根目录,find_*命令会在此查找
CMAKE_STAGING_PREFIX可选;宿主上用于install的暂存路径。注意 CMAKE_INSTALL_PREFIX始终是运行时安装位置,交叉编译时也不变
CMAKE_ _COMPILER可设为完整路径,或设为名字让 CMake 在标准位置搜索
CMAKE_TRY_COMPILE_TARGET_TYPE设为STATIC_LIBRARY可让 CMake 在能力检查时不尝试链接可执行文件(适合无法直接链接二进制的工具链)

CMAKE_TRY_COMPILE_TARGET_TYPE在源码中对应 Source/cmTryCompileCommand.cxx#L57-L63:当其值为STATIC_LIBRARY时,try_compile 生成的目标类型为静态库。Renesas CC-RL 一节中正是用它规避测试可执行文件超出 const section 大小限制的问题。

CMAKE_FIND_ROOT_PATH_MODE_*的查找语义

默认情况下,find_*命令会依次查找 sysroot、CMAKE_FIND_ROOT_PATH 条目,以及宿主系统根前缀。交叉编译时,通常希望:

  • 头文件、库、包:只在目标系统前缀中查找(ONLY);
  • 必须作为构建一部分在宿主上运行的程序(编译器、链接器、打包工具等):只在宿主上查找(NEVER)。

这就是CMAKE_FIND_ROOT_PATH_MODE_PROGRAM/LIBRARY/INCLUDE/PACKAGE四个变量的用途,取值均为NEVER、ONLY或BOTH(默认)。实现上,Source/cmFindCommon.cxx#L160 会按查找路径类别动态读取CMAKE_FIND_ROOT_PATH_MODE_<类别>对应的值来约束搜索范围。

面向 Linux 的交叉编译

一份典型的面向 Linux(如树莓派)的交叉编译 Toolchain File:

set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) set(CMAKE_SYSROOT /home/devel/rasp-pi-rootfs) set(CMAKE_STAGING_PREFIX /home/devel/stage) set(tools /home/devel/gcc-4.7-linaro-rpi-gnueabihf) set(CMAKE_C_COMPILER ${tools}/bin/arm-linux-gnueabihf-gcc) set(CMAKE_CXX_COMPILER ${tools}/bin/arm-linux-gnueabihf-g++) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

说明:CMAKE_SYSTEM_NAME与CMAKE_SYSTEM_PROCESSOR是必填项;CMAKE_SYSROOT与CMAKE_STAGING_PREFIX可选。若工具链无法直接链接可执行文件,可追加set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)。

面向 Cray Linux 环境(CLE)的交叉编译

Cray 登录节点与计算节点交叉编译无需单独的 Toolchain File:在命令行指定-DCMAKE_SYSTEM_NAME=CrayLinuxEnvironment即可保证正确的构建设置与搜索路径(对应平台模块为 Modules/Platform/CrayLinuxEnvironment.cmake 与 Modules/Platform/CrayLinuxEnvironment-Initialize.cmake)。平台会从当前环境变量拉取配置,并在存在且已加载时使用 Cray Programming Environment 的PrgEnv-*模块中的编译器包装器。

  • CLE 默认仅支持静态库;设置环境变量CRAYPE_LINK_TYPE=dynamic可启用共享库。
  • 不指定CMAKE_SYSTEM_NAME时,配置阶段按标准 Linux 环境以主机模式运行;此时若未覆盖,PrgEnv-*包装器会被使用——登录节点构建通常不希望这样。
  • 例外:直接在 NID 上构建(而非从登录节点交叉编译)时可以使用包装器。
  • 若为登录节点构建软件:要么先unload已加载的PrgEnv-*模块,要么显式让 CMake 使用/usr/bin下的系统编译器。
  • 若为计算节点构建:如上所述指定CMAKE_SYSTEM_NAME=CrayLinuxEnvironment即可。

使用 Clang 交叉编译

Clang 等编译器本身即是交叉编译器。通过CMAKE_ _COMPILER_TARGET向编译器传递目标三元组(triple):

set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) set(triple arm-linux-gnueabihf) set(CMAKE_C_COMPILER clang) set(CMAKE_C_COMPILER_TARGET ${triple}) set(CMAKE_CXX_COMPILER clang++) set(CMAKE_CXX_COMPILER_TARGET ${triple})

另外,某些编译器不自带链接器等配套工具,但允许指定外部工具链位置供编译器驱动使用。可在 Toolchain File 中设置CMAKE_ _COMPILER_EXTERNAL_TOOLCHAIN来传递该路径。典型场景:用 Clang 驱动 GNU 工具链(--gcc-toolchain),其配套 binutils 来自交叉 GCC 安装目录。

面向 QNX 的交叉编译

QNX 的 QCC 编译器与 Clang 一样是天然的交叉编译器,同样通过CMAKE_<LANG>_COMPILER_TARGET传递目标:

set(CMAKE_SYSTEM_NAME QNX) set(arch gcc_ntoaarch64) set(CMAKE_C_COMPILER qcc) set(CMAKE_C_COMPILER_TARGET ${arch}) set(CMAKE_CXX_COMPILER q++) set(CMAKE_CXX_COMPILER_TARGET ${arch}) set(CMAKE_SYSROOT $ENV{QNX_TARGET})

arch的值(如gcc_ntoaarch64)是 QNX 定义的目标变体名,决定 QCC 选择的 CPU 目标;sysroot 直接取环境变量QNX_TARGET。

面向 Windows CE 的交叉编译

面向 Windows CE 交叉编译要求系统安装对应 SDK,通常位于C:/Program Files (x86)/Windows CE Tools/SDKs。配置 Visual Studio 生成器的 Toolchain File 形如:

set(CMAKE_SYSTEM_NAME WindowsCE) set(CMAKE_SYSTEM_VERSION 8.0) set(CMAKE_SYSTEM_PROCESSOR arm) set(CMAKE_GENERATOR_TOOLSET CE800) # 8.0 可省略 set(CMAKE_GENERATOR_PLATFORM SDK_AM335X_SK_WEC2013_V310)
  • CMAKE_GENERATOR_PLATFORM 告诉生成器使用哪个 SDK;
  • CMAKE_SYSTEM_VERSION 告诉生成器使用哪个 Windows CE 版本。目前开箱支持 8.0(Windows Embedded Compact 2013);其他版本可能需要将 CMAKE_GENERATOR_TOOLSET 设置为正确值。

面向 Windows 10 通用应用(UWP)的交叉编译

配置 Visual Studio 生成器构建 Windows 10 通用应用:

set(CMAKE_SYSTEM_NAME WindowsStore) set(CMAKE_SYSTEM_VERSION 10.0)

Windows 10 通用应用同时面向 Windows Store 与 Windows Phone。CMAKE_SYSTEM_VERSION需设为10.0或更高。CMake 按 CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION 变量文档所述选择 Windows SDK。

面向 Windows Phone / Windows Store 的交叉编译

Windows Phone:

set(CMAKE_SYSTEM_NAME WindowsPhone) set(CMAKE_SYSTEM_VERSION 8.1)

Windows Store:

set(CMAKE_SYSTEM_NAME WindowsStore) set(CMAKE_SYSTEM_VERSION 8.1)

二者均用于配置 Visual Studio 生成器。

面向 ADSP SHARC/Blackfin 的交叉编译

面向 ADSP SHARC 或 Blackfin 交叉编译:

  • 设置 CMAKE_SYSTEM_NAME 为ADSP;
  • 设置 CMAKE_SYSTEM_PROCESSOR 为去掉ADSP-前缀的“部件号”,例如21594、SC589;该值不区分大小写。

CMake 会自动在默认安装位置搜索 CCES 或 VDSP++ 安装并选择最近版本;两者都装时优先 CCES。自定义安装路径可通过 CMAKE_ADSP_ROOT 变量或 ADSP_ROOT 环境变量设置。编译器(cc21k对应 SHARC,ccblkfn对应 Blackfin)会根据CMAKE_SYSTEM_PROCESSOR自动选择。

面向 Android 的交叉编译

环境选择规则

将 CMAKE_SYSTEM_NAME 设为Android即可启用 Android 交叉编译,其余配置取决于使用的 Android 开发环境:

  • Visual Studio 生成器:需要 NVIDIA Nsight Tegra Visual Studio Edition 或 Visual Studio Tools for Android;
  • Makefile 生成器 / Ninja:需要 NDK 或 Standalone Toolchain。

CMake 按以下顺序选择环境(任一命中即止):

  1. 若 CMAKE_ANDROID_NDK 已设置 → 使用指定位置的 NDK;
  2. 否则若 CMAKE_ANDROID_STANDALONE_TOOLCHAIN 已设置 → 使用 Standalone Toolchain;
  3. 否则若 CMAKE_SYSROOT 形如<ndk>/platforms/android-<api>/arch-<arch>→ 提取<ndk>作为 NDK;
  4. 否则若CMAKE_SYSROOT形如<standalone-toolchain>/sysroot→ 提取<standalone-toolchain>作为 Standalone Toolchain;
  5. 否则若 CMake 变量ANDROID_NDK已设置 → 用作 NDK;
  6. 否则若 CMake 变量ANDROID_STANDALONE_TOOLCHAIN已设置 → 用作 Standalone Toolchain;
  7. 否则若环境变量ANDROID_NDK_ROOT或ANDROID_NDK已设置 → 用作 NDK;
  8. 否则若环境变量ANDROID_STANDALONE_TOOLCHAIN已设置 → 用作 Standalone Toolchain;
  9. 否则报错:找不到 NDK 或 Standalone Toolchain。

从 3.20 起,若选中 NDK,其版本号会记录在 CMAKE_ANDROID_NDK_VERSION 变量中。

平台模块实现位于 Modules/Platform/Android-Initialize.cmake,其会按需include(${CMAKE_ANDROID_NDK}/build/cmake/hooks/...),将 NDK 自带的钩子(hooks)纳入配置流程。

使用 NDK 交叉编译

可配置 Makefile、Ninja 或 Visual Studio 生成器。相关变量:

变量说明
CMAKE_SYSTEM_NAME必须为Android
CMAKE_SYSTEM_VERSIONAndroid API level。未指定时:若 CMAKE_ANDROID_API 已设置则用之;否则若CMAKE_SYSROOT已设置则从 NDK 目录结构检测;否则用 NDK 中最新的 API level
CMAKE_ANDROID_ARCH_ABIAndroid ABI(架构)。未指定时默认取armeabi、armeabi-v7a、arm64-v8a中第一个受支持的;CMAKE_ANDROID_ARCH 会自动由它计算得出。另参见 CMAKE_ANDROID_ARM_MODE 与 CMAKE_ANDROID_ARM_NEON
CMAKE_ANDROID_NDKNDK 根目录的绝对路径;未指定时按上述选择规则取默认
CMAKE_ANDROID_NDK_DEPRECATED_HEADERS置真以使用已废弃的按 API level 划分的头文件,而非统一头文件;默认 false(NDK 不提供统一头文件时除外)
CMAKE_ANDROID_NDK_TOOLCHAIN_VERSIONNDK r19 及以上必须不设置或设为clang;r18 及以下设为要选用的 NDK 工具链版本,默认最新 GCC 工具链
CMAKE_ANDROID_STL_TYPE指定使用的 C++ 标准库;未指定时按变量文档选择默认

自动计算并提供以下变量:

Toolchain File 示例:

set(CMAKE_SYSTEM_NAME Android) set(CMAKE_SYSTEM_VERSION 21) # API level set(CMAKE_ANDROID_ARCH_ABI arm64-v8a) set(CMAKE_ANDROID_NDK /path/to/android-ndk) set(CMAKE_ANDROID_STL_TYPE gnustl_static)

也可不使用 Toolchain File,直接在命令行指定:

$ cmake ../src \ -DCMAKE_SYSTEM_NAME=Android \ -DCMAKE_SYSTEM_VERSION=21 \ -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \ -DCMAKE_ANDROID_NDK=/path/to/android-ndk \ -DCMAKE_ANDROID_STL_TYPE=gnustl_static

使用 Standalone Toolchain 交叉编译

可配置 Makefile 或 Ninja 生成器。相关变量:

变量说明
CMAKE_SYSTEM_NAME必须为Android
CMAKE_ANDROID_STANDALONE_TOOLCHAINStandalone Toolchain 根目录的绝对路径;其下必须存在sysroot子目录;未指定时按上述规则取默认
CMAKE_ANDROID_ARM_MODE当工具链面向 ARM 时,可选设为ON以面向 32 位 ARM 而非 16 位 Thumb
CMAKE_ANDROID_ARM_NEON当工具链面向 ARM v7 时,可选设为ON以面向 ARM NEON 设备

自动计算并提供:

Toolchain File 示例:

set(CMAKE_SYSTEM_NAME Android) set(CMAKE_ANDROID_STANDALONE_TOOLCHAIN /path/to/android-toolchain)

命令行等价写法:

$ cmake ../src \ -DCMAKE_SYSTEM_NAME=Android \ -DCMAKE_ANDROID_STANDALONE_TOOLCHAIN=/path/to/android-toolchain

使用 NVIDIA Nsight Tegra Visual Studio Edition

配置 Visual Studio 生成器以使用 Nsight Tegra 构建 Android 应用:

set(CMAKE_SYSTEM_NAME Android)

CMAKE_GENERATOR_TOOLSET 可用于选择 Nsight Tegra 的 "Toolchain Version" 值。还可参见以下目标属性:ANDROID_API、ANDROID_API_MIN、ANDROID_ARCH、ANDROID_ASSETS_DIRECTORIES、ANDROID_GUI、ANDROID_JAR_DEPENDENCIES、ANDROID_JAR_DIRECTORIES、ANDROID_JAVA_SOURCE_DIR、ANDROID_NATIVE_LIB_DEPENDENCIES、ANDROID_NATIVE_LIB_DIRECTORIES、ANDROID_PROCESS_MAX、ANDROID_PROGUARD、ANDROID_PROGUARD_CONFIG_PATH、ANDROID_SECURE_PROPS_PATH、ANDROID_SKIP_ANT_STEP、ANDROID_STL_TYPE 与 ANDROID_ANT_ADDITIONAL_OPTIONS。

面向 iOS、tvOS、visionOS、watchOS 的交叉编译

向这些 Apple 平台交叉编译时推荐使用 Xcode 生成器;Unix Makefiles 或 Ninja 也可用,但需要项目自行处理目标 CPU 选择与代码签名等更多环节。

将 CMAKE_SYSTEM_NAME 设为下表对应值即可定位对应平台,默认选择最新的 Device SDK;与所有 Apple 平台一致,可通过 CMAKE_OSX_SYSROOT 选择不同 SDK(如模拟器 SDK),但通常无需显式设置(见下文“设备与模拟器切换”)。可用xcodebuild -showsdks列出可用 SDK。

OSCMAKE_SYSTEM_NAMEDevice SDK(默认)Simulator SDKCatalyst SDK
iOSiOSiphoneosiphonesimulatormacosx
tvOStvOSappletvosappletvsimulatorN/A
visionOSvisionOSxrosxrsimulatorN/A
watchOSwatchOSwatchoswatchsimulatorN/A

例如,为 iOS 创建 CMake 配置只需:

cmake .. -GXcode -DCMAKE_SYSTEM_NAME=iOS

CMAKE_OSX_ARCHITECTURES 可为设备与模拟器同时设置架构;CMAKE_OSX_DEPLOYMENT_TARGET 可设置部署目标。

以下示例在一个通用二进制(universal binary)中安装 5 个架构的 iOS 库,并在需要处自动添加-miphoneos-version-min=9.3或-mios-simulator-version-min=9.3编译标志。注意:示例中的 CMAKE_IOS_INSTALL_COMBINED 已废弃,此做法不再推荐:

$ cmake -S. -B_builds -GXcode \ -DCMAKE_SYSTEM_NAME=iOS \ "-DCMAKE_OSX_ARCHITECTURES=armv7;armv7s;arm64;i386;x86_64" \ -DCMAKE_OSX_DEPLOYMENT_TARGET=9.3 \ -DCMAKE_INSTALL_PREFIX=`pwd`/_install \ -DCMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH=NO \ -DCMAKE_IOS_INSTALL_COMBINED=YES

配套的 CMakeLists.txt 与验证命令:

# CMakeLists.txt cmake_minimum_required(VERSION 3.14) project(foo) add_library(foo foo.cpp) install(TARGETS foo DESTINATION lib)
$ cmake --build _builds --config Release --target install

用lipo检查通用二进制:

$ lipo -info _install/lib/libfoo.a Architectures in the fat file: _install/lib/libfoo.a are: i386 armv7 armv7s x86_64 arm64

用otool检查最低 iOS 版本:

$ otool -l _install/lib/libfoo.a | grep -A2 LC_VERSION_MIN_IPHONEOS cmd LC_VERSION_MIN_IPHONEOS cmdsize 16 version 9.3

代码签名

Apple 嵌入式平台的部分构建产物强制要求代码签名。使用 Xcode 生成器且需要/希望签名时,可通过 CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM 指定开发团队 ID,该 ID 会写入生成的 Xcode 工程。默认情况下,CMake 在内部配置阶段(编译器 ID 探测与特性检测)会避免代码签名需求。

设备与模拟器切换

配置任一嵌入式平台时,可面向真机或模拟器;两者有各自独立的 SDK,而 CMake 在配置阶段只支持指定一个 SDK,因此必须在配置时二选一。使用 Xcode 生成器时这个限制影响较小——Xcode 仍允许在配置只针对其一的情况下,同时为设备或模拟器构建;从 Xcode IDE 构建时按所选 "destination" 平台进行,命令行构建时可直接向底层构建工具(xcodebuild)传-sdk参数:

$ cmake --build ... -- -sdk iphonesimulator

注意:配置阶段所做的检查针对配置时的 SDK,未必适用于其他 SDK。find_package()、find_library() 等命令只存储和使用所配置 SDK/平台的信息,跨设备/模拟器切换时可能出问题。让“设备 + 模拟器”配置同时工作的规则:

  • 使用显式-l链接标志,例如target_link_libraries(foo PUBLIC "-lz");
  • 使用显式-framework链接标志,例如target_link_libraries(foo PUBLIC "-framework CoreFoundation");
  • 只对通过 CMAKE_IOS_INSTALL_COMBINED 特性安装的库使用find_package。

面向 Emscripten(WebAssembly)的交叉编译

4.2 新增支持。

将 CMAKE_SYSTEM_NAME 设为Emscripten即可配置面向 Emscripten 的交叉编译。Toolchain File 示例:

set(CMAKE_SYSTEM_NAME Emscripten) set(CMAKE_C_COMPILER /path/to/emcc) set(CMAKE_CXX_COMPILER /path/to/em++)

对应的平台模块为 Modules/Platform/Emscripten.cmake,其中将共享库后缀设为.wasm、可执行文件后缀设为.js(见 Modules/Platform/Emscripten.cmake#L18-L19),即链接产物为.wasm模块与.js加载器。另有配套的 Modules/Platform/Emscripten-Clang.cmake、Emscripten-Determine-*.cmake等文件处理编译器探测细节。

面向 Renesas 编译器的交叉编译

Renesas 交叉编译至少需要指定:

变量说明
CMAKE_SYSTEM_NAME设为Generic,必须指定以启用交叉编译
CMAKE_C_COMPILERRenesas C 编译器路径,如ccrx、ccrl、ccrh
CMAKE_C_FLAGS编译器要求的-isa=或-cpu=标志

Renesas CC-RX

set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_C_COMPILER "ccrx.exe") set(CMAKE_ASM_COMPILER "ccrx.exe") # 如启用 ASM 语言 set(CMAKE_C_FLAGS "-isa=rxv3") # 指定目标 RX CPU 版本 set(CMAKE_EXE_LINKER_FLAGS "-lnkopt=<your linker option here>")

Renesas CC-RL

set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_C_COMPILER "ccrl.exe") set(CMAKE_ASM_COMPILER "ccrl.exe") # 如启用 ASM 语言 set(CMAKE_C_FLAGS "-cpu=S3") # 指定目标 RL CPU 版本 # 避免测试可执行文件超出 const section 大小限制 set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) # 通过编译器驱动指定设备文件与段布局链接选项 set(CMAKE_EXE_LINKER_FLAGS "-lnkopt=-device=dr5f10y14.dvf -lnkopt=-auto_section_layout")

Renesas CC-RH

set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_C_COMPILER "ccrh.exe") set(CMAKE_ASM_COMPILER "ccrh.exe") # 如启用 ASM 语言 set(CMAKE_C_FLAGS "-Xcommon=rh850") # 指定目标 RH850 CPU 版本 set(CMAKE_EXE_LINKER_FLAGS "-lnkopt=<your linker option here>")

实战总结:编写 Toolchain File 的检查清单

  1. 必填:CMAKE_SYSTEM_NAME(触发交叉编译模式的开关);目标平台不同,其余必填项不同(如 Android 还需CMAKE_ANDROID_NDK或CMAKE_ANDROID_STANDALONE_TOOLCHAIN);
  2. 架构:CMAKE_SYSTEM_PROCESSOR(ARM 平台还需CMAKE_ANDROID_ARCH_ABI等);
  3. 编译器:CMAKE_<LANG>_COMPILER,必要时补CMAKE_<LANG>_COMPILER_TARGET(Clang/QCC)、CMAKE_<LANG>_COMPILER_EXTERNAL_TOOLCHAIN(外部 binutils);
  4. 根文件系统:CMAKE_SYSROOT(可选);
  5. 安装布局:CMAKE_STAGING_PREFIX(可选,仅宿主暂存);CMAKE_INSTALL_PREFIX始终是运行时安装位置;
  6. 查找范围:根据产物类型设置CMAKE_FIND_ROOT_PATH_MODE_{PROGRAM,LIBRARY,INCLUDE,PACKAGE}为NEVER/ONLY/BOTH;
  7. 能力检查:无法链接可执行文件时设CMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY;
  8. 路径安全:Toolchain File 内解析路径用CMAKE_CURRENT_LIST_DIR,不要依赖CMAKE_SOURCE_DIR/CMAKE_BINARY_DIR;
  9. 与 preset 集成:3.19 起可在 cmake-presets(7) 中通过toolchainFile字段指定,替代命令行--toolchain;
  10. 缓存失效:更换 Toolchain File 后 CMake 会检测到CMAKE_TOOLCHAIN_FILE变化并触发重新配置(Source/cmGlobalGenerator.cxx#L724-L739);若能力探测结果异常,清理构建目录的CMakeCache.txt与CMakeFiles/重新配置。

上述所有变量、属性与命令的权威定义均可进一步查阅本仓库 Help/variable(828 个变量文档)、Help/prop_tgt(456 个目标属性文档)与 Help/command(148 个命令文档)目录;对应实现位于 Source 与 Modules(含 Modules/Platform 下 779 个平台相关.cmake文件)。围绕具体平台的落地配置,可结合 Modules/Platform 中对应平台模块(如Linux-GNU.cmake、Android-Initialize.cmake、Emscripten.cmake、CrayLinuxEnvironment.cmake等)进一步核对默认行为。

  • 构建工具
  • 开发工具
  • CLI

【免费下载链接】CMake

Mirror of CMake upstream repository

项目地址:https://gitcode.com/gh_mirrors/cm/CMake
点击查看免费下载

相关推荐

上一篇:GraphQL Playground实时数据处理:订阅实现原理
下一篇:告别手动API文档:gh_mirrors/fr/frontend-stuff 自动化文档生成实践

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/7 21:04:53

Agent-Reach 实战:CLI 版 AI Agent 架构解析与工作流集成

1. 从标题到落地&#xff1a;Agent-Reach 到底想解决什么问题第一次看到 Agent-Reach 这个名字&#xff0c;我下意识把它拆成了两半&#xff1a;Agent 和 Reach。Agent 是当下最热的 AI 智能体概念&#xff0c;Reach 是触达、延伸、够得着的意思。合在一起&#xff0c;直觉告诉…

作者头像 李华
网站建设 2026/10/7 21:04:44

darktable RAW 冲洗教程:免费开源,从安装到出片一次讲清

darktable RAW 冲洗教程&#xff1a;免费开源&#xff0c;从安装到出片一次讲清 【免费下载链接】darktable darktable is an open source photography workflow application and raw developer 项目地址: https://gitcode.com/GitHub_Trending/da/darktable darktable …

作者头像 李华
网站建设 2026/10/7 21:01:34

STM32参考设计资源全攻略:官方渠道、社区平台与实战避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/7 20:59:30

Tessent_StdcellLib 标准单元库 DFT 建模与扫描链实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/7 20:56:55

vLLM异步调度实战:CPU/GPU重叠与KV Cache管理优化

1. 从一次显存打满说起&#xff1a;异步调度到底在解决什么如果你部署过 vLLM&#xff0c;大概率遇到过这样的场景&#xff1a;模型权重加载完毕&#xff0c;服务正常启动&#xff0c;前几个请求响应飞快&#xff0c;但并发一上来&#xff0c;GPU 利用率曲线就开始剧烈抖动——…

作者头像 李华