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 withlatest
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:
option
: Define basic boolean optionsset(CACHE)
: Define non-boolean optionscmake_dependent_option
: Define dependent boolean option
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:
find_package
: Import system-installed packagesFetchContent_Declare
: Define downloadable dependenciesFetchContent_MakeAvailable
: Import the projects defined by the previous commandfeature_summary
withFATAL_ON_MISSING_REQUIRED_PACKAGES
: Make sure required dependencies defined inset_package_properties
are treated properly
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:
add_library
: Create library targetsadd_executable
: Create executable targetsset_target_properties
: Set basic target propertiesadd_subdirectory
: Import the main CMake project definitionsenable_testing
: Enablectest
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:
install(FILE)
: Define the installed files. Primarily the files relevant for CMake package importing.install(EXPORT)
andexport(EXPORT)
: Define the component files forfind_package
.configure_file
,write_basic_package_version_file
, andconfigure_package_config_file
: Configure the<Project>Config.cmake
filesreturn(PROPAGATE)
orset(PARENT_SCOPE)
: Export the variables defined in<Project>Config.cmake
for projects usingFetchContent
as well
More details can be found in the export section