Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

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?

like image 951
arghol Avatar asked Nov 06 '19 12:11

arghol


People also ask

How do you link headers in CMake?

To include headers in CMake targets, use the command target_include_directories(...) . Depending on the purpose of the included directories, you will need to define the scope specifier – either PUBLIC , PRIVATE or INTERFACE .

What is .CMake file?

CMake is a meta build system that uses scripts called CMakeLists to generate build files for a specific environment (for example, makefiles on Unix machines). When you create a new CMake project in CLion, a CMakeLists. txt file is automatically generated under the project root.

Where does CMake look CMakeLists txt?

When CMake processes a project source tree, the entry point is a source file called CMakeLists. txt in the top-level source directory. This file may contain the entire build specification or use the add_subdirectory() command to add subdirectories to the build.

How do I create a Makefile from CMakeLists txt?

In Qt Creator, go to File → Open File or Project… and choose CMakeLists. txt from the source folder you want to build. Qt Creator will prompt you for the location of the binary folder, calling it the “build directory”. By default, it suggests a path adjacent to the source folder.


1 Answers

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)
like image 123
Kevin Avatar answered Oct 20 '22 17:10

Kevin