0

这个问题是我上一个问题的后续:如何将这种源生成器集成到 CMake 构建链中?

目前,从 XS 生成 C 源文件是这样的:

set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${file_src_by_xs} PROPERTIES GENERATED 1)
add_custom_target(${file_src_by_xs}
    COMMAND ${XSUBPP_EXECUTABLE} ${XSUBPP_EXTRA_OPTIONS} ${lang_args} ${typemap_args} ${file_xs} >${CMAKE_CURRENT_BINARY_DIR}/${file_src_by_xs}
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    DEPENDS ${file_xs} ${files_xsh} ${_XSUBPP_TYPEMAP_FILES}
    COMMENT "generating source from XS file ${file_xs}"
)

GENERATED属性让 cmake 在配置时不检查此源文件的存在,并add_custom_targetxsubpp每次编译时总是重新运行。总是重新运行的原因是因为xsubpp即使失败也会生成一个不完整的源文件,所以整个编译有可能以一个不完整的源文件继续。

我发现总是重新运行源代码生成器并重新编译它很耗时。所以我想让它仅在修改依赖的 XS 文件时重新运行。但是,如果这样做,则必须删除不完整的生成源文件。

所以我的问题是:有什么办法可以删除生成的文件,只有当程序在编译时异常退出?

或更通用:有没有办法根据另一个命令在编译时的退出状态来运行命令?

4

2 回答 2

1

你总是可以用你喜欢的语言编写一个包装脚本,例如 Perl 或 Ruby,它运行 xsubpp 并在命令失败时删除输出文件。这样你就可以确定它是否存在,它是正确的。

另外,我建议您使用OUTPUT关键字 ofadd_custom_command告诉 CMake 该文件是执行命令的结果。(而且,如果你这样做,你不必GENERATED手动设置属性。)

于 2014-08-21T09:14:53.717 回答
0

受@Lindydancer 的回答启发,我通过多个命令在一个目标中实现了目的,并且不需要编写外部包装脚本。

set(source_file_ok ${source_file}.ok)
add_custom_command(
    OUTPUT ${source_file} ${source_file_ok}
    DEPENDS ${xs_file} ${xsh_files}
    COMMAND rm -f ${source_file_ok}
    COMMAND xsubpp ...... >${source_file}
    COMMAND touch ${source_file_ok}
)

add_library(${xs_lib} ${source_file})
add_dependencies(${xs_lib} ${source_file} ${source_file_ok})

自定义目标有 3 个命令。OK文件只有在xsubpp成功的时候才存在,这个文件是作为库的依赖加入的。当 xsubpp 不成功时,对 OK 文件的依赖会强制重新运行自定义命令。

唯一的缺陷是跨平台:并非所有操作系统都有touchrm,因此这两个命令的名称应根据操作系统类型确定。

于 2014-08-25T08:59:31.900 回答