summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Modules/CMakeFindDependencyMacro.cmake85
-rw-r--r--Tests/RunCMake/find_dependency/transitive-stdout.txt5
2 files changed, 59 insertions, 31 deletions
diff --git a/Modules/CMakeFindDependencyMacro.cmake b/Modules/CMakeFindDependencyMacro.cmake
index 921333b..2c04abe 100644
--- a/Modules/CMakeFindDependencyMacro.cmake
+++ b/Modules/CMakeFindDependencyMacro.cmake
@@ -3,7 +3,7 @@
#[=======================================================================[.rst:
CMakeFindDependencyMacro
--------------------------
+------------------------
.. command:: find_dependency
@@ -28,37 +28,70 @@ CMakeFindDependencyMacro
The call to :command:`return` makes this macro unsuitable to call
from :ref:`Find Modules`.
+
+Package Dependency Search Optimizations
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If ``find_dependency`` is called with arguments identical to a previous
+call in the same directory, perhaps due to diamond-shaped package
+dependencies, the underlying call to :command:`find_package` is optimized
+out. This optimization is important to support large package dependency
+graphs while avoiding a combinatorial explosion of repeated searches.
+However, the heuristic cannot account for ambient variables that
+affect package behavior, such as ``<PackageName>_USE_STATIC_LIBS``,
+offered by some packages. Therefore package configuration files should
+avoid setting such variables before their calls to ``find_dependency``.
+
+.. versionchanged:: 3.15
+ Previously, the underlying call to :command:`find_package` was always
+ optimized out if the package had already been found. CMake 3.15
+ removed the optimization to support cases in which ``find_dependency``
+ call arguments request different components.
+
+.. versionchanged:: 3.26
+ The pre-3.15 optimization was restored, but with the above-described
+ heuristic to account for varying ``find_dependency`` call arguments.
+
#]=======================================================================]
macro(find_dependency dep)
- set(cmake_fd_quiet_arg)
- if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY)
- set(cmake_fd_quiet_arg QUIET)
- endif()
- set(cmake_fd_required_arg)
- if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED)
- set(cmake_fd_required_arg REQUIRED)
- endif()
+ string(SHA256 cmake_fd_call_hash "${dep};${ARGN};${${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED}")
+ if(_CMAKE_${dep}_${cmake_fd_call_hash}_FOUND)
+ unset(cmake_fd_call_hash)
+ else()
+ list(APPEND _CMAKE_${dep}_HASH_STACK ${cmake_fd_call_hash})
+ set(cmake_fd_quiet_arg)
+ if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY)
+ set(cmake_fd_quiet_arg QUIET)
+ endif()
+ set(cmake_fd_required_arg)
+ if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED)
+ set(cmake_fd_required_arg REQUIRED)
+ endif()
- get_property(cmake_fd_alreadyTransitive GLOBAL PROPERTY
- _CMAKE_${dep}_TRANSITIVE_DEPENDENCY
- )
+ get_property(cmake_fd_alreadyTransitive GLOBAL PROPERTY
+ _CMAKE_${dep}_TRANSITIVE_DEPENDENCY
+ )
- find_package(${dep} ${ARGN}
- ${cmake_fd_quiet_arg}
- ${cmake_fd_required_arg}
- )
+ find_package(${dep} ${ARGN}
+ ${cmake_fd_quiet_arg}
+ ${cmake_fd_required_arg}
+ )
+ list(POP_BACK _CMAKE_${dep}_HASH_STACK cmake_fd_call_hash)
+ set("_CMAKE_${dep}_${cmake_fd_call_hash}_FOUND" "${${dep}_FOUND}")
- if(NOT DEFINED cmake_fd_alreadyTransitive OR cmake_fd_alreadyTransitive)
- set_property(GLOBAL PROPERTY _CMAKE_${dep}_TRANSITIVE_DEPENDENCY TRUE)
- endif()
+ if(NOT DEFINED cmake_fd_alreadyTransitive OR cmake_fd_alreadyTransitive)
+ set_property(GLOBAL PROPERTY _CMAKE_${dep}_TRANSITIVE_DEPENDENCY TRUE)
+ endif()
- unset(cmake_fd_alreadyTransitive)
- unset(cmake_fd_quiet_arg)
- unset(cmake_fd_required_arg)
- if (NOT ${dep}_FOUND)
- set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "${CMAKE_FIND_PACKAGE_NAME} could not be found because dependency ${dep} could not be found.")
- set(${CMAKE_FIND_PACKAGE_NAME}_FOUND False)
- return()
+ unset(cmake_fd_alreadyTransitive)
+ unset(cmake_fd_call_hash)
+ unset(cmake_fd_quiet_arg)
+ unset(cmake_fd_required_arg)
+ if (NOT ${dep}_FOUND)
+ set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "${CMAKE_FIND_PACKAGE_NAME} could not be found because dependency ${dep} could not be found.")
+ set(${CMAKE_FIND_PACKAGE_NAME}_FOUND False)
+ return()
+ endif()
endif()
endmacro()
diff --git a/Tests/RunCMake/find_dependency/transitive-stdout.txt b/Tests/RunCMake/find_dependency/transitive-stdout.txt
index 0f5b366..6fe40e9 100644
--- a/Tests/RunCMake/find_dependency/transitive-stdout.txt
+++ b/Tests/RunCMake/find_dependency/transitive-stdout.txt
@@ -4,11 +4,6 @@
-- Loading B with components: 'B1'
-- Loading A with components: ''
-- Loading C with components: ''
--- Loading A with components: ''
-- Loading D with components: ''
--- Loading A with components: 'A1'
-- Loading B with components: ''
--- Loading A with components: ''
--- Loading C with components: ''
--- Loading A with components: ''
-- end