- 构建工具
- 开发工具
- CLI
【免费下载链接】CMake
Mirror of CMake upstream repository
build_name是 CMake 历史上最早引入的辅助命令之一,用于生成"操作系统 + 编译器组合"的构建环境标识字符串。自 CMake 3.0 起该命令已被禁止调用(对应 CMake Policy CMP0036),并在 CMake 4.0 中被彻底移除。本文以 build_name 官方文档 为骨架,结合仓库源码与策略文档,完整讲解该命令的历史作用、语法、被禁原因、迁移方案与兼容性注意事项,帮助读者在维护老旧 CMake 项目时正确识别并改写这类调用。
一、命令速览:语法与作用
在 build_name 命令文档 中,命令的完整语法只有一行:
build_name(variable)其语义是:将指定的变量设置为一个代表当前平台(操作系统)与编译器设置的字符串。例如,早期 CMake 脚本中常见这样的写法:
build_name(MY_BUILD_TAG) message(STATUS "Current build environment: ${MY_BUILD_TAG}")该字符串通常用于构造构建输出目录名、日志前缀或发布包命名。但文档明确指出,这种"平台 + 编译器组合"信息如今已不再需要通过命令动态计算——它们已经作为标准变量暴露给所有 CMake 脚本:
CMAKE_SYSTEM:CMake 正在为之编译的目标操作系统组合名称;CMAKE_CXX_COMPILER:C++ 编译器的完整路径(即 CMAKE_ _COMPILER 在LANG为CXX时的具体实例)。
因此文档给出的官方结论是:不要再用build_name,改用这两个变量即可。
二、历史背景:2001 年诞生的早期命令
为什么 CMake 曾需要这样一个命令?CMP0036 策略文档 给出了清晰的溯源:
This command was added in May 2001 to compute a name for the current operating system and compiler combination.
也就是说,build_name于2001 年 5 月加入 CMake,其设计目的就是为"当前操作系统 + 编译器组合"计算一个名字。在 CMake 的早期版本中,平台探测与编译器探测的结果尚未系统化地沉淀为脚本变量,开发者需要一个统一的入口来获取这类环境信息,于是build_name应运而生。
该命令随后长期处于"官方文档标注为不推荐使用(discouraged)"的状态——文档中记载 "The command has long been documented as discouraged",因为它所提供的能力逐渐被标准变量体系取代。随着CMAKE_SYSTEM与CMAKE_<LANG>_COMPILER系列变量的完善,保留该命令已无必要,最终被列入移除计划。
三、被禁用的机制:CMP0036 策略
命令被禁用,在 CMake 中是通过**策略(Policy)**机制实现的。CMP0036 的完整名称即 "Thebuild_namecommand should not be called"(不应再调用build_name命令)。
3.1 策略的时间线
| 阶段 | 版本 | 行为 |
|---|---|---|
| 命令引入 | 2001-05 | 计算操作系统与编译器组合名 |
| 策略引入 / 命令禁止 | CMake 3.0 | 调用build_name时按策略处理:OLD允许调用,NEW直接报FATAL_ERROR |
策略OLD行为移除 | CMake 4.0 | OLD行为被彻底删除,策略必须为NEW |
CMP0036 策略文档使用的 REMOVED_COMMAND 模板 明确了两种行为模式:
- OLD(旧行为):允许调用
build_name命令; - NEW(新行为):一旦脚本调用
build_name,CMake 直接抛出FATAL_ERROR终止配置。
同时,REMOVED_PROLOGUE 模板 记录了策略演进的后半段:CMake 4.0 起,OLD行为已被移除,策略必须通过cmake_minimum_required或cmake_policy显式设置为NEW,即任何对build_name的调用都会被视为致命错误。
3.2 源码中的策略注册与命令移除
在仓库源码中可以找到与这条策略链对应的两处关键实现:
- 策略注册:在 Source/cmPolicies.h 中,
CMP0036以如下形式注册,其标题文本与官方文档完全一致:
SELECT(POLICY, CMP0036, "The build_name command should not be called.", 3, ...)其中3即策略引入版本 3.0,与文档一致。
- 命令移除:在 Source/cmCommands.cxx 中,
build_name已从命令表中移除,仅保留一条错误提示:
"build_name", "The build_name command has been removed; see CMP0036."这从源码层面印证了:在现代 CMake 中,build_name已不是可执行的命令,而只是一个指向 CMP0036 的"路标"——当旧脚本试图调用它时,CMake 会引导用户查看该策略了解原因。
四、官方推荐的替代方案
文档给出的迁移路径非常明确:
Use ${CMAKE_SYSTEM} and ${CMAKE_CXX_COMPILER} instead.即:用${CMAKE_SYSTEM}与${CMAKE_CXX_COMPILER}两个变量取代build_name的输出。
4.1 CMAKE_SYSTEM:目标操作系统组合名
CMAKE_SYSTEM 变量文档 给出了精确定义:
Composite name of operating system CMake is compiling for. This variable is the composite of
CMAKE_SYSTEM_NAMEandCMAKE_SYSTEM_VERSION, e.g.${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_VERSION}. IfCMAKE_SYSTEM_VERSIONis not set, then this variable is the same asCMAKE_SYSTEM_NAME.
要点归纳:
CMAKE_SYSTEM=CMAKE_SYSTEM_NAME与CMAKE_SYSTEM_VERSION的组合,形如Linux-5.15.0;- 若
CMAKE_SYSTEM_VERSION未设置,则CMAKE_SYSTEM就等于CMAKE_SYSTEM_NAME(例如某些嵌入式目标平台); - 它是目标系统(CMake 正在为谁编译)的信息,而非运行 CMake 的宿主系统信息。
4.2 CMAKE_ _COMPILER:编译器路径
CMAKE_CXX_COMPILER是通用变量 CMAKE_ _COMPILER 的一个实例(LANG = CXX),保存 C++ 编译器的完整路径。同理还有CMAKE_C_COMPILER、CMAKE_Fortran_COMPILER等。当需要标识"编译器组合"时,按项目实际启用的语言取对应的<LANG>变量即可,而不仅仅局限于 C++。
五、实战迁移示例
下面给出一个从旧写法迁移到新写法的完整对照。
旧式写法(已失效,CMake 3.0+ 会报错,4.0+ 必报错):
build_name(MY_BUILD_TAG) message(STATUS "Build environment: ${MY_BUILD_TAG}") set(OUTPUT_DIR "${CMAKE_BINARY_DIR}/${MY_BUILD_TAG}")新式写法(官方推荐):
# 目标操作系统组合名,例如 Linux-5.15.0 set(PLATFORM_TAG "${CMAKE_SYSTEM}") # 编译器标识:CMake_<LANG>_COMPILER 的 C++ 实例 set(COMPILER_TAG "${CMAKE_CXX_COMPILER}") message(STATUS "Platform tag: ${PLATFORM_TAG}") message(STATUS "Compiler tag: ${COMPILER_TAG}") set(OUTPUT_DIR "${CMAKE_BINARY_DIR}/${PLATFORM_TAG}-${CMAKE_CXX_COMPILER_ID}")补充说明:
- 若只需操作系统级标识,
${CMAKE_SYSTEM}已完全覆盖build_name在这方面的能力; - 若需要编译器路径级标识,使用
CMAKE_CXX_COMPILER(或对应语言的CMAKE_<LANG>_COMPILER); - 若希望得到更稳定、更易读的编译器家族标识(如
GNU、Clang、MSVC),可以配合使用 CMAKE_ _COMPILER_ID 变量,而不是直接拼接路径。
六、兼容性与升级注意事项
对于仍然包含build_name调用的历史项目,需要注意以下几点:
CMake 3.0 起默认行为已收紧:自 3.0 起,除非通过
cmake_minimum_required(VERSION < 3.0)或cmake_policy(SET CMP0036 OLD)显式声明旧行为,否则调用build_name会触发FATAL_ERROR,配置直接中断。CMake 4.0 起 OLD 行为已移除:根据 REMOVED_PROLOGUE 模板,4.0 之后策略必须为
NEW,不再存在任何"允许调用"的余地。也就是说,迁移不是可选项,而是硬性要求。推荐做法是直接改写:与其靠
cmake_policy(SET CMP0036 OLD)暂时绕过,不如按本文第五节的方式直接用${CMAKE_SYSTEM}与${CMAKE_CXX_COMPILER}重写脚本——变量取值由 CMake 内部探测逻辑保证一致性,结果稳定且跨版本可维护。验证方式:改写后可在配置阶段打印验证:
message(STATUS "CMAKE_SYSTEM = ${CMAKE_SYSTEM}") message(STATUS "CMAKE_CXX_COMPILER = ${CMAKE_CXX_COMPILER}")运行cmake -S . -B build后,对比输出与旧build_name曾生成的字符串,确认命名规则符合预期。
七、总结
build_name是 CMake 早期(2001 年)为"操作系统 + 编译器组合"命名而生的命令,其功能在现代 CMake 中已由标准变量体系完整取代。通过 CMP0036 策略,CMake 自 3.0 起禁止该命令(NEW行为直接FATAL_ERROR),自 4.0 起删除OLD行为、命令实现本身也从 Source/cmCommands.cxx 的命令表中移除。迁移路径简单明确:使用 CMAKE_SYSTEM 与 CMAKE_ _COMPILER 变量即可获得等价甚至更丰富的信息。维护旧项目时,建议直接改写脚本而非依赖策略回退,从根本上消除与未来 CMake 版本的兼容隐患。
- 构建工具
- 开发工具
- CLI
【免费下载链接】CMake
Mirror of CMake upstream repository
相关推荐
CMake 非目标指令(Non-Target Directives)为何被官方劝阻:从 add_* 到 target_* 命令的设计取舍与迁移实践
CMake 非目标指令(Non Target Directives)为何被官方劝阻:从 add_ 到 target_ 命令的设计取舍与迁移实践 本文围绕 CMa
构建工具开发工具CLI为什么 LaravelCollective HTML 被废弃?以及如何迁移到 Spatie Laravel HTML
为什么 LaravelCollective HTML 被废弃?以及如何迁移到 Spatie Laravel HTML LaravelCollective HTM
Spring SimpleCommandLineArgsParser 源码解析:命令行参数如何被解析为属性源
Spring SimpleCommandLineArgsParser 源码解析:命令行参数如何被解析为属性源 导读 本文聚焦 Spring 框架 org.spr
文档教程知识库
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考