1 # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 # file Copyright.txt or https://cmake.org/licensing for details.
4 #[=======================================================================[.rst:
5 CMakeFindDependencyMacro
6 ------------------------
8 .. command:: find_dependency
10 The ``find_dependency()`` macro wraps a :command:`find_package` call for
11 a package dependency::
13 find_dependency(<dep> [...])
15 It is designed to be used in a
16 :ref:`Package Configuration File <Config File Packages>`
17 (``<PackageName>Config.cmake``). ``find_dependency`` forwards the correct
18 parameters for ``QUIET`` and ``REQUIRED`` which were passed to
19 the original :command:`find_package` call. Any additional arguments
20 specified are forwarded to :command:`find_package`.
22 If the dependency could not be found it sets an informative diagnostic
23 message and calls :command:`return` to end processing of the calling
24 package configuration file and return to the :command:`find_package`
25 command that loaded it.
29 The call to :command:`return` makes this macro unsuitable to call
30 from :ref:`Find Modules`.
32 Package Dependency Search Optimizations
33 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
35 If ``find_dependency`` is called with arguments identical to a previous
36 call in the same directory, perhaps due to diamond-shaped package
37 dependencies, the underlying call to :command:`find_package` is optimized
38 out. This optimization is important to support large package dependency
39 graphs while avoiding a combinatorial explosion of repeated searches.
40 However, the heuristic cannot account for ambient variables that
41 affect package behavior, such as ``<PackageName>_USE_STATIC_LIBS``,
42 offered by some packages. Therefore package configuration files should
43 avoid setting such variables before their calls to ``find_dependency``.
45 .. versionchanged:: 3.15
46 Previously, the underlying call to :command:`find_package` was always
47 optimized out if the package had already been found. CMake 3.15
48 removed the optimization to support cases in which ``find_dependency``
49 call arguments request different components.
51 .. versionchanged:: 3.26
52 The pre-3.15 optimization was restored, but with the above-described
53 heuristic to account for varying ``find_dependency`` call arguments.
55 #]=======================================================================]
57 macro(find_dependency dep)
58 string(SHA256 cmake_fd_call_hash "${dep};${ARGN};${${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED}")
59 if(_CMAKE_${dep}_${cmake_fd_call_hash}_FOUND)
60 unset(cmake_fd_call_hash)
62 list(APPEND _CMAKE_${dep}_HASH_STACK ${cmake_fd_call_hash})
63 set(cmake_fd_quiet_arg)
64 if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY)
65 set(cmake_fd_quiet_arg QUIET)
67 set(cmake_fd_required_arg)
68 if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED)
69 set(cmake_fd_required_arg REQUIRED)
72 get_property(cmake_fd_alreadyTransitive GLOBAL PROPERTY
73 _CMAKE_${dep}_TRANSITIVE_DEPENDENCY
76 find_package(${dep} ${ARGN}
78 ${cmake_fd_required_arg}
80 list(POP_BACK _CMAKE_${dep}_HASH_STACK cmake_fd_call_hash)
81 set("_CMAKE_${dep}_${cmake_fd_call_hash}_FOUND" "${${dep}_FOUND}")
83 if(NOT DEFINED cmake_fd_alreadyTransitive OR cmake_fd_alreadyTransitive)
84 set_property(GLOBAL PROPERTY _CMAKE_${dep}_TRANSITIVE_DEPENDENCY TRUE)
87 unset(cmake_fd_alreadyTransitive)
88 unset(cmake_fd_call_hash)
89 unset(cmake_fd_quiet_arg)
90 unset(cmake_fd_required_arg)
92 set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "${CMAKE_FIND_PACKAGE_NAME} could not be found because dependency ${dep} could not be found.")
93 set(${CMAKE_FIND_PACKAGE_NAME}_FOUND False)