- 构建工具
- 开发工具
- CLI
【免费下载链接】CMake
Mirror of CMake upstream repository
CMake 策略 CMP0106 于 CMake 3.18 引入,宣布随 CMake 发行的Documentation模块被移除:该模块原本是 CMake 为 VTK 项目提供的文档构建支持机制,其缓存变量与依赖查找逻辑与 VTK 深度耦合。本文以 CMP0106.rst 为骨架,结合当前仓库中该策略的注册代码、include()命令的模块拦截实现以及模块本体源码,说明 OLD/NEW 两种行为的具体差异、策略的触发与警告路径,并给出面向普通项目的迁移与设置方法,帮助读者在升级 CMake 时正确处置include(Documentation)调用。
策略背景:一个为 VTK 量身定做的模块
Documentation模块最初并非通用工具,而是 CMake 为 VTK 项目提供文档构建支持而添加的机制,其内容专门针对 VTK 的文档框架做了调优。按照 CMP0106.rst 的说明,CMake 不再随自身发行这个带有"过时 VTK 模式"(now old VTK patterns)的模块,而是由 CMake 自己将其标记为废弃。
从仓库中 Modules/Documentation.cmake 的旧逻辑可以看到它的真实面貌:当BUILD_DOCUMENTATION选项开启后,模块会依次find_package()查找UnixCommands、Doxygen、Gnuplot、HTMLHelp、Perl、Wget等一系列与文档生成链条相关的工具,并定义DOCUMENTATION_HTML_HELP、DOCUMENTATION_HTML_TARZ等缓存选项——这些依赖集合正是围绕 VTK 的文档流水线设计的,对绝大多数普通项目毫无意义。
OLD 与 NEW 行为对比
策略的核心分歧在于include(Documentation)被调用时会发生什么:
| 行为 | 效果 |
|---|---|
OLD | 模块正常加载:添加BUILD_DOCUMENTATION、DOCUMENTATION_HTML_HELP、DOCUMENTATION_HTML_TARZ等缓存变量,并查找 VTK 文档所依赖的包(Doxygen、Perl、Wget 等) |
NEW | 模块被视为空模块:不添加任何缓存变量,不查找任何包,include(Documentation)实际不产生任何副作用 |
需要注意,策略文档中"NEW 行为是充当空模块"的表述,在实现层面体现为两层机制:
include()层面的拦截:在 Source/cmIncludeCommand.cxx 中,Documentation被登记在DeprecatedModules映射表内,对应cmPolicies::CMP0106。当include(Documentation)解析到系统模块时(同一文件),若策略状态为NEW,模块文件路径会被置空(mfile = ""),即模块根本不会被加载,等价于空操作。- 模块本体层面的防护:
Modules/Documentation.cmake开头通过cmake_policy(GET CMP0106 ...)读取策略,若为NEW会直接message(FATAL_ERROR)拒绝执行,提示该逻辑应随使用它的项目一同分发,而非由 CMake 提供。
策略如何被触发:警告与未设置状态
CMP0106 在 Source/cmPolicies.h 中以WARN状态注册,版本为 3.18:
SELECT(POLICY, CMP0106, "The Documentation module is removed.", 3, 18, 0, WARN)按照 STANDARD_ADVICE.rst 的通用规则:该策略由cmake_policy或cmake_minimum_required设置;若项目未显式设置,CMake 会发出警告并采用 OLD 行为。
在实际行为中,include()命令在策略处于WARN状态时会调用IssuePolicyWarning(见 Source/cmIncludeCommand.cxx)。而Modules/Documentation.cmake内部对未设置状态还有一处"VTK 特赦":如果检测到项目自身就是 VTK(CMAKE_PROJECT_NAME或PROJECT_NAME为VTK),则抑制警告,避免干扰 VTK 自身的构建;对非 VTK 项目则照常告警(Modules/Documentation.cmake)。
如何设置与迁移
方式一:通过cmake_minimum_required按版本启用
策略机制的设计原则是"按 CMake 版本批量设置",而不是逐个开关。在顶层CMakeLists.txt开头使用:
cmake_minimum_required(VERSION 3.18)此时 CMake 会把 3.18 及之前引入的所有策略(含 CMP0106)设置为 NEW 行为。若要保留较低的最低版本、同时按策略上限启用新行为,可写成cmake_minimum_required(VERSION 3.10...3.18)形式,详见 cmake_minimum_required.rst 对<min>[...<policy_max>]语法的说明。
方式二:显式cmake_policy(SET)
需要局部或逐个控制时使用:
if(POLICY CMP0106) cmake_policy(SET CMP0106 NEW) endif()相关命令的完整签名(SET、GET、PUSH/POP)见 cmake_policy.rst。注意cmake_policy作用于策略栈顶,include()和find_package()加载的脚本默认拥有独立策略作用域,除非显式指定NO_POLICY_SCOPE。
方式三:命令行缓存变量(不改项目文件)
用户在不修改项目的前提下,可在cmake命令行传入缓存变量压制警告:
cmake -DCMAKE_POLICY_DEFAULT_CMP0106=NEW ...该做法与cmake -DCMAKE_POLICY_DEFAULT_CMP0990=OLD的通用形式一致,见 cmake-policies.7.rst 的"Transition Schedule"一节。
迁移建议:把 VTK 专用逻辑带回项目自身
CMP0106 给出的方向非常明确:文档构建这类与具体项目强相关的逻辑,"最好随使用它的项目一起分发,而不是放在 CMake 里"。对仍依赖旧行为的项目,建议把Modules/Documentation.cmake中的相关逻辑(BUILD_DOCUMENTATION选项、Doxygen/Perl/Wget 查找等)复制到项目自己的模块目录,通过CMAKE_MODULE_PATH引入,并移除对include(Documentation)的依赖。
OLD 行为的寿命:废弃时间线
正如 DEPRECATED.rst 所强调的,策略的OLD行为"按定义即已废弃",可能在未来版本中被移除。通用时间线(见 cmake-policies.7.rst):
- 策略引入 2 年后,显式设置
OLD的版本可能开始警告其将被移除; - 策略引入 6 年后,主版本号更高的 CMake 可能直接报错,拒绝继续使用
OLD行为。
因此,长期维护的项目不应停留在OLD/警告静默阶段,而应尽早迁移到NEW行为或自维护文档模块。从当前仓库的 cmake-policies.7.rst 策略清单可见,CMP0106 与 CMP0107、CMP0108 等一同列于"CMake 3.18 引入的策略"分组中;同时该清单也展示了本仓库已演进至包含 CMake 4.x 时代策略的较新开发版本,CMP0106 的 OLD 行为正在逐步走向淘汰边缘。
常见问题速查
- 为什么
include(Documentation)现在会警告?因为策略未设置时默认走 OLD 并告警;设置NEW后模块不再加载。 - 我是普通项目,用不到 VTK 文档,怎么处理?直接让项目版本不低于 3.18(
cmake_minimum_required(VERSION 3.18)),或显式cmake_policy(SET CMP0106 NEW)。 - 我是 VTK 或基于 VTK 的文档项目怎么办?若项目名恰为
VTK可免于警告;否则把模块逻辑搬入项目自身,或临时设置OLD并规划迁移。 NEW行为下模块还会报 FATAL_ERROR 吗?通过include(Documentation)正常加载时,模块在NEW下根本不会被执行(被include()拦截为空);仅当模块文件被其他方式直接执行且策略为NEW时,其内部才会触发致命错误,这是模块自带的二次防护。
延伸阅读
- 策略文档正文:Help/policy/CMP0106.rst
- 模块源码(含 OLD 行为实现):Modules/Documentation.cmake
- 模块文档入口:Help/module/Documentation.rst
- 策略注册表(
SELECT(POLICY, CMP0106, ...)):Source/cmPolicies.h include()对废弃模块的拦截实现:Source/cmIncludeCommand.cxx- 策略机制总览与过渡时间线:Help/manual/cmake-policies.7.rst
- 策略设置命令:Help/command/cmake_policy.rst、Help/command/cmake_minimum_required.rst
- 构建工具
- 开发工具
- CLI
【免费下载链接】CMake
Mirror of CMake upstream repository
相关推荐
CMake 的 Documentation 模块与 CMP0106 策略:VTK 专属文档框架的废弃与迁移指南
CMake 的 Documentation 模块与 CMP0106 策略:VTK 专属文档框架的废弃与迁移指南 导读 本文围绕 CMake 仓库中已废弃的 Do
构建工具开发工具CLICMake 策略 CMP0120 详解:WriteCompilerDetectionHeader 模块的移除与迁移实践
CMake 策略 CMP0120 详解:WriteCompilerDetectionHeader 模块的移除与迁移实践 导读 本文围绕 CMake 3.20 引
构建工具开发工具CLICMake 策略 CMP0196 解析:CMakeDetermineVSServicePack 模块移除与迁移指南
CMake 策略 CMP0196 解析:CMakeDetermineVSServicePack 模块移除与迁移指南 CMP0196 是 CMake 4.1 引入
构建工具开发工具CLI
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考