arghol
arghol

Reputation: 795

How to always re-generate version header file when underlying VERSION text file changes using CMake?

I maintain a C++ framework/library that uses CMake as its build system. The framework's version is reflected in a file called VERSION (as in many open source libraries).

I would like to generate a C++ header file with a version string, using VERSION as input. I also want this to happen during a re-build, not just when recreating project files. It would be desirable if VERSION was a dependency so the header file is created only when VERSION has changed.

I am familiar with the technique using the file() command in CMake to read the contests of VERSION, e.g.

file(STRINGS "VERSION" FRAMEWORK_VERSION)

And then generating a file using the configure_file command, e.g.:

configure_file(version.h.in version.h)

But this only generates the header file during the generation of project files. If the VERSION file is changed, the version header file will not be re-generated when re-building (i.e. running cmake --build .).

I know I can use like a Python script run as a CMake macro and always create the version header during the build, but I find it a bit annoying.

What is the best practice here?

Isn't it possible to solve this by only using CMake?

Upvotes: 6

Views: 8117

Answers (1)

Kevin
Kevin

Reputation: 18243

One CMake-only solution is to wrap the commands you suggested in a custom target to run a CMake script. If you make your library depend on the custom target, it will behave per the following:

  • Generates version.h at compile-time, before building your library.
  • Only re-generates version.h if its contents will change (new version number or new template file, version.h.in)

The script (let's say VersionHeader.cmake) for the custom target will read the version number from the VERSION file, and generate a new version.h file if necessary. The script can look like this:

file(STRINGS "${CMAKE_SOURCE_DIR}/VERSION" FRAMEWORK_VERSION)
configure_file(${CMAKE_CURRENT_LIST_DIR}/version.h.in ${CMAKE_CURRENT_LIST_DIR}/version.h @ONLY)

Then, in your CMakeLists.txt file, define a custom target to run a script:

add_custom_target(VersionHeader
  ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_LIST_DIR}/VersionHeader.cmake
)
add_dependencies(MyFrameworkLib VersionHeader)

Upvotes: 4

Related Questions