cmake-generator-expressions(7)

简介

生成器表达式在构建系统生成期间被求值,以生成特定于每个构建配置的信息。它们的形式为 $<...>。例如:

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

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

生成器表达式允许在许多目标属性的上下文中使用,例如 LINK_LIBRARIESINCLUDE_DIRECTORIESCOMPILE_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 的任何其他值都会导致错误。

3.28 版本新增: 此生成器表达式会短路求值,因此当 condition1 时,false_string 中的生成器表达式将不会求值,当 condition 为 0 时,true_string 中的生成器表达式将不会求值。

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

$<$<CONFIG:Debug>:DEBUG_MODE>

可以使用 $<BOOL:...> 生成器表达式包装布尔值类型的 condition 值(10 以外):

$<BOOL:string>

string 转换为 01。如果满足以下任一条件,则求值为 0

  • string 为空,

  • string0FALSEOFFNNOIGNORENOTFOUND 在大小写不敏感的情况下相等,或者

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

否则求值为 1

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

$<$<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

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 版本中添加。

将每个 item 追加到 list 后的列表。多个项目应以逗号分隔。

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

在 3.27 版本中添加。

将每个 item 插入到 list 开头的列表。如果有多个项目,则应以逗号分隔,并且将保留前置项目的顺序。

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

在 3.27 版本中添加。

item(或多个项目)插入到指定 indexlist。多个项目应以逗号分隔。

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

$<LIST:POP_BACK,list>

在 3.27 版本中添加。

删除最后一个项目的 list

$<LIST:POP_FRONT,list>

在 3.27 版本中添加。

删除第一个项目的 list

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

在 3.27 版本中添加。

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

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

在 3.27 版本中添加。

删除每个给定 index 处项目的 list

$<LIST:REMOVE_DUPLICATES,list>

在 3.27 版本中添加。

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

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

在 3.27 版本中添加。

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

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

在 3.27 版本中添加。

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

注意

TRANSFORM 子命令不会更改列表中项目的数量。如果指定了 SELECTOR,则只会更改某些项目,其他项目将保持与转换前相同的状态。

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

APPENDPREPEND

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

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

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

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

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

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

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

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

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) 的手册页),以便将连续的数字作为整数进行比较。例如,以下列表 10.0 1.1 2.1 8.0 2.0 3.1 如果选择 NATURAL 比较,将被排序为 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 选项之一:

升序

以升序对列表进行排序。当未给出 ORDER 选项时,这是默认行为。

降序

以降序对列表进行排序。

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

$<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: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 版本中添加。

如果路径是绝对路径,则返回 1,否则返回 0

$<PATH:IS_RELATIVE,path>

在 3.24 版本中添加。

这将返回与 IS_ABSOLUTE 相反的结果。

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

在 3.24 版本中添加。

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

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

路径分解

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

$<PATH:GET_*,...>

在 3.24 版本中添加。

以下操作从路径中检索不同的组件或组件组。有关每个路径组件的含义,请参阅 路径结构和术语

在 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 样式格式。

在 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,返回所有附加到 pathinput 参数。根据 input 的值,可能会丢弃 path 的值。

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

$<PATH:REMOVE_FILENAME,path...>

在 3.24 版本中添加。

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

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

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

在 3.24 版本中添加。

返回文件名组件被 input 替换的 path。如果 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 版本中添加。

返回扩展名(如果有)被 input 替换的 path

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

$<PATH:NORMAL_PATH,path...>

在 3.24 版本中添加。

根据规范化中描述的步骤,返回规范化的 path

$<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 路径。... 必须是绝对路径。

在 3.14 版本中添加: ... 可以是分号分隔的路径列表,在这种情况下,每个路径都会单独转换,并使用 shell 路径分隔符(POSIX 上为 :,Windows 上为 ;)生成结果列表。请务必将包含此生成器表达式的参数用双引号括起来,以便 ; 不会拆分参数。

配置表达式

$<CONFIG>

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

$<CONFIG:cfgs>

如果配置是逗号分隔列表 cfgs 中的任何一个条目,则返回 1,否则返回 0。这是不区分大小写的比较。当在 MAP_IMPORTED_CONFIG_<CONFIG> 中的映射在 IMPORTED 目标的属性上评估时,此表达式也会考虑该映射。

在 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

在 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

在 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 是逗号分隔的列表。如果 Fortran 编译器的 CMake 编译器 ID 与 compiler_ids 中的任何一个条目匹配,则返回 1,否则返回 0

在 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 是逗号分隔的列表。如果 HIP 编译器的 CMake 编译器 ID 与 compiler_ids 中的任何一个条目匹配,则返回 1,否则返回 0

$<ISPC_COMPILER_ID>

在 3.19 版本中添加。

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

$<ISPC_COMPILER_ID:compiler_ids>

在 3.19 版本中添加。

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

$<C_COMPILER_FRONTEND_VARIANT>

在 3.30 版本中添加。

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

$<C_COMPILER_FRONTEND_VARIANT:compiler_ids>

在 3.30 版本中添加。

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

$<CXX_COMPILER_FRONTEND_VARIANT>

在 3.30 版本中添加。

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

$<CXX_COMPILER_FRONTEND_VARIANT:compiler_ids>

在 3.30 版本中添加。

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

$<CUDA_COMPILER_FRONTEND_VARIANT>

在 3.30 版本中添加。

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

$<CUDA_COMPILER_FRONTEND_VARIANT:compiler_ids>

在 3.30 版本中添加。

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

$<OBJC_COMPILER_FRONTEND_VARIANT>

在 3.30 版本中添加。

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

$<OBJC_COMPILER_FRONTEND_VARIANT:compiler_ids>

在 3.30 版本中添加。

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

$<OBJCXX_COMPILER_FRONTEND_VARIANT>

在 3.30 版本中添加。

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

$<OBJCXX_COMPILER_FRONTEND_VARIANT:compiler_ids>

在 3.30 版本中添加。

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

$<Fortran_COMPILER_FRONTEND_VARIANT>

在 3.30 版本中添加。

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

$<Fortran_COMPILER_FRONTEND_VARIANT:compiler_ids>

在 3.30 版本中添加。

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

$<HIP_COMPILER_FRONTEND_VARIANT>

在 3.30 版本中添加。

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

$<HIP_COMPILER_FRONTEND_VARIANT:compiler_ids>

在 3.30 版本中添加。

其中 compiler_ids 是逗号分隔的列表。如果 HIP 编译器的 CMake 编译器前端变体与 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:language>,了解关于此生成器表达式可移植性的说明。

$<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 包含目录(编译器 ID 检查被省略)。它还为 CUDA 指定了 COMPILING_CUDA 编译定义。

请注意,对于 Visual Studio 生成器Xcode,没有办法分别为 CCXX 语言表示目标范围的编译定义或包含目录。此外,对于 Visual Studio 生成器,没有办法分别为 CCXX 语言表示目标范围的标志。在这些生成器下,如果存在任何 C++ 源文件,则 C 和 C++ 源文件的表达式都将使用 CXX 进行评估,否则将使用 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 版本中添加。

当用于编译单元的语言与 language 匹配,并且 CMake 的 language 编译器 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 是一个逗号分隔的列表。如果所有 features 对于“head”目标都可用,则评估为 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

在 3.18 版本中添加。

评估链接选项时目标的链接语言。请参阅相关的布尔表达式 $<LINK_LANGUAGE:languages>,了解关于此生成器表达式可移植性的说明。

注意

链接库属性不支持此生成器表达式,以避免由于这些属性的双重评估而产生的副作用。

在 3.18 版本中添加。

当用于链接步骤的语言与 language 匹配,并且语言链接器的 CMake 编译器 ID 与 compiler_ids 中的任何一个逗号分隔的条目匹配时,为 1,否则为 0。此表达式是 $<LINK_LANGUAGE:language>$<LANG_COMPILER_ID:compiler_ids> 组合的简写形式。此表达式可用于为目标中特定语言和链接器组合指定链接库、链接选项、链接目录和链接依赖项。例如

add_library(libC_Clang ...)
add_library(libCXX_Clang ...)
add_library(libC_Intel ...)
add_library(libCXX_Intel ...)

add_executable(myapp main.c)
if (CXX_CONFIG)
  target_sources(myapp PRIVATE file.cxx)
endif()
target_link_libraries(myapp
  PRIVATE $<$<LINK_LANG_AND_ID:CXX,Clang,AppleClang>:libCXX_Clang>
          $<$<LINK_LANG_AND_ID:C,Clang,AppleClang>:libC_Clang>
          $<$<LINK_LANG_AND_ID:CXX,Intel>:libCXX_Intel>
          $<$<LINK_LANG_AND_ID:C,Intel>:libC_Intel>)

这指定了基于编译器 ID 和链接语言的不同链接库。当 ClangAppleClangCXX 链接器时,此示例将具有目标 libCXX_Clang 作为链接依赖项,当 IntelCXX 链接器时,将具有 libCXX_Intel 作为链接依赖项。同样,当 C 链接器是 ClangAppleClang 时,将添加目标 libC_Clang 作为链接依赖项,当 IntelC 链接器时,将添加 libC_Intel 作为链接依赖项。

请参阅 $<LINK_LANGUAGE:language> 相关的说明,了解有关此生成器表达式用法的约束。

目标依赖表达式

目标元数据

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

$<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”目标时 policyNEW,则为 1,否则为 0。如果未设置 policy,则将发出策略的警告消息。此生成器表达式仅适用于策略的子集。

目标属性

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

$<TARGET_PROPERTY:tgt,prop>

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

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

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

$<TARGET_PROPERTY:prop>

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

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

目标构建规范属性

这些评估为 分号分隔的列表,表示目标本身的值与目标的 LINK_LIBRARIES 命名的目标上相应 目标使用要求 值的并集

LINK_LIBRARIES 本身的评估不是传递的。

目标使用要求属性

这些评估为 分号分隔的列表,表示目标本身的值与目标的 INTERFACE_LINK_LIBRARIES 命名的目标上相同属性值的并集

INTERFACE_LINK_LIBRARIES 本身的评估不是传递的。

自定义传递属性

在 3.30 版本中添加。

这些在评估期间按如下方式处理

如果 PROPTRANSITIVE_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>

在 3.15 版本中添加。

tgt 的基本名称,即不带前缀和后缀的 $<TARGET_FILE_NAME:tgt>。例如,如果 tgt 文件名是 libbase.so,则基本名称是 base

另请参见 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 文件名。

请注意,tgt 不会作为评估此表达式的目标的依赖项添加(请参阅策略 CMP0112)。

$<TARGET_FILE_DIR:tgt>

tgt 二进制文件的目录。

请注意,tgt 不会作为评估此表达式的目标的依赖项添加(请参阅策略 CMP0112)。

$<TARGET_IMPORT_FILE:tgt>

在 3.27 版本中添加。

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

当没有与目标关联的导入文件时,这将扩展为空字符串。

$<TARGET_IMPORT_FILE_BASE_NAME:tgt>

在 3.27 版本中添加。

目标 tgt 的链接器导入文件的基本名称,不带前缀或后缀。例如,如果目标文件名是 libbase.tbd,则基本名称是 base

另请参见 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 上,根据 ENABLE_EXPORTS 属性的值,它可能是与共享库关联的 .tbd 导入文件。

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

$<TARGET_LINKER_FILE_BASE_NAME:tgt>

在 3.15 版本中添加。

用于链接目标 tgt 的文件的基本名称,即不带前缀和后缀的 $<TARGET_LINKER_FILE_NAME:tgt>。例如,如果目标文件名是 libbase.a,则基本名称是 base

另请参见 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 的文件的名称。

请注意,tgt 不会作为评估此表达式的目标的依赖项添加(请参阅策略 CMP0112)。

$<TARGET_LINKER_FILE_DIR:tgt>

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

请注意,tgt 不会作为评估此表达式的目标的依赖项添加(请参阅策略 CMP0112)。

$<TARGET_LINKER_LIBRARY_FILE:tgt>

在 3.27 版本中添加。

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

$<TARGET_LINKER_LIBRARY_FILE_BASE_NAME:tgt>

在 3.27 版本中添加。

用于链接目标 tgt 的库文件的基本名称,即不带前缀和后缀的 $<TARGET_LINKER_LIBRARY_FILE_NAME:tgt>。例如,如果目标文件名是 libbase.a,则基本名称是 base

另请参见 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>

在 3.27 版本中添加。

用于链接目标 tgt 的导入文件的基本名称,即不带前缀和后缀的 $<TARGET_LINKER_IMPORT_FILE_NAME:tgt>。例如,如果目标文件名是 libbase.tbd,则基本名称是 base

另请参见 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)。

请注意,tgt 不会作为评估此表达式的目标的依赖项添加(请参阅策略 CMP0112)。

$<TARGET_SONAME_FILE_DIR:tgt>

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

请注意,tgt 不会作为评估此表达式的目标的依赖项添加(请参阅策略 CMP0112)。

$<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 是目标的名称。

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

$<TARGET_PDB_FILE_BASE_NAME:tgt>

在 3.15 版本中添加。

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

基本名称对应于目标 PDB 文件名(参见 $<TARGET_PDB_FILE_NAME:tgt>),不带前缀和后缀。例如,如果目标文件名是 base.pdb,则基本名称是 base

另请参见 PDB_NAME 目标属性及其配置特定的变体 PDB_NAME_<CONFIG>

还可以考虑 <CONFIG>_POSTFIXDEBUG_POSTFIX 目标属性。

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

$<TARGET_PDB_FILE_NAME:tgt>

在 3.1 版本中添加。

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

请注意,tgt 不会作为评估此表达式的目标的依赖项添加(请参阅策略 CMP0112)。

$<TARGET_PDB_FILE_DIR:tgt>

在 3.1 版本中添加。

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

请注意,tgt 不会作为评估此表达式的目标的依赖项添加(请参阅策略 CMP0112)。

$<TARGET_BUNDLE_DIR:tgt>

3.9 版本新增。

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

请注意,tgt 不会作为评估此表达式的目标的依赖项添加(请参阅策略 CMP0112)。

$<TARGET_BUNDLE_DIR_NAME:tgt>

在 3.24 版本中添加。

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

请注意,tgt 不会作为评估此表达式的目标的依赖项添加(请参阅策略 CMP0112)。

$<TARGET_BUNDLE_CONTENT_DIR:tgt>

3.9 版本新增。

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

请注意,tgt 不会作为评估此表达式的目标的依赖项添加(请参阅策略 CMP0112)。

$<TARGET_OBJECTS:tgt>

在 3.1 版本中添加。

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

$<TARGET_RUNTIME_DLLS:tgt>

在 3.21 版本中添加。

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

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

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 导入的库 部分。“Find Modules”产生许多类型为 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 环境变量。

导出和安装表达式

$<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) 的 file 参数中评估为安装前缀的内容。

多级表达式求值

$<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