如何在编译时使用程序的退出状态?

时间:2014-08-21 06:17:15

标签: cmake perl-xs

这个问题是我之前的问题:How to integrate such kind of source generator into CMake build chain?

目前,C源文件是以这种方式从XS生成的:

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文件时重新运行它。但是,如果我这样做,则必须删除未完成的源文件。

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

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

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

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

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,因此应根据操作系统类型决定这两个命令的名称。