2c90f7cf67
(PS: I created a GitLab account just to submit this typo fix. The signup process required a lot of needless stuff that wasted a bunch of my time and which has no current relevance whatsoever to what I'm doing e.g. creating a group and project when I have no interest in doing so etc. Perhaps you should switch to a site that has much better understanding of basic user interface/experience design. The experience has definitely left a negative initial impression of GitLab's sense of judgement and taste compared to e.g. GitHub etc.)
54 lines
2.5 KiB
Markdown
54 lines
2.5 KiB
Markdown
# 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
|
|
|
|
```cpp
|
|
#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:
|
|
```cmake
|
|
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](https://cliutils.gitlab.io/modern-cmake/chapters/install/installing.html)).
|
|
|
|
## 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:
|
|
|
|
```cmake
|
|
# 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.
|