$<...> $<>

本文详细解释了CMake的配置和生成步骤,重点介绍了生成器表达式如何在多配置环境中的应用,以及如何利用它们进行条件逻辑、提供目标信息和处理目标文件路径。
摘要由CSDN通过智能技术生成

CMake生成器表达式$<…>

当运行CMake时,开发人员倾向于认为它是一个简单的步骤,需要读取项目的CMakeLists.txt文件,并生成相关的特定于生成器的项目文件集(例如Visual Studio解决方案和项目文件,Xcode项目,Unix Makefiles或Ninja输入文件)。然而,这涉及两个截然不同的步骤。当运行CMake时,输出日志的末尾通常看起来像这样:

-- Configuring done
-- Generating done
-- Build files have been written to: /some/path/build

​ 当CMake被调用时,它首先读取并处理源树顶部的CMakeLists.txt文件,包括它拉进来的任何其他文件。在执行命令、函数等时,创建项目的内部表示。这称为配置步骤。控制台日志的大部分输出都是在此阶段生成的,包括message()命令的任何内容。在configure步骤的末尾,–configure done消息被打印到日志中。

​ 一旦CMake完成了读取和处理CMakeLists.txt文件,它就会执行生成步骤。这是使用在配置步骤中构建的内部表示创建构建工具的项目文件的地方。在大多数情况下,开发人员倾向于忽略生成步骤,只是将其视为配置的最终结果。控制台日志几乎总是在配置步骤完成后立即显示–Generating done消息,所以这是可以理解的。但在某些情况下,将其分为两个不同的阶段尤为重要。

​ 考虑一个项目处理一个多配置的CMake生成器,如Xcode或Visual Studio。当读取CMakeLists.txt文件时,CMake并不知道要为哪个配置构建目标。这是一个多配置的设置,所以有不止一个选择(例如调试,发布,等等)。开发人员在构建时选择配置,在CMake完成之后。如果CMakeLists.txt文件想要做一些事情,比如将文件复制到与给定目标的最终可执行文件相同的目录中,这似乎会出现一个问题,因为该目录的位置取决于正在构建的配置。需要一些占位符来告诉CMake“对于正在构建的任何配置,使用最终可执行文件的目录”。

​ 这是生成器表达式提供的功能的一个主要示例。它们提供了一种对某些逻辑进行编码的方法,这些逻辑在配置时不会计算,而是推迟到项目文件被写入时的生成阶段。它们可以用来执行条件逻辑,输出字符串,提供关于构建的各个方面的信息,如目录、名称、平台细节等。它们甚至可以用于根据正在执行的构建或安装提供不同的内容。

9.1 简单的布尔逻辑
​ 生成器表达式不能在任何地方使用,但是在很多地方都支持它们。在CMake参考文档中,如果一个特定的命令或属性支持生成器表达式,文档中会提到它。随着时间的推移,支持生成器表达式的属性集已经扩展,一些CMake版本也扩展了支持的表达式集。项目应该确认,对于他们所需要的最小CMake版本,被修改的属性确实支持所使用的生成器表达式。

​ 使用语法$<…>指定一个生成器表达式,其中尖括号之间的内容可以采用几种不同的形式。很快就会清楚,一个基本特征是有条件地包含内容。下面是最基本的生成器表达式:

$<1:...>
$<0:...>
$<BOOL:...>

​ 对于 < 1 : … > ,表达式的结果将是 … 部分,而对于 <1:…>,表达式的结果将是…部分,而对于 <1:>,表达式的结果将是部分,而对于<0:…>,…部分将被忽略,表达式将产生一个空字符串。 $BOOL:…表达式可以用来将任何被CMake识别为布尔型假值的值转换为0,其他值转换为1。这些生成器表达式一起提供了一种简单而强大的方法来选择性地包含内容。还支持逻辑操作:

$<AND:expr[,expr...]>
$<OR:expr[,expr...]>
$<NOT:expr>

​ 每个expr的值预期为1或0。AND和OR表达式可以接受任意数量的逗号分隔参数,并提供相应的逻辑结果,而NOT只接受一个表达式,并将产生其参数的否定。因为AND、OR和NOT要求它们的表达式的值只能为0或1,所以考虑将这些表达式封装在$中,以强制对被认为是true或false的表达式进行更宽容的逻辑处理。

​ 在CMake 3.8及以后的版本中,IF -then-else逻辑也可以非常方便地用一个专用的$表达式来表达:

$<IF:expr,val1,val0>

​ 通常,expr的值必须为1或0。如果expr的值为1,则结果为val1;如果expr的值为0,则结果为val0。在CMake 3.8之前,等价的逻辑必须以以下更冗长的方式表示,需要给出两次表达式:

$<expr:val1>$<$<NOT:expr>:val0>

​ 生成器表达式可以嵌套,允许构造任意复杂度的表达式。上面的例子显示了一个嵌套的条件,但是生成器表达式的任何部分都可以嵌套。下面的例子演示了到目前为止所讨论的特性:

Expression	Result	Notes
$<1:foo>	foo	
$<0:foo>		
$<true:foo>		Error, not a 1 or 0
$<$<​BOOL:true>:foo>	foo	
$<$<​NOT:0>:foo>	foo	
$<$<NOT:1>:foo>		
$<$<NOT:tree>:foo>	foo	Error, NOT requires a 1 or 0
$<$<AND:1,0>:foo>		
$<$<OR:1,0>:foo>	foo	
$<1:$<$<BOOL:false>:foo>>		
$<IF:$<BOOL:${foo}>,yes,no>	Result will be yes or no depending on ${foo}	

​ 就像if()命令一样,CMake也支持在生成器表达式中测试字符串、数字和版本,尽管语法略有不同。如果满足各自的条件,下列所有项的值都为1,否则为0。

$<STREQUAL:string1,string2>
$<EQUAL:number1,number2>
$<VERSION_EQUAL:version1,version2>
$<VERSION_GREATER:version1,version2>
$<VERSION_LESS:version1,version2>

​ 另一个非常有用的条件表达式是测试构建类型:

$<CONFIG:arg>

​ 如果arg对应于实际正在构建的构建类型,那么它的值将为1,对于所有其他构建类型,它的值将为0。它的常用用途是仅为调试构建提供编译器标志,或者为不同的构建类型选择不同的实现。例如:

add_executable(myApp src1.cpp src2.cpp)
# Before CMake 3.8
target_link_libraries(myApp PRIVATE
  $<$<CONFIG:Debug>:checkedAlgo>
  $<$<NOT:$<CONFIG:Debug>>:fastAlgo>
)
# CMake 3.8 or later allows a more concise form
target_link_libraries(myApp PRIVATE
  $<IF:$<CONFIG:Debug>,checkedAlgo,fastAlgo>
)

​ 上面会将可执行文件链接到用于调试构建的checkedAlgo库,以及用于所有其他构建类型的fastAlgo库。$CONFIG:… 生成器表达式是健壮地提供这种功能的唯一方法,它适用于所有的CMake项目生成器,包括像Xcode或Visual Studio这样的多配置生成器。

​ CMake提供了更多的基于平台和编译器细节、CMake策略设置等的条件测试。开发人员应该查阅CMake参考文档,了解支持的条件表达式的完整集合。

9.2 目标的细节
​ 生成器表达式的另一个常见用途是提供关于目标的信息。目标的任何属性都可以通过以下两种形式之一获得:

$<TARGET_PROPERTY:target,property>
$<TARGET_PROPERTY:property>

1
2
​ 第一个表单提供来自指定目标的命名属性的值,而第二个表单将从使用生成器表达式的目标检索属性。

​ 虽然TARGET_PROPERTY是一种非常灵活的表达式类型,但它并不总是获取目标信息的最佳方式。例如,CMake还提供了其他表达式,它们提供了关于目标构建的二进制文件的目录和文件名的详细信息。这些更直接的表达式负责提取某些属性的部分或基于原始属性计算值。其中最常用的是TARGET_FILE生成器表达式集:

TARGET_FILE

这将生成目标二进制文件的绝对路径和文件名,包括任何与平台相关的文件前缀和后缀(例如.exe, .dylib)。对于基于unix的平台,其中共享库的文件名中通常包含版本细节,这些也将包括在内。

TARGET_FILE_NAME

与TARGET_FILE相同,但没有路径(也就是说,它只提供文件名部分)。

TARGET_FILE_DIR

与TARGET_FILE相同,但没有文件名。这是获取构建最终可执行文件或库所在目录的最健壮的方式。当使用像Xcode或Visual Studio这样的多配置生成器时,它的价值对于不同的构建配置是不同的。

​ 上面的三个TARGET_FILE表达式在定义自定义构建规则以在构建后的步骤中复制文件时特别有用。除了TARGET

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值