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

CMakeUserPresets.json#
{
  "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 through cmake --preset

  • binaryDir: The build directory

  • inherits: A list of other presets that the current preset will add on top

  • cacheVariables: 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

CC

CMAKE_C_COMPILER

Selects C compiler used

CXX

CMAKE_CXX_COMPILER

Selects C++ compiler used

FC

CMAKE_Fortran_COMPILER

Selects Fortran compiler used

CFLAGS

Project specified options

Appends to CMAKE_C_FLAGS

CXXFLAGS

Project specified options

Appends to CMAKE_CXX_FLAGS

FFLAGS

Project specified options

Appends to CMAKE_Fortran_FLAGS

CPATH

Unset the variable

Uncontrollable consequences [1]

LIBRARY_PATH

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.