From 606124c5cceba0dd4a406a9278588b58bb9f9800 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Thu, 21 Oct 2021 14:01:29 +0200 Subject: [PATCH] CMake: Fix -rpath-link dependencies take two The previous implementation would pick up static Qt deps of a shared Qt library as packages to find, but packages are not created for these static libraries in a shared Qt build. For example Qt::BundledSpirv_Cross is a static helper lib that is linked directly into ShaderTools shared lib and no CMake package is created for it, so we shouldn't look for it. Separate the code path to filter out private dependencies of a shared library target that don't have packages. Amends 87215c70c0ff0bdc52dfa463f050d2aa049cdd91 Pick-to: 6.2 Fixes: QTBUG-97673 Task-number: QTBUG-86533 Change-Id: I43490b4d20c150256ccfa8b511a6e0e6b0f4b313 Reviewed-by: Qt CI Bot Reviewed-by: Alexey Edelev --- cmake/QtFindPackageHelpers.cmake | 61 +++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/cmake/QtFindPackageHelpers.cmake b/cmake/QtFindPackageHelpers.cmake index 8519922f85..da96f3f176 100644 --- a/cmake/QtFindPackageHelpers.cmake +++ b/cmake/QtFindPackageHelpers.cmake @@ -300,6 +300,20 @@ function(qt_record_extra_third_party_dependency main_target_name dep_target) endif() endfunction() +# Sets out_var to TRUE if the non-namespaced ${lib} target is exported as part of Qt6Targets.cmake. +function(qt_internal_is_lib_part_of_qt6_package lib out_var) + if (lib STREQUAL "Platform" + OR lib STREQUAL "GlobalConfig" + OR lib STREQUAL "GlobalConfigPrivate" + OR lib STREQUAL "PlatformModuleInternal" + OR lib STREQUAL "PlatformPluginInternal" + OR lib STREQUAL "PlatformToolInternal") + set(${out_var} "TRUE" PARENT_SCOPE) + else() + set(${out_var} "FALSE" PARENT_SCOPE) + endif() +endfunction() + # This function stores the list of Qt targets a library depend on, # along with their version info, for usage in ${target}Depends.cmake file function(qt_register_target_dependencies target public_libs private_libs) @@ -308,22 +322,31 @@ function(qt_register_target_dependencies target public_libs private_libs) set(target_deps "") endif() - # Only process private dependencies if target is a static library get_target_property(target_type ${target} TYPE) set(lib_list ${public_libs}) - if (target_type STREQUAL "STATIC_LIBRARY") + + set(target_is_shared FALSE) + set(target_is_static FALSE) + if(target_type STREQUAL "SHARED_LIBRARY") + set(target_is_shared TRUE) + elseif(target_type STREQUAL "STATIC_LIBRARY") + set(target_is_static TRUE) + endif() + + # Record 'Qt::Foo'-like private dependencies of static library targets, this will be used to + # generate find_dependency() calls. + # + # Private static library dependencies will become $ dependencies in + # INTERFACE_LINK_LIBRARIES. + if(target_is_static) list(APPEND lib_list ${private_libs}) endif() foreach(lib IN LISTS lib_list) if ("${lib}" MATCHES "^Qt::(.*)") set(lib "${CMAKE_MATCH_1}") - if (lib STREQUAL "Platform" - OR lib STREQUAL "GlobalConfig" - OR lib STREQUAL "GlobalConfigPrivate" - OR lib STREQUAL "PlatformModuleInternal" - OR lib STREQUAL "PlatformPluginInternal" - OR lib STREQUAL "PlatformToolInternal") + qt_internal_is_lib_part_of_qt6_package("${lib}" is_part_of_qt6) + if (is_part_of_qt6) list(APPEND target_deps "Qt6\;${PROJECT_VERSION}") else() list(APPEND target_deps "${INSTALL_CMAKE_NAMESPACE}${lib}\;${PROJECT_VERSION}") @@ -331,6 +354,28 @@ function(qt_register_target_dependencies target public_libs private_libs) endif() endforeach() + # Record 'Qt::Foo'-like shared private dependencies of shared library targets. + # + # Private shared library dependencies are listed in the target's + # IMPORTED_LINK_DEPENDENT_LIBRARIES and used in rpath-link calculation. + # See QTBUG-86533 for some details. + # We filter out static libraries and common platform targets, but include both SHARED and + # 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 "${CMAKE_MATCH_1}") + + qt_internal_is_lib_part_of_qt6_package("${lib}" is_part_of_qt6) + get_target_property(lib_type "${lib_namespaced}" TYPE) + if(NOT lib_type STREQUAL "STATIC_LIBRARY" AND NOT is_part_of_qt6) + list(APPEND target_deps "${INSTALL_CMAKE_NAMESPACE}${lib}\;${PROJECT_VERSION}") + endif() + endif() + endforeach() + endif() + set_target_properties("${target}" PROPERTIES _qt_target_deps "${target_deps}") endfunction()