如果某些布尔条件为真(例如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: $<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
部分中,我需要依靠特殊令牌,例如<BINARY_DIR>
.
COMMAND ./b2 "--stagedir=<BINARY_DIR>" --with-filesystem --with-program_options --with-test
我无法将命令移动到其他地方的 if 语句中,因为如果我这样做,则目录令牌不会展开。
代码可读性方面,生成器表达式是 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>
...
)
您可以在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