【问题标题】:Ternary operator in CMake's generator expressionsCMake 生成器表达式中的三元运算符
【发布时间】:2016-03-27 09:39:34
【问题描述】:

Cmake 的generator expressions 允许我在某些函数调用中使用逻辑表达式。例如,如果我想在 Debug 模式下添加 /MTd 编译器标志,我可以说

add_compile_options($<$<CONFIG:Debug>:/MTd>)

如果CONFIG 等于“Debug”,这将使用值“/MTd”调用add_compile_options,否则使用空字符串。

但通常,我不想在一个值和空字符串之间做出决定,而是在两个值之间做出决定。在上面的例子中,如果CONFIGnot“调试”,我想传递/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>)

但这对我来说似乎相当 hacky,并且仅在一个选项是另一个选项的子字符串的情况下才有效。

【问题讨论】:

标签: cmake ternary-operator


【解决方案1】:

这是一个带有宏的工作示例:

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 . &amp;&amp; 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;

【讨论】:

  • 只是一个提示:如果boolean 包含生成器表达式,我认为第一个定义(取消引用变量的内容)和第二个定义(if 检查变量内容)都不起作用。跨度>
  • @Florian 你是对的。我已经尝试修复它,但是没有成功。但恕我直言,拥有一些 CMake 三元模块或至少一个 IIF() 样式的函数会很好。
【解决方案2】:

请注意,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

【讨论】:

  • 不错的发现!它记录在这里:cmake.org/cmake/help/v3.8/manual/…
  • 谢谢,但文档没有给出 $&lt;IF.. 构造的单个示例,这是我感到困惑的原因。
  • @vulcanraven 实际上,cmake 文档中的有用示例非常少。 Dawid Drozd 添加的示例是否对您有足够的帮助?
  • @LanceE.T.Compte,并没有只是作为示例 :) 我在某处看到了 $&lt;IF: $&lt;cond&gt;, trueValue&gt; 形式的代码,无需指定 false。我正在搜索有关$&lt;IF 构造的文档,但找不到。对我来说,$&lt;IF 听起来像是一个非常基本的东西,可以作为任何平台的文档的一部分。
  • @vulcanraven $ 记录在这里:cmake.org/cmake/help/latest/manual/… 省略 falseValue 将替换为空字符串。我实际上是在添加调试标志等时这样做的。
【解决方案3】:

让我们更明确一点:

add_custom_command(TARGET myProject PRE_BUILD
    COMMAND cd \"D:/projects/$<IF:$<CONFIG:Debug>,Debug,Release>\"
    COMMAND call prebuild.bat)

然后在生成的Visual Studio Project中,在项目“myProject”的属性窗口中。

当构建配置为“Debug”时,评估过程为:

  1. $&lt;IF:$&lt;CONFIG:Debug&gt;,Debug,Release&gt;
  2. $&lt;IF:1,Debug,Release&gt;
  3. Debug

当构建配置为“发布”时,评估过程为:

  1. $&lt;IF:$&lt;CONFIG:Debug&gt;,Debug,Release&gt;
  2. $&lt;IF:0,Debug,Release&gt;
  3. Release

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-14
    • 2019-02-10
    • 2012-09-02
    • 1970-01-01
    • 1970-01-01
    • 2016-04-06
    • 2011-09-09
    • 1970-01-01
    相关资源
    最近更新 更多