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.