Importing dependencies¶
This section covers both how to import a project in another CMake project (importing), and how a user can control where a project is found (finding).
Importing dependencies in a CMake project¶
Tl;dr
include(FetchContent)
FetchContent_Declare(awesome-project
GIT_REPOSITORY https://github.com/user/awesome-project
GIT_TAG main
FIND_PACKAGE_ARGS CONFIG
)
FetchContent_MakeAvailable(awesome-project)
The best way to consume a project is within CMake, using the
FetchContent/find_package integration. This will run find_package
first to try and import the system installed packaged version, and if none is
available it will git clone the source project and include it as
add_subdirectory. See the configuration section on how to configure the
included project.
From there, navigate the dependency’s top-level CMakeLists.txt to find the
available targets you can use.
If you need to overwrite the upstream project’s options, simply add the
option before the FetchContent_MakeAvailable call, e.g.:
option(PROJECT2_TESTS "Project1: Override" OFF)
FetchContent_MakeAvailable(Project2)
Making a dependency optional¶
Currently, the only clear design for supporting optional dependencies is by
avoiding FetchContent and using find_package only:
find_package(awesome-project)
See the controlling section on how to disable or make it a required dependency.
Todo
Make the optional dependency work with FetchContent. Currently, there is no
clear way how to combine find_package and FetchContent fallthrough.
Key part is the interaction with CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>
and CMAKE_DISABLE_FIND_PACKAGE_<PackageName>.
How dependencies are found¶
Here we assume that all projects in the chain use the modern importing approach to define their dependencies.
Default behavior¶
By default, the project will first try to find the <PackageName>Config.cmake
file from the system installed packaged, and if that fails, it would either
use FetchContent to download the source project if it is a required
dependency, or simply disable the feature if it is an optional dependency.
Controlling how dependencies are imported¶
Option |
Effect |
Notes |
|---|---|---|
Where to look for system installed package |
||
Where to look for system installed package |
It can happen that this is not enforced |
|
If |
||
Path to package source to use (instead of downloading) |
Takes precedence of any other option |
|
Make optional dependency required |
If dependency is already required via |
|
Disable finding system installed package |
Here <PackageName> is the case-sensitive name of the dependency, and
<PACKAGENAME> is the equivalent uppercase name.
Caution
CMAKE_REQUIRE_FIND_PACKAGE_<PackageName> and
CMAKE_DISABLE_FIND_PACKAGE_<PackageName> options propagate to other
dependencies in the chain. Normally this would not be an issue, unless a project
uses Find<PackageName>.cmake and do not take this into account [1].
Troubleshooting the dependency search¶
Tl;dr
$ cmake -b ./build --debug-find-pkg=<PackageName>
The most comprehensive way of finding out how a dependency has been searched is
to use the --debug-find-pkg option. This does not cover the
Find<PackageName>.cmake, where the find process is non-standard.