diff --git a/cmake/QtPublicTargetHelpers.cmake b/cmake/QtPublicTargetHelpers.cmake index 1a01a3066bd..3673b6ce24d 100644 --- a/cmake/QtPublicTargetHelpers.cmake +++ b/cmake/QtPublicTargetHelpers.cmake @@ -32,19 +32,49 @@ function(__qt_internal_process_dependency_resource_objects target) endfunction() function(__qt_internal_collect_dependency_resource_objects target out_var) - # TODO: The __qt_internal_collect_all_target_dependencies function is not cheap and called - # multiple times in the finalizer jobs. It make sense to re-use its results. - __qt_internal_collect_all_target_dependencies(${target} dep_targets) + set_property(GLOBAL PROPERTY _qt_resource_processed_targets "") + __qt_internal_collect_resource_objects_recursively(resource_targets ${target} ${target}) + set_property(GLOBAL PROPERTY _qt_resource_processed_targets "") + list(REMOVE_DUPLICATES resource_targets) set(resource_objects "") - foreach(dep IN LISTS dep_targets) - get_target_property(dep_resource_targets ${dep} _qt_resource_object_libraries) - foreach(resource_target IN LISTS dep_resource_targets) - if(resource_target) - list(PREPEND resource_objects "$>") - endif() - endforeach() + foreach(dep IN LISTS resource_targets) + list(PREPEND resource_objects "$") endforeach() set(${out_var} "${resource_objects}" PARENT_SCOPE) endfunction() + +function(__qt_internal_collect_resource_objects_recursively out_var target initial_target) + get_property(resource_processed_targets GLOBAL PROPERTY _qt_resource_processed_targets) + if(NOT "${target}" STREQUAL "${initial_target}") + get_target_property(interface_libs ${target} INTERFACE_LINK_LIBRARIES) + endif() + get_target_property(libs ${target} LINK_LIBRARIES) + + set(resource_targets "") + foreach(lib IN LISTS libs interface_libs) + if(TARGET ${lib}) + get_target_property(aliased_target ${lib} ALIASED_TARGET) + if(aliased_target) + set(lib ${aliased_target}) + endif() + + if(${lib} IN_LIST resource_processed_targets) + continue() + else() + list(APPEND resource_processed_targets ${lib}) + set_property(GLOBAL APPEND PROPERTY _qt_resource_processed_targets ${lib}) + endif() + + get_target_property(is_qt_resource ${lib} _is_qt_resource_target) + if(is_qt_resource) + list(APPEND resource_targets ${lib}) + else() + __qt_internal_collect_resource_objects_recursively(next_level_resources ${lib} ${initial_target}) + list(APPEND resource_targets ${next_level_resources}) + endif() + endif() + endforeach() + set(${out_var} "${resource_targets}" PARENT_SCOPE) +endfunction() diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake index 91fa4590c73..57c730b42d9 100644 --- a/src/corelib/Qt6CoreMacros.cmake +++ b/src/corelib/Qt6CoreMacros.cmake @@ -1452,20 +1452,19 @@ function(__qt_propagate_generated_resource target resource_name generated_source # After internal discussion we decided to not rely on the linker order that CMake # offers, until CMake provides the guaranteed linking order that suites our needs in a # future CMake version. - # The _qt_resource_object_libraries collects all resource targets owned by the 'target' - # instead of the implicit propagating and is used by the executable finalizer to expose - # objects as the end-point sources. If the user prefers not to use a finalizer or the CMake - # version does not support DEFER calls, fall back to interface linking of the resource - # objects. + # All resource object libraries mark themselves with the _is_qt_resource_target property. + # Using a finalizer approach we walk through the target dependencies and look for + # resource libraries using the _is_qt_resource_target property. Then, resource objects of + # the collected libraries are moved to the beginnig of the linker line using target_sources. + # # target_link_libraries works well with linkers other than ld. If user didn't enforce # a finalizer we rely on linker to resolve circular dependencies between resource # objects and static libraries. - set_property(TARGET ${target} APPEND PROPERTY - _qt_resource_object_libraries ${resource_target} - ) - set_property(TARGET ${target} APPEND PROPERTY - EXPORT_PROPERTIES _qt_resource_object_libraries + set_property(TARGET ${resource_target} PROPERTY _is_qt_resource_target TRUE) + set_property(TARGET ${resource_target} APPEND PROPERTY + EXPORT_PROPERTIES _is_qt_resource_target ) + # Keep the implicit linking if finalizers are not used. set(finalizer_mode_condition "$>>"