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 的值更改为 01,看看会发生什么。

下面的定义也可以,而且更清楚:

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"时,评估过程为:

  1. $<IF:$<CONFIG:Debug>,Debug,Release>
  2. $<IF:1,Debug,Release>
  3. Debug

构建配置为"Release"时,评估过程为:

  1. $<IF:$<CONFIG:Debug>,Debug,Release>
  2. $<IF:0,Debug,Release>
  3. Release