Communication with your code#
Configure File#
CMake allows you to access CMake variables from your code using configure_file
. This command copies a file (traditionally ending in .in
) from one place to another, substituting all CMake variables it finds. If you want to avoid replacing existing ${}
syntax in your input file, use the @ONLY
keyword. There’s also a COPY_ONLY
keyword if you are just using this as a replacement for file(COPY
.
This functionality is used quite frequently; for example, on Version.h.in
:
Version.h.in#
#pragma once
#define MY_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define MY_VERSION_MINOR @PROJECT_VERSION_MINOR@
#define MY_VERSION_PATCH @PROJECT_VERSION_PATCH@
#define MY_VERSION_TWEAK @PROJECT_VERSION_TWEAK@
#define MY_VERSION "@PROJECT_VERSION@"
CMake lines:#
configure_file (
"${PROJECT_SOURCE_DIR}/include/My/Version.h.in"
"${PROJECT_BINARY_DIR}/include/My/Version.h"
)
You should include the binary include directory as well when building your project. If you want to put any true/false variables in a header, CMake has C specific #cmakedefine
and #cmakedefine01
replacements to make appropriate define lines.
You can also (and often do) use this to produce .cmake
files, such as the configure files (see installing).
Reading files#
The other direction can be done too; you can read in something (like a version) from your source files. If you have a header only library that you’d like to make available with or without CMake, for example, then this would be the best way to handle a version. This would look something like this:
# Assuming the canonical version is listed in a single line
# This would be in several parts if picking up from MAJOR, MINOR, etc.
set(VERSION_REGEX "#define MY_VERSION[ \t]+\"(.+)\"")
# Read in the line containing the version
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/My/Version.hpp"
VERSION_STRING REGEX ${VERSION_REGEX})
# Pick out just the version
string(REGEX REPLACE ${VERSION_REGEX} "\\1" VERSION_STRING "${VERSION_STRING}")
# Automatically getting PROJECT_VERSION_MAJOR, My_VERSION_MAJOR, etc.
project(My LANGUAGES CXX VERSION ${VERSION_STRING})
Above, file(STRINGS file_name variable_name REGEX regex)
picks lines that match a regex; and the same regex is used to then pick out the parentheses capture group with the version part. Replace is used with back substitution to output only that one group.