CMake中如何运行复合脚本语句及解决ExternProject_Add带参命令执行报错
问题根因
报错本质是CMake参数传递机制和自定义宏的拼接逻辑不匹配,和空格没有直接关系:
- 当初在宏的
arg和ARGN之间手动加分号的操作,完全是冗余设计:CMake宏接收到的连续多参数,会自动整合成用分号分隔的列表存入ARGN,根本不需要手动拼接 - 当你把已经是列表格式的
PATCH_CMD传入宏时,如果操作时误把整个列表用引号包成单个字符串传入,宏的形参arg会直接接收到整段带分号的命令字符串,此时ARGN为空,拼接完成的补丁命令会把整段字符串当成可执行文件路径调用,自然抛出“文件不存在”的报错 - 之前
mkdir -p <SOURCE_DIR>/install能正常跑,只是因为传参时刚好没触发宏的参数错位逻辑,属于凑巧适配的场景,换带多参数的脚本命令就会暴露拼接逻辑的bug
可行修正方案
1. 重构自定义宏的拼接逻辑
去掉手动加分号的冗余操作,直接透传所有入参为补丁命令列表,从根源上避免参数错位:
macro(SET_PATCH_CMD) # 直接把所有宏入参作为补丁命令,天然是ExternalProject可识别的分号分隔列表格式 set(${PROJECT_NAME}_patch_cmd ${ARGN}) message(STATUS "Patch command : ${${PROJECT_NAME}_patch_cmd}") endmacro(SET_PATCH_CMD)
这种写法下,不管传入的是短命令、带多参数的脚本路径,还是复杂的复合shell命令,所有片段都会被正确识别为独立元素,不会出现黏连错位。
2. 正确调用宏传入已有命令变量
当你提前把补丁命令存在PATCH_CMD变量里时,不要用引号把整个变量包裹成单字符串传入,直接让CMake展开列表元素即可:
SET(PATCH_CMD <SOURCE_DIR>/scripts/my_schript.sh arg1 arg2 arg3) # 直接展开列表传入宏,不要加多余引号包裹 SET_PATCH_CMD(${PATCH_CMD})
展开后传入宏的参数会自动拆分为独立元素:脚本路径、arg1、arg2、arg3,宏会把这些元素正确组装为ExternalProject要求的补丁命令格式。
3. 兼容带空格的路径/参数场景
如果脚本路径、命令参数本身包含空格,不要靠空格硬拼命令字符串,用list(APPEND)逐元素构造标准命令列表,从根源避免拆分错位:
# 逐元素追加命令片段,自动处理路径里的空格、特殊字符 set(patch_script "<SOURCE_DIR>/scripts/my schript with space.sh") list(APPEND PATCH_CMD ${patch_script} "arg with space" "arg2" "arg3") SET_PATCH_CMD(${PATCH_CMD})
内容的提问来源于stack exchange,提问作者a k
相关产品推荐
相关产品推荐

