当我们使用 CMake 工具
编译项目的 CMakeLists.txt
存在两个问题。
第一个问题是 CMake 工具版本太旧,
第二个问题是 CMake 工具版本太新。
CMake 工具版本太旧的话,可能 CMakeLists.txt
使用了新的语法,就会不兼容;
CMake 工具版本太新的话,也会出现不兼容问题,因为 CMake 新版本在更新时 不一定向后兼容,CMake 老版本的一些功能可能删除、更改。
如果我们使用了 CMake 新的语法
如果我们使用了 CMake 新的语法
,那么需要通过 cmake_minimum_required()
命令限制 CMake 最低版本需求
。
如果 CMake 运行的版本
不在 <min>...<max> 版本
之间,会报错。
cmake_minimum_required()
命令,语法如下:
cmake_minimum_required(VERSION <min>[...<max>] [FATAL_ERROR])
<min>
与 <max>
表示 CMake 版本区间
,每个 CMake 版本
由 major.minor[.patch[.tweak]]
的组成。
FATAL_ERROR
选项,在 CMake 2.6
及更高版本忽略。如果使用 CMake 2.4
及耕地版本,失败时,显示错误,而不仅仅是警告。
使用 cmake_minimum_required()
命令,会隐式调用 cmake_policy(VERSION)
命令,指定版本引入的所有策略都将设置为 NEW
行为。
cmake_policy()
命令有多种形式,关于设置全局策略,语法如下
cmake_policy(VERSION <min>[...<max>])
例如,我们由于使用了新版本的语法,CMake 版本
最低为 3.0
。
cmake_minimum_required(VERSION 3.0)
# 相当于调用了
cmake_policy(VERSION 3.0)
例如,在上面例子上,加上最高版本为 3.7
。
cmake_minimum_required(VERSION 3.0...3.7)
# 相当于调用了
cmake_policy(VERSION 3.0...3.7)
如果 CMake 运行的版本
在 <min>...<max> 版本
或 更早版本
中,引入的所有策略都将设置为 NEW
行为。高于设置的版本,引入所有的策略都将取消设置。
只有通过 cmake_policy()
显示设置策略,才会有用。如果需要运行 的 CMake 版本
高于 3.0
,但是引入的策略为 CMake 版本
在 3.0
和 3.5
之间。
cmake_minimum_required(VERSION 3.0)
cmake_policy(VERSION 3.0...3.5)
策略中 NEW
与 OLD
的区别
例如,我们在 CMake 3.0
版本中,引入策略 CMP0048
。表示在 CMake 3.0
版本中,引入 project()
命令使用 VERSION
设定版本。
默认情况下,cmake-3.19.2
会启用策略 CMP0048
。如果不想使用该策略,通过 cmake_policy
命令设置为 OLD
。一般设置该策略为 OLD
,如果在 project()
命令使用 VERSION
会报错。
if(POLICY CMP0048)
cmake_policy(SET CMP0048 OLD)
endif()
通过 cmake_policy
命令设置为 NEW
,使用该策略。
if(POLICY CMP0048)
cmake_policy(SET CMP0048 NEW)
endif()
上述是通过 显示设置策略,通过给定策略使用 OLD
或 NEW
行为,语法如下。
cmake_policy(SET CMP<NNNN> NEW)
cmake_policy(SET CMP<NNNN> OLD)
更多策略参考 cmake-policies(7)
避免策略兼容性警告
我们虽然指定了 CMake 最低运行版本
,但是源文件使用了高于 CMake 版本
的语法,但是我们不想为了使用了 新的语法
,而更改 cmake_minimum_required()
命令,那么怎么做?
对于一些不重要的策略,可以使用一种兼容的手段。如果运行的 CMake 版本
足够,支持该策略,那么设置为 NEW
行为,因为使用 cmake_minimum_required()
命令通过隐式设置的最新策略为 OLD
行为;如果运行的 CMake 版本
不足够,不支持该策略,那么什么都不做。
cmake_minimum_required(VERSION 2.6)
if(POLICY CMP0048)
cmake_policy(SET CMP0048NEW)
endif()
如果 CMake
运行版本虽然高于 3.0
,但是因为使用 cmake_minimum_required(VERSION 2.6)
指定策略版本为 2.6
,CMP0048
策略是 CMake 3.0
引入的,用兼容性语法,不会发出兼容性警告。
检查策略设置
cmake_policy(GET)
检查策略是否设置为 OLD
或 NEW
行为,如果未设置策略,返回 空。
cmake_policy()
命令检查策略设置,语法如下:
cmake_policy(GET CMP<NNNN> <variable>)
CMake 策略堆栈
CMake
将策略设置
保存在一个栈结构
中,当进入
一个项目
的子目录
时,就会在策略栈
中入栈
新的一层元素
,离开子目录时就会出栈
这层元素
。因此在一个项目
的子目录
中设置策略
并不会影响父目录
以及同层路径
,但会影响子目录
。
这在一个项目
包含了多个分别维护的子目录
但在一起编译时非常有用
,它可以让不同的子目录
使用不同的策略版本
。
用户可以使用 cmake_policy 命令
来入栈出栈
自己的临时策略层
,只要入栈
和出栈
是成对出现
的,这对于临时对一小段代码改变策略设置时比较有用。
cmake_policy (PUSH)
#change cmake policy
#do something
cmake_policy (POP)