summaryrefslogtreecommitdiffstats
path: root/cmake/QtPublicWalkLibsHelpers.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'cmake/QtPublicWalkLibsHelpers.cmake')
-rw-r--r--cmake/QtPublicWalkLibsHelpers.cmake115
1 files changed, 78 insertions, 37 deletions
diff --git a/cmake/QtPublicWalkLibsHelpers.cmake b/cmake/QtPublicWalkLibsHelpers.cmake
index 038d5d0625..959283aca1 100644
--- a/cmake/QtPublicWalkLibsHelpers.cmake
+++ b/cmake/QtPublicWalkLibsHelpers.cmake
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# 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.
@@ -73,6 +76,8 @@ endfunction()
# Used for prl file generation.
# 'promote_global' promotes walked 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)
#
#
function(__qt_internal_walk_libs
@@ -83,12 +88,19 @@ function(__qt_internal_walk_libs
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.
+ if(operation MATCHES "^direct")
+ set(direct TRUE)
+ else()
+ set(direct FALSE)
+ endif()
+
+ if(target STREQUAL "${QT_CMAKE_EXPORT_NAMESPACE}::EntryPointPrivate")
+ # We can't (and don't need to) process EntryPointPrivate because it brings in
+ # $<TARGET_PROPERTY:prop> genexes which get replaced with
+ # $<TARGET_PROPERTY:EntryPointPrivate,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()
@@ -147,6 +159,13 @@ function(__qt_internal_walk_libs
continue()
endif()
+ # Skip optional dependencies for now. They are likely to be handled manually for prl
+ # file purposes (like nolink handling). And for one of the other operations, we don't
+ # have a use case yet. This might be revisited.
+ if(lib MATCHES "^\\$<TARGET_NAME_IF_EXISTS:")
+ continue()
+ endif()
+
# Strip any directory scope tokens.
__qt_internal_strip_target_directory_scope_token("${lib}" lib)
@@ -165,32 +184,36 @@ function(__qt_internal_walk_libs
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
+ if(NOT "${lib_target}" MATCHES "^(Qt|${QT_CMAKE_EXPORT_NAMESPACE})::.+")
+ # If both, Qt::Foo and Foo targets exist, prefer the target name with versioned
# 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})
+ set(versioned_qt_target "${QT_CMAKE_EXPORT_NAMESPACE}::${lib_target}")
+ if(TARGET "${versioned_qt_target}")
+ set(lib_target ${versioned_qt_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}})
+ if(NOT ${direct})
+ __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()
+ else()
+ __qt_internal_merge_libs(libs ${lib})
endif()
elseif(NOT lib_target_type STREQUAL "OBJECT_LIBRARY")
- if(operation STREQUAL "collect_targets")
+ if(operation MATCHES "^(collect|direct)_targets$")
__qt_internal_merge_libs(libs ${lib_target})
else()
__qt_internal_merge_libs(libs "$<TARGET_LINKER_FILE:${lib_target}>")
@@ -201,11 +224,13 @@ function(__qt_internal_walk_libs
__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(NOT ${direct})
+ __qt_internal_walk_libs(
+ ${lib_target}
+ lib_libs_${target}
+ lib_rcc_objects_${target}
+ "${dict_name}" "${operation}" ${collected})
+ endif()
if(lib_libs_${target})
__qt_internal_merge_libs(libs ${lib_libs_${target}})
endif()
@@ -221,21 +246,20 @@ function(__qt_internal_walk_libs
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)
+ if(is_imported AND NOT should_not_promote)
+ __qt_internal_promote_target_to_global(${lib_target_unaliased})
endif()
endif()
- elseif("${lib_target}" MATCHES "^Qt::(.*)")
- message(FATAL_ERROR "The ${CMAKE_MATCH_1} target is mentioned as a dependency for \
+ elseif("${lib_target}" MATCHES "^(Qt|${QT_CMAKE_EXPORT_NAMESPACE})::(.*)")
+ message(FATAL_ERROR "The ${CMAKE_MATCH_2} target is mentioned as a dependency for \
${target}, but not declared.")
else()
- if(NOT operation STREQUAL "collect_targets")
+ if(NOT operation MATCHES "^(collect|direct)_targets$")
set(final_lib_name_to_merge "${lib_target}")
if(lib_target MATCHES "/([^/]+).framework$")
set(final_lib_name_to_merge "-framework ${CMAKE_MATCH_1}")
@@ -253,6 +277,18 @@ ${target}, but not declared.")
set(${rcc_objects_out_var} ${rcc_objects} PARENT_SCOPE)
endfunction()
+function(__qt_internal_print_missing_dependency_target_warning target dep)
+ if(QT_SILENCE_MISSING_DEPENDENCY_TARGET_WARNING)
+ return()
+ endif()
+ message(WARNING
+ "When trying to collect dependencies of target '${target}', "
+ "the non-existent target '${dep}' was encountered. "
+ "This can likely be fixed by moving the find_package call that pulls in "
+ "'${dep}' to the scope of directory '${CMAKE_CURRENT_LIST_DIR}' or higher. "
+ "This warning can be silenced by setting QT_SILENCE_MISSING_DEPENDENCY_TARGET_WARNING to "
+ "ON.")
+endfunction()
# Given ${target}, collect all its private dependencies that are CMake targets.
#
@@ -279,9 +315,14 @@ function(__qt_internal_collect_all_target_dependencies target out_var)
"qt_private_link_library_targets"
"collect_targets")
- if(lib_walked_targets)
- list(APPEND dep_targets ${lib_walked_targets})
- endif()
+ foreach(lib_target IN LISTS lib_walked_targets)
+ if(NOT TARGET "${lib_target}")
+ __qt_internal_print_missing_dependency_target_warning(${target}
+ ${lib_target})
+ continue()
+ endif()
+ list(APPEND dep_targets ${lib_target})
+ endforeach()
endif()
endforeach()
endif()