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 withlatestversion.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>_STANDARDand 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_summarywithFATAL_ON_MISSING_REQUIRED_PACKAGES: Make sure required dependencies defined inset_package_propertiesare 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.cmakefilesreturn(PROPAGATE)orset(PARENT_SCOPE): Export the variables defined in<Project>Config.cmakefor projects usingFetchContentas well
More details can be found in the export section