summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2022-11-22 14:49:59 (GMT)
committerKitware Robot <kwrobot@kitware.com>2022-11-22 14:50:12 (GMT)
commite1b757602cece9b81b94ad5ce21ae2e158a9f060 (patch)
treeb13b4a0ba6afdc959468694042921ce7b33f265e
parent1f6a6d6aad970c611a8e194b4f9c45d6e88fb54d (diff)
parentfb9a3d0c7da7dd581d378891fc423574c52f0489 (diff)
downloadCMake-e1b757602cece9b81b94ad5ce21ae2e158a9f060.zip
CMake-e1b757602cece9b81b94ad5ce21ae2e158a9f060.tar.gz
CMake-e1b757602cece9b81b94ad5ce21ae2e158a9f060.tar.bz2
Merge topic 'find_dependency-dedup'
fb9a3d0c7d find_dependency: Avoid repeating identical dependency searches 5fbda0f572 find_dependency: Unset temporary variables before returning 591b75ee17 Tests: Add case covering transitive find_dependency calls Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: buildbot <buildbot@kitware.com> Merge-request: !7936
-rw-r--r--Modules/CMakeFindDependencyMacro.cmake84
-rw-r--r--Tests/RunCMake/find_dependency/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/find_dependency/transitive-stdout.txt9
-rw-r--r--Tests/RunCMake/find_dependency/transitive.cmake3
-rw-r--r--Tests/RunCMake/find_dependency/transitive/AConfig.cmake1
-rw-r--r--Tests/RunCMake/find_dependency/transitive/BConfig.cmake3
-rw-r--r--Tests/RunCMake/find_dependency/transitive/CConfig.cmake3
-rw-r--r--Tests/RunCMake/find_dependency/transitive/DConfig.cmake5
-rw-r--r--Tests/RunCMake/find_dependency/transitive/EConfig.cmake6
9 files changed, 90 insertions, 25 deletions
diff --git a/Modules/CMakeFindDependencyMacro.cmake b/Modules/CMakeFindDependencyMacro.cmake
index bcdfbeb..2c04abe 100644
--- a/Modules/CMakeFindDependencyMacro.cmake
+++ b/Modules/CMakeFindDependencyMacro.cmake
@@ -3,7 +3,7 @@
#[=======================================================================[.rst:
CMakeFindDependencyMacro
--------------------------
+------------------------
.. command:: find_dependency
@@ -28,36 +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()
- 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()
- set(cmake_fd_required_arg)
- set(cmake_fd_quiet_arg)
endmacro()
diff --git a/Tests/RunCMake/find_dependency/RunCMakeTest.cmake b/Tests/RunCMake/find_dependency/RunCMakeTest.cmake
index a72d189..6a53133 100644
--- a/Tests/RunCMake/find_dependency/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_dependency/RunCMakeTest.cmake
@@ -3,6 +3,7 @@ include(RunCMake)
# Success tests
run_cmake(realistic)
run_cmake(basic)
+run_cmake(transitive)
# Failure tests
run_cmake(invalid-arg)
diff --git a/Tests/RunCMake/find_dependency/transitive-stdout.txt b/Tests/RunCMake/find_dependency/transitive-stdout.txt
new file mode 100644
index 0000000..6fe40e9
--- /dev/null
+++ b/Tests/RunCMake/find_dependency/transitive-stdout.txt
@@ -0,0 +1,9 @@
+-- begin
+-- Loading E with components: ''
+-- Loading A with components: 'A1'
+-- Loading B with components: 'B1'
+-- Loading A with components: ''
+-- Loading C with components: ''
+-- Loading D with components: ''
+-- Loading B with components: ''
+-- end
diff --git a/Tests/RunCMake/find_dependency/transitive.cmake b/Tests/RunCMake/find_dependency/transitive.cmake
new file mode 100644
index 0000000..5a07f96
--- /dev/null
+++ b/Tests/RunCMake/find_dependency/transitive.cmake
@@ -0,0 +1,3 @@
+message(STATUS "begin")
+find_package(E REQUIRED NO_DEFAULT_PATH PATHS ${CMAKE_CURRENT_SOURCE_DIR}/transitive)
+message(STATUS "end")
diff --git a/Tests/RunCMake/find_dependency/transitive/AConfig.cmake b/Tests/RunCMake/find_dependency/transitive/AConfig.cmake
new file mode 100644
index 0000000..b2bf294
--- /dev/null
+++ b/Tests/RunCMake/find_dependency/transitive/AConfig.cmake
@@ -0,0 +1 @@
+message(STATUS "Loading A with components: '${A_FIND_COMPONENTS}'")
diff --git a/Tests/RunCMake/find_dependency/transitive/BConfig.cmake b/Tests/RunCMake/find_dependency/transitive/BConfig.cmake
new file mode 100644
index 0000000..42c2ecd
--- /dev/null
+++ b/Tests/RunCMake/find_dependency/transitive/BConfig.cmake
@@ -0,0 +1,3 @@
+message(STATUS "Loading B with components: '${B_FIND_COMPONENTS}'")
+include(CMakeFindDependencyMacro)
+find_dependency(A NO_DEFAULT_PATH PATHS ${CMAKE_CURRENT_LIST_DIR})
diff --git a/Tests/RunCMake/find_dependency/transitive/CConfig.cmake b/Tests/RunCMake/find_dependency/transitive/CConfig.cmake
new file mode 100644
index 0000000..645aedc
--- /dev/null
+++ b/Tests/RunCMake/find_dependency/transitive/CConfig.cmake
@@ -0,0 +1,3 @@
+message(STATUS "Loading C with components: '${C_FIND_COMPONENTS}'")
+include(CMakeFindDependencyMacro)
+find_dependency(A NO_DEFAULT_PATH PATHS ${CMAKE_CURRENT_LIST_DIR})
diff --git a/Tests/RunCMake/find_dependency/transitive/DConfig.cmake b/Tests/RunCMake/find_dependency/transitive/DConfig.cmake
new file mode 100644
index 0000000..488c85b
--- /dev/null
+++ b/Tests/RunCMake/find_dependency/transitive/DConfig.cmake
@@ -0,0 +1,5 @@
+message(STATUS "Loading D with components: '${D_FIND_COMPONENTS}'")
+include(CMakeFindDependencyMacro)
+find_dependency(A COMPONENTS A1 NO_DEFAULT_PATH PATHS ${CMAKE_CURRENT_LIST_DIR})
+find_dependency(B NO_DEFAULT_PATH PATHS ${CMAKE_CURRENT_LIST_DIR})
+find_dependency(C NO_DEFAULT_PATH PATHS ${CMAKE_CURRENT_LIST_DIR})
diff --git a/Tests/RunCMake/find_dependency/transitive/EConfig.cmake b/Tests/RunCMake/find_dependency/transitive/EConfig.cmake
new file mode 100644
index 0000000..c8d31de
--- /dev/null
+++ b/Tests/RunCMake/find_dependency/transitive/EConfig.cmake
@@ -0,0 +1,6 @@
+message(STATUS "Loading E with components: '${E_FIND_COMPONENTS}'")
+include(CMakeFindDependencyMacro)
+find_dependency(A COMPONENTS A1 NO_DEFAULT_PATH PATHS ${CMAKE_CURRENT_LIST_DIR})
+find_dependency(B COMPONENTS B1 NO_DEFAULT_PATH PATHS ${CMAKE_CURRENT_LIST_DIR})
+find_dependency(C NO_DEFAULT_PATH PATHS ${CMAKE_CURRENT_LIST_DIR})
+find_dependency(D NO_DEFAULT_PATH PATHS ${CMAKE_CURRENT_LIST_DIR})