diff --git a/cmake/QtBuildRepoHelpers.cmake b/cmake/QtBuildRepoHelpers.cmake index d8d14e87486..739f2a1fd08 100644 --- a/cmake/QtBuildRepoHelpers.cmake +++ b/cmake/QtBuildRepoHelpers.cmake @@ -11,7 +11,6 @@ macro(qt_internal_project_setup) # Check for the minimum CMake version. qt_internal_require_suitable_cmake_version() qt_internal_upgrade_cmake_policies() - qt_internal_promote_platform_targets_to_global() endmacro() macro(qt_build_internals_set_up_private_api) diff --git a/cmake/QtFindPackageHelpers.cmake b/cmake/QtFindPackageHelpers.cmake index 4ed79ec2a1e..a9cc931ad6c 100644 --- a/cmake/QtFindPackageHelpers.cmake +++ b/cmake/QtFindPackageHelpers.cmake @@ -209,15 +209,8 @@ macro(qt_find_package) ) endif() - get_property(is_global TARGET ${qt_find_package_target_name} PROPERTY - IMPORTED_GLOBAL) - _qt_internal_should_not_promote_package_target_to_global( - "${qt_find_package_target_name}" should_not_promote) - if(NOT is_global AND NOT should_not_promote) - __qt_internal_promote_target_to_global(${qt_find_package_target_name}) - _qt_find_package_promote_targets_to_global_scope( - "${qt_find_package_target_name}") - endif() + _qt_internal_promote_3rd_party_provided_target_and_3rd_party_deps_to_global( + "${qt_find_package_target_name}") set(_qt_find_package_sbom_args "") diff --git a/cmake/QtPublicDependencyHelpers.cmake b/cmake/QtPublicDependencyHelpers.cmake index f426cbc0b48..afaeb10aa96 100644 --- a/cmake/QtPublicDependencyHelpers.cmake +++ b/cmake/QtPublicDependencyHelpers.cmake @@ -52,19 +52,20 @@ macro(_qt_internal_find_third_party_dependencies target target_dep_list) ) endif() - # Work around: QTBUG-125371 - if(NOT "${ARGV0}" STREQUAL "Qt6") - foreach(__qt_${target}_provided_target - IN LISTS - __qt_${target}_third_party_package_${__qt_${target}_package_components_id}_provided_targets) - _qt_internal_sbom_record_system_library_usage( - "${__qt_${target}_provided_target}" - TYPE SYSTEM_LIBRARY - FRIENDLY_PACKAGE_NAME "${__qt_${target}_pkg}" - ${__qt_${target}_sbom_args} - ) - endforeach() - endif() + foreach(__qt_${target}_provided_target + IN LISTS + __qt_${target}_third_party_package_${__qt_${target}_package_components_id}_provided_targets) + + _qt_internal_promote_3rd_party_provided_target_and_3rd_party_deps_to_global( + "${__qt_${target}_provided_target}") + + _qt_internal_sbom_record_system_library_usage( + "${__qt_${target}_provided_target}" + TYPE SYSTEM_LIBRARY + FRIENDLY_PACKAGE_NAME "${__qt_${target}_pkg}" + ${__qt_${target}_sbom_args} + ) + endforeach() endif() endforeach() endmacro() diff --git a/cmake/QtPublicTargetHelpers.cmake b/cmake/QtPublicTargetHelpers.cmake index c1735de8664..a534d5e8752 100644 --- a/cmake/QtPublicTargetHelpers.cmake +++ b/cmake/QtPublicTargetHelpers.cmake @@ -260,20 +260,46 @@ function(_qt_internal_should_not_promote_package_target_to_global target out_var endfunction() # This function recursively walks transitive link libraries of the given target -# and promotes those targets to be IMPORTED_GLOBAL if they are not. +# and promotes encountered 3rd party targets to be IMPORTED_GLOBAL if they are not. # # This is required for .prl file generation in top-level builds, to make sure that imported 3rd # party library targets in any repo are made global, so there are no scoping issues. # -# Only works if called from qt_find_package(), because the promotion needs to happen in the same -# directory scope where the imported target is first created. +# The promotion needs to happen in the same directory scope where the imported target is +# first created. # # Uses __qt_internal_walk_libs. -function(_qt_find_package_promote_targets_to_global_scope target) +function(_qt_internal_promote_3rd_party_link_targets_to_global target) __qt_internal_walk_libs("${target}" _discarded_out_var _discarded_out_var_2 - "qt_find_package_targets_dict" "promote_global") + "qt_find_package_targets_dict" "promote_3rd_party_global") endfunction() +# Check if a target is an internal target (one added by qt_internal_* API, executables, libraries, +# etc). +function(_qt_internal_is_internal_target target out_var) + get_target_property(is_internal ${target} _qt_is_internal_target) + if(is_internal) + set(value TRUE) + else() + set(value FALSE) + endif() + set(${out_var} "${value}" PARENT_SCOPE) +endfunction() + +# Check if a target should never be promoted to global. +# Some targets like the Platform target is public, and can't have _qt_is_internal_target set. +# But we still want to avoid promoting it to global. Setting this property achieves that. +function(_qt_internal_should_skip_3rd_party_global_promotion target out_var) + get_target_property(should_skip ${target} _qt_should_skip_3rd_party_global_promotion) + if(should_skip) + set(value TRUE) + else() + set(value FALSE) + endif() + set(${out_var} "${value}" PARENT_SCOPE) +endfunction() + +# Tries to promote any non-global imported target to global scope. function(__qt_internal_promote_target_to_global target) get_property(is_global TARGET ${target} PROPERTY IMPORTED_GLOBAL) if(NOT is_global) @@ -282,6 +308,48 @@ function(__qt_internal_promote_target_to_global target) endif() endfunction() +# Promotes a 3rd party provided target to global, which was found by qt_find_package or +# _qt_internal_find_third_party_dependencies. +# Only does it when building Qt, but not when building user projects. +function(_qt_internal_promote_3rd_party_provided_target_and_3rd_party_deps_to_global target) + # Return early if building a user project, and not Qt. + # QT_BUILDING_QT is set when building a qt repo, but we also check for QT_REPO_MODULE_VERSION, + # which is set in .cmake.conf, because _qt_internal_find_third_party_dependencies is called + # before QT_BUILDING_QT is set. + if(NOT (QT_BUILDING_QT OR QT_REPO_MODULE_VERSION)) + return() + endif() + + # Return early if the provided target does not exist, which can happen in the case of zstd, + # where we list multiple possible target names, but only some will be available. + if(NOT TARGET "${target}") + return() + endif() + + get_property(is_global TARGET "${target}" PROPERTY IMPORTED_GLOBAL) + _qt_internal_should_not_promote_package_target_to_global("${target}" should_not_promote) + if(NOT is_global AND NOT should_not_promote) + _qt_internal_promote_3rd_party_target_to_global(${target}) + _qt_internal_promote_3rd_party_link_targets_to_global("${target}") + endif() +endfunction() + +# Tries to promote a non-global imported 3rd party target to global scope. +# 3rd party targets are usually system library targets. +# - targets that were not created by qt_internal_add_foo commands +# - targets that don't have the should_skip_global_promotion property +function(_qt_internal_promote_3rd_party_target_to_global target) + get_property(is_global TARGET ${target} PROPERTY IMPORTED_GLOBAL) + + if(NOT is_global) + _qt_internal_is_internal_target("${target}" is_internal) + _qt_internal_should_skip_3rd_party_global_promotion("${target}" should_skip) + if(NOT is_internal AND NOT should_skip) + __qt_internal_promote_target_to_global("${target}") + endif() + endif() +endfunction() + function(__qt_internal_promote_target_to_global_checked target) # With CMake version 3.21 we use a different mechanism that allows us to promote all targets # within a scope. diff --git a/cmake/QtPublicWalkLibsHelpers.cmake b/cmake/QtPublicWalkLibsHelpers.cmake index f801b1152e2..a7bef65fc56 100644 --- a/cmake/QtPublicWalkLibsHelpers.cmake +++ b/cmake/QtPublicWalkLibsHelpers.cmake @@ -74,7 +74,7 @@ endfunction() # operation: a string to tell the function what additional behaviors to execute. # 'collect_libs' (default) operation is to collect linker file paths and flags. # Used for prl file generation. -# 'promote_global' promotes walked imported targets to global scope. +# 'promote_3rd_party_global' promotes walked 3rd party imported targets to global scope. # 'collect_targets' collects all target names (discards framework or link flags) # 'direct_targets' collects only the direct target names (discards framework or link # flags) @@ -238,7 +238,7 @@ function(__qt_internal_walk_libs __qt_internal_merge_libs(rcc_objects ${lib_rcc_objects_${target}}) endif() endif() - if(operation STREQUAL "promote_global") + if(operation STREQUAL "promote_3rd_party_global") set(lib_target_unaliased "${lib_target}") get_target_property(aliased_target ${lib_target} ALIASED_TARGET) if(aliased_target) @@ -252,7 +252,8 @@ function(__qt_internal_walk_libs _qt_internal_should_not_promote_package_target_to_global( "${lib_target_unaliased}" should_not_promote) if(is_imported AND NOT should_not_promote) - __qt_internal_promote_target_to_global(${lib_target_unaliased}) + _qt_internal_promote_3rd_party_target_to_global( + ${lib_target_unaliased}) endif() endif() elseif("${lib_target}" MATCHES "^(Qt|${QT_CMAKE_EXPORT_NAMESPACE})::(.*)") diff --git a/cmake/QtTargetHelpers.cmake b/cmake/QtTargetHelpers.cmake index fd1cbc43be7..af840bb3e44 100644 --- a/cmake/QtTargetHelpers.cmake +++ b/cmake/QtTargetHelpers.cmake @@ -1737,6 +1737,12 @@ endfunction() function(qt_internal_add_platform_target target) _qt_internal_add_library("${target}" INTERFACE) qt_internal_add_target_aliases("${target}") + + # The platform targets should never be promoted to global via the + # _qt_internal_promote_3rd_party_target_to_global command. + set_property(TARGET "${target}" PROPERTY _qt_should_skip_3rd_party_global_promotion TRUE) + set_property(TARGET "${target}" APPEND PROPERTY EXPORT_PROPERTIES + "_qt_should_skip_3rd_party_global_promotion") endfunction() # A small wrapper for adding the PlatformXInternal and GlobalConfig INTERFACE targets to apply @@ -1752,32 +1758,3 @@ function(qt_internal_add_platform_internal_target target) IMMEDIATE_FINALIZATION ) endfunction() - -# The macro promotes the Qt platform targets and their dependencies to global. The macro shouldn't -# be called explicitly in regular cases. It's called right after the first find_package(Qt ...) -# call in the qt_internal_project_setup macro. -# This allows using the qt_find_package(Wrap<3rdparty> PROVIDED_TARGETS ...) function, -# without the risk of having duplicated global promotion of Qt internals. This is especially -# sensitive for the bundled 3rdparty libraries. -macro(qt_internal_promote_platform_targets_to_global) - if(TARGET Qt6::Platform) - get_target_property(is_imported Qt6::Platform IMPORTED) - if(is_imported) - set(known_platform_targets - Platform - PlatformCommonInternal - PlatformModuleInternal - PlatformPluginInternal - PlatformAppInternal - PlatformToolInternal - ) - set(versionless_platform_targets ${known_platform_targets}) - - list(TRANSFORM known_platform_targets PREPEND Qt6::) - list(TRANSFORM versionless_platform_targets PREPEND Qt::) - qt_find_package(Qt6 PROVIDED_TARGETS - ${known_platform_targets} - ${versionless_platform_targets}) - endif() - endif() -endmacro()