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?
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 .
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.
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.
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.
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:
version.h
at compile-time, before building your library.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)
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