问题描述
考虑以下自定义命令(最新的 CMake + ninja):
add_custom_command(
OUTPUT
${OUTPUT}
COMMAND
${python3_EXECUTABLE} script.py ${INPUT} > ${OUTPUT}
DEPENDS
${INPUT}
VERBATIM
COMMAND_EXPAND_LISTS
)
当 script.py
运行没有错误时,它工作正常。
然而,当 script.py
因错误而失败时,${OUTPUT}
仍会被创建。
因此,当前构建按预期失败,但下一个构建看到 ${OUTPUT}
比 ${INPUT}
更新,并且不会尝试再次运行自定义命令。
我希望构建系统在命令失败时自动删除 ${OUTPUT}
以防止出现这种情况,但显然这不会发生。
我天真地尝试做类似的事情:
${python3_EXECUTABLE} script.py ${INPUT} > ${OUTPUT} || rm -f ${OUTPUT}
但这不起作用,因为命令结果代码实际上是 rm
结果代码而不是 Python 的结果代码,因此自定义命令不会在后续构建中失败。
解决方法
您快到了,只需在 rm
之后添加一个命令,该命令将返回错误代码。例如。那样:
${Python3_EXECUTABLE} script.py ${INPUT} > ${OUTPUT} || (rm -f ${OUTPUT} && /bin/false)
使用这样的命令 VERBATIM
不应使用 add_custom_command
选项:使用该选项 CMake 引用方括号((
和 )
),这会阻止 shell 进行解释用于分组目的。
我希望构建系统在命令失败时自动删除 ${OUTPUT}
请注意,CMake 本身不是构建系统,它只是为构建系统生成代码。
例如,当 CMake 生成 Makefile 时,它 adds .DELETE_ON_ERROR target,因此 make
实用程序实际上会在失败时删除输出文件。
看起来,Ninja 没有 Make 那样的功能。或者 CMake 在为 Ninja 生成代码时不使用此功能。