Cmake命令之cmake_policy

2023-08-24  本文已影响0人  Domibaba

CMake中的策略机制是用来保证多个版本之间的后向兼容性,也就是当新版本的CMake在某些特性上有变更时,如何对已有构建工程保持兼容的一种手段。当引入新的策略时,新的CMake版本会对后向兼容行为发出告警,可以通过显式的在策略中指定OLD(保持后向兼容行为)来禁止告警,或者在策略中指定NEW(不后向兼容)也会禁止告警,不过NEW会放弃后向兼容。

策略的定义形式

通过CMP<NNNN>形式来唯一定义一个策略,例如CMake3.23版本,定义的策略有130个,从CMP0000CMP0129

如何在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>来将策略的行为设置为OLDNEWcmake -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(VERSION 3.10)
 PROJECT(policy_test)
 CMAKE_POLICY(GET CMP0072 var)
 MESSAGE("CMP0072 behavior is: ${var}")
> 输出结果:
> `CMP0072 behavior is:`

2)对于策略CMP0072cmake_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`
    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`
    # 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选项来控制策略的传递范围。


附录:参考文档

  1. https://cmake.org/cmake/help/latest/command/cmake_policy.html

  2. https://cmake.org/cmake/help/latest/manual/cmake-policies.7.html#manual:cmake-policies(7)

上一篇 下一篇

猜你喜欢

热点阅读