如何在命令输出发生变化时触发CMake重新配置

时间:2016-07-06 09:14:15

标签: git cmake

我希望在命令输出发生变化时触发CMake配置;具体来说,我正在尝试在git describe --always --dirty的输出与之前配置CMake时发生变化时尝试进行CMake配置。

大多数此问题都可以通过观看HEAD文件并将symref解析为refs/heads/[branch]并将其与configure_file(...)相关联来解决,但是这种情况在树时无法解决处于脏状态(IE有未提交的修改时)。在这种情况下,git describe --always --dirty会将-dirty后缀附加到输出。

当发生这种情况时,git文件没有变化,只有git注意到存储状态的差异所以我不能configure_file(...)这里的任何文件让cmake注意到更改并重新配置。< / p>

所以我想找到一种方法让cmake运行git命令注意输出的差异并触发重新配置,几乎需要类似于预重新配置检查阶段。

如果有人知道如何能够实现这种行为,那么不确定这是否可行?

1 个答案:

答案 0 :(得分:1)

问题

这里的问题是&#34;预重新配置检查阶段&#34;由您的构建环境处理。 CMake仅在其某些输入文件被更改时被调用(因为CMake已为您的构建环境生成规则以跟踪这些文件是否被更改)。

对于这个讨论,我们假设你有类似的东西:

execute_process(
    COMMAND ${GIT_EXECUTABLE} describe --always --dirty
    OUTPUT_VARIABLE _git_file_list
    OUTPUT_STRIP_TRAILING_WHITESPACE
)

configure_file(version.h.in version.h)

外部命令输出更改时没有内置重新配置

我不认为&#34;将外部命令的输出检查为预重新配置步骤&#34;没有您参与构建过程的其他脚本是可能的。

您可以强制CMake每次重新配置,例如在实际构建之前调用make rebuild_cache或添加例如add_custom_command(TARGET MyExe POST_BUILD ${CMAKE_COMMAND} -E remove ${CMAKE_CURRENT_BINARY_DIR}/version.h),但每次调用配置过程都是非常耗时的事情。

<强>解决方案

在我的项目中,我将上面的代码移到了自己的WriteVersionInfo.cmake脚本中:

set(_version_cpp_full_path "${CMAKE_CURRENT_BINARY_DIR}/version.cpp")
set(_version_obj_full_path "${_version_cpp_full_path}${CMAKE_CXX_OUTPUT_EXTENSION}")

string(REPLACE " " ";" _compiler_flags_list ${CMAKE_CXX_FLAGS})

# Create a dummy output to satisfy dependency check
if (NOT EXISTS ${_version_obj_full_path})
    file(WRITE ${_version_obj_full_path} "")
endif()

add_custom_command(
    TARGET MyExe
    PRE_LINK 
    COMMAND ${CMAKE_COMMAND} -D GIT_EXECUTABLE=${GIT_EXECUTABLE} 
                             -D _version_cpp_name=${_version_cpp_full_path} 
                             -P ${CMAKE_CURRENT_SOURCE_DIR}/WriteVersionInfo.cmake
    COMMAND ${CMAKE_CXX_COMPILER} ${_compiler_flags_list} 
                                  -o ${_version_obj_full_path} 
                                  -c ${_version_cpp_full_path}
    VERBATIM
)

target_link_libraries(
    MyExe
    ${_version_obj_full_path}
)

我直接写入.cpp文件并直接将其作为PRE_LINK步骤传递给编译器。请注意,上述方法不适用于库目标(因为没有预链接步骤)。

<强>参考