summaryrefslogtreecommitdiffstats
path: root/cmake
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2021-04-29 12:47:52 +0200
committerAlexandru Croitor <alexandru.croitor@qt.io>2021-05-11 18:57:17 +0200
commit471ff20f33677fe5dd598b1fbd27d10fdb4056a6 (patch)
treedc44b917cc8cc038b5476c8137b0af05461e11e3 /cmake
parentb70a4da4f7c7f47c35ccfe64f533cdeccf8701c1 (diff)
CMake: Make qt_internal_walk_libs available in public projects
Needed for the upcoming static plugin mechanism, where we have to extract the list of Qt module dependencies of a target and then extract the plugins associated with those modules. To do that we need to recursively collect the dependencies of a given target. Rename the moved functions to contain the __qt_internal prefix. Also rename the existing QtPublicTargetsHelpers.cmake into QtPlatformTargetHelpers.cmake to avoid confusion with the newly introduced QtPublicTargetHelpers.cmake. Task-number: QTBUG-92933 Change-Id: I48b5b6a8718a3424f59ca60f11fc9e97a809765d Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Diffstat (limited to 'cmake')
-rw-r--r--cmake/QtBaseGlobalTargets.cmake6
-rw-r--r--cmake/QtBuild.cmake2
-rw-r--r--cmake/QtConfig.cmake.in2
-rw-r--r--cmake/QtFindPackageHelpers.cmake6
-rw-r--r--cmake/QtPlatformTargetHelpers.cmake (renamed from cmake/QtPublicTargetsHelpers.cmake)0
-rw-r--r--cmake/QtPostProcessHelpers.cmake2
-rw-r--r--cmake/QtPrlHelpers.cmake239
-rw-r--r--cmake/QtPublicTargetHelpers.cmake16
-rw-r--r--cmake/QtPublicWalkLibsHelpers.cmake237
-rw-r--r--cmake/QtTargetHelpers.cmake17
10 files changed, 267 insertions, 260 deletions
diff --git a/cmake/QtBaseGlobalTargets.cmake b/cmake/QtBaseGlobalTargets.cmake
index 0f5d68cd0c..54891f9206 100644
--- a/cmake/QtBaseGlobalTargets.cmake
+++ b/cmake/QtBaseGlobalTargets.cmake
@@ -134,7 +134,7 @@ target_include_directories(GlobalConfigPrivate INTERFACE
)
add_library(Qt::GlobalConfigPrivate ALIAS GlobalConfigPrivate)
-include(QtPublicTargetsHelpers)
+include(QtPlatformTargetHelpers)
qt_internal_setup_public_platform_target()
# defines PlatformCommonInternal PlatformModuleInternal PlatformPluginInternal PlatformToolInternal
@@ -214,7 +214,7 @@ qt_copy_or_install(FILES
cmake/QtPrecompiledHeadersHelpers.cmake
cmake/QtPriHelpers.cmake
cmake/QtPrlHelpers.cmake
- cmake/QtPublicTargetsHelpers.cmake
+ cmake/QtPlatformTargetHelpers.cmake
cmake/QtProcessConfigureArgs.cmake
cmake/QtQmakeHelpers.cmake
cmake/QtResourceHelpers.cmake
@@ -245,6 +245,8 @@ set(__public_cmake_helpers
cmake/QtFeature.cmake
cmake/QtFeatureCommon.cmake
cmake/QtPublicPluginHelpers.cmake
+ cmake/QtPublicTargetHelpers.cmake
+ cmake/QtPublicWalkLibsHelpers.cmake
)
qt_copy_or_install(FILES ${__public_cmake_helpers} DESTINATION "${__GlobalConfig_install_dir}")
diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake
index 20efee0d6e..d246685952 100644
--- a/cmake/QtBuild.cmake
+++ b/cmake/QtBuild.cmake
@@ -547,6 +547,8 @@ endif()
# Helpers that are available in public projects and while building Qt itself.
include(QtPublicPluginHelpers)
+include(QtPublicTargetHelpers)
+include(QtPublicWalkLibsHelpers)
# TODO: This block provides support for old variables. It should be removed once
diff --git a/cmake/QtConfig.cmake.in b/cmake/QtConfig.cmake.in
index d762cd50ca..7708954b90 100644
--- a/cmake/QtConfig.cmake.in
+++ b/cmake/QtConfig.cmake.in
@@ -56,6 +56,8 @@ file(TO_CMAKE_PATH "$ENV{QT_ADDITIONAL_PACKAGES_PREFIX_PATH}" _qt_additional_pac
# Public helpers available to all Qt packages.
include("${CMAKE_CURRENT_LIST_DIR}/QtFeature.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/QtPublicPluginHelpers.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/QtPublicTargetHelpers.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/QtPublicWalkLibsHelpers.cmake")
# Find required dependencies, if any.
include(CMakeFindDependencyMacro)
diff --git a/cmake/QtFindPackageHelpers.cmake b/cmake/QtFindPackageHelpers.cmake
index 1162f2c39e..85dc1ff7db 100644
--- a/cmake/QtFindPackageHelpers.cmake
+++ b/cmake/QtFindPackageHelpers.cmake
@@ -7,10 +7,10 @@
# 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.
#
-# Uses qt_internal_walk_libs.
+# Uses __qt_internal_walk_libs.
function(qt_find_package_promote_targets_to_global_scope target)
- qt_internal_walk_libs("${target}" _discarded_out_var _discarded_out_var_2
- "qt_find_package_targets_dict" "promote_global")
+ __qt_internal_walk_libs("${target}" _discarded_out_var _discarded_out_var_2
+ "qt_find_package_targets_dict" "promote_global")
endfunction()
macro(qt_find_package)
diff --git a/cmake/QtPublicTargetsHelpers.cmake b/cmake/QtPlatformTargetHelpers.cmake
index 68ff8a3ea0..68ff8a3ea0 100644
--- a/cmake/QtPublicTargetsHelpers.cmake
+++ b/cmake/QtPlatformTargetHelpers.cmake
diff --git a/cmake/QtPostProcessHelpers.cmake b/cmake/QtPostProcessHelpers.cmake
index 6e09fcdf94..c8d310d93d 100644
--- a/cmake/QtPostProcessHelpers.cmake
+++ b/cmake/QtPostProcessHelpers.cmake
@@ -36,7 +36,7 @@ macro(qt_collect_third_party_deps target)
endif()
# Strip any directory scope tokens.
- qt_internal_strip_target_directory_scope_token("${dep}" dep)
+ __qt_internal_strip_target_directory_scope_token("${dep}" dep)
if(TARGET ${dep})
list(FIND third_party_deps_seen ${dep} dep_seen)
diff --git a/cmake/QtPrlHelpers.cmake b/cmake/QtPrlHelpers.cmake
index f843fb4bbe..86555dbb65 100644
--- a/cmake/QtPrlHelpers.cmake
+++ b/cmake/QtPrlHelpers.cmake
@@ -1,250 +1,15 @@
-# Add libraries to variable ${out_libs_var} in a way that duplicates
-# are added at the end. This ensures the library order needed for the
-# linker.
-function(qt_merge_libs out_libs_var)
- foreach(dep ${ARGN})
- list(REMOVE_ITEM ${out_libs_var} ${dep})
- list(APPEND ${out_libs_var} ${dep})
- endforeach()
- set(${out_libs_var} ${${out_libs_var}} PARENT_SCOPE)
-endfunction()
-
# Collects the library dependencies of a target.
# As well as rcc object file dependencies.
# This takes into account transitive usage requirements.
function(qt_collect_libs target libs_out_var rcc_objects_out_var)
- qt_internal_walk_libs("${target}" "${libs_out_var}"
- "${rcc_objects_out_var}" "qt_collect_libs_dict" "collect_libs")
+ __qt_internal_walk_libs("${target}" "${libs_out_var}"
+ "${rcc_objects_out_var}" "qt_collect_libs_dict" "collect_libs")
set("${libs_out_var}" "${${libs_out_var}}" PARENT_SCOPE)
set(${rcc_objects_out_var} "${${rcc_objects_out_var}}" PARENT_SCOPE)
endfunction()
-# Extracts value from per-target dict key and assigns it to out_var.
-# Assumes dict_name to be an existing INTERFACE target.
-function(qt_internal_get_dict_key_values out_var target_infix dict_name dict_key)
- get_target_property(values "${dict_name}" "INTERFACE_${target_infix}_${dict_key}")
- set(${out_var} "${values}" PARENT_SCOPE)
-endfunction()
-
-# Assigns 'values' to per-target dict key, including for aliases of the target.
-# Assumes dict_name to be an existing INTERFACE target.
-function(qt_internal_memoize_values_in_dict target dict_name dict_key values)
- # Memoize the computed values for the target as well as its aliases.
- #
- # Aka assigns the contents of ${values} to INTERFACE_Core, INTERFACE_Qt::Core,
- # INTERFACE_Qt6::Core.
- #
- # Yes, i know it's crazy that target names are legal property names.
- #
- # Assigning for library aliases is needed to avoid multiple recomputation of values.
- # Scenario in the context of qt_internal_walk_libs:
- # 'values' are computed for Core target and memoized to INTERFACE_Core.
- # When processing Gui, it depends on Qt::Core, but there are no values for INTERFACE_Qt::Core.
- set_target_properties(${dict_name} PROPERTIES INTERFACE_${target}_${dict_key} "${values}")
-
- get_target_property(versionless_alias "${target}" "_qt_versionless_alias")
- if(versionless_alias)
- qt_internal_get_dict_key_values(
- versionless_values "${versionless_alias}" "${dict_name}" "${dict_key}")
- if(versionless_values MATCHES "-NOTFOUND$")
- set_target_properties(${dict_name}
- PROPERTIES INTERFACE_${versionless_alias}_${dict_key} "${values}")
- endif()
- endif()
-
- get_target_property(versionfull_alias "${target}" "_qt_versionfull_alias")
- if(versionfull_alias)
- qt_internal_get_dict_key_values(
- versionfull_values "${versionfull_alias}" "${dict_name}" "${dict_key}")
- if(versionfull_values MATCHES "-NOTFOUND$")
- set_target_properties(${dict_name}
- PROPERTIES INTERFACE_${versionfull_alias}_${dict_key} "${values}")
- endif()
- endif()
-endfunction()
-
-# Walks a target's link libraries recursively, and performs some actions (poor man's polypmorphism)
-#
-# out_var is the name of the variable where the result will be assigned. The result is a list of
-# libraries, mostly in generator expression form.
-# rcc_objects_out_var is the name of the variable where the collected rcc object files will be
-# assigned (for the initial target and its dependencies)
-# dict_name is used for caching the results, and preventing the same target from being processed
-# twice
-# operation is a string to tell the function what additional behaviors to execute.
-function(qt_internal_walk_libs
- target out_var rcc_objects_out_var dict_name operation)
- set(collected ${ARGN})
- if(target IN_LIST collected)
- return()
- endif()
- list(APPEND collected ${target})
-
- if(target STREQUAL "${QT_CMAKE_EXPORT_NAMESPACE}::EntryPoint")
- # We can't (and don't need to) process EntryPoint because it brings in $<TARGET_PROPERTY:prop>
- # genexes which get replaced with $<TARGET_PROPERTY:EntryPoint,prop> genexes in the code below
- # and that causes 'INTERFACE_LIBRARY targets may only have whitelisted properties.' errors
- # with CMake versions equal to or lower than 3.18. These errors are super unintuitive to
- # debug because there's no mention that it's happening during a file(GENERATE) call.
- return()
- endif()
-
- if(NOT TARGET ${dict_name})
- add_library(${dict_name} INTERFACE IMPORTED GLOBAL)
- endif()
- qt_internal_get_dict_key_values(libs "${target}" "${dict_name}" "libs")
- qt_internal_get_dict_key_values(rcc_objects "${target}" "${dict_name}" "rcc_objects")
-
- if(libs MATCHES "-NOTFOUND$")
- unset(libs)
- unset(rcc_objects)
- get_target_property(target_libs ${target} INTERFACE_LINK_LIBRARIES)
- if(NOT target_libs)
- unset(target_libs)
- endif()
- get_target_property(target_type ${target} TYPE)
- if(target_type STREQUAL "STATIC_LIBRARY")
- get_target_property(link_libs ${target} LINK_LIBRARIES)
- if(link_libs)
- list(APPEND target_libs ${link_libs})
- endif()
- endif()
-
- # Need to record the rcc object file info not only for dependencies, but also for
- # the current target too. Otherwise the saved information is incomplete for prl static
- # build purposes.
- get_target_property(main_target_rcc_objects ${target} _qt_rcc_objects)
- if(main_target_rcc_objects)
- qt_merge_libs(rcc_objects ${main_target_rcc_objects})
- endif()
-
- foreach(lib ${target_libs})
- # Cannot use $<TARGET_POLICY:...> in add_custom_command.
- # Check the policy now, and replace the generator expression with the value.
- while(lib MATCHES "\\$<TARGET_POLICY:([^>]+)>")
- cmake_policy(GET ${CMAKE_MATCH_1} value)
- if(value STREQUAL "NEW")
- set(value "TRUE")
- else()
- set(value "FALSE")
- endif()
- string(REPLACE "${CMAKE_MATCH_0}" "${value}" lib "${lib}")
- endwhile()
-
- # Fix up $<TARGET_PROPERTY:FOO> expressions that refer to the "current" target.
- # Those cannot be used with add_custom_command.
- while(lib MATCHES "\\$<TARGET_PROPERTY:([^,>]+)>")
- string(REPLACE "${CMAKE_MATCH_0}" "$<TARGET_PROPERTY:${target},${CMAKE_MATCH_1}>"
- lib "${lib}")
- endwhile()
-
- # Skip static plugins.
- set(_is_plugin_marker_genex "\\$<BOOL:QT_IS_PLUGIN_GENEX>")
- if(lib MATCHES "${_is_plugin_marker_genex}")
- continue()
- endif()
-
- # Strip any directory scope tokens.
- qt_internal_strip_target_directory_scope_token("${lib}" lib)
-
- if(lib MATCHES "^\\$<TARGET_OBJECTS:")
- # Skip object files.
- continue()
- elseif(lib MATCHES "^\\$<LINK_ONLY:(.*)>$")
- set(lib_target ${CMAKE_MATCH_1})
- else()
- set(lib_target ${lib})
- endif()
-
- # Skip CMAKE_DIRECTORY_ID_SEP. If a target_link_libraries is applied to a target
- # that was defined in a different scope, CMake appends and prepends a special directory
- # id separator. Filter those out.
- if(lib_target MATCHES "^::@")
- continue()
- elseif(TARGET ${lib_target})
- if ("${lib_target}" MATCHES "^Qt::(.*)")
- # If both, Qt::Foo and Foo targets exist, prefer the target name without
- # namespace. Which one is preferred doesn't really matter. This code exists to
- # avoid ending up with both, Qt::Foo and Foo in our dependencies.
- set(namespaceless_lib_target "${CMAKE_MATCH_1}")
- if(TARGET namespaceless_lib_target)
- set(lib_target ${namespaceless_lib_target})
- endif()
- endif()
- get_target_property(lib_target_type ${lib_target} TYPE)
- if(lib_target_type STREQUAL "INTERFACE_LIBRARY")
- qt_internal_walk_libs(
- ${lib_target}
- lib_libs_${target}
- lib_rcc_objects_${target}
- "${dict_name}" "${operation}" ${collected})
- if(lib_libs_${target})
- qt_merge_libs(libs ${lib_libs_${target}})
- set(is_module 0)
- endif()
- if(lib_rcc_objects_${target})
- qt_merge_libs(rcc_objects ${lib_rcc_objects_${target}})
- endif()
- elseif(NOT lib_target_type STREQUAL "OBJECT_LIBRARY")
- qt_merge_libs(libs "$<TARGET_LINKER_FILE:${lib_target}>")
-
- get_target_property(target_rcc_objects "${lib_target}" _qt_rcc_objects)
- if(target_rcc_objects)
- qt_merge_libs(rcc_objects ${target_rcc_objects})
- endif()
-
- qt_internal_walk_libs(
- ${lib_target}
- lib_libs_${target}
- lib_rcc_objects_${target}
- "${dict_name}" "${operation}" ${collected})
- if(lib_libs_${target})
- qt_merge_libs(libs ${lib_libs_${target}})
- endif()
- if(lib_rcc_objects_${target})
- qt_merge_libs(rcc_objects ${lib_rcc_objects_${target}})
- endif()
- endif()
- if(operation STREQUAL "promote_global")
- set(lib_target_unaliased "${lib_target}")
- get_target_property(aliased_target ${lib_target} ALIASED_TARGET)
- if(aliased_target)
- set(lib_target_unaliased ${aliased_target})
- endif()
-
- get_property(is_imported TARGET ${lib_target_unaliased} PROPERTY IMPORTED)
- get_property(is_global TARGET ${lib_target_unaliased} PROPERTY IMPORTED_GLOBAL)
-
- # Allow opting out of promotion. This is useful in certain corner cases
- # like with WrapLibClang and Threads in qttools.
- qt_internal_should_not_promote_package_target_to_global(
- "${lib_target_unaliased}" should_not_promote)
- if(NOT is_global AND is_imported AND NOT should_not_promote)
- set_property(TARGET ${lib_target_unaliased} PROPERTY IMPORTED_GLOBAL TRUE)
- endif()
- endif()
- elseif("${lib_target}" MATCHES "^Qt::(.*)")
- message(FATAL_ERROR "The ${CMAKE_MATCH_1} target is mentioned as a dependency for \
-${target}, but not declared.")
- else()
- set(final_lib_name_to_merge "${lib_target}")
- if(lib_target MATCHES "/([^/]+).framework$")
- set(final_lib_name_to_merge "-framework ${CMAKE_MATCH_1}")
- endif()
- qt_merge_libs(libs "${final_lib_name_to_merge}")
- endif()
- endforeach()
- qt_internal_memoize_values_in_dict("${target}" "${dict_name}" "libs" "${libs}")
- qt_internal_memoize_values_in_dict("${target}" "${dict_name}"
- "rcc_objects" "${rcc_objects}")
-
- endif()
- set(${out_var} ${libs} PARENT_SCOPE)
- set(${rcc_objects_out_var} ${rcc_objects} PARENT_SCOPE)
-endfunction()
-
# Generate a qmake .prl file for the given target.
# The install_dir argument is a relative path, for example "lib".
function(qt_generate_prl_file target install_dir)
diff --git a/cmake/QtPublicTargetHelpers.cmake b/cmake/QtPublicTargetHelpers.cmake
new file mode 100644
index 0000000000..9ce8cbf700
--- /dev/null
+++ b/cmake/QtPublicTargetHelpers.cmake
@@ -0,0 +1,16 @@
+function(__qt_internal_strip_target_directory_scope_token target out_var)
+ # In CMake versions earlier than CMake 3.18, a subdirectory scope id is appended to the
+ # target name if the target is referenced in a target_link_libraries command from a
+ # different directory scope than where the target was created.
+ # Strip it.
+ #
+ # For informational purposes, in CMake 3.18, the target name looks as follows:
+ # ::@(0x5604cb3f6b50);Threads::Threads;::@
+ # This case doesn't have to be stripped (at least for now), because when we iterate over
+ # link libraries, the tokens appear as separate target names.
+ #
+ # Example: Threads::Threads::@<0x5604cb3f6b50>
+ # Output: Threads::Threads
+ string(REGEX REPLACE "::@<.+>$" "" target "${target}")
+ set("${out_var}" "${target}" PARENT_SCOPE)
+endfunction()
diff --git a/cmake/QtPublicWalkLibsHelpers.cmake b/cmake/QtPublicWalkLibsHelpers.cmake
new file mode 100644
index 0000000000..674a9da7a7
--- /dev/null
+++ b/cmake/QtPublicWalkLibsHelpers.cmake
@@ -0,0 +1,237 @@
+# Add libraries to variable ${out_libs_var} in a way that duplicates
+# are added at the end. This ensures the library order needed for the
+# linker.
+function(__qt_internal_merge_libs out_libs_var)
+ foreach(dep ${ARGN})
+ list(REMOVE_ITEM ${out_libs_var} ${dep})
+ list(APPEND ${out_libs_var} ${dep})
+ endforeach()
+ set(${out_libs_var} ${${out_libs_var}} PARENT_SCOPE)
+endfunction()
+
+
+# Extracts value from per-target dict key and assigns it to out_var.
+# Assumes dict_name to be an existing INTERFACE target.
+function(__qt_internal_get_dict_key_values out_var target_infix dict_name dict_key)
+ get_target_property(values "${dict_name}" "INTERFACE_${target_infix}_${dict_key}")
+ set(${out_var} "${values}" PARENT_SCOPE)
+endfunction()
+
+
+# Assigns 'values' to per-target dict key, including for aliases of the target.
+# Assumes dict_name to be an existing INTERFACE target.
+function(__qt_internal_memoize_values_in_dict target dict_name dict_key values)
+ # Memoize the computed values for the target as well as its aliases.
+ #
+ # Aka assigns the contents of ${values} to INTERFACE_Core, INTERFACE_Qt::Core,
+ # INTERFACE_Qt6::Core.
+ #
+ # Yes, i know it's crazy that target names are legal property names.
+ #
+ # Assigning for library aliases is needed to avoid multiple recomputation of values.
+ # Scenario in the context of __qt_internal_walk_libs:
+ # 'values' are computed for Core target and memoized to INTERFACE_Core.
+ # When processing Gui, it depends on Qt::Core, but there are no values for INTERFACE_Qt::Core.
+ set_target_properties(${dict_name} PROPERTIES INTERFACE_${target}_${dict_key} "${values}")
+
+ get_target_property(versionless_alias "${target}" "_qt_versionless_alias")
+ if(versionless_alias)
+ __qt_internal_get_dict_key_values(
+ versionless_values "${versionless_alias}" "${dict_name}" "${dict_key}")
+ if(versionless_values MATCHES "-NOTFOUND$")
+ set_target_properties(${dict_name}
+ PROPERTIES INTERFACE_${versionless_alias}_${dict_key} "${values}")
+ endif()
+ endif()
+
+ get_target_property(versionfull_alias "${target}" "_qt_versionfull_alias")
+ if(versionfull_alias)
+ __qt_internal_get_dict_key_values(
+ versionfull_values "${versionfull_alias}" "${dict_name}" "${dict_key}")
+ if(versionfull_values MATCHES "-NOTFOUND$")
+ set_target_properties(${dict_name}
+ PROPERTIES INTERFACE_${versionfull_alias}_${dict_key} "${values}")
+ endif()
+ endif()
+endfunction()
+
+
+# Walks a target's link libraries recursively, and performs some actions (poor man's polypmorphism)
+#
+# out_var is the name of the variable where the result will be assigned. The result is a list of
+# libraries, mostly in generator expression form.
+# rcc_objects_out_var is the name of the variable where the collected rcc object files will be
+# assigned (for the initial target and its dependencies)
+# dict_name is used for caching the results, and preventing the same target from being processed
+# twice
+# operation is a string to tell the function what additional behaviors to execute.
+function(__qt_internal_walk_libs
+ target out_var rcc_objects_out_var dict_name operation)
+ set(collected ${ARGN})
+ if(target IN_LIST collected)
+ return()
+ endif()
+ list(APPEND collected ${target})
+
+ if(target STREQUAL "${QT_CMAKE_EXPORT_NAMESPACE}::EntryPoint")
+ # We can't (and don't need to) process EntryPoint because it brings in $<TARGET_PROPERTY:prop>
+ # genexes which get replaced with $<TARGET_PROPERTY:EntryPoint,prop> genexes in the code below
+ # and that causes 'INTERFACE_LIBRARY targets may only have whitelisted properties.' errors
+ # with CMake versions equal to or lower than 3.18. These errors are super unintuitive to
+ # debug because there's no mention that it's happening during a file(GENERATE) call.
+ return()
+ endif()
+
+ if(NOT TARGET ${dict_name})
+ add_library(${dict_name} INTERFACE IMPORTED GLOBAL)
+ endif()
+ __qt_internal_get_dict_key_values(libs "${target}" "${dict_name}" "libs")
+ __qt_internal_get_dict_key_values(rcc_objects "${target}" "${dict_name}" "rcc_objects")
+
+ if(libs MATCHES "-NOTFOUND$")
+ unset(libs)
+ unset(rcc_objects)
+ get_target_property(target_libs ${target} INTERFACE_LINK_LIBRARIES)
+ if(NOT target_libs)
+ unset(target_libs)
+ endif()
+ get_target_property(target_type ${target} TYPE)
+ if(target_type STREQUAL "STATIC_LIBRARY")
+ get_target_property(link_libs ${target} LINK_LIBRARIES)
+ if(link_libs)
+ list(APPEND target_libs ${link_libs})
+ endif()
+ endif()
+
+ # Need to record the rcc object file info not only for dependencies, but also for
+ # the current target too. Otherwise the saved information is incomplete for prl static
+ # build purposes.
+ get_target_property(main_target_rcc_objects ${target} _qt_rcc_objects)
+ if(main_target_rcc_objects)
+ __qt_internal_merge_libs(rcc_objects ${main_target_rcc_objects})
+ endif()
+
+ foreach(lib ${target_libs})
+ # Cannot use $<TARGET_POLICY:...> in add_custom_command.
+ # Check the policy now, and replace the generator expression with the value.
+ while(lib MATCHES "\\$<TARGET_POLICY:([^>]+)>")
+ cmake_policy(GET ${CMAKE_MATCH_1} value)
+ if(value STREQUAL "NEW")
+ set(value "TRUE")
+ else()
+ set(value "FALSE")
+ endif()
+ string(REPLACE "${CMAKE_MATCH_0}" "${value}" lib "${lib}")
+ endwhile()
+
+ # Fix up $<TARGET_PROPERTY:FOO> expressions that refer to the "current" target.
+ # Those cannot be used with add_custom_command.
+ while(lib MATCHES "\\$<TARGET_PROPERTY:([^,>]+)>")
+ string(REPLACE "${CMAKE_MATCH_0}" "$<TARGET_PROPERTY:${target},${CMAKE_MATCH_1}>"
+ lib "${lib}")
+ endwhile()
+
+ # Skip static plugins.
+ set(_is_plugin_marker_genex "\\$<BOOL:QT_IS_PLUGIN_GENEX>")
+ if(lib MATCHES "${_is_plugin_marker_genex}")
+ continue()
+ endif()
+
+ # Strip any directory scope tokens.
+ __qt_internal_strip_target_directory_scope_token("${lib}" lib)
+
+ if(lib MATCHES "^\\$<TARGET_OBJECTS:")
+ # Skip object files.
+ continue()
+ elseif(lib MATCHES "^\\$<LINK_ONLY:(.*)>$")
+ set(lib_target ${CMAKE_MATCH_1})
+ else()
+ set(lib_target ${lib})
+ endif()
+
+ # Skip CMAKE_DIRECTORY_ID_SEP. If a target_link_libraries is applied to a target
+ # that was defined in a different scope, CMake appends and prepends a special directory
+ # id separator. Filter those out.
+ if(lib_target MATCHES "^::@")
+ continue()
+ elseif(TARGET ${lib_target})
+ if ("${lib_target}" MATCHES "^Qt::(.*)")
+ # If both, Qt::Foo and Foo targets exist, prefer the target name without
+ # namespace. Which one is preferred doesn't really matter. This code exists to
+ # avoid ending up with both, Qt::Foo and Foo in our dependencies.
+ set(namespaceless_lib_target "${CMAKE_MATCH_1}")
+ if(TARGET namespaceless_lib_target)
+ set(lib_target ${namespaceless_lib_target})
+ endif()
+ endif()
+ get_target_property(lib_target_type ${lib_target} TYPE)
+ if(lib_target_type STREQUAL "INTERFACE_LIBRARY")
+ __qt_internal_walk_libs(
+ ${lib_target}
+ lib_libs_${target}
+ lib_rcc_objects_${target}
+ "${dict_name}" "${operation}" ${collected})
+ if(lib_libs_${target})
+ __qt_internal_merge_libs(libs ${lib_libs_${target}})
+ set(is_module 0)
+ endif()
+ if(lib_rcc_objects_${target})
+ __qt_internal_merge_libs(rcc_objects ${lib_rcc_objects_${target}})
+ endif()
+ elseif(NOT lib_target_type STREQUAL "OBJECT_LIBRARY")
+ __qt_internal_merge_libs(libs "$<TARGET_LINKER_FILE:${lib_target}>")
+
+ get_target_property(target_rcc_objects "${lib_target}" _qt_rcc_objects)
+ if(target_rcc_objects)
+ __qt_internal_merge_libs(rcc_objects ${target_rcc_objects})
+ endif()
+
+ __qt_internal_walk_libs(
+ ${lib_target}
+ lib_libs_${target}
+ lib_rcc_objects_${target}
+ "${dict_name}" "${operation}" ${collected})
+ if(lib_libs_${target})
+ __qt_internal_merge_libs(libs ${lib_libs_${target}})
+ endif()
+ if(lib_rcc_objects_${target})
+ __qt_internal_merge_libs(rcc_objects ${lib_rcc_objects_${target}})
+ endif()
+ endif()
+ if(operation STREQUAL "promote_global")
+ set(lib_target_unaliased "${lib_target}")
+ get_target_property(aliased_target ${lib_target} ALIASED_TARGET)
+ if(aliased_target)
+ set(lib_target_unaliased ${aliased_target})
+ endif()
+
+ get_property(is_imported TARGET ${lib_target_unaliased} PROPERTY IMPORTED)
+ get_property(is_global TARGET ${lib_target_unaliased} PROPERTY IMPORTED_GLOBAL)
+
+ # Allow opting out of promotion. This is useful in certain corner cases
+ # like with WrapLibClang and Threads in qttools.
+ qt_internal_should_not_promote_package_target_to_global(
+ "${lib_target_unaliased}" should_not_promote)
+ if(NOT is_global AND is_imported AND NOT should_not_promote)
+ set_property(TARGET ${lib_target_unaliased} PROPERTY IMPORTED_GLOBAL TRUE)
+ endif()
+ endif()
+ elseif("${lib_target}" MATCHES "^Qt::(.*)")
+ message(FATAL_ERROR "The ${CMAKE_MATCH_1} target is mentioned as a dependency for \
+${target}, but not declared.")
+ else()
+ set(final_lib_name_to_merge "${lib_target}")
+ if(lib_target MATCHES "/([^/]+).framework$")
+ set(final_lib_name_to_merge "-framework ${CMAKE_MATCH_1}")
+ endif()
+ __qt_internal_merge_libs(libs "${final_lib_name_to_merge}")
+ endif()
+ endforeach()
+ __qt_internal_memoize_values_in_dict("${target}" "${dict_name}" "libs" "${libs}")
+ __qt_internal_memoize_values_in_dict("${target}" "${dict_name}"
+ "rcc_objects" "${rcc_objects}")
+
+ endif()
+ set(${out_var} ${libs} PARENT_SCOPE)
+ set(${rcc_objects_out_var} ${rcc_objects} PARENT_SCOPE)
+endfunction()
diff --git a/cmake/QtTargetHelpers.cmake b/cmake/QtTargetHelpers.cmake
index 6b9af27c7e..cc8bfde85f 100644
--- a/cmake/QtTargetHelpers.cmake
+++ b/cmake/QtTargetHelpers.cmake
@@ -264,23 +264,6 @@ function(qt_internal_check_directory_or_type name dir type default result_var)
endif()
endfunction()
-function(qt_internal_strip_target_directory_scope_token target out_var)
- # In CMake versions earlier than CMake 3.18, a subdirectory scope id is appended to the
- # target name if the target is referenced in a target_link_libraries command from a
- # different directory scope than where the target was created.
- # Strip it.
- #
- # For informational purposes, in CMake 3.18, the target name looks as follows:
- # ::@(0x5604cb3f6b50);Threads::Threads;::@
- # This case doesn't have to be stripped (at least for now), because when we iterate over
- # link libraries, the tokens appear as separate target names.
- #
- # Example: Threads::Threads::@<0x5604cb3f6b50>
- # Output: Threads::Threads
- string(REGEX REPLACE "::@<.+>$" "" target "${target}")
- set("${out_var}" "${target}" PARENT_SCOPE)
-endfunction()
-
# Create a Qt*AdditionalTargetInfo.cmake file that is included by Qt*Config.cmake
# and sets IMPORTED_*_<CONFIG> properties on the exported targets.
#