CMake
中的策略机制是用来保证多个版本之间的后向兼容性,也就是当新版本的CMake
在某些特性上有变更时,如何对已有构建工程保持兼容的一种手段。当引入新的策略时,新的CMake
版本会对后向兼容行为发出告警,可以通过显式的在策略中指定OLD
(保持后向兼容行为)来禁止告警,或者在策略中指定NEW
(不后向兼容)也会禁止告警,不过NEW
会放弃后向兼容。
策略的定义形式
通过
CMP<NNNN>
形式来唯一定义一个策略,例如CMake
的3.23
版本,定义的策略有130
个,从CMP0000
到CMP0129
。
如何在CMake
中设置策略
每个策略都有
OLD
(保持后向兼容性)和NEW
(不保持后向兼容性)两个值,可以通过如下两种方式来设置:
- 通过
cmake_policy
命令针对单个策略进行设置:cmake_policy(SET CMP<NNN> NEW)
或cmake_policy(SET CMP<NNN> OLD)
;
- 通过
cmake_policy
命令针对指定的版本区间进行设置:cmake_policy(VERSION <min>[...<max>] NEW)
或cmake_policy(VERSION <min>[...<max>] NEW)
,其中版本区间的<max>
是可选的;
- 在命令行中通过
CMAKE_POLICY_DEFAULT_CMP<NNN>
来将策略的行为设置为OLD
或NEW
:cmake -DCMAKE_POLICY_DEFAULT_CMP<NNNN>=NEW .
或cmake -DCMAKE_POLICY_DEFAULT_CMP<NNNN>=OLD .
。
注意:策略机制不是一个可靠的功能开关,也不建议将其设置为OLD
,在将来的版本中可能会使用错误来替代当前的告警提示。
一些示例说明
本文所使用的相关软件版本:
软件名称 | 软件版本 |
---|---|
Linux操作系统 | Ubuntu 22.04 LTS |
cmake | 3.22.1 |
-
cmake_minimum_required
命令除了在CMake
版本过低时产生一条错误之外,它还会隐式地调用make_policy
,将该命令中指定的CMake
版本及之前版本引入的策略都设置为NEW
。举个例子:CMP0072
这个策略是在3.11
版本中引入,因此如果cmake_minimum_required
中的版本大于等于3.11
时,CMP0072
会被默认置为NEW
,当cmake_minimum_required
中的版本小于3.11
时,CMP0072
则是未定义的。1)对于策略
CMP0072
,cmake_minimum_required
指定版本小于3.11
时,本文例子中为3.10
,该策略的值是未定义(空)
CMAKE_MINIMUM_REQUIRED(VERSION 3.10)
PROJECT(policy_test)
CMAKE_POLICY(GET CMP0072 var)
MESSAGE("CMP0072 behavior is: ${var}")
> 输出结果:
> `CMP0072 behavior is:`
2)对于策略CMP0072
,cmake_minimum_required
指定版本大于等于3.11
时,本文例子中为3.20
,该策略的值是NEW
CMAKE_MINIMUM_REQUIRED(VERSION 3.20)
PROJECT(policy_test)
CMAKE_POLICY(GET CMP0072 var)
MESSAGE("CMP0072 behavior is: ${var}")
> 输出结果:
> `CMP0072 behavior is: NEW`
- 可以通过判断策略是否存在的方式,使用
if
命令(if命令可以参考这里)判断,并通过cmake_policy
来显示的将策略设置为NEW
。
CMAKE_MINIMUM_REQUIRED(VERSION 3.10)
PROJECT(policy_test)
CMAKE_POLICY(GET CMP0072 var)
MESSAGE("CMP0072 behavior is: ${var}")
if(POLICY CMP0072)
CMAKE_POLICY(SET CMP0072 NEW)
endif()
CMAKE_POLICY(GET CMP0072 var)
MESSAGE("Finally CMP0072 behavior is: ${var}")
> 输出结果:
> `CMP0072 behavior is: Finally CMP0072 behavior is: NEW`
-
CMP0000
:必须指定CMake
的最小要求版本,在2.6
版本中引入。默认情况下必须在CMakeLists.txt
的第一行调用cmake_minimum_required
命令指定要求的最小CMake
版本,如果没有指定,则会报错。1)如果未调用
cmake_minimum_required
,默认情况下会报错
# CMakeLists.txt文件内容
PROJECT(policy_test)
> 输出结果:
> CMake Error in CMakeLists.txt: No cmake_minimum_required command is present. A line of code such as
> `cmake_minimum_required(VERSION 3.22)`
> should be added at the top of the file. The version specified may be lower if you wish to support older CMake versions for this project. For more information run "cmake --help-policy CMP0000".
2)我们可以使用cmake -DCMAKE_POLICY_DEFAULT_CMP0000=OLD .
来禁止这个策略,不需要指定最小版本(CMakeLists.txt
的第一行不调用cmake_minimum_required
命令),但是CMake
仍然会产生一条告警
# CMakeLists.txt文件内容
PROJECT(policy_test)
CMAKE_POLICY(GET CMP0072 var)
MESSAGE("CMP0072 behavior is: ${var}")
# 命令行中调用
cmake -DCMAKE_POLICY_DEFAULT_CMP0000=OLD .
> 输出结果:
> CMP0072 behavior is:
> CMake Warning: Manually-specified variables were not used by the project:
> `CMAKE_POLICY_DEFAULT_CMP000`
需要注意的是,某些场景下设置策略是受约束的,设置的策略行为不会传递到上层范围。例如,通过include()
或者find_package()
命令调用包含的文件中,如果有使用cmake_policy
,该策略是不会影响到命令的调用者。当然,这两个命令都可以通过NO_POLICY_SCOPE
选项来控制策略的传递范围。
网友评论