CMake 生成器表达式中的三元运算符
Ternary operator in CMake's generator expressions
Cmake 的 generator expressions 允许我在某些函数调用中使用逻辑表达式。例如,如果我想在调试模式下添加 /MTd
编译器标志,我可以说
add_compile_options($<$<CONFIG:Debug>:/MTd>)
如果 CONFIG
等于 "Debug",这将使用值“/MTd”调用 add_compile_options
,否则使用空字符串。
但通常,我不想在一个值和空字符串之间做出决定,而是在两个值之间做出决定。在上面的例子中,如果 CONFIG
是 而不是 "Debug",我想传递 /MT
(没有尾随的 d)。我喜欢这样的语法:
add_compile_options($<$<CONFIG:Debug>:/MTd:/MT>)
请注意,根据 CMake 规范,以上是无效代码。我想出的最好的方法是:
add_compile_options($<$<CONFIG:Debug>:/MTd>$<$<NOT:$<CONFIG:Debug>>:/MT>)
这对我来说似乎非常多余。是否有更短、更易读的方式来决定两个值?
注意:我意识到在这种特殊情况下,我可以这样写:
add_compile_options(/MT$<$<CONFIG:Debug>:d>)
但这对我来说似乎很老套,并且只适用于一个选项是另一个选项的子字符串的情况。
这是一个工作示例,带有一个宏:
cmake_minimum_required(VERSION 2.8.12)
macro(ternary var boolean value1 value2)
set(${var} $<${${boolean}}:${value1}>$<$<NOT:${${boolean}}>:${value2}>)
endmacro()
set(mybool 0)
ternary(myvar mybool hello world)
add_custom_target(print
${CMAKE_COMMAND} -E echo ${myvar}
)
创建一个 CMakeLists.txt
文件和 运行 cmake . && make print
(生成器表达式仅在构建时计算)。
尝试将 mybool
的值更改为 0
或 1
,看看会发生什么。
下面的定义也可以,而且更清楚:
cmake_minimum_required(VERSION 2.8.12)
macro(ternary var boolean value1 value2)
if(${boolean})
set(${var} ${value1})
else()
set(${var} ${value2})
endif()
endmacro()
set(mybool 0)
ternary(myvar mybool hello world)
add_custom_target(print
${CMAKE_COMMAND} -E echo ${myvar}
)
TL;DR
ternary(var boolean value1 value2)
表示,与C/C++相比:
int var = boolean ? value1 : value2;
请注意,cmake 3.8 准确地添加了您想要的生成器表达式...
$<IF:?,true-value...,false-value...>
true-value... if ? is 1, false-value... if ? is 0
用法示例:
target_link_libraries(MyLib PUBLIC
$<IF:$<CONFIG:Debug>,cppzmq,cppzmq-static>
)
其中 cppzmq
是在 Debug
构建中使用的共享库,而 cppzmq-static
是在其他情况下使用的静态库,例如Release
让我们更明确一点:
add_custom_command(TARGET myProject PRE_BUILD
COMMAND cd \"D:/projects/$<IF:$<CONFIG:Debug>,Debug,Release>\"
COMMAND call prebuild.bat)
然后在生成的Visual Studio工程中,在工程"myProject"window中属性.
构建配置为"Debug"时,评估过程为:
$<IF:$<CONFIG:Debug>,Debug,Release>
$<IF:1,Debug,Release>
Debug
构建配置为"Release"时,评估过程为:
$<IF:$<CONFIG:Debug>,Debug,Release>
$<IF:0,Debug,Release>
Release
Cmake 的 generator expressions 允许我在某些函数调用中使用逻辑表达式。例如,如果我想在调试模式下添加 /MTd
编译器标志,我可以说
add_compile_options($<$<CONFIG:Debug>:/MTd>)
如果 CONFIG
等于 "Debug",这将使用值“/MTd”调用 add_compile_options
,否则使用空字符串。
但通常,我不想在一个值和空字符串之间做出决定,而是在两个值之间做出决定。在上面的例子中,如果 CONFIG
是 而不是 "Debug",我想传递 /MT
(没有尾随的 d)。我喜欢这样的语法:
add_compile_options($<$<CONFIG:Debug>:/MTd:/MT>)
请注意,根据 CMake 规范,以上是无效代码。我想出的最好的方法是:
add_compile_options($<$<CONFIG:Debug>:/MTd>$<$<NOT:$<CONFIG:Debug>>:/MT>)
这对我来说似乎非常多余。是否有更短、更易读的方式来决定两个值?
注意:我意识到在这种特殊情况下,我可以这样写:
add_compile_options(/MT$<$<CONFIG:Debug>:d>)
但这对我来说似乎很老套,并且只适用于一个选项是另一个选项的子字符串的情况。
这是一个工作示例,带有一个宏:
cmake_minimum_required(VERSION 2.8.12)
macro(ternary var boolean value1 value2)
set(${var} $<${${boolean}}:${value1}>$<$<NOT:${${boolean}}>:${value2}>)
endmacro()
set(mybool 0)
ternary(myvar mybool hello world)
add_custom_target(print
${CMAKE_COMMAND} -E echo ${myvar}
)
创建一个 CMakeLists.txt
文件和 运行 cmake . && make print
(生成器表达式仅在构建时计算)。
尝试将 mybool
的值更改为 0
或 1
,看看会发生什么。
下面的定义也可以,而且更清楚:
cmake_minimum_required(VERSION 2.8.12)
macro(ternary var boolean value1 value2)
if(${boolean})
set(${var} ${value1})
else()
set(${var} ${value2})
endif()
endmacro()
set(mybool 0)
ternary(myvar mybool hello world)
add_custom_target(print
${CMAKE_COMMAND} -E echo ${myvar}
)
TL;DR
ternary(var boolean value1 value2)
表示,与C/C++相比:
int var = boolean ? value1 : value2;
请注意,cmake 3.8 准确地添加了您想要的生成器表达式...
$<IF:?,true-value...,false-value...>
true-value... if ? is 1, false-value... if ? is 0
用法示例:
target_link_libraries(MyLib PUBLIC
$<IF:$<CONFIG:Debug>,cppzmq,cppzmq-static>
)
其中 cppzmq
是在 Debug
构建中使用的共享库,而 cppzmq-static
是在其他情况下使用的静态库,例如Release
让我们更明确一点:
add_custom_command(TARGET myProject PRE_BUILD
COMMAND cd \"D:/projects/$<IF:$<CONFIG:Debug>,Debug,Release>\"
COMMAND call prebuild.bat)
然后在生成的Visual Studio工程中,在工程"myProject"window中属性.
构建配置为"Debug"时,评估过程为:
$<IF:$<CONFIG:Debug>,Debug,Release>
$<IF:1,Debug,Release>
Debug
构建配置为"Release"时,评估过程为:
$<IF:$<CONFIG:Debug>,Debug,Release>
$<IF:0,Debug,Release>
Release