diff options
Diffstat (limited to 'cmake/QtFindPackageHelpers.cmake')
-rw-r--r-- | cmake/QtFindPackageHelpers.cmake | 137 |
1 files changed, 131 insertions, 6 deletions
diff --git a/cmake/QtFindPackageHelpers.cmake b/cmake/QtFindPackageHelpers.cmake index 407e41b833..b71226f322 100644 --- a/cmake/QtFindPackageHelpers.cmake +++ b/cmake/QtFindPackageHelpers.cmake @@ -16,6 +16,15 @@ function(qt_find_package_promote_targets_to_global_scope target) "qt_find_package_targets_dict" "promote_global") endfunction() +# As an optimization when using -developer-build, qt_find_package records which +# packages were found during the initial configuration. Then on subsequent +# reconfigurations it skips looking for packages that were not found on the +# initial run. +# For the build system to pick up a newly added qt_find_package call, you need to: +# - Start with a clean build dir +# - Or remove the <builddir>/CMakeCache.txt file and configure from scratch +# - Or remove the QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES cache variable (by +# editing CMakeCache.txt) and reconfigure. macro(qt_find_package) # Get the target names we expect to be provided by the package. set(find_package_options CONFIG NO_MODULE MODULE REQUIRED) @@ -41,10 +50,13 @@ macro(qt_find_package) # Due to this behavior being different from what general CMake projects expect, it is only # done for -developer-builds. if(QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES AND - NOT "${ARGV0}" IN_LIST QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES) + NOT "${ARGV0}" IN_LIST QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES + AND "${ARGV0}" IN_LIST QT_INTERNAL_PREVIOUSLY_SEARCHED_PACKAGES) set(_qt_find_package_skip_find_package TRUE) endif() + set_property(GLOBAL APPEND PROPERTY _qt_previously_searched_packages "${ARGV0}") + if(QT_DEBUG_QT_FIND_PACKAGE AND ${ARGV0}_FOUND AND arg_PROVIDED_TARGETS) set(_qt_find_package_skip_find_package TRUE) foreach(qt_find_package_target_name ${arg_PROVIDED_TARGETS}) @@ -178,6 +190,15 @@ macro(qt_find_package) PROPERTIES INTERFACE_QT_PACKAGE_VERSION ${ARGV1}) endif() + # Save the retrieved package version. + set(_qt_find_package_found_version "") + if(${ARGV0}_VERSION) + set(_qt_find_package_found_version "${${ARGV0}_VERSION}") + set_target_properties(${qt_find_package_target_name} + PROPERTIES + _qt_package_found_version "${_qt_find_package_found_version}") + endif() + if(arg_COMPONENTS) string(REPLACE ";" " " components_as_string "${arg_COMPONENTS}") set_property(TARGET ${qt_find_package_target_name} @@ -191,6 +212,18 @@ macro(qt_find_package) ${components_as_string}) endif() + # Work around: QTBUG-125371 + if(NOT "${ARGV0}" STREQUAL "Qt6") + # Record the package + component + optional component provided targets. + qt_internal_record_package_component_provided_targets( + PACKAGE_NAME "${ARGV0}" + ON_TARGET ${qt_find_package_target_name} + PROVIDED_TARGETS ${arg_PROVIDED_TARGETS} + COMPONENTS ${arg_COMPONENTS} + OPTIONAL_COMPONENTS ${arg_OPTIONAL_COMPONENTS} + ) + endif() + get_property(is_global TARGET ${qt_find_package_target_name} PROPERTY IMPORTED_GLOBAL) qt_internal_should_not_promote_package_target_to_global( @@ -200,8 +233,25 @@ macro(qt_find_package) qt_find_package_promote_targets_to_global_scope( "${qt_find_package_target_name}") endif() - endif() + set(_qt_find_package_sbom_args "") + + if(_qt_find_package_found_version) + list(APPEND _qt_find_package_sbom_args + PACKAGE_VERSION "${_qt_find_package_found_version}" + ) + endif() + + # Work around: QTBUG-125371 + if(NOT "${ARGV0}" STREQUAL "Qt6") + _qt_internal_sbom_record_system_library_usage( + "${qt_find_package_target_name}" + TYPE SYSTEM_LIBRARY + FRIENDLY_PACKAGE_NAME "${ARGV0}" + ${_qt_find_package_sbom_args} + ) + endif() + endif() endforeach() if(arg_MODULE_NAME AND arg_QMAKE_LIB @@ -216,12 +266,62 @@ macro(qt_find_package) endif() endmacro() +# Records information about a package's provided targets, given a specific list of components. +# +# A package might contain multiple components, and create only a subset of targets based on which +# components are looked for. +# This function computes a unique key / id using the package name and the components that are +# passed. +# Then it saves the id in a property on the ON_TARGET target. The ON_TARGET target is one +# of the provided targets for that package id. This allows us to create a relationship to find +# the package id, given a target. +# The function also appends the list of provided targets for that package id to a global property. +# This information will later be saved into the module Dependencies.cmake file. +function(qt_internal_record_package_component_provided_targets) + set(opt_args "") + set(single_args + PACKAGE_NAME + ON_TARGET + ) + set(multi_args + COMPONENTS + OPTIONAL_COMPONENTS + PROVIDED_TARGETS + ) + cmake_parse_arguments(PARSE_ARGV 0 arg "${opt_args}" "${single_args}" "${multi_args}") + _qt_internal_validate_all_args_are_parsed(arg) + + if(NOT arg_PACKAGE_NAME) + message(FATAL_ERROR "PACKAGE_NAME is required.") + endif() + + if(NOT arg_ON_TARGET) + message(FATAL_ERROR "ON_TARGET is required.") + endif() + + _qt_internal_get_package_components_id( + PACKAGE_NAME "${arg_PACKAGE_NAME}" + COMPONENTS ${arg_COMPONENTS} + OPTIONAL_COMPONENTS ${arg_OPTIONAL_COMPONENTS} + OUT_VAR_KEY package_key + ) + + set_target_properties(${arg_ON_TARGET} PROPERTIES + _qt_package_components_id "${package_key}" + ) + + _qt_internal_append_to_cmake_property_without_duplicates( + _qt_find_package_${package_key}_provided_targets + "${arg_PROVIDED_TARGETS}" + ) +endfunction() + # Save found packages in the cache. They will be read on next reconfiguration to skip looking # for packages that were not previously found. # Only applies to -developer-builds by default. # Can also be opted in or opted out via QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES. # Opting out will need two reconfigurations to take effect. -function(qt_internal_save_previously_found_packages) +function(qt_internal_save_previously_visited_packages) if(DEFINED QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES) set(should_save "${QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES}") else() @@ -235,6 +335,7 @@ function(qt_internal_save_previously_found_packages) if(NOT should_save) # When the value is flipped to OFF, remove any previously saved packages. unset(QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES CACHE) + unset(QT_INTERNAL_PREVIOUSLY_SEARCHED_PACKAGES CACHE) return() endif() @@ -244,6 +345,15 @@ function(qt_internal_save_previously_found_packages) set(QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES "${_qt_previously_found_packages}" CACHE INTERNAL "List of CMake packages found during configuration using qt_find_package.") endif() + + get_property(_qt_previously_searched_packages GLOBAL PROPERTY _qt_previously_searched_packages) + if(_qt_previously_searched_packages) + list(REMOVE_DUPLICATES _qt_previously_searched_packages) + set(QT_INTERNAL_PREVIOUSLY_SEARCHED_PACKAGES + "${_qt_previously_searched_packages}" CACHE INTERNAL + "List of CMake packages searched during configuration using qt_find_package." + ) + endif() endfunction() # Return qmake library name for the given target, e.g. return "vulkan" for "Vulkan::Vulkan". @@ -493,8 +603,15 @@ function(qt_register_target_dependencies target public_libs private_libs) endif() foreach(lib IN LISTS lib_list) - if ("${lib}" MATCHES "^Qt::(.*)") + if("${lib}" MATCHES "^Qt::(.*)") + set(lib "${CMAKE_MATCH_1}") + elseif("${lib}" MATCHES "^${QT_CMAKE_EXPORT_NAMESPACE}::(.*)") set(lib "${CMAKE_MATCH_1}") + else() + set(lib "") + endif() + + if(lib) qt_internal_get_package_name_of_target("${lib}" package_name) qt_internal_get_package_version_of_target("${lib}" package_version) list(APPEND target_deps "${package_name}\;${package_version}") @@ -510,8 +627,16 @@ function(qt_register_target_dependencies target public_libs private_libs) # INTERFACE libraries. INTERFACE libraries in most cases will be FooPrivate libraries. if(target_is_shared AND private_libs) foreach(lib IN LISTS private_libs) - if ("${lib}" MATCHES "^Qt::(.*)") - set(lib_namespaced "${lib}") + set(lib_namespaced "${lib}") + if("${lib}" MATCHES "^Qt::(.*)") + set(lib "${CMAKE_MATCH_1}") + elseif("${lib}" MATCHES "^${QT_CMAKE_EXPORT_NAMESPACE}::(.*)") + set(lib "${CMAKE_MATCH_1}") + else() + set(lib "") + endif() + + if(lib) set(lib "${CMAKE_MATCH_1}") qt_internal_is_lib_part_of_qt6_package("${lib}" is_part_of_qt6) |