【问题标题】:Cmake generator expression commandCmake 生成器表达式命令
【发布时间】:2018-10-01 06:23:35
【问题描述】:

如果某些布尔条件为真(例如 ENABLE_TESTING),那么我想运行类似:

COMMAND ./b2 --with-filesystem --with-program_options --with-test

如果布尔条件为假,那么我想要:

COMMAND ""

看来我可以用这个非常丑陋的代码来实现:

COMMAND $<$<BOOL:${ENABLE_TESTING}>:./b2> $<$<BOOL:${ENABLE_TESTING}>:--with-filesystem> $<$<BOOL:${ENABLE_TESTING}>:--with-program_options> $<$<BOOL:${ENABLE_TESTING}>:--with-test>

但正如您所见,我必须一遍又一遍地重复布尔测试。如果我天真地尝试将它们组合成一个表达式:

COMMAND $<$<BOOL:${ENABLE_TESTING}>:./b2 --with-filesystem --with-program_options --with-test>

然后我收到错误/bin/sh: 1: $&lt;1:./b2: not found。显然,这些空格在生成器表达式被评估之前被解析。所以我引用了整件事:

COMMAND "$<$<BOOL:${ENABLE_TESTING}>:./b2 --with-filesystem --with-program_options --with-test>"

但这会产生错误/bin/sh 1: /b2 --with-filesystem --with-program_options --with-test: not found。我想它将整个事情视为命令的名称,而不是带有选项的命令。我怎样才能以一种干净且有效的方式编写这个?

编辑:我试图简化代码以作为一个最小示例,但我遗漏了一个额外的复杂性。此命令发生在 ExternalProject_Add 部分,我需要依赖特殊标记,例如 &lt;BINARY_DIR&gt;

COMMAND ./b2 "--stagedir=<BINARY_DIR>" --with-filesystem --with-program_options --with-test

我不能将命令移到其他地方的 if 语句中,因为如果我这样做了,那么目录标记就不会展开。

【问题讨论】:

  • 我不明白,你能发布一个最小的例子吗?
  • ? if (ENABLE_TESTING) set(args "./b2 --with-filesystem --with-program_options --with-test") else() set(args "\"\"") endif() execute_command(COMMAND "${args}") ???哦,我明白了。如果你COMMAND /bin/sh -c "[ -n \"$&lt;${ENABLE_TESTING}&gt;:x&gt;\" ] &amp;&amp; ./b2 --with-filesystem --with-program_options --with-test; " 怎么办?
  • @KamilCuk 我添加了一个编辑,解释了为什么第一个不起作用。第二个是特定于平台的,这违背了 cmake 的目的。

标签: cmake


【解决方案1】:

在代码可读性方面,生成器表达式是对 CMake 语言的不幸补充。在像您这样无法避免生成器表达式的情况下,我使用常规 CMake 变量来避免代码重复,即:

set (_runB2GenEx "$<BOOL:${ENABLE_TESTING}>")
ExternalProject_Add(example
    ...
    COMMAND 
        $<${_runB2GenEx}:./b2> 
        $<${_runB2GenEx}:--stagedir=<BINARY_DIR>> 
        $<${_runB2GenEx}:--with-filesystem> 
        $<${_runB2GenEx}:--with-program_options> 
        $<${_runB2GenEx}:--with-test>
    ...
)

【讨论】:

    【解决方案2】:

    你可以在COMMAND_EXPAND_LISTS的帮助下做到这一点:

    cmake_minimum_required(VERSION 3.11)
    set(ENABLE_TESTING 1)
    add_custom_target(
      foo COMMAND "$<$<BOOL:${ENABLE_TESTING}>:./b2;--with-filesystem;--with-program_options;--with-test>"
      COMMAND_EXPAND_LISTS)
    

    让我们检查它是否有效:

    $ cmake .
    $ VERBOSE=1 make foo
    ...
    ./b2 --with-filesystem --with-program_options --with-test
    Built target foo
    

    【讨论】:

    • 其中一个警告是不能提前在变量中设置命令(据我所知),否则不会出现特殊的 ExternalProject 标记,例如 &lt;BINARY_DIR&gt;评估。
    • @JeffM 它也可以在没有变量的情况下工作。我更新了答案。
    • 对不起,我应该更具体一些。 &lt;BINARY_DIR&gt;ExternalProject_Add 命令的上下文之外不起作用,这意味着自定义目标也不会扩展它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多