cmake-generator-expressions(7)

简介

生成器表达式在生成构建系统时进行求值,以产生特定于每个构建配置的信息。它们的格式为 $<...>。例如

target_include_directories(tgt PRIVATE /opt/include/$<CXX_COMPILER_ID>)

这将展开为 /opt/include/GNU, /opt/include/Clang, 等等,具体取决于使用的 C++ 编译器。

生成器表达式允许在许多目标属性的上下文中,例如 LINK_LIBRARIES, INCLUDE_DIRECTORIES, COMPILE_DEFINITIONS 等。它们也可以在命令中使用来填充这些属性,例如 target_link_libraries(), target_include_directories(), target_compile_definitions() 等。它们实现了条件链接、编译时使用的条件定义、条件包含目录等。条件可以基于构建配置、目标属性、平台信息或任何其他可查询的信息。

生成器表达式可以嵌套

target_compile_definitions(tgt PRIVATE
  $<$<VERSION_LESS:$<CXX_COMPILER_VERSION>,4.2.0>:OLD_COMPILER>
)

上面这行在 CMAKE_CXX_COMPILER_VERSION 小于 4.2.0 时会展开为 OLD_COMPILER

空格和引用

生成器表达式通常在命令参数之后进行解析。如果生成器表达式包含空格、换行符、分号或其他可能被解释为命令参数分隔符的字符,则在将整个表达式传递给命令时,应将其括在引号中。否则,可能会导致表达式被拆分,并且可能不再被识别为生成器表达式。

在使用 add_custom_command()add_custom_target() 时,请使用 VERBATIMCOMMAND_EXPAND_LISTS 选项以获得稳健的参数拆分和引用。

# WRONG: Embedded space will be treated as an argument separator.
# This ends up not being seen as a generator expression at all.
add_custom_target(run_some_tool
  COMMAND some_tool -I$<JOIN:$<TARGET_PROPERTY:tgt,INCLUDE_DIRECTORIES>, -I>
  VERBATIM
)
# Better, but still not robust. Quotes prevent the space from splitting the
# expression. However, the tool will receive the expanded value as a single
# argument.
add_custom_target(run_some_tool
  COMMAND some_tool "-I$<JOIN:$<TARGET_PROPERTY:tgt,INCLUDE_DIRECTORIES>, -I>"
  VERBATIM
)
# Nearly correct. Using a semicolon to separate arguments and adding the
# COMMAND_EXPAND_LISTS option means that paths with spaces will be handled
# correctly. Quoting the whole expression ensures it is seen as a generator
# expression. But if the target property is empty, we will get a bare -I
# with nothing after it.
add_custom_target(run_some_tool
  COMMAND some_tool "-I$<JOIN:$<TARGET_PROPERTY:tgt,INCLUDE_DIRECTORIES>,;-I>"
  COMMAND_EXPAND_LISTS
  VERBATIM
)

使用变量来构建更复杂的生成器表达式也是减少错误和提高可读性的好方法。上面的示例可以进一步改进如下:

# The $<BOOL:...> check prevents adding anything if the property is empty,
# assuming the property value cannot be one of CMake's false constants.
set(prop "$<TARGET_PROPERTY:tgt,INCLUDE_DIRECTORIES>")
add_custom_target(run_some_tool
  COMMAND some_tool "$<$<BOOL:${prop}>:-I$<JOIN:${prop},;-I>>"
  COMMAND_EXPAND_LISTS
  VERBATIM
)

最后,可以使用备用的生成器表达式以更简单、更稳健的方式表达上述示例:

add_custom_target(run_some_tool
  COMMAND some_tool "$<LIST:TRANSFORM,$<TARGET_PROPERTY:tgt,INCLUDE_DIRECTORIES>,PREPEND,-I>"
  COMMAND_EXPAND_LISTS
  VERBATIM
)

一个常见的错误是尝试使用缩进将生成器表达式跨越多行。

# WRONG: New lines and spaces all treated as argument separators, so the
# generator expression is split and not recognized correctly.
target_compile_definitions(tgt PRIVATE
  $<$<AND:
      $<CXX_COMPILER_ID:GNU>,
      $<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,5>
    >:HAVE_5_OR_LATER>
)

同样,使用具有良好命名约定的辅助变量来构建可读性强的表达式,而不是:

set(is_gnu "$<CXX_COMPILER_ID:GNU>")
set(v5_or_later "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,5>")
set(meet_requirements "$<AND:${is_gnu},${v5_or_later}>")
target_compile_definitions(tgt PRIVATE
  "$<${meet_requirements}:HAVE_5_OR_LATER>"
)

调试

由于生成器表达式是在生成构建系统时求值的,而不是在处理 CMakeLists.txt 文件时求值的,因此无法使用 message() 命令来检查其结果。生成调试消息的一种可能方法是添加一个自定义目标:

add_custom_target(genexdebug COMMAND ${CMAKE_COMMAND} -E echo "$<...>")

运行 cmake 后,您可以构建 genexdebug 目标来打印 $<...> 表达式的结果(即,运行命令 cmake --build ... --target genexdebug)。

另一种方法是使用 file(GENERATE) 将调试消息写入文件:

file(GENERATE OUTPUT filename CONTENT "$<...>")

生成器表达式参考

注意

此参考偏离了 CMake 文档的大部分内容,它省略了占位符(如 conditionstringtarget 等)周围的尖括号 <...>。这是为了防止这些占位符被误解为生成器表达式。

条件表达式

生成器表达式的一个基本类别与条件逻辑相关。支持两种形式的条件生成器表达式:

$<condition:true_string>

如果 condition1,则求值为 true_string;如果 condition 求值为 0,则求值为空字符串。 condition 的任何其他值都会导致错误。

$<IF:condition,true_string,false_string>

版本 3.8 新增。

如果 condition1,则求值为 true_string;如果 condition0,则求值为 false_stringcondition 的任何其他值都会导致错误。

Added in version 3.28: 此生成器表达式采用短路求值方式,因此当 condition1 时,false_string 中的生成器表达式不会被求值;当 condition 为 0 时,true_string 中的生成器表达式不会被求值。

通常,condition 本身就是一个生成器表达式。例如,以下表达式在使用 Debug 配置时展开为 DEBUG_MODE,对于所有其他配置则为空字符串:

$<$<CONFIG:Debug>:DEBUG_MODE>

布尔型 condition 值(非 10)可以通过使用 $<BOOL:...> 生成器表达式进行处理:

$<BOOL:string>

string 转换为 01。当以下任一情况为真时,求值为 0

  • string 为空,

  • string0FALSEOFFNNOIGNORENOTFOUND(不区分大小写)相等,或者

  • string 以后缀 -NOTFOUND(区分大小写)结尾。

否则,求值为 1

通常,$<BOOL:...> 生成器表达式用于 condition 由 CMake 变量提供时:

$<$<BOOL:${HAVE_SOME_FEATURE}>:-DENABLE_SOME_FEATURE>

逻辑运算符

支持常见的布尔逻辑运算符:

$<AND:conditions>

其中 conditions 是一个逗号分隔的布尔表达式列表,所有表达式都必须求值为 10。当所有条件都为 1 时,整个表达式求值为 1。如果任何条件为 0,则整个表达式求值为 0

$<OR:conditions>

其中 conditions 是一个逗号分隔的布尔表达式列表。所有表达式都必须求值为 10。当至少一个 conditions1 时,整个表达式求值为 1。如果所有 conditions 都求值为 0,则整个表达式求值为 0

$<NOT:condition>

condition 必须为 01。如果 condition1,则表达式结果为 0,否则为 1

Added in version 3.28: 逻辑运算符采用短路求值方式,因此一旦可以确定返回值,表达式列表中的生成器表达式就不会被求值。

主要比较表达式

CMake 支持各种比较生成器表达式。本节介绍主要的、最常用的比较类型。其他更具体的比较类型在下文自己的单独章节中介绍。

字符串比较

$<STREQUAL:string1,string2>

如果 string1string2 相等,则为 1,否则为 0。比较是区分大小写的。对于不区分大小写的比较,请与 字符串转换生成器表达式 结合使用。例如,以下表达式在 ${foo}BARBarbar 等之一时,求值为 1

$<STREQUAL:$<UPPER_CASE:${foo}>,BAR>
$<EQUAL:value1,value2>

如果 value1value2 在数值上相等,则为 1,否则为 0

版本比较

$<VERSION_LESS:v1,v2>

如果 v1 是一个版本小于 v2,则为 1,否则为 0

$<VERSION_GREATER:v1,v2>

如果 v1 是一个版本大于 v2,则为 1,否则为 0

$<VERSION_EQUAL:v1,v2>

如果 v1v2 是相同版本,则为 1,否则为 0

$<VERSION_LESS_EQUAL:v1,v2>

3.7 版本中新增。

如果 v1 是一个版本小于或等于 v2,则为 1,否则为 0

$<VERSION_GREATER_EQUAL:v1,v2>

3.7 版本中新增。

如果 v1 是一个版本大于或等于 v2,则为 1,否则为 0

字符串转换

$<LOWER_CASE:string>

string 的内容转换为小写。

$<UPPER_CASE:string>

string 的内容转换为大写。

$<MAKE_C_IDENTIFIER:...>

... 的内容转换为 C 标识符。转换遵循 string(MAKE_C_IDENTIFIER) 的相同行为。

列表表达式

本节中的大多数表达式都与 list() 命令紧密相关,提供相同的功能,但以生成器表达式的形式。

在以下所有与列表相关的生成器表达式中,如果生成器表达式期望在 list 之后提供某些内容,则 list 必须不包含任何逗号。例如,表达式 $<LIST:FIND,list,value>list 之后需要一个 value。由于逗号用于分隔 listvalue,因此 list 本身不能包含逗号。此限制不适用于 list() 命令,它仅限于处理列表的生成器表达式。

列表比较

$<IN_LIST:string,list>

3.12 版本新增。

如果 string 是分号分隔的 list 中的一个项,则为 1,否则为 0。它使用区分大小写的比较。

列表查询

$<LIST:LENGTH,list>

在 3.27 版本中新增。

list 中的项目数。

$<LIST:GET,list,index,...>

在 3.27 版本中新增。

展开为从 list 中由索引指定的项目列表。

$<LIST:SUBLIST,list,begin,length>

在 3.27 版本中新增。

给定 list 的一个子列表。如果 length 为 0,则返回空列表。如果 length 为 -1 或列表小于 begin + length,则返回从 begin 开始的列表的剩余项。

$<LIST:FIND,list,value>

在 3.27 版本中新增。

list 中第一个具有指定 value 的项目的索引,如果 value 不在 list 中,则为 -1。

列表转换

$<LIST:JOIN,list,glue>

在 3.27 版本中新增。

list 转换为单个字符串,并在每个项目之间插入 glue 字符串的内容。这在概念上与 $<JOIN:list,glue> 操作相同,但两者在处理空项目方面行为不同。$<LIST:JOIN,list,glue> 保留所有空项目,而 $<JOIN:list,glue> 则从列表中删除所有空项目。

$<LIST:APPEND,list,item,...>

在 3.27 版本中新增。

list,并在其后附加每个 item。多个项目应以逗号分隔。

$<LIST:PREPEND,list,item,...>

在 3.27 版本中新增。

list,并在其前插入每个 item。如果存在多个项目,它们应以逗号分隔,并且插入项目的顺序将得以保留。

$<LIST:INSERT,list,index,item,...>

在 3.27 版本中新增。

list,并在指定 index 处插入 item(或多个项目)。多个项目应以逗号分隔。

指定超出范围的 index 是错误的。有效索引是 0 到 N,其中 N 是列表的长度(包括 N)。空列表的长度为 0。

$<LIST:POP_BACK,list>

在 3.27 版本中新增。

list,并移除最后一个项目。

$<LIST:POP_FRONT,list>

在 3.27 版本中新增。

list,并移除第一个项目。

$<LIST:REMOVE_ITEM,list,value,...>

在 3.27 版本中新增。

list,并移除给定 value(或多个值)的所有实例。如果给出多个值,它们应以逗号分隔。

$<LIST:REMOVE_AT,list,index,...>

在 3.27 版本中新增。

list,并移除每个给定 index 处的项目。

$<LIST:REMOVE_DUPLICATES,list>

在 3.27 版本中新增。

list,并移除所有重复的项目。项目的相对顺序得以保留,但如果遇到重复项,则只保留第一个实例。结果与 $<REMOVE_DUPLICATES:list> 相同。

$<LIST:FILTER,list,INCLUDE|EXCLUDE,regex>

在 3.27 版本中新增。

来自 list 的项目列表,这些项目匹配 (INCLUDE) 或不匹配 (EXCLUDE) 正则表达式 regex。结果与 $<FILTER:list,INCLUDE|EXCLUDE,regex> 相同。

$<LIST:TRANSFORM,list,ACTION[,SELECTOR]>

在 3.27 版本中新增。

list,通过将 ACTION 应用于所有项目或(通过指定 SELECTOR)应用于选定的列表项目来转换。

注意

TRANSFORM 子命令不改变列表中的项目数。如果指定了 SELECTOR,则只有部分项目会被更改,其他项目将保持转换前的状态。

ACTION 指定应用于列表项目的操作。操作具有与 list(TRANSFORM) 命令完全相同的语义。ACTION 必须是以下之一:

APPEND, PREPEND

将指定的值附加或前置到列表的每个项目。

$<LIST:TRANSFORM,list,(APPEND|PREPEND),value[,SELECTOR]>
TOLOWER, TOUPPER

将列表的每个项目转换为小写或大写字符。

$<LIST:TRANSFORM,list,(TOLOWER|TOUPPER)[,SELECTOR]>
STRIP

删除列表每个项目的前导和尾随空格。

$<LIST:TRANSFORM,list,STRIP[,SELECTOR]>
REPLACE

尽可能多次匹配正则表达式,并用替换表达式替换列表每个项目的匹配项。

$<LIST:TRANSFORM,list,REPLACE,regular_expression,replace_expression[,SELECTOR]>

Changed in version 4.1: ^ 锚点现在仅匹配输入元素的开头,而不是每次重复搜索的开头。请参阅策略 CMP0186

SELECTOR 确定将转换哪些列表项目。一次只能指定一种选择器。当给出时,SELECTOR 必须是以下之一:

AT

指定索引列表。

$<LIST:TRANSFORM,list,ACTION,AT,index[,index...]>
FOR

指定一个范围,可选地带有用于迭代该范围的增量。

$<LIST:TRANSFORM,list,ACTION,FOR,start,stop[,step]>
REGEX

指定一个正则表达式。只有匹配正则表达式的项目才会被转换。

$<LIST:TRANSFORM,list,ACTION,REGEX,regular_expression>
$<JOIN:list,glue>

使用 glue 字符串的内容作为分隔符将 list 连接起来。这在概念上与 $<LIST:JOIN,list,glue> 相同,但两者在处理空项目方面行为不同。$<LIST:JOIN,list,glue> 保留所有空项目,而 $<JOIN:list,glue> 则从列表中删除所有空项目。

$<REMOVE_DUPLICATES:list>

版本 3.15 新增。

删除给定 list 中的重复项。项目的相对顺序得以保留,并且如果遇到重复项,则只保留第一个实例。结果与 $<LIST:REMOVE_DUPLICATES,list> 相同。

$<FILTER:list,INCLUDE|EXCLUDE,regex>

版本 3.15 新增。

包含或删除 list 中匹配正则表达式 regex 的项目。结果与 $<LIST:FILTER,list,INCLUDE|EXCLUDE,regex> 相同。

列表排序

$<LIST:REVERSE,list>

在 3.27 版本中新增。

list,项目顺序颠倒。

$<LIST:SORT,list[,(COMPARE:option|CASE:option|ORDER:option)]...>

在 3.27 版本中新增。

list,按照指定的选项进行排序。

使用 COMPARE 选项之一来选择排序的比较方法:

STRING

按字母顺序对字符串列表进行排序。如果未给出 COMPARE 选项,则这是默认行为。

FILE_BASENAME

按基本名称对文件路径列表进行排序。

NATURAL

使用自然顺序(请参阅 strverscmp(3) 的 man 页)对字符串列表进行排序,其中连续的数字被视为整数。例如,如果选择了 NATURAL 比较,以下列表 10.0 1.1 2.1 8.0 2.0 3.1 将按 1.1 2.0 2.1 3.1 8.0 10.0 排序,而使用 STRING 比较时,它将按 1.1 10.0 2.0 2.1 3.1 8.0 排序。

使用 CASE 选项之一来选择区分大小写或不区分大小写的排序模式:

SENSITIVE

列表项按区分大小写的方式排序。如果未给出 CASE 选项,则这是默认行为。

INSENSITIVE

列表项按不区分大小写的方式排序。仅大小写不同的项目顺序未指定。

要控制排序顺序,可以给出 ORDER 选项之一:

ASCENDING

按升序对列表进行排序。如果未给出 ORDER 选项,则这是默认行为。

DESCENDING

按降序对列表进行排序。

选项可以按任何顺序指定,但多次指定同一选项是错误的。

$<LIST:SORT,list,CASE:SENSITIVE,COMPARE:STRING,ORDER:DESCENDING>

路径表达式

本节中的大多数表达式都与 cmake_path() 命令紧密相关,提供相同的功能,但以生成器表达式的形式。

在本节的所有生成器表达式中,路径应采用 cmake 风格格式。可以使用 $<PATH:CMAKE_PATH> 生成器表达式将本地路径转换为 cmake 风格的路径。

路径比较

$<PATH_EQUAL:path1,path2>

在 3.24 版本中添加。

比较两个路径的词法表示。不对任一路径执行规范化。如果路径相等,则返回 1,否则返回 0

有关更多详细信息,请参阅 cmake_path(COMPARE)

路径查询

这些表达式提供了 cmake_path() 命令的 Query 选项的生成时等效功能。所有路径都应采用 cmake 风格格式。

$<PATH:HAS_*,path>

在 3.24 版本中添加。

以下操作在特定路径组件存在时返回 1,否则返回 0。有关每个路径组件的含义,请参阅 Path Structure And Terminology

$<PATH:HAS_ROOT_NAME,path>
$<PATH:HAS_ROOT_DIRECTORY,path>
$<PATH:HAS_ROOT_PATH,path>
$<PATH:HAS_FILENAME,path>
$<PATH:HAS_EXTENSION,path>
$<PATH:HAS_STEM,path>
$<PATH:HAS_RELATIVE_PART,path>
$<PATH:HAS_PARENT_PATH,path>

请注意以下特殊情况:

  • 对于 HAS_ROOT_PATH,只有当 root-nameroot-directory 至少有一个非空时,才会返回 true 结果。

  • 对于 HAS_PARENT_PATH,根目录也被认为有一个父目录,即它本身。除非路径仅包含 filename,否则结果为 true。

$<PATH:IS_ABSOLUTE,path>

在 3.24 版本中添加。

如果路径根据 cmake_path(IS_ABSOLUTE) 为绝对路径,则返回 1,否则返回 0

$<PATH:IS_RELATIVE,path>

在 3.24 版本中添加。

如果路径根据 cmake_path(IS_RELATIVE) 为相对路径,则返回 1,否则返回 0

$<PATH:IS_PREFIX[,NORMALIZE],path,input>

在 3.24 版本中添加。

如果 pathinput 的前缀,则返回 1,否则返回 0

当指定 NORMALIZE 选项时,在检查之前会对 pathinput 进行 规范化

路径分解

这些表达式提供了 cmake_path() 命令的 Decomposition 选项的生成时等效功能。所有路径都应采用 cmake 风格格式。

$<PATH:GET_*,...>

在 3.24 版本中添加。

以下操作从路径中检索不同的组件或组件组。有关每个路径组件的含义,请参阅 Path Structure And Terminology

Changed in version 3.27: 所有操作现在都接受路径列表作为参数。当指定路径列表时,操作将应用于每个路径。

$<PATH:GET_ROOT_NAME,path...>
$<PATH:GET_ROOT_DIRECTORY,path...>
$<PATH:GET_ROOT_PATH,path...>
$<PATH:GET_FILENAME,path...>
$<PATH:GET_EXTENSION[,LAST_ONLY],path...>
$<PATH:GET_STEM[,LAST_ONLY],path...>
$<PATH:GET_RELATIVE_PART,path...>
$<PATH:GET_PARENT_PATH,path...>

如果请求的组件在路径中不存在,则返回空字符串。

路径转换

这些表达式提供了 cmake_path() 命令的 ModificationGeneration 选项的生成时等效功能。所有路径都应采用 cmake 风格格式。

Changed in version 3.27: 所有操作现在都接受路径列表作为参数。当指定路径列表时,操作将应用于每个路径。

$<PATH:CMAKE_PATH[,NORMALIZE],path...>

在 3.24 版本中添加。

返回 path。如果 path 是本地路径,则将其转换为 cmake 风格路径,使用正斜杠 (/)。在 Windows 上,会考虑长文件名标记。

当指定 NORMALIZE 选项时,转换后会对路径进行 规范化

$<PATH:NATIVE_PATH[,NORMALIZE],path...>

4.0 版本新增。

返回 path,并将其转换为本地格式,使用特定于平台的斜杠(Windows 主机上为 \,其他地方为 /)。

当指定 NORMALIZE 选项时,在转换之前会对路径进行 规范化

$<PATH:APPEND,path...,input,...>

在 3.24 版本中添加。

使用 / 作为 directory-separator,返回所有 input 参数附加到 path 之后的结果。根据 input 的值,path 的值可能会被丢弃。

有关更多详细信息,请参阅 cmake_path(APPEND)

$<PATH:REMOVE_FILENAME,path...>

在 3.24 版本中添加。

返回 path,移除文件名组件(由 $<PATH:GET_FILENAME> 返回)。移除后,如果存在任何尾随的 directory-separator,将保留它。

有关更多详细信息,请参阅 cmake_path(REMOVE_FILENAME)

$<PATH:REPLACE_FILENAME,path...,input>

在 3.24 版本中添加。

返回 path,并将文件名组件替换为 input。如果 path 没有文件名组件(即 $<PATH:HAS_FILENAME> 返回 0),则 path 保持不变。

有关更多详细信息,请参阅 cmake_path(REPLACE_FILENAME)

$<PATH:REMOVE_EXTENSION[,LAST_ONLY],path...>

在 3.24 版本中添加。

返回 path,并移除扩展名(如果存在)。

有关更多详细信息,请参阅 cmake_path(REMOVE_EXTENSION)

$<PATH:REPLACE_EXTENSION[,LAST_ONLY],path...,input>

在 3.24 版本中添加。

返回 path,并将扩展名替换为 input(如果存在)。

有关更多详细信息,请参阅 cmake_path(REPLACE_EXTENSION)

$<PATH:NORMAL_PATH,path...>

在 3.24 版本中添加。

返回 path,并根据 Normalization 中描述的步骤进行规范化。

$<PATH:RELATIVE_PATH,path...,base_directory>

在 3.24 版本中添加。

返回 path,并修改使其相对于 base_directory 参数。

有关更多详细信息,请参阅 cmake_path(RELATIVE_PATH)

$<PATH:ABSOLUTE_PATH[,NORMALIZE],path...,base_directory>

在 3.24 版本中添加。

返回 path 的绝对路径。如果 path 是相对路径($<PATH:IS_RELATIVE> 返回 1),则相对于 base_directory 参数指定的基目录进行计算。

当指定 NORMALIZE 选项时,在计算路径后会对路径进行 规范化

有关更多详细信息,请参阅 cmake_path(ABSOLUTE_PATH)

Shell 路径

$<SHELL_PATH:...>

3.4 版本新增。

... 的内容转换为 shell 路径样式。例如,在 Windows shell 中,斜杠会被转换为反斜杠;在 MSYS shell 中,驱动器号会被转换为 POSIX 路径。 ... 必须是绝对路径。

Added in version 3.14: ... 可以是 分号分隔的列表,在这种情况下,每个路径都会单独转换,并使用 shell 路径分隔符(POSIX 上为 :,Windows 上为 ;)生成一个结果列表。请确保在 CMake 源代码中将包含此生成器表达式的参数括在双引号中,以防止 ; 分割参数。

配置表达式

$<CONFIG>

配置名称。使用此表达式代替已弃用的 CONFIGURATION 生成器表达式。

$<CONFIG:cfgs>

如果配置是逗号分隔列表 cfgs 中的任意一个条目,则为 1,否则为 0。这是一个不区分大小写的比较。在为 IMPORTED 目标计算属性时,也会考虑 MAP_IMPORTED_CONFIG_<CONFIG> 中的映射。

Changed in version 3.19: 可以为 cfgs 指定多个配置。CMake 3.18 及更早版本仅接受单个配置。

$<OUTPUT_CONFIG:...>

在 3.20 版本中添加。

仅在 add_custom_command()add_custom_target() 中作为参数的最外层生成器表达式有效。对于 Ninja Multi-Config 生成器,... 中的生成器表达式使用自定义命令的“输出配置”进行求值。对于其他生成器,... 的内容正常求值。

$<COMMAND_CONFIG:...>

在 3.20 版本中添加。

仅在 add_custom_command()add_custom_target() 中作为参数的最外层生成器表达式有效。对于 Ninja Multi-Config 生成器,... 中的生成器表达式使用自定义命令的“命令配置”进行求值。对于其他生成器,... 的内容正常求值。

工具链和语言表达式

平台

$<PLATFORM_ID>

当前系统的 CMake 平台 ID。另请参阅变量 CMAKE_SYSTEM_NAME

$<PLATFORM_ID:platform_ids>

如果 CMake 的平台 ID 匹配逗号分隔列表 platform_ids 中的任意一个条目,则为 1,否则为 0。另请参阅变量 CMAKE_SYSTEM_NAME

编译器版本

另请参阅变量 CMAKE_<LANG>_COMPILER_VERSION,它与此子节中的表达式密切相关。

$<C_COMPILER_VERSION>

使用的 C 编译器的版本。

$<C_COMPILER_VERSION:version>

如果 C 编译器的版本与 version 匹配,则为 1,否则为 0

$<CXX_COMPILER_VERSION>

使用的 CXX 编译器的版本。

$<CXX_COMPILER_VERSION:version>

如果 C++ 编译器的版本与 version 匹配,则为 1,否则为 0

$<CUDA_COMPILER_VERSION>

版本 3.15 新增。

使用的 CUDA 编译器的版本。

$<CUDA_COMPILER_VERSION:version>

版本 3.15 新增。

如果 C++ 编译器的版本与 version 匹配,则为 1,否则为 0

$<OBJC_COMPILER_VERSION>

3.16 版新增。

使用的 Objective-C 编译器的版本。

$<OBJC_COMPILER_VERSION:version>

3.16 版新增。

如果 Objective-C 编译器的版本与 version 匹配,则为 1,否则为 0

$<OBJCXX_COMPILER_VERSION>

3.16 版新增。

使用的 Objective-C++ 编译器的版本。

$<OBJCXX_COMPILER_VERSION:version>

3.16 版新增。

如果 Objective-C++ 编译器的版本与 version 匹配,则为 1,否则为 0

$<Fortran_COMPILER_VERSION>

使用的 Fortran 编译器的版本。

$<Fortran_COMPILER_VERSION:version>

如果 Fortran 编译器的版本与 version 匹配,则为 1,否则为 0

$<HIP_COMPILER_VERSION>

3.21 版本新增。

使用的 HIP 编译器的版本。

$<HIP_COMPILER_VERSION:version>

3.21 版本新增。

如果 HIP 编译器的版本与 version 匹配,则为 1,否则为 0

$<ISPC_COMPILER_VERSION>

3.19 版本新增。

使用的 ISPC 编译器的版本。

$<ISPC_COMPILER_VERSION:version>

3.19 版本新增。

如果 ISPC 编译器的版本与 version 匹配,则为 1,否则为 0

编译器语言、ID 和前端变体

另请参阅变量 CMAKE_<LANG>_COMPILER_IDCMAKE_<LANG>_COMPILER_FRONTEND_VARIANT,它们与此子节中的大多数表达式密切相关。

$<C_COMPILER_ID>

使用的 C 编译器的 CMake 编译器 ID。

$<C_COMPILER_ID:compiler_ids>

其中 compiler_ids 是一个逗号分隔列表。如果 C 编译器的 CMake 编译器 ID 匹配 compiler_ids 中的任意一个条目,则为 1,否则为 0

Changed in version 3.15: 可以指定多个 compiler_ids。CMake 3.14 及更早版本仅接受单个编译器 ID。

$<CXX_COMPILER_ID>

使用的 C++ 编译器的 CMake 编译器 ID。

$<CXX_COMPILER_ID:compiler_ids>

其中 compiler_ids 是一个逗号分隔列表。如果 C++ 编译器的 CMake 编译器 ID 匹配 compiler_ids 中的任意一个条目,则为 1,否则为 0

Changed in version 3.15: 可以指定多个 compiler_ids。CMake 3.14 及更早版本仅接受单个编译器 ID。

$<CUDA_COMPILER_ID>

版本 3.15 新增。

使用的 CUDA 编译器的 CMake 编译器 ID。

$<CUDA_COMPILER_ID:compiler_ids>

版本 3.15 新增。

其中 compiler_ids 是一个逗号分隔列表。如果 CUDA 编译器的 CMake 编译器 ID 匹配 compiler_ids 中的任意一个条目,则为 1,否则为 0

$<OBJC_COMPILER_ID>

3.16 版新增。

使用的 Objective-C 编译器的 CMake 编译器 ID。

$<OBJC_COMPILER_ID:compiler_ids>

3.16 版新增。

其中 compiler_ids 是一个逗号分隔列表。如果 Objective-C 编译器的 CMake 编译器 ID 匹配 compiler_ids 中的任意一个条目,则为 1,否则为 0

$<OBJCXX_COMPILER_ID>

3.16 版新增。

使用的 Objective-C++ 编译器的 CMake 编译器 ID。

$<OBJCXX_COMPILER_ID:compiler_ids>

3.16 版新增。

其中 compiler_ids 是一个逗号分隔列表。如果 Objective-C++ 编译器的 CMake 编译器 ID 匹配 compiler_ids 中的任意一个条目,则为 1,否则为 0

$<Fortran_COMPILER_ID>

使用的 Fortran 编译器的 CMake 编译器 ID。

$<Fortran_COMPILER_ID:compiler_ids>

其中 compiler_ids 是一个逗号分隔的列表。如果 CMake 的 Fortran 编译器 ID 匹配 compiler_ids 中的任何一个条目,则为 1,否则为 0

Changed in version 3.15: 可以指定多个 compiler_ids。CMake 3.14 及更早版本仅接受单个编译器 ID。

$<HIP_COMPILER_ID>

3.21 版本新增。

正在使用的 HIP 编译器的 CMake 编译器 ID。

$<HIP_COMPILER_ID:compiler_ids>

3.21 版本新增。

其中 compiler_ids 是一个逗号分隔的列表。如果 CMake 的 HIP 编译器 ID 匹配 compiler_ids 中的任何一个条目,则为 1,否则为 0

$<ISPC_COMPILER_ID>

3.19 版本新增。

正在使用的 ISPC 编译器的 CMake 编译器 ID。

$<ISPC_COMPILER_ID:compiler_ids>

3.19 版本新增。

其中 compiler_ids 是一个逗号分隔的列表。如果 CMake 的 ISPC 编译器 ID 匹配 compiler_ids 中的任何一个条目,则为 1,否则为 0

$<C_COMPILER_FRONTEND_VARIANT>

3.30 版本新增。

正在使用的 C 编译器的 CMake 编译器前端变体。

$<C_COMPILER_FRONTEND_VARIANT:compiler_ids>

3.30 版本新增。

其中 compiler_ids 是一个逗号分隔的列表。如果 CMake 的 C 编译器前端变体匹配 compiler_ids 中的任何一个条目,则为 1,否则为 0

$<CXX_COMPILER_FRONTEND_VARIANT>

3.30 版本新增。

正在使用的 C++ 编译器的 CMake 编译器前端变体。

$<CXX_COMPILER_FRONTEND_VARIANT:compiler_ids>

3.30 版本新增。

其中 compiler_ids 是一个逗号分隔的列表。如果 CMake 的 C++ 编译器前端变体匹配 compiler_ids 中的任何一个条目,则为 1,否则为 0

$<CUDA_COMPILER_FRONTEND_VARIANT>

3.30 版本新增。

使用的 CUDA 编译器的 CMake 编译器 ID。

$<CUDA_COMPILER_FRONTEND_VARIANT:compiler_ids>

3.30 版本新增。

其中 compiler_ids 是一个逗号分隔的列表。如果 CMake 的 CUDA 编译器前端变体匹配 compiler_ids 中的任何一个条目,则为 1,否则为 0

$<OBJC_COMPILER_FRONTEND_VARIANT>

3.30 版本新增。

正在使用的 Objective-C 编译器的 CMake 编译器前端变体。

$<OBJC_COMPILER_FRONTEND_VARIANT:compiler_ids>

3.30 版本新增。

其中 compiler_ids 是一个逗号分隔的列表。如果 CMake 的 Objective-C 编译器前端变体匹配 compiler_ids 中的任何一个条目,则为 1,否则为 0

$<OBJCXX_COMPILER_FRONTEND_VARIANT>

3.30 版本新增。

正在使用的 Objective-C++ 编译器的 CMake 编译器前端变体。

$<OBJCXX_COMPILER_FRONTEND_VARIANT:compiler_ids>

3.30 版本新增。

其中 compiler_ids 是一个逗号分隔的列表。如果 CMake 的 Objective-C++ 编译器前端变体匹配 compiler_ids 中的任何一个条目,则为 1,否则为 0

$<Fortran_COMPILER_FRONTEND_VARIANT>

3.30 版本新增。

使用的 Fortran 编译器的 CMake 编译器 ID。

$<Fortran_COMPILER_FRONTEND_VARIANT:compiler_ids>

3.30 版本新增。

其中 compiler_ids 是一个逗号分隔的列表。如果 CMake 的 Fortran 编译器前端变体匹配 compiler_ids 中的任何一个条目,则为 1,否则为 0

$<HIP_COMPILER_FRONTEND_VARIANT>

3.30 版本新增。

正在使用的 HIP 编译器的 CMake 编译器 ID。

$<HIP_COMPILER_FRONTEND_VARIANT:compiler_ids>

3.30 版本新增。

其中 compiler_ids 是一个逗号分隔的列表。如果 CMake 的 HIP 编译器前端变体匹配 compiler_ids 中的任何一个条目,则为 1,否则为 0

$<ISPC_COMPILER_FRONTEND_VARIANT>

3.30 版本新增。

正在使用的 ISPC 编译器的 CMake 编译器 ID。

$<ISPC_COMPILER_FRONTEND_VARIANT:compiler_ids>

3.30 版本新增。

其中 compiler_ids 是一个逗号分隔的列表。如果 CMake 的 ISPC 编译器前端变体匹配 compiler_ids 中的任何一个条目,则为 1,否则为 0

$<COMPILE_LANGUAGE>

3.3 版本中新增。

评估编译选项时的源文件的编译语言。有关此生成器表达式可移植性的注意事项,请参阅相关的布尔表达式 $<COMPILE_LANGUAGE:languages>

$<COMPILE_LANGUAGE:languages>

3.3 版本中新增。

在 3.15 版本中更改: 可以为 languages 指定多个语言。CMake 3.14 及更早版本仅接受单一语言。

当用于编译单元的语言与 languages 中的逗号分隔条目之一匹配时,则为 1,否则为 0。此表达式可用于为目标中特定语言的源文件指定编译选项、编译定义和包含目录。例如

add_executable(myapp main.cpp foo.c bar.cpp zot.cu)
target_compile_options(myapp
  PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>
)
target_compile_definitions(myapp
  PRIVATE $<$<COMPILE_LANGUAGE:CXX>:COMPILING_CXX>
          $<$<COMPILE_LANGUAGE:CUDA>:COMPILING_CUDA>
)
target_include_directories(myapp
  PRIVATE $<$<COMPILE_LANGUAGE:CXX,CUDA>:/opt/foo/headers>
)

这指定了仅用于 C++ 的 -fno-exceptions 编译选项、COMPILING_CXX 编译定义和 cxx_headers include 目录(已省略编译器 ID 检查)。它还为 CUDA 指定了 COMPILING_CUDA 编译定义。

请注意,对于 Visual Studio GeneratorsXcode,无法为 CCXX 语言分别表示目标范围的编译定义或包含目录。此外,对于 Visual Studio Generators,无法为 CCXX 语言分别表示目标范围的标志。在这些生成器下,C 和 C++ 源的表达式都将使用 CXX 进行评估,如果存在 C++ 源,否则使用 C。一种解决方法是为每个源文件语言创建单独的库。

add_library(myapp_c foo.c)
add_library(myapp_cxx bar.cpp)
target_compile_options(myapp_cxx PUBLIC -fno-exceptions)
add_executable(myapp main.cpp)
target_link_libraries(myapp myapp_c myapp_cxx)
$<COMPILE_LANG_AND_ID:language,compiler_ids>

版本 3.15 新增。

当用于编译单元的语言匹配 languagelanguage 编译器的 CMake 编译器 ID 匹配逗号分隔的 compiler_ids 中的任何一个条目时,则为 1,否则为 0。此表达式是 $<COMPILE_LANGUAGE:language>$<LANG_COMPILER_ID:compiler_ids> 的组合的简写形式。此表达式可用于为目标中特定语言和编译器组合的源文件指定编译选项、编译定义和包含目录。例如

add_executable(myapp main.cpp foo.c bar.cpp zot.cu)
target_compile_definitions(myapp
  PRIVATE $<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang>:COMPILING_CXX_WITH_CLANG>
          $<$<COMPILE_LANG_AND_ID:CXX,Intel>:COMPILING_CXX_WITH_INTEL>
          $<$<COMPILE_LANG_AND_ID:C,Clang>:COMPILING_C_WITH_CLANG>
)

这指定了基于编译器 ID 和编译语言使用不同的编译定义。此示例将在 Clang 为 CXX 编译器时具有 COMPILING_CXX_WITH_CLANG 编译定义,在 Intel 为 CXX 编译器时具有 COMPILING_CXX_WITH_INTEL 编译定义。同样,当 C 编译器是 Clang 时,它只会看到 COMPILING_C_WITH_CLANG 定义。

如果不使用 compile_LANG_AND_ID 生成器表达式,则相同的逻辑将表示为

target_compile_definitions(myapp
  PRIVATE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:AppleClang,Clang>>:COMPILING_CXX_WITH_CLANG>
          $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:Intel>>:COMPILING_CXX_WITH_INTEL>
          $<$<AND:$<COMPILE_LANGUAGE:C>,$<C_COMPILER_ID:Clang>>:COMPILING_C_WITH_CLANG>
)

编译特性

$<COMPILE_FEATURES:features>

版本 3.1 中新增。

其中 features 是一个逗号分隔的列表。如果 'head' 目标可用的 features 全部满足,则求值为 1,否则为 0。如果在使用此表达式评估目标的链接实现时,并且任何依赖项传递性地增加了 'head' 目标的必需 C_STANDARDCXX_STANDARD,则会报告错误。有关编译特性的信息和支持的编译器的列表,请参阅 cmake-compile-features(7) 手册。

编译上下文

$<COMPILE_ONLY:...>

在 3.27 版本中新增。

在收集 传递编译属性 时,... 的内容会被保留,否则为空字符串。这适用于 INTERFACE_LINK_LIBRARIESLINK_LIBRARIES 目标属性,通常通过 target_link_libraries() 命令填充。它提供了编译使用要求,但没有链接要求。

用例包括仅头文件使用,其中所有使用都已知没有链接要求(例如,全 inline 或 C++ 模板库)。

注意,为了正确评估此表达式,需要将策略 CMP0099 设置为 NEW

链接器 ID 和前端变体

另请参阅与本节大多数表达式密切相关的 CMAKE_<LANG>_COMPILER_LINKER_IDCMAKE_<LANG>_COMPILER_LINKER_FRONTEND_VARIANT 变量。

$<C_COMPILER_LINKER_ID>

版本 4.2 中添加。

正在使用的 C 链接器的 CMake 链接器 ID。

$<C_COMPILER_LINKER_ID:linker_ids>

版本 4.2 中添加。

其中 linker_ids 是一个逗号分隔的列表。如果 CMake 的 C 链接器 ID 匹配 linker_ids 中的任何一个条目,则为 1,否则为 0

$<CXX_COMPILER_LINKER_ID>

版本 4.2 中添加。

正在使用的 C++ 链接器的 CMake 链接器 ID。

$<CXX_COMPILER_LINKER_ID:linker_ids>

版本 4.2 中添加。

其中 linker_ids 是一个逗号分隔的列表。如果 CMake 的 C++ 链接器 ID 匹配 linker_ids 中的任何一个条目,则为 1,否则为 0

$<CUDA_COMPILER_LINKER_ID>

版本 4.2 中添加。

正在使用的 CUDA 链接器的 CMake 链接器 ID。

$<CUDA_COMPILER_LINKER_ID:linker_ids>

版本 4.2 中添加。

其中 linker_ids 是一个逗号分隔的列表。如果 CMake 的 CUDA 链接器 ID 匹配 linker_ids 中的任何一个条目,则为 1,否则为 0

$<OBJC_COMPILER_LINKER_ID>

版本 4.2 中添加。

正在使用的 Objective-C 链接器的 CMake 链接器 ID。

$<OBJC_COMPILER_LINKER_ID:linker_ids>

版本 4.2 中添加。

其中 linker_ids 是一个逗号分隔的列表。如果 CMake 的 Objective-C 链接器 ID 匹配 linker_ids 中的任何一个条目,则为 1,否则为 0

$<OBJCXX_COMPILER_LINKER_ID>

版本 4.2 中添加。

正在使用的 Objective-C++ 链接器的 CMake 链接器 ID。

$<OBJCXX_COMPILER_LINKER_ID:linker_ids>

版本 4.2 中添加。

其中 linker_ids 是一个逗号分隔的列表。如果 CMake 的 Objective-C++ 链接器 ID 匹配 linker_ids 中的任何一个条目,则为 1,否则为 0

$<Fortran_COMPILER_LINKER_ID>

版本 4.2 中添加。

正在使用的 Fortran 链接器的 CMake 链接器 ID。

$<Fortran_COMPILER_LINKER_ID:linker_ids>

版本 4.2 中添加。

其中 linker_ids 是一个逗号分隔的列表。如果 CMake 的 Fortran 链接器 ID 匹配 linker_ids 中的任何一个条目,则为 1,否则为 0

$<HIP_COMPILER_LINKER_ID>

版本 4.2 中添加。

正在使用的 HIP 链接器的 CMake 链接器 ID。

$<HIP_COMPILER_LINKER_ID:linker_ids>

版本 4.2 中添加。

其中 linker_ids 是一个逗号分隔的列表。如果 CMake 的 HIP 链接器 ID 匹配 linker_ids 中的任何一个条目,则为 1,否则为 0

$<C_COMPILER_LINKER_FRONTEND_VARIANT>

版本 4.2 中添加。

正在使用的 C 链接器的 CMake 链接器前端变体。

$<C_COMPILER_LINKER_FRONTEND_VARIANT:variant_ids>

版本 4.2 中添加。

其中 variant_ids 是一个逗号分隔的列表。如果 CMake 的 C 链接器前端变体匹配 variant_ids 中的任何一个条目,则为 1,否则为 0

$<CXX_COMPILER_LINKER_FRONTEND_VARIANT>

版本 4.2 中添加。

正在使用的 C++ 链接器的 CMake 链接器前端变体。

$<CXX_COMPILER_LINKER_FRONTEND_VARIANT:variant_ids>

版本 4.2 中添加。

其中 variant_ids 是一个逗号分隔的列表。如果 CMake 的 C++ 链接器前端变体匹配 variant_ids 中的任何一个条目,则为 1,否则为 0

$<CUDA_COMPILER_LINKER_FRONTEND_VARIANT>

版本 4.2 中添加。

正在使用的 CUDA 链接器的 CMake 链接器前端变体。

$<CUDA_COMPILER_LINKER_FRONTEND_VARIANT:variant_ids>

版本 4.2 中添加。

其中 variant_ids 是一个逗号分隔的列表。如果 CMake 的 CUDA 链接器前端变体匹配 variant_ids 中的任何一个条目,则为 1,否则为 0

$<OBJC_COMPILER_LINKER_FRONTEND_VARIANT>

版本 4.2 中添加。

正在使用的 Objective-C 链接器的 CMake 链接器前端变体。

$<OBJC_COMPILER_LINKER_FRONTEND_VARIANT:variant_ids>

版本 4.2 中添加。

其中 variant_ids 是一个逗号分隔的列表。如果 CMake 的 Objective-C 链接器前端变体匹配 variant_ids 中的任何一个条目,则为 1,否则为 0

$<OBJCXX_COMPILER_LINKER_FRONTEND_VARIANT>

版本 4.2 中添加。

正在使用的 Objective-C++ 链接器的 CMake 链接器前端变体。

$<OBJCXX_COMPILER_LINKER_FRONTEND_VARIANT:variant_ids>

版本 4.2 中添加。

其中 variant_ids 是一个逗号分隔的列表。如果 CMake 的 Objective-C++ 链接器前端变体匹配 variant_ids 中的任何一个条目,则为 1,否则为 0

$<Fortran_COMPILER_LINKER_FRONTEND_VARIANT>

版本 4.2 中添加。

正在使用的 Fortran 链接器的 CMake 链接器前端变体。

$<Fortran_COMPILER_LINKER_FRONTEND_VARIANT:variant_ids>

版本 4.2 中添加。

其中 variant_ids 是一个逗号分隔的列表。如果 CMake 的 Fortran 链接器前端变体匹配 variant_ids 中的任何一个条目,则为 1,否则为 0

$<HIP_COMPILER_LINKER_FRONTEND_VARIANT>

版本 4.2 中添加。

正在使用的 HIP 链接器的 CMake 链接器前端变体。

$<HIP_COMPILER_LINKER_FRONTEND_VARIANT:variant_ids>

版本 4.2 中添加。

其中 variant_ids 是一个逗号分隔的列表。如果 CMake 的 HIP 链接器前端变体匹配 variant_ids 中的任何一个条目,则为 1,否则为 0

与目标相关的表达式

目标元数据

这些表达式会查找有关目标的信息。

$<TARGET_EXISTS:tgt>

3.12 版本新增。

如果 tgt 作为 CMake 目标存在,则为 1,否则为 0

$<TARGET_NAME_IF_EXISTS:tgt>

3.12 版本新增。

如果目标存在,则为目标名称 tgt,否则为空字符串。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_NAME:tgt>

目标名称 tgt 的书写形式。这会将 tgt 标记为较大表达式中目标的名称,如果将目标导出到多个依赖的导出集,则需要此项。tgt 文本必须是目标的文字名称;它可能不包含生成器表达式。目标不必存在。

$<TARGET_POLICY:policy>

如果创建 'head' 目标时 policy 设置为 NEW,则为 1,否则为 0。如果 policy 未设置,则会发出该策略的警告消息。此生成器表达式仅适用于一部分策略。

目标属性

这些表达式会查找 目标属性 的值。

$<TARGET_PROPERTY:tgt,prop>

目标 tgt 上属性 prop 的值,如果属性未设置,则为空。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

在 3.26 版本中更改: 在评估 目标使用要求 时,通常是在 INTERFACE_* 目标属性中,tgt 名称的查找发生在指定需求的目录中,而不是正在评估表达式的消耗目标的目录中。

$<TARGET_PROPERTY:prop>

正在评估表达式的目标上属性 prop 的值,如果属性未设置,则为空。请注意,对于 目标使用要求 中的生成器表达式,这是消耗目标而不是指定需求的那个目标。

对于某些属性,这些表达式具有特殊的评估规则

目标构建规范属性

这些属性的计算结果是一个 分号分隔的列表,表示目标本身的值与由目标 LINK_LIBRARIES 指定的名称的目标的相应 目标使用要求 的值的并集。

在 4.1 版本中更改: 现在 LINK_LIBRARIES 本身的评估也变为传递性的。请参阅策略 CMP0189

目标使用要求属性

这些属性的计算结果是一个 分号分隔的列表,表示目标本身的值与目标 INTERFACE_LINK_LIBRARIES 指定的名称的目标的相同属性的值的并集。

版本 4.1 中已更改: INTERFACE_LINK_LIBRARIES本身的求值现在是传递的。请参阅策略CMP0189

自定义传递属性

3.30 版本新增。

这些在求值过程中按如下方式处理:

如果PROP同时被TRANSITIVE_COMPILE_PROPERTIESTRANSITIVE_LINK_PROPERTIES命名,则后者优先。

兼容接口属性

这些属性的求值结果为一个单一值,该值结合了目标本身、目标LINK_LIBRARIES命名的目标以及链接目标INTERFACE_LINK_LIBRARIES的传递闭包。来自多个目标的兼容接口属性的值会根据定义它的COMPATIBLE_INTERFACE_*属性所需的兼容性类型进行组合。

目标产物

这些表达式查找与给定目标tgt关联的产物信息。除非另有说明,这可以是任何运行时产物,即:

在以下内容中,“tgt文件名”表示tgt二进制文件的名称。这需要与“目标名称”区分开来,后者仅仅是字符串tgt

$<TARGET_FILE:tgt>

tgt二进制文件的完整路径。

请注意,除非表达式在add_custom_command()add_custom_target()中使用,否则tgt不会被添加为计算此表达式的目标的依赖项。

$<TARGET_FILE_BASE_NAME:tgt[,POSTFIX:(INCLUDE|EXCLUDE)]>

版本 3.15 新增。

版本 4.2 中添加: 选项POSTFIX,可用于控制<CONFIG>_POSTFIX目标属性值是否作为基本名称的一部分。默认值为POSTFIX:INCLUDE

tgt的基本名称,即$<TARGET_FILE_NAME:tgt>在去除前缀和后缀后,以及可选地去除后缀。例如,如果tgt文件名是libbase_postfix.so,则基本名称是

  • base_postfix,对应于$<TARGET_FILE_BASE_NAME:tgt>$<TARGET_FILE_BASE_NAME:tgt,POSTFIX:INCLUDE>

  • base,对应于$<TARGET_FILE_BASE_NAME:tgt,POSTFIX:EXCLUDE>

另请参阅OUTPUT_NAMEARCHIVE_OUTPUT_NAMELIBRARY_OUTPUT_NAMERUNTIME_OUTPUT_NAME目标属性,它们的配置特定变体OUTPUT_NAME_<CONFIG>ARCHIVE_OUTPUT_NAME_<CONFIG>LIBRARY_OUTPUT_NAME_<CONFIG>RUNTIME_OUTPUT_NAME_<CONFIG>,以及<CONFIG>_POSTFIXDEBUG_POSTFIX目标属性。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_FILE_PREFIX:tgt>

版本 3.15 新增。

tgt文件名的前缀(例如lib)。

另请参阅PREFIX目标属性。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_FILE_SUFFIX:tgt>

版本 3.15 新增。

tgt文件名的后缀(扩展名,例如.so.exe)。

另请参阅SUFFIX目标属性。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_FILE_NAME:tgt>

tgt文件名。

请注意,除非在CMP0112策略中另有说明,否则tgt不会被添加为计算此表达式的目标的依赖项。

$<TARGET_FILE_DIR:tgt>

tgt二进制文件的目录。

请注意,除非在CMP0112策略中另有说明,否则tgt不会被添加为计算此表达式的目标的依赖项。

$<TARGET_IMPORT_FILE:tgt>

在 3.27 版本中新增。

链接器导入文件的完整路径。在DLL平台上,这将是.lib文件。在AIX上用于可执行文件,以及在macOS上用于共享库,它可能是.imp.tbd导入文件,具体取决于ENABLE_EXPORTS属性的值。

当没有与目标关联的导入文件时,此表达式将展开为空字符串。

$<TARGET_IMPORT_FILE_BASE_NAME:tgt[,POSTFIX:(INCLUDE|EXCLUDE)]>

在 3.27 版本中新增。

版本 4.2 中添加: 选项POSTFIX,可用于控制<CONFIG>_POSTFIX目标属性值是否作为基本名称的一部分。默认值为POSTFIX:INCLUDE

目标tgt的链接器导入文件的基本名称,不包括前缀或后缀,并且可选地不包括后缀。例如,如果目标文件名是libbase_postfix.tbd,则基本名称是

  • base_postfix,对应于$<TARGET_IMPORT_FILE_BASE_NAME:tgt>$<TARGET_IMPORT_FILE_BASE_NAME:tgt,POSTFIX:INCLUDE>

  • base,对应于$<TARGET_IMPORT_FILE_BASE_NAME:tgt,POSTFIX:EXCLUDE>

另请参阅OUTPUT_NAMEARCHIVE_OUTPUT_NAME目标属性,它们的配置特定变体OUTPUT_NAME_<CONFIG>ARCHIVE_OUTPUT_NAME_<CONFIG>,以及<CONFIG>_POSTFIXDEBUG_POSTFIX目标属性。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_IMPORT_FILE_PREFIX:tgt>

在 3.27 版本中新增。

目标tgt的导入文件的前缀。

另请参阅IMPORT_PREFIX目标属性。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_IMPORT_FILE_SUFFIX:tgt>

在 3.27 版本中新增。

目标tgt的导入文件的后缀。

后缀对应于文件扩展名(例如.lib.tbd)。

另请参阅IMPORT_SUFFIX目标属性。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_IMPORT_FILE_NAME:tgt>

在 3.27 版本中新增。

目标tgt的导入文件的名称。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_IMPORT_FILE_DIR:tgt>

在 3.27 版本中新增。

目标tgt的导入文件的目录。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_LINKER_FILE:tgt>

链接到tgt目标时使用的文件。这通常是tgt所代表的库(.a.lib.so),但对于DLL平台上的共享库,它将是与DLL关联的.lib导入库。

版本 3.27 中添加: 在macOS上,它可能是与共享库关联的.tbd导入文件,具体取决于ENABLE_EXPORTS属性的值。

此生成器表达式等价于$<TARGET_LINKER_LIBRARY_FILE>$<TARGET_LINKER_IMPORT_FILE>生成器表达式,具体取决于目标和平台的特性。

$<TARGET_LINKER_FILE_BASE_NAME:tgt[,POSTFIX:(INCLUDE|EXCLUDE)]>

版本 3.15 新增。

版本 4.2 中添加: 选项POSTFIX,可用于控制<CONFIG>_POSTFIX目标属性值是否作为基本名称的一部分。默认值为POSTFIX:INCLUDE

用于链接tgt目标的文件名的基本名称,即$<TARGET_LINKER_FILE_NAME:tgt>去除前缀和后缀后,并且可选地去除后缀。例如,如果目标文件名是libbase_postfix.a,则基本名称是

  • base_postfix,对应于$<TARGET_LINKER_FILE_BASE_NAME:tgt>$<TARGET_LINKER_FILE_BASE_NAME:tgt,POSTFIX:INCLUDE>

  • base,对应于$<TARGET_LINKER_FILE_BASE_NAME:tgt,POSTFIX:EXCLUDE>

另请参阅OUTPUT_NAMEARCHIVE_OUTPUT_NAMELIBRARY_OUTPUT_NAME目标属性,它们的配置特定变体OUTPUT_NAME_<CONFIG>ARCHIVE_OUTPUT_NAME_<CONFIG>LIBRARY_OUTPUT_NAME_<CONFIG>,以及<CONFIG>_POSTFIXDEBUG_POSTFIX目标属性。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_LINKER_FILE_PREFIX:tgt>

版本 3.15 新增。

用于链接tgt目标的文件的前缀。

另请参阅PREFIXIMPORT_PREFIX目标属性。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_LINKER_FILE_SUFFIX:tgt>

版本 3.15 新增。

用于链接tgt目标的文件名后缀。

后缀对应于文件扩展名(例如“.so”或“.lib”)。

另请参阅SUFFIXIMPORT_SUFFIX目标属性。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_LINKER_FILE_NAME:tgt>

用于链接tgt目标的文件的名称。

请注意,除非在CMP0112策略中另有说明,否则tgt不会被添加为计算此表达式的目标的依赖项。

$<TARGET_LINKER_FILE_DIR:tgt>

用于链接tgt目标的文件的目录。

请注意,除非在CMP0112策略中另有说明,否则tgt不会被添加为计算此表达式的目标的依赖项。

$<TARGET_LINKER_LIBRARY_FILE:tgt>

在 3.27 版本中新增。

当链接到tgt目标时,使用直接库而不是导入文件。这通常是tgt所代表的库(.a.so.dylib)。因此,在DLL平台上,它将是空字符串。

$<TARGET_LINKER_LIBRARY_FILE_BASE_NAME:tgt[,POSTFIX:(INCLUDE|EXCLUDE)]>

在 3.27 版本中新增。

版本 4.2 中添加: 选项POSTFIX,可用于控制<CONFIG>_POSTFIX目标属性值是否作为基本名称的一部分。默认值为POSTFIX:INCLUDE

用于链接tgt目标库文件的基本名称,即$<TARGET_LINKER_LIBRARY_FILE_NAME:tgt>去除前缀和后缀后,并且可选地去除后缀。例如,如果目标文件名是libbase_postfix.a,则基本名称是

  • base_postfix,对应于$<TARGET_LINKER_LIBRARY_FILE_BASE_NAME:tgt>$<TARGET_LINKER_LIBRARY_FILE_BASE_NAME:tgt,POSTFIX:INCLUDE>

  • base,对应于$<TARGET_LINKER_LIBRARY_FILE_BASE_NAME:tgt,POSTFIX:EXCLUDE>

另请参阅OUTPUT_NAMEARCHIVE_OUTPUT_NAMELIBRARY_OUTPUT_NAME目标属性,它们的配置特定变体OUTPUT_NAME_<CONFIG>ARCHIVE_OUTPUT_NAME_<CONFIG>LIBRARY_OUTPUT_NAME_<CONFIG>,以及<CONFIG>_POSTFIXDEBUG_POSTFIX目标属性。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_LINKER_LIBRARY_FILE_PREFIX:tgt>

在 3.27 版本中新增。

用于链接tgt目标的库文件的前缀。

另请参阅PREFIX目标属性。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_LINKER_LIBRARY_FILE_SUFFIX:tgt>

在 3.27 版本中新增。

用于链接tgt目标库文件的后缀。

后缀对应于文件扩展名(例如“.a”或“.dylib”)。

另请参阅SUFFIX目标属性。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_LINKER_LIBRARY_FILE_NAME:tgt>

在 3.27 版本中新增。

用于链接tgt目标的库文件的名称。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_LINKER_LIBRARY_FILE_DIR:tgt>

在 3.27 版本中新增。

用于链接tgt目标库文件的目录。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_LINKER_IMPORT_FILE:tgt>

在 3.27 版本中新增。

当链接到tgt目标时,使用导入文件。这通常是tgt所代表的导入文件(.lib.tbd)。因此,当链接步骤不涉及导入文件时,将返回空字符串。

$<TARGET_LINKER_IMPORT_FILE_BASE_NAME:tgt[,POSTFIX:(INCLUDE|EXCLUDE)]>

在 3.27 版本中新增。

版本 4.2 中添加: 选项POSTFIX,可用于控制<CONFIG>_POSTFIX目标属性值是否作为基本名称的一部分。默认值为POSTFIX:INCLUDE

用于链接tgt目标导入文件的基本名称,即$<TARGET_LINKER_IMPORT_FILE_NAME:tgt>去除前缀和后缀后,并且可选地去除后缀。例如,如果目标文件名是libbase_postfix.tbd,则基本名称是

  • base_postfix,对应于$<TARGET_LINKER_IMPORT_FILE_BASE_NAME:tgt>$<TARGET_LINKER_IMPORT_FILE_BASE_NAME:tgt,POSTFIX:INCLUDE>

  • base,对应于$<TARGET_LINKER_IMPORT_FILE_BASE_NAME:tgt,POSTFIX:EXCLUDE>

另请参阅OUTPUT_NAMEARCHIVE_OUTPUT_NAME,目标属性,它们的配置特定变体OUTPUT_NAME_<CONFIG>ARCHIVE_OUTPUT_NAME_<CONFIG>,以及<CONFIG>_POSTFIXDEBUG_POSTFIX目标属性。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_LINKER_IMPORT_FILE_PREFIX:tgt>

在 3.27 版本中新增。

用于链接tgt目标的导入文件的前缀。

另请参阅IMPORT_PREFIX目标属性。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_LINKER_IMPORT_FILE_SUFFIX:tgt>

在 3.27 版本中新增。

用于链接tgt目标的导入文件的后缀。

后缀对应于文件扩展名(例如“.lib”或“.tbd”)。

另请参阅IMPORT_SUFFIX目标属性。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_LINKER_IMPORT_FILE_NAME:tgt>

在 3.27 版本中新增。

用于链接tgt目标的导入文件的名称。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_LINKER_IMPORT_FILE_DIR:tgt>

在 3.27 版本中新增。

用于链接tgt目标的导入文件的目录。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_SONAME_FILE:tgt>

带soname(.so.3)的文件,其中tgt是目标名称。

$<TARGET_SONAME_FILE_NAME:tgt>

带soname(.so.3)的文件名。

请注意,除非在CMP0112策略中另有说明,否则tgt不会被添加为计算此表达式的目标的依赖项。

$<TARGET_SONAME_FILE_DIR:tgt>

带soname(.so.3)的文件的目录。

请注意,除非在CMP0112策略中另有说明,否则tgt不会被添加为计算此表达式的目标的依赖项。

$<TARGET_SONAME_IMPORT_FILE:tgt>

在 3.27 版本中新增。

带soname(.3.tbd)的导入文件,其中tgt是目标名称。

$<TARGET_SONAME_IMPORT_FILE_NAME:tgt>

在 3.27 版本中新增。

带soname(.3.tbd)的导入文件的名称。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_SONAME_IMPORT_FILE_DIR:tgt>

在 3.27 版本中新增。

带soname(.3.tbd)的导入文件的目录。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_PDB_FILE:tgt>

版本 3.1 中新增。

链接器生成的程序数据库文件(.pdb)的完整路径,其中tgt是目标名称。

版本 4.2 中已更改: PDB文件名始终包含DEBUG_POSTFIX<CONFIG>_POSTFIX目标属性指定的后缀。请参阅策略CMP0202

另请参阅PDB_NAMEPDB_OUTPUT_DIRECTORY目标属性及其配置特定变体PDB_NAME_<CONFIG>PDB_OUTPUT_DIRECTORY_<CONFIG>

$<TARGET_PDB_FILE_BASE_NAME:tgt[,POSTFIX:(INCLUDE|EXCLUDE)]>

版本 3.15 新增。

链接器生成的程序数据库文件(.pdb)的基本名称,其中tgt是目标名称。

版本 4.2 中添加: 选项POSTFIX,可用于控制<CONFIG>_POSTFIX目标属性值是否作为基本名称的一部分。默认值为POSTFIX:INCLUDE

版本 4.2 中已更改: PDB基本名称始终包含DEBUG_POSTFIX<CONFIG>_POSTFIX目标属性指定的后缀,除非选项POSTFIX的值为EXCLUDE。请参阅策略CMP0202

基本名称对应于目标PDB文件名(参见$<TARGET_PDB_FILE_NAME:tgt>)去除前缀和后缀后,并且可选地去除后缀。例如,如果目标文件名是base_postfix.pdb,则基本名称是

  • base_postfix,对应于$<TARGET_PDB_FILE_BASE_NAME:tgt>$<TARGET_PDB_FILE_BASE_NAME:tgt,POSTFIX:INCLUDE>

  • base,对应于$<TARGET_PDB_FILE_BASE_NAME:tgt,POSTFIX:EXCLUDE>

另请参阅OUTPUT_NAMEPDB_NAME目标属性及其配置特定变体OUTPUT_NAME_<CONFIG>PDB_NAME_<CONFIG>,以及<CONFIG>_POSTFIXDEBUG_POSTFIX目标属性。

请注意,tgt 不会作为此表达式正在评估的目标的依赖项添加。

$<TARGET_PDB_FILE_NAME:tgt>

版本 3.1 中新增。

链接器生成的程序数据库文件(.pdb)的名称。

请注意,除非在CMP0112策略中另有说明,否则tgt不会被添加为计算此表达式的目标的依赖项。

$<TARGET_PDB_FILE_DIR:tgt>

版本 3.1 中新增。

链接器生成的程序数据库文件(.pdb)的目录。

请注意,除非在CMP0112策略中另有说明,否则tgt不会被添加为计算此表达式的目标的依赖项。

$<TARGET_BUNDLE_DIR:tgt>

版本 3.9 中添加。

包目录(/path/to/my.app/path/to/my.framework/path/to/my.bundle)的完整路径,其中tgt是目标名称。

请注意,除非在CMP0112策略中另有说明,否则tgt不会被添加为计算此表达式的目标的依赖项。

$<TARGET_BUNDLE_DIR_NAME:tgt>

在 3.24 版本中添加。

包目录(my.appmy.frameworkmy.bundle)的名称,其中tgt是目标名称。

请注意,除非在CMP0112策略中另有说明,否则tgt不会被添加为计算此表达式的目标的依赖项。

$<TARGET_BUNDLE_CONTENT_DIR:tgt>

版本 3.9 中添加。

包内容目录的完整路径,其中tgt是目标名称。对于macOS SDK,它指向/path/to/my.app/Contents/path/to/my.framework/path/to/my.bundle/Contents。对于所有其他SDK(例如iOS),由于扁平包结构,它指向/path/to/my.app/path/to/my.framework/path/to/my.bundle

请注意,除非在CMP0112策略中另有说明,否则tgt不会被添加为计算此表达式的目标的依赖项。

$<TARGET_OBJECTS:tgt>

版本 3.1 中新增。

构建tgt产生的对象列表。这通常用于对象库目标。

$<TARGET_RUNTIME_DLLS:tgt>

3.21 版本新增。

目标在运行时依赖的DLL列表。这是通过目标传递依赖项中所有SHARED目标的位置确定的。如果只需要DLL的目录,请参阅TARGET_RUNTIME_DLL_DIRS生成器表达式。对可执行文件、SHARED库和MODULE库以外的目标使用此生成器表达式是错误的。在非DLL平台上,此表达式始终评估为空字符串

此生成器表达式可用于在POST_BUILD自定义命令中使用cmake -E copy -t命令,将目标依赖的所有DLL复制到其输出目录。例如:

find_package(foo CONFIG REQUIRED) # package generated by install(EXPORT)

add_executable(exe main.c)
target_link_libraries(exe PRIVATE foo::foo foo::bar)
add_custom_command(TARGET exe POST_BUILD
  COMMAND ${CMAKE_COMMAND} -E copy -t $<TARGET_FILE_DIR:exe> $<TARGET_RUNTIME_DLLS:exe>
  COMMAND_EXPAND_LISTS
)

注意

导入的目标仅在它们知道其.dll文件位置时才受支持。导入的SHARED库必须将IMPORTED_LOCATION设置为其.dll文件。有关详细信息,请参阅add_library导入库部分。许多查找模块会生成类型为UNKNOWN的导入目标,因此将被忽略。

在支持运行时路径(RPATH)的平台上,请参阅INSTALL_RPATH目标属性。在Apple平台上,请参阅INSTALL_NAME_DIR目标属性。

$<TARGET_RUNTIME_DLL_DIRS:tgt>

在 3.27 版本中新增。

包含目标在运行时依赖的DLL的目录列表(参见TARGET_RUNTIME_DLLS)。这是通过目标传递依赖项中所有SHARED目标的位置确定的。对可执行文件、SHARED库和MODULE库以外的目标使用此生成器表达式是错误的。在非DLL平台上,此表达式始终评估为空字符串

此生成器表达式可用于通过file(GENERATE)创建批处理文件,该文件相应地设置PATH环境变量。

$<TARGET_INTERMEDIATE_DIR:tgt>

版本 4.2 中添加。

存储中间目标文件(如对象文件和依赖项文件)的目录的完整路径。

导出与安装表达式

$<INSTALL_INTERFACE:...>

当属性通过install(EXPORT)导出时,...的内容;否则为空。

$<BUILD_INTERFACE:...>

当属性通过export()导出,或者当目标在同一构建系统中被另一个目标使用时,...的内容。否则展开为空字符串。

$<BUILD_LOCAL_INTERFACE:...>

3.26 版新增。

当目标在同一构建系统中被另一个目标使用时,...的内容。否则展开为空字符串。

$<INSTALL_PREFIX>

当目标通过install(EXPORT)导出时,安装前缀的内容,或在INSTALL_NAME_DIR属性或install(RUNTIME_DEPENDENCY_SET)INSTALL_NAME_DIR参数求值时,否则为空。

版本 3.27 中已更改: install(CODE)code参数或install(SCRIPT)的文件参数中,求值为安装前缀的内容。

多级表达式求值

$<GENEX_EVAL:expr>

3.12 版本新增。

在当前上下文中作为生成器表达式求值的expr的内容。这使得可以使用其求值结果本身是生成器表达式的生成器表达式。

$<TARGET_GENEX_EVAL:tgt,expr>

3.12 版本新增。

tgt目标的上下文中作为生成器表达式求值的expr的内容。这使得可以消耗自身包含生成器表达式的自定义目标属性。

能够求值生成器表达式对于管理支持生成器表达式的自定义属性非常有用。例如:

add_library(foo ...)

set_property(TARGET foo PROPERTY
  CUSTOM_KEYS $<$<CONFIG:DEBUG>:FOO_EXTRA_THINGS>
)

add_custom_target(printFooKeys
  COMMAND ${CMAKE_COMMAND} -E echo $<TARGET_PROPERTY:foo,CUSTOM_KEYS>
)

printFooKeys自定义命令的简单实现是错误的,因为CUSTOM_KEYS目标属性没有被求值,内容被原样传递(即$<$<CONFIG:DEBUG>:FOO_EXTRA_THINGS>)。

为了获得预期的结果(即,如果配置是Debug,则为FOO_EXTRA_THINGS),需要求值$<TARGET_PROPERTY:foo,CUSTOM_KEYS>的输出。

add_custom_target(printFooKeys
  COMMAND ${CMAKE_COMMAND} -E
    echo $<TARGET_GENEX_EVAL:foo,$<TARGET_PROPERTY:foo,CUSTOM_KEYS>>
)

转义字符

这些表达式求值为特定的字符串字面量。在需要防止它们具有特殊含义的地方使用它们代替实际的字符串字面量。

$<ANGLE-R>

字面上的 >。例如,用于比较包含 > 的字符串。

$<COMMA>

字面上的 ,。例如,用于比较包含 , 的字符串。

$<SEMICOLON>

字面上的 ;。用于防止包含 ; 的参数发生列表展开。

$<QUOTE>

3.30 版本新增。

字面上的 "。用于允许在生成器表达式中包含字符串字面量引号。

已弃用的表达式

$<CONFIGURATION>

配置名称。自 CMake 3.0 起已弃用。请改用 CONFIG