如何在CMake中使用MultiValueArg使echo输出为单个字符串?
解决CMake中MultiValueArg参数列表换行导致Shell执行错误的问题
你遇到的问题是CMake中MultiValueArg类型的参数列表在传递给add_custom_command的COMMAND时,会被拆分成多行,Shell将换行后的内容识别为独立命令,最终执行报错。
根本原因
- CMake的列表元素如果包含空格,且传递时未加引号,会被拆分为多个列表项(比如
--some additional会变成两个元素:--some和additional)。 - 直接在
COMMAND中展开列表时,CMake会将每个列表元素单独传递,换行符会被Shell解析为命令分隔符,导致后续元素被当作新命令执行。
解决方案
方法1:配置阶段将列表转为单行字符串
使用string(JOIN)命令在CMake配置阶段将MultiValueArg列表合并为一个用空格分隔的单行字符串,再传递给Shell命令:
cmake_minimum_required(VERSION 3.22.1) function(MyFunc) set(options VERBOSE) set(oneValueArgs PROJECT_NAME) set(multiValueArgs PROJECT_ARGS) cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) # 将列表元素用空格连接成单行字符串 string(JOIN " " PROJECT_ARGS_STR "${ARG_PROJECT_ARGS}") project(${ARG_PROJECT_NAME}) add_custom_command( OUTPUT sample COMMAND echo "starting..." COMMAND echo "ARG_PROJECT_ARGS = [${PROJECT_ARGS_STR}]" COMMAND echo "done..." ) add_custom_target(${PROJECT_NAME} DEPENDS sample) endfunction() # 注意:带空格的参数必须用引号包裹,确保作为单个列表元素传递 MyFunc( PROJECT_NAME testing PROJECT_ARGS "--some additional" "--parameters here" "--to-test")
方法2:使用生成器表达式延迟合并(适合构建阶段动态参数)
如果参数列表需要在构建阶段才确定(比如依赖其他目标的输出),可以使用CMake的$<JOIN>生成器表达式,在构建阶段完成列表合并:
add_custom_command( OUTPUT sample COMMAND echo "starting..." # 用生成器表达式将列表元素用空格连接 COMMAND echo "ARG_PROJECT_ARGS = [$<JOIN:${ARG_PROJECT_ARGS}, >]" COMMAND echo "done..." )
验证效果
修改后执行cmake .和make testing,会得到正确的单行输出:
[100%] Generating sample starting... ARG_PROJECT_ARGS = [--some additional --parameters here --to-test] done...
内容的提问来源于stack exchange,提问作者Alexis Wilke
相关产品推荐
相关产品推荐

