I have a project with a configuration file in it.
configure_file(version.h.in version/version.h)
The same code base is used for multiple build in a day, without cleaning between builds. The version.h file will be built the first time the build is run, but subsequent builds will not rebuild (and update the revision number) in the version.h.
Is there a way I can force CMake to always rebuild version.h regardless of changes, or better yet based on a change (or lack of change) in a subversion revision number?
There are a few issues you need to overcome to have this work.
CMakeLists.txt file is updated)custom_target which will be run every time you build (from the docs: "The target has no output file and is ALWAYS CONSIDERED OUT OF DATE") which generates the file, but that will force you to rebuild your generated version file every time.Here is an approach which overcomes all of the above hurdles:
First, create a library which will contain the compiled version information.
add_library(version STATIC ${CMAKE_CURRENT_BINARY_DIR}/version_gen.cc)
Now, add an artificial dependency between the library and a custom_target called gen_version
add_dependencies(version gen_version)
This will force gen_version to be run before building the version library.
Now create a custom_target called gen_version which will generate the version information:
add_custom_target(
gen_version
ALL
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/gen_version.cmake)
This custom target is added to the ALL target, and will be run every time you build. It will execute another cmake script called gen_version.cmake
This is the first trick. We get cmake to execute a subprocess and run a new cmake script on each build, in which the required version information is calculated anew each build.
The next trick is to call configure_file with a temporary output file, and only update the real version file if necessary. This prevents the need to recompile when the version doesn't change.
In the below example I show obtaining the version information from git - you can swap this for your subversion method.
gen_version.cmake:
# obtain the git version
execute_process(
OUTPUT_VARIABLE ${VERSION}
COMMAND git rev-parse --short HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
# configure the version file, but output to a temporary location
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/version_gen.in
${CMAKE_CURRENT_BINARY_DIR}/version_gen.cc.tmp
)
# compare with the real version file
execute_process(
COMMAND
${CMAKE_COMMAND} -E compare_files
${CMAKE_CURRENT_BINARY_DIR}/version_gen.cc.tmp
${CMAKE_CURRENT_BINARY_DIR}/version_gen.cc
RESULT_VARIABLE
VERSION_NEEDS_UPDATING
OUTPUT_QUIET
ERROR_QUIET
)
# update the real version file if necessary
if(VERSION_NEEDS_UPDATING)
execute_process(
COMMAND
${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_BINARY_DIR}/version_gen.cc.tmp
${CMAKE_CURRENT_BINARY_DIR}/version_gen.cc
)
endif()
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/version_gen.cc
PROPERTIES GENERATED TRUE)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With