diff options
author | Brad King <brad.king@kitware.com> | 2022-11-22 14:49:59 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2022-11-22 14:50:12 (GMT) |
commit | e1b757602cece9b81b94ad5ce21ae2e158a9f060 (patch) | |
tree | b13b4a0ba6afdc959468694042921ce7b33f265e | |
parent | 1f6a6d6aad970c611a8e194b4f9c45d6e88fb54d (diff) | |
parent | fb9a3d0c7da7dd581d378891fc423574c52f0489 (diff) | |
download | CMake-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
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}) |