Configuring the project#
The heart of a CMake project is the configure stage, where most of the user experience diverge between each user and their needs.
We will first focus on the situation where you have downloaded the project from
source. The case where we are using FetchContent
is more-or-less the same,
and will be explored in more details in the importing projects section.
Note
This section only covers how you interact with CMake in order to pass configuration options. The details of the configuration options standard themselves are covered in configuration options section.
How do I configure the project?#
Use the pre-defined presets that are defined by the project maintainers. This can be complemented with manual options if needed.
You should setup your CMakeUserPresets.json
file. See the presets section
on how to interact with presets.
Often times the packaging system will define the default configuration options and pass them as manual options, but sometimes they can also be introduced via environment variables.
Attention
Do not create any build
folder manually. Stay in the project’s root path and
run your commands from there.
CMake presets#
Tl;dr
$ cmake --preset default
The project should be designed to have already provided all the common configurations that the user would need. These already take care of:
using the appropriate compiler
setting up any compiler options needed
detecting and importing the dependencies
Pay attention to the output of this configure step to check if there have been any errors encountered. Some common issues are collected in the troubleshooting section. If the configuration was successful, you will see an output summary at the end listing the dependencies imported and the features used.
Note that this typically does not display all the configuration setup, e.g. the compiler used. Pay attention to the full log for such information.
To get the list of all presets that are exported, use:
$ cmake --list-presets
Caution
The installation path cannot be set within the preset itself as that varies for
each person. By default, this is set to a system dependent path like
/usr/local
, which you should not be installing to unless you are aware of the
consequences.
The installation path can be overwritten using when calling cmake --install
:
$ cmake --install ./build --prefix /path/to/install/prefix
But beware that this might affect projects that hard-code the installation path at compile/build time.
CMakeUserPresets.json
#
Tl;dr
{
"version": 6,
"configurePresets": [
{
"name": "debug",
"displayName": "Debug",
"binaryDir": "cmake-build-debug",
"inherits": ["default"],
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
}
]
}
As the developer you would have specific configuration option that you always
want to use, such as setting the BUILD_TYPE
to Debug
. In order to save such
options, you can create your personal CMakeUserPresets.json
outside of the git
version control. This is a simple json file, for which you are primarily
concerned about the configurePresets
which is a list of preset objects. There
the crucial variables are:
name
: The name you interface with throughcmake --preset
binaryDir
: The build directoryinherits
: A list of other presets that the current preset will add on topcacheVariables
: A dictionary of configuration options to be setup
All the cacheVariables
can be taken from the manual options, but often times
the project would also export component-like presets so that you only need to
interface via the inherits
field.
Component presets#
These component presets are just shortcuts for having to manually define
cacheVariables
, and are a preferred way of designing a preset, mainly due to
the more natural naming it can use. They are typically found in a file like
cmake/CMakePresets-components.json
. These component presets are typically
hidden, and, currently, there is no interface to print hidden interfaces.
Warning
If there is a conflict in the cacheVariables
defined in the cache presets used
by inherits
, precedence goes to the first preset that defined in, and NOT
to the last preset to define it.
The cacheVariables
defined in the current preset always takes precedence over
those defined from inherits
.
Passing manual options#
Tl;dr
$ cmake -b ./build -DAWESOME_PROJECT_COOL_OPTION=On
Manually passing options is done by prepending -D
to the option name and
assigning its value, i.e. -D<Option_Name>=<Option_Value>
. For the list of
available options, it is best to simply navigate the top-level CMakeLists.txt
and find the option
and cmake_dependent_option
in the relevant section,
e.g.:
#[==============================================================================================[
# Options #
]==============================================================================================]
option(TEMPLATE_TESTS "Template: Build test-suite" ${PROJECT_IS_TOP_LEVEL})
option(TEMPLATE_SHARED_LIBS "Template: Build as a shared library" ${PROJECT_IS_TOP_LEVEL})
option(TEMPLATE_INSTALL "Template: Install project" ${PROJECT_IS_TOP_LEVEL})
Note
Option names are case-sensitive, make sure you pass it correctly to -D
argument.
These options should always be prefixed by the project’s name (in this case
TEMPLATE_*
), including the CMake native options (CMAKE_*
).
which you can interpret as:
option(<Option_Name> <Help_Text> <Default_Value>)
cmake_dependent_option(<Option_Name> <Help_Text> <Default_Value_If_Condition_True> <Condition> <Forced_Value_If_Condition_False>)
Because these options can be dynamic, this is the only reliable way of
identifying the project defined options available. You can sometimes use
ccmake
, to display the options, but this is not recommended because it will
not show the options that have been dynamically skipped.
Beware of environment variables#
Finally, be careful that environment variables can inject or alter the CMake options. For the most part, you can ignore the cmake specific, but beware of the following environment variables:
Variable |
Preferred alternative |
Effect |
---|---|---|
Selects C compiler used |
||
Selects C++ compiler used |
||
Selects Fortran compiler used |
||
Project specified options |
Appends to |
|
Project specified options |
Appends to |
|
Project specified options |
Appends to |
|
|
Unset the variable |
Uncontrollable consequences [1] |
|
Unset the variable |
Uncontrollable consequences [1] |
It is recommended to just clear out these environment variables, if you are not aware of how these may affect the build.