权威指南:CMAKE_、_CMAKE_ 与命令名前缀命名规范)
构建工具开发工具CLI【免费下载链接】CMakeMirror of CMake upstream repository项目地址https://gitcode.com/gh_mirrors/cm/CMake点击查看免费下载导读CMake 语言中并非所有变量名、函数名都可以随意使用以CMAKE_、_CMAKE_开头或以_后跟任意 CMake 命令名开头的标识符均被 CMake官方保留。本文基于 Help/manual/include/ID_RESERVE.rst 中的官方约定结合 CMake 源码与文档体系系统讲解保留标识符的三种规则、其背后的命名空间设计动机、以及项目代码应如何规避冲突帮助读者写出不踩命名雷区的 CMake 脚本。官方保留标识符的三条规则CMake 官方文档通过ID_RESERVE.rst这个共享 include 片段向读者明确声明了保留标识符的范围。该片段同时被两处权威文档引用Help/manual/cmake-language.7.rst#L582CMake 语言手册的「Variables」章节在介绍变量作用域与引用规则之后直接引入Help/manual/cmake-variables.7.rst#L17CMake 变量参考手册的开篇位置先于全部 828 个变量条目声明保留规则。被保留的标识符包含三类规则原文如下CMake reserves identifiers that: * begin with CMAKE_ (upper-, lower-, or mixed-case), or * begin with _CMAKE_ (upper-, lower-, or mixed-case), or * begin with _ followed by the name of any CMake Command.即规则前缀形式示例均为保留规则一CMAKE_大小写任意组合CMAKE_BINARY_DIR、cmake_binary_dir、Cmake_Source_Dir规则二_CMAKE_大小写任意组合_CMAKE_TOOLCHAIN_PREFIX、_CMAKE_OSX_ARCHITECTURES规则三_ 任意 CMake 命令名_message、_set、_add_executable需要注意三条规则都以「前缀匹配」为判定标准而不是精确匹配任何以这些前缀开头的标识符都在保留之列无论其后跟什么字符。规则一与规则二CMAKE_与_CMAKE_命名空间的含义CMAKE_*CMake 对外提供的公共变量命名空间CMAKE_前缀是 CMake 提供给项目代码读取的「公共 API」命名空间。CMake 内置的绝大多数信息型变量、行为控制变量都使用这一前缀例如目录信息CMAKE_SOURCE_DIR、CMAKE_BINARY_DIR、CMAKE_CURRENT_SOURCE_DIR、CMAKE_CURRENT_LIST_DIR编译器与工具链CMAKE_C_COMPILER、CMAKE_CXX_COMPILER、CMAKE_BUILD_TYPE、CMAKE_MAKE_PROGRAM平台与架构CMAKE_SYSTEM_NAME、CMAKE_SIZEOF_VOID_P、CMAKE_ANDROID_ARCH_ABI仅 Help/variable 目录下就有649 个以CMAKE_命名的变量文档如 CMAKE_SOURCE_DIR.rst、CMAKE_BUILD_TYPE.rst加上属性、缓存条目等这一命名空间承载着 CMake 全部公共状态。由于 CMake 官方文档明确「reserves」该命名空间项目代码不得自行定义任何以CMAKE_开头的变量、函数或宏。这是双向约定一方面保证 CMake 内置变量在项目中的值不被意外篡改例如项目若擅自set(CMAKE_BUILD_TYPE ...)会直接干扰 CMake 的构建类型逻辑另一方面保证项目自定义名称未来不会与 CMake 新增变量冲突。_CMAKE_*CMake 内部实现专用的「私有」命名空间_CMAKE_前缀是 CMake 内部实现使用的命名空间可以理解为「以下划线开头的私有 API」。与对外公开的CMAKE_*不同_CMAKE_*变量属于实现细节其名称、含义与生命周期可能随版本变化官方不保证稳定。这类变量在仓库源码中大量出现。例如在 Modules/CMakeDetermineCCompiler.cmake#L149-L179 中CMake 探测 C 编译器时使用了一系列_CMAKE_*内部变量保存临时状态# If the internal cmake variable _CMAKE_TOOLCHAIN_PREFIX is set, this is used # to prefix the compiler name, e.g. arm-none-eabi- if (NOT _CMAKE_TOOLCHAIN_LOCATION) get_filename_component(_CMAKE_TOOLCHAIN_LOCATION ${CMAKE_C_COMPILER} PATH) endif() if (NOT _CMAKE_TOOLCHAIN_PREFIX) ... set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1}) set(_CMAKE_TOOLCHAIN_SUFFIX ${CMAKE_MATCH_2})类似的内部变量还见于 Source/cmState.cxx#L677-L678其中 CMake 自身也维护_CMAKE_RUNNING_IN_BUILD_TREE之类的内部全局属性。这些_CMAKE_*名称全部属于保留范畴项目代码不应假设其存在、不应覆盖其值也不应仿照该前缀自行发明新变量——因为 CMake 内部实现可能在任意版本中占用同名标识符导致难以排查的冲突。规则三_ CMake 命令名的深层含义第三条规则比较隐蔽但同样重要以_开头、后跟任意 CMake 命令名的标识符也被保留。理解这一规则需要先明白 CMake 的文档结构。CMake 的全部命令command清单位于 Help/command 目录下共 148 个命令文档例如add_executable、set、message、foreach、function等。规则三的含义是_add_executable、_set、_message、_foreach、_function这类名字同样不能由项目使用。从命名设计角度看这条规则为 CMake 及其生态保留了「下划线 命令名」的命名空间常见动机包括辅助/包装函数许多项目习惯用_前缀命名内部辅助函数如_add_exe但如果辅助函数名恰好是_ 真实命令名就与保留规则冲突命令前向声明的潜在扩展CMake 未来可能为某个命令引入带下划线前缀的关联实体如同名命令的底层实现、内部宏等保留该命名空间可避免破坏现有项目与命令名产生歧义用户若定义function(_message ...)在阅读与调试时极易与内置命令message(...)混淆。因此项目代码在命名自己的函数、宏和变量时应避免「_ 已存在的 CMake 命令名」这一组合。完整的命令名清单可查阅 Help/command 下的 148 个命令文档如 add_executable.rst、set.rst、function.rst。更广泛意义上的「保留名称」从源码看 CMake 的保护机制保留标识符并非文档层面的空泛约定CMake 源码中有多处对应的运行时校验逻辑从实现上印证了「保留」二字的实际含义。目标名保留列表在 Source/cmGlobalGenerator.cxx#L4039-L4052 中cmGlobalGenerator::IsReservedTarget()维护了一份被各生成器占用的目标名列表static cm::static_string_view const reservedTargets[] { all_s, ALL_BUILD_s, help_s, install_s, INSTALL_s, preinstall_s, clean_s, edit_cache_s, rebuild_cache_s, ZERO_CHECK_s };任何add_executable、add_library、add_custom_target若试图使用这些名字CMake 会通过CheckReservedTargetName见 Source/cmGlobalGenerator.cxx#L3327-L3345报错。相关调用点见 cmAddExecutableCommand.cxx#L62、cmAddLibraryCommand.cxx#L153、cmAddCustomTargetCommand.cxx#L165。源码注释还特别提醒「Adding additional targets to this list will require a policy!」向该列表新增条目需要引入新策略可见保留名单的扩展极为慎重。规则名保留模式类似地在 Source/cmGeneratorRule.cxx#L32-L134 中自定义规则rule也维护了一份保留模式列表std::vectorcm::string_view ReservedPatterns{ RULE_s, ... };规则名匹配到ReservedPatterns中的模式时会被拒绝。此外 cmAddCustomRuleCommand.cxx#L29-L34 中还有独立的IsReservedName()校验用于拒绝纯大写/特殊字符构成的规则名。这些机制表明CMake 通过「文档声明 源码强校验」双层手段维护自己的命名空间而ID_RESERVE.rst正是这一整体策略在变量与标识符层面的权威声明。项目实践建议如何避开保留标识符综合官方约定与源码实现给项目开发者的命名建议如下绝不定义任何CMAKE_*变量。即使当前 CMake 版本没有同名变量未来版本也可能占用且set(CMAKE_* ...)极易干扰 CMake 内置逻辑如篡改CMAKE_BUILD_TYPE、CMAKE_CXX_STANDARD会改变整个构建行为。绝不定义任何_CMAKE_*变量。该命名空间属于 CMake 内部实现跨版本不稳定项目一旦依赖即埋下兼容性隐患。避免_ 命令名的组合。命名辅助函数时可使用项目前缀如myproject_add_library、_myproject_util而不是_add_library。命名空间自持推荐为自定义函数、宏统一加项目专属前缀如PROJECTNAME_既规避保留规则又提升脚本可读性。保留规则同时适用于变量、函数与宏名function()、macro()定义的名称同样受ID_RESERVE.rst约束因为它们是 CMake 语言中的「标识符」。小结ID_RESERVE.rst虽仅有寥寥数行却是 CMake 标识符命名规范的核心声明并被同时收录进 CMake 语言手册与变量参考手册CMAKE_*CMake 公共变量命名空间Help/variable 下 649 个文档项目只读、不得定义_CMAKE_*CMake 内部实现命名空间如 Modules/CMakeDetermineCCompiler.cmake 中的_CMAKE_TOOLCHAIN_PREFIX项目不得占用_ 命令名CMake 命令关联命名空间命令清单见 Help/command项目不得使用。理解并遵守这三条前缀规则是编写健壮、可长期维护的 CMake 脚本的基本功——它能避免与 CMake 内置功能意外冲突也能让项目在 CMake 版本升级时不受保留名称扩展的波及。赞分享构建工具开发工具CLI【免费下载链接】CMakeMirror of CMake upstream repository项目地址https://gitcode.com/gh_mirrors/cm/CMake点击查看免费下载相关推荐yuzu在 PC 上免费跑 Switch 游戏从装到出画面一次讲清yuzu在 PC 上免费跑 Switch 游戏从装到出画面一次讲清 昨晚 Switch 底座 HDMI 线松了你想直接在大屏 PC 上接着打。yuzu 就虚拟化桌面应用图形学CMake变量命名规范从CMAKE_到PROJECT_的命名最佳实践CMake变量命名规范从CMAKE_到PROJECT_的命名最佳实践 在CMake项目开发中变量命名不仅关系到代码的可读性更直接影响项目的可维护性和团队协构建工具开发工具CLIlibui 名称保留契约ui / uipriv 前缀体系与跨平台符号命名规范全解析libui 名称保留契约ui / uipriv 前缀体系与跨平台符号命名规范全解析 libui 是一套使用各平台原生 GUI 技术实现的可移植 C 图形库为桌面应用UI组件上一篇drawio-desktop 免费导入 VSDX 文件跨平台编辑 Visio 图表的完整指南下一篇RR引导终极部署指南5分钟快速搭建专业NAS系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考