Top level CMakeLists.txt

The top-level CMakeLists.txt should be as navigable as the project’s top-level README.md file. For this reason, I encourage to organize the top-level file as follows:

Sectioning

There are various ways of writing a section separator. In this template I use comment blocks spanning roughly 80 characters wide:

#[=============================================================================[
#                           Basic project definition                           #
]=============================================================================]

This format may be changed in the future once sphinx cmake documentation is further developed.

More important here is the division of the sections that is documented here.

Preamble

This is the part just before any actual section separation that has to be defined for all CMake projects.

This section consists of:

  • cmake_minimum_required: Specify the minimum CMake version supported by the project. Should be covered by the CI, along with latest version.

  • cmake_policy: Allow for future CMake compatibility.

Basic project definition

This section defines the main metadata of the project.

This section consists of:

  • project: Define main project metadata.

  • CMAKE_<LANG>_STANDARD and equivalents: Specify the language standards used for the whole project. Should always be specified.

Warning

Do NOT set CMAKE_<LANG>_STANDARD as a cached variable. This would affect the values of other projects. Use a project option instead to re-define this value.

This is also where the CMAKE_MESSAGE_CONTEXT stack should be pushed onto.

Options

It is preferred to have the options section within the main CMakeLists.txt file, being as brief as possible, and with minimal logic.

This section consist of:

Further documentation of the options should be done in the sphinx documentation, not in the CMakeLists.txt file.

Project configuration

Here is where much of the CMake boilerplate configuration occurs, e.g. setting BUILD_SHARED_LIBS variable locally according to the <PROJECT>_SHARED_LIBS option.

This section should be as minimal as possible, having most of it deferred to src/CMakeLists.txt and further on.

External packages

Here is where all the required and optional dependencies are defined.

This section consist of:

For readability, another call to feature_summary with FILENAME and VAR should occur prior to that with cmake_language(DEFER) printing, as shown in the template.

Main definition

Here is where the exported targets are defined, along with their basic properties. The main definition and linkage is deferred to the src/CMakeLists.txt and further on.

This section consist of:

Attention

Make sure enable_testing is called at this top-level, otherwise ctest would not be executable in the build directory.

Some target definitions can be deferred to a subproject if they are gated by a project option, e.g. in the case of binding APIs.

Install or Export

Finally, the install and export configurations are defined

This section consist of:

More details can be found in the export section