这个问题是我之前的问题: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_target
让xsubpp
始终在每次编译时重新运行。始终重新运行的原因是因为xsubpp
将生成一个不完整的源文件,即使它失败了,因此整个编译可能会继续使用不完整的源文件。
我发现总是重新运行源代码生成器并重新编译它是很费时间的。因此,我希望仅在修改相关XS文件时重新运行它。但是,如果我这样做,则必须删除未完成的源文件。
所以我的问题是:有没有办法删除生成的文件,只有当程序在编译时异常退出?
或更通用:有没有办法在编译时根据另一个命令的退出状态运行命令?
答案 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文件的依赖将强制再次运行自定义命令。
唯一的缺陷是跨平台:并非所有操作系统都有touch
和rm
,因此应根据操作系统类型决定这两个命令的名称。