Rework resource finalizer approach

In the previous implementation of the resource object finalizer, we
used the name of the resource object library without namespaces when
recording it in the resource libraries list. This causes an issue when
we or users export resource targets.

This approach marks resource object libraries with the exporting
property instead of collecting resource targets when creating them.

Amends 19e789bace

Change-Id: I8596815921f2c681ddd78d9b2e9a4e1cafe5000b
Reviewed-by: Lorn Potter <lorn.potter@gmail.com>
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This commit is contained in:
Alexey Edelev 2021-05-28 14:02:29 +02:00
parent 64d6003f49
commit a1fd4f51ad
2 changed files with 49 additions and 20 deletions

View File

@ -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 "$<TARGET_OBJECTS:$<TARGET_NAME:${resource_target}>>")
endif()
endforeach()
foreach(dep IN LISTS resource_targets)
list(PREPEND resource_objects "$<TARGET_OBJECTS:${dep}>")
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()

View File

@ -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
"$<NOT:$<BOOL:$<TARGET_PROPERTY:_qt_resource_objects_finalizer_mode>>>"