当我们使用 CMake工具编译项目的 CMakeLists.txt 存在两个问题。
CMake 工具版本太旧的话,可能 CMakeLists.txt 使用了新的语法,就会不兼容;
CMake 工具版本太新的话,也会出现不兼容问题,因为 CMake 新版本在更新时 不一定向后兼容,CMake 老版本的一些功能可能删除、更改。
为了解决这些差异,保证我们的cmake代码始终可用,cmake 从版本2.0开始提出了policy这个概念。
使用语法:
CMP< NNNN >
的标识符,
对应四个0到9的整数。每个策略都在文档中描述了OLD和NEW的行为,以及引入的原因。1 cmake_policy(VERSION
[... ]) //通过版本来设置策略
使用场景:
CMake 新的语法
,那么需要通过 cmake_minimum_required()
命令限制 CMake 最低版本需求。...
版本 之间,会报错。关于cmake_minimum_required和cmake_policy:
调用cmake_minimum_required
会隐式调用cmake_policy(VERSION)
,指定版本引入的所有策略都将设置为 NEW 行为。
如果没有特别的策略要指定,可以直接通过调用cmake_minimum_required
即可,无需调用cmake_policy。
使用示例:
cmake_minimum_required(VERSION 3.0)
# 相当于调用了
cmake_policy(VERSION 3.0)
cmake_minimum_required(VERSION 3.0...3.7)
# 相当于调用了
cmake_policy(VERSION 3.0...3.7)
cmake_minimum_required(VERSION 3.0)
cmake_policy(VERSION 3.0...3.5)
也可以直接使用cmake_policy显示设置策略的行为,为OLD或为NEW。如下:
// 使用 NEW 来声明后续代码依赖于此policy。
cmake_policy(SET CMP NEW)
// 使用OLD来向使用此policy的配置过程发出警告信息。
cmake_policy(SET CMP OLD)
告诉CMake对给定的策略使用旧的或新的行为。
注意:策略的OLD行为一般不可取,因为在未来的版本中可能被抛弃。
// 使用GET来获取当前支持的policy。
cmake_policy(GET CMP )
检查策略是否设置为 OLD 或 NEW 行为,值存放到< variable >中。如果没有设置,那么< variable >为空
使用此条件来判断当前的cmake是否支持某条policy。
cmake_policy (PUSH)
#change cmake policy
#do something
cmake_policy (POP)
// PUSH和POP必须是成对的。
说明:
向一个CMakeLists.txt中添加以下内容(new表示后继代码必须支持此策略):
cmake_policy(SET CMP9999 NEW) # CMP9999 is not defined yet
会发现报错:
> [CMake] CMake Error at CMakeLists.txt:14 (cmake_policy):
1> [CMake] Policy "CMP9999" is not known to this version of CMake.
例如,我们在 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()
注意,如果你想要查询CMP0048 之类的是什么行为,去官网找吧
当前场景:
cmake_minimum_required(VERSION 2.6)
指定策略版本为 2.6,但是我们要使用cmake 3.0
版本引入的CMP0048
怎么办?也就是说:
解决方法:
cmake_minimum_required(VERSION 2.6)
if(POLICY CMP0048)
cmake_policy(SET CMP0048NEW)
endif()
说明:
cmake_policy(PUSH)
cmake_policy(SET CMP0057 NEW)
...
if (SOME_ITEM IN_LIST SOME_LIST) # IN_LIST needs CMP0057
...
cmake_policy(POP)
当使用不支持此policy的cmake版本configure时,cmake会报错并终止configure流程:
1> [CMake] CMake Error at CMakeProject1/CMakeLists.txt:15 (cmake_policy):
1> [CMake] Policy "CMP0057" is not known to this version of CMake.
我们可以使用此方式来声明该段代码必须使用支持此policy的cmake版本。注意作用域仅限于此段代码。
cmake_policy(PUSH)
cmake_policy(VERSION 3.15)
list(PREPEND SOME_LIST ${SOME_ITEM}) # PREPEND needs cmake 3.15
cmake_policy(POP)
当使用低于此version的cmake版本configure时,cmake会报错并终止configure流程:
1> [CMake] CMake Error at CMakeProject1/CMakeLists.txt:15 (cmake_policy):
1> [CMake] An attempt was made to set the policy version of CMake to "3.15" which is
1> [CMake] greater than this version of CMake. This is not allowed because the
1> [CMake] greater version may have new policies not known to this CMake. You may
1> [CMake] need a newer CMake version to build this project.
当某个cmake feature没有设置特定的policy时,我们可以使用此方式来声明该段代码必须使用不低于这个版本的cmake。注意作用域仅限于此段代码。