Cmake 的 生成器表达式 允许我在某些函数调用中使用逻辑表达式。例如,如果我想在调试模式下添加
/MTd
编译器标志,我可以说
add_compile_options($<$<CONFIG:Debug>:/MTd>)
如果
CONFIG
等于“Debug”,则会使用值“/MTd”调用 add_compile_options
,否则使用空字符串。
但通常,我不想在一个值和空字符串之间做出决定,而是在两个值之间做出决定。在上面的示例中,如果
CONFIG
是 not“调试”,我想传递 /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>)
但这对我来说似乎相当老套,并且仅在一个选项是另一个选项的子字符串的情况下才有效。
$<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_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;博士
ternary(var boolean value1 value2)
意味着,与 C/C++ 相比:
int var = boolean ? value1 : value2;
add_custom_command(TARGET myProject PRE_BUILD
COMMAND cd \"D:/projects/$<IF:$<CONFIG:Debug>,Debug,Release>\"
COMMAND call prebuild.bat)
然后在生成的 Visual Studio 项目中,在项目“myProject”的属性窗口中。
当构建配置为“Debug”时,评估过程为:
$<IF:$<CONFIG:Debug>,Debug,Release>
$<IF:1,Debug,Release>
Debug
$<IF:$<CONFIG:Debug>,Debug,Release>
$<IF:0,Debug,Release>
Release
macro(build_target src_dir install_dir i2c_addr is_prod_build)
set(SUB_PROJ_PROD_QA $<IF:$<BOOL:${is_prod_build}>,PROD,QA>)
message("SUB_PROJ_PROD_QA=${SUB_PROJ_PROD_QA}")
endmacro()
然后我明白了,表达式根本没有被评估
[cmake] SUB_PROJ_PROD_QA=$<IF:$<BOOL:0>,PROD,QA>