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