使用CMake 3.20.1版,我正在做一些我认为相对简单的事情:检验cfg
通过-DCMAKE_BUILD_TYPE=<cfg>
的值是否为有效配置。
参考CMake generator expressions文档,$<CONFIG:cfgs>
似乎是$<IN_LIST:string,list>
的特殊情况,其中字符串是${CMAKE_CONFIGURATION_TYPES}
。我得到的CMake运行时错误强化了这一点,并告诉我遗漏了一些东西。
我期待的是这样的:
set( CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Build Configurations" FORCE )
if( NOT $<CONFIG:${CMAKE_CONFIGURATION_TYPES}> )
# Handle_the_bad_value()
endif()
当从命令行调用cmake .. -DCMAKE_BUILD_TYPE=Debug
时,但我得到以下错误:
CMake Error at CMakeLists.txt:45 (if):
if given arguments:
"NOT" "\$<CONFIG:Debug" "Release>"
Unknown arguments specified
替换
$<CONFIG:<cfg_list>
其中一项为:
$<IN_LIST:${CMAKE_BUILD_TYPE},${CMAKE_CONFIGURATION_TYPES}>
或
$<IN_LIST:"Debug","Debug;Release">
得到以下结果:
CMake Error at CMakeLists.txt:43 (if):
if given arguments:
"NOT" "\$<IN_LIST:Debug,Debug" "Release>"
Unknown arguments specified
在试验$<IN_LIST:str,list>
之前,我已经尝试了对原始语法的各种更改,但是由于我无法使IN_LIST
语法工作,我觉得我犯了一些根本性的错误,我也没有从文档中领会到这些错误。
后续实验,使用:
if( NOT ${CMAKE_BUILD_TYPE} IN_LIST ${CMAKE_CONFIGURATION_TYPES} )
产量:
CMake Error at CMakeLists.txt:43 (if):
if given arguments:
"NOT" "Debug" "IN_LIST" "Debug" "Release"
Unknown arguments specified
所以我尝试了蛮力:
if( NOT ( "Debug" IN_LIST "Debug;Release" ) )
它会进行计算,但计算结果不正确,因为它在列表中找不到"Debug",所以它会在if语句中输入代码。
if( NOT ( CMAKE_BUILD_TYPE IN_LIST CMAKE_CONFIGURATION_TYPES ) )
***是否按预期工作。注意:NOT
应该应用于括号内的 * expression *,但它仍然不能帮助我理解CONFIG
生成器表达式的正确语法。
2条答案
按热度按时间hs1ihplo1#
不能在
if
命令中使用 * 生成器表达式 *,因为生成器表达式仅在配置过程结束时展开,但需要立即计算if
条件。表达式
$<IN_LIST:<$CONFIG>,${CMAKE_CONFIGURATION_TYPES}>
在其他生成器表达式的BOOL上下文中有效。但它只能用于生成另一个字符串,不能用于发出错误。如果要检查用户指定的生成类型的正确性,则应考虑以下事项:
1.在多配置生成器(如Visual Studio)上,构建类型由构建阶段的
--config
选项给定。CMake自动检查此类构建类型是否与CMAKE_CONFIGURATION_TYPES
匹配,因此无需手动检查。1.在single-configiration生成器(如Makefile)上,构建类型通过
CMAKE_BUILD_TYPE
变量指定。因此生成器表达式中不需要引用构建类型。1.变量
CMAKE_CONFIGURATION_TYPES
应仅指定给多配置生成器。为单配置生成器设置该变量可能会混淆某些脚本(例如FindXXX.cmake
)。因此,您可以通过以下方式检查构建类型(基于that answer中的代码)
ma8fv8wu2#
使用CMake包括两个阶段:
cmake -S . -B _build
或cd _build && cmake ..
等cmake --build _build
或cd _build && make
等生成器表达式
$<suff>
在 * 构建项目时 * 被展开。它们在CMake脚本中 * 不 * 被展开。对于CMake脚本,在配置项目时,它只是文本。要在CMake中比较,就在CMake中比较。我猜: