强制CMake为每个构建生成configure_file目标

时间:2015-06-25 17:44:36

标签: c++ cmake

我的CMakeLists.txt文件中有以下命令

configure_file([...]/Version.h.in [...]/Version.h @ONLY)

如何在每次构建时运行它,但不仅仅在Version.h.in更改时运行?我需要这个,因为Version.h中有__DATE__个宏,实际上应该被视为每个构建的新内容,即使它保持不变。

Version.h.in看起来像

static const char VERSION[] = "Bla-bla-bla " @FOOBAR@ " built on " __DATE__;

2 个答案:

答案 0 :(得分:4)

I transfered my version string generation into its own CMake script that I call with ${CMAKE_COMMAND} -P ... in a add_custom_command()/add_custom_target() and make my target using it depend on it.

In your case let's say you have a DateToVersionH.cmake script like this:

string(TIMESTAMP _date "%d %m %Y %H:%M")
file(WRITE ${VERSION_FILE_NAME} "#define MY_VERSION \"Bla-bla-bla ${FOOBAR} built on ${_date}\"\n")

you can do something like:

add_custom_command(
    TARGET MyExe
    PRE_BUILD
    COMMAND ${CMAKE_COMMAND} -DVERSION_FILE_NAME=Version.h -DFOOBAR="${FOOBAR}" -P "${CMAKE_CURRENT_LIST_DIR}/DateToVersionH.cmake"
)

See also use CMake to get build-time svn revision

That may not be enough if your make environment checks all the "needs to be rebuild" prior of calling the necessary steps (e.g. in Ninja only the outputs of custom commands are re-scanned; for more details see the Ninja documentation for the restat rule variable and this discussion which led to the introduction of the BYPRODUCTS option in add_custom_command()).

So you could simply add to your build shell script - prior to calling the actual make - removing the object file containing the version information.

Or you are forcing the re-compilation of the object before linking. This would - assuming you have a Version.c which includes Version.h - look like this:

include_directories(${CMAKE_CURRENT_BINARY_DIR})
execute_process(COMMAND "${CMAKE_COMMAND}" -DVERSION_FILE_NAME=Version.h -DFOOBAR="${FOOBAR}" -P "${CMAKE_CURRENT_LIST_DIR}/DateToVersionH.cmake")
add_library(MyVersionObj OBJECT Version.c)

add_executable(MyExe ... $<TARGET_OBJECTS:MyVersionObj>)

add_custom_command(
    TARGET MyExe
    PRE_LINK 
    COMMAND "${CMAKE_COMMAND}" -DVERSION_FILE_NAME=Version.h -DFOOBAR="${FOOBAR}" -P "${CMAKE_CURRENT_LIST_DIR}/DateToVersionH.cmake"
    COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" --config $<CONFIG> --target "MyVersionObj"
)

Thinking about it, just deleting the object file and utilizing your current __DATE__ solution is the simplest solution.

For another "git version solution" see CMake: Automatically use git tags as version strings and How can I pass git SHA1 to compiler as definition using cmake?

答案 1 :(得分:1)

只是提交一个对我来说似乎更简单的替代答案,并且如果您在任何 *nix 操作系统下都能做到这一点:

touch Version.h.in 作为预构建命令运行,无论是在您的 IDE 中实现,还是在您的 shell 或您的 CI(它可能无用)中运行您的 cmake 命令之前手动执行,都允许系统地生成Version.h 文件,即使它没有被修改。