summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Edelev <alexey.edelev@qt.io>2021-06-15 13:09:57 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-06-18 23:44:31 +0000
commit2f8572dd3b5781b1e4c4d627ae74172ac8ac3c19 (patch)
tree857e3a90da6b88c1a455a75e56e290abca215c09
parent30026fa0eed914065508a77ce8cdad9593afcf7c (diff)
Move the linking logic of the object libraries to a common function
The linking logic of object libraries should be reusable outside of the resource context. This introduces a __qt_internal_propagate_object_library function that prepares all the necessary genexes to link and propagate the object library to the end-point executable. Rename resource object finalizer API to make the naming more generic to object libraries of any kind. Amends 5fb99e3860eb43f4bacacec7f4a4626cb0159b14 Task-number: QTBUG-93002 Task-number: QTBUG-94528 Change-Id: I69d0f34c0dadbd67232de91035aaa53af93d1fa1 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io> (cherry picked from commit 3329212815777e33dfb4697b748d10927d73f44c) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--cmake/QtPublicTargetHelpers.cmake78
-rw-r--r--src/corelib/Qt6CoreMacros.cmake188
-rw-r--r--tests/auto/cmake/test_static_resources/test_static_resources_propagation/CMakeLists.txt2
3 files changed, 154 insertions, 114 deletions
diff --git a/cmake/QtPublicTargetHelpers.cmake b/cmake/QtPublicTargetHelpers.cmake
index be76efd835..94bda88d66 100644
--- a/cmake/QtPublicTargetHelpers.cmake
+++ b/cmake/QtPublicTargetHelpers.cmake
@@ -87,8 +87,8 @@ function(__qt_internal_check_link_order_matters)
endif()
endfunction()
-function(__qt_internal_process_dependency_resource_objects target)
- # The CMake versions greater than 3.21 take care about the resource object files order in a
+function(__qt_internal_process_dependency_object_libraries target)
+ # The CMake versions greater than 3.21 take care about the order of object files in a
# linker line, it's expected that all object files are located at the beginning of the linker
# line.
# So circular dependencies between static libraries and object files are resolved and no need
@@ -98,68 +98,68 @@ function(__qt_internal_process_dependency_resource_objects target)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.21)
return()
endif()
- get_target_property(processed ${target} _qt_resource_object_finalizers_processed)
+ get_target_property(processed ${target} _qt_object_libraries_finalizer_processed)
if(processed)
return()
endif()
- set_target_properties(${target} PROPERTIES _qt_resource_object_finalizers_processed TRUE)
+ set_target_properties(${target} PROPERTIES _qt_object_libraries_finalizer_processed TRUE)
__qt_internal_check_finalizer_mode(${target}
use_finalizer_mode
- resource_objects
+ object_libraries
)
if(NOT use_finalizer_mode)
return()
endif()
- __qt_internal_collect_dependency_resource_objects(${target} resource_objects)
- target_sources(${target} PRIVATE "${resource_objects}")
+ __qt_internal_collect_dependency_object_libraries(${target} objects)
+ target_sources(${target} PRIVATE "${objects}")
endfunction()
-function(__qt_internal_collect_dependency_resource_objects target out_var)
- set_property(GLOBAL PROPERTY _qt_resource_processed_targets "")
+function(__qt_internal_collect_dependency_object_libraries target out_var)
+ set_property(GLOBAL PROPERTY _qt_processed_object_libraries "")
- __qt_internal_collect_resource_objects_recursively(resource_targets ${target} ${target})
+ __qt_internal_collect_object_libraries_recursively(object_libraries ${target} ${target})
- # Collect resource objects of plugins and plugin dependencies.
+ # Collect object libraries of plugins and plugin dependencies.
__qt_internal_collect_plugin_targets_from_dependencies(${target} plugin_targets)
- __qt_internal_collect_dependency_plugin_resource_objects(${target}
+ __qt_internal_collect_dependency_plugin_object_libraries(${target}
"${plugin_targets}"
- plugin_resource_objects
+ plugin_objects
)
- set_property(GLOBAL PROPERTY _qt_resource_processed_targets "")
+ set_property(GLOBAL PROPERTY _qt_processed_object_libraries "")
- list(REMOVE_DUPLICATES resource_targets)
- set(resource_objects "")
- foreach(dep IN LISTS resource_targets)
- list(PREPEND resource_objects "$<TARGET_OBJECTS:${dep}>")
+ list(REMOVE_DUPLICATES object_libraries)
+ set(objects "")
+ foreach(dep IN LISTS object_libraries)
+ list(PREPEND objects "$<TARGET_OBJECTS:${dep}>")
endforeach()
- set(${out_var} "${plugin_resource_objects};${resource_objects}" PARENT_SCOPE)
+ set(${out_var} "${plugin_objects};${objects}" PARENT_SCOPE)
endfunction()
-function(__qt_internal_collect_dependency_plugin_resource_objects target plugin_targets out_var)
- set(plugin_resource_objects "")
+function(__qt_internal_collect_dependency_plugin_object_libraries target plugin_targets out_var)
+ set(plugin_objects "")
foreach(plugin_target IN LISTS plugin_targets)
- __qt_internal_collect_resource_objects_recursively(plugin_resource_targets
+ __qt_internal_collect_object_libraries_recursively(plugin_object_libraries
"${QT_CMAKE_EXPORT_NAMESPACE}::${plugin_target}"
${target}
)
__qt_internal_get_static_plugin_condition_genex("${plugin_target}" plugin_condition)
- foreach(plugin_resource_target IN LISTS plugin_resource_targets)
- list(APPEND plugin_resource_objects
- "$<${plugin_condition}:$<TARGET_OBJECTS:${plugin_resource_target}>>"
+ foreach(plugin_object_library IN LISTS plugin_object_libraries)
+ list(APPEND plugin_objects
+ "$<${plugin_condition}:$<TARGET_OBJECTS:${plugin_object_library}>>"
)
endforeach()
endforeach()
- set(${out_var} "${plugin_resource_objects}" PARENT_SCOPE)
+ set(${out_var} "${plugin_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)
+function(__qt_internal_collect_object_libraries_recursively out_var target initial_target)
+ get_property(processed_object_libraries GLOBAL PROPERTY _qt_processed_object_libraries)
set(interface_libs "")
set(libs "")
@@ -171,7 +171,7 @@ function(__qt_internal_collect_resource_objects_recursively out_var target initi
get_target_property(libs ${target} LINK_LIBRARIES)
endif()
- set(resource_targets "")
+ set(object_libraries "")
foreach(lib IN LISTS libs interface_libs)
if(TARGET ${lib})
get_target_property(aliased_target ${lib} ALIASED_TARGET)
@@ -179,26 +179,28 @@ function(__qt_internal_collect_resource_objects_recursively out_var target initi
set(lib ${aliased_target})
endif()
- if(${lib} IN_LIST resource_processed_targets)
+ if(${lib} IN_LIST processed_object_libraries)
continue()
else()
- list(APPEND resource_processed_targets ${lib})
- set_property(GLOBAL APPEND PROPERTY _qt_resource_processed_targets ${lib})
+ list(APPEND processed_object_libraries ${lib})
+ set_property(GLOBAL APPEND PROPERTY _qt_processed_object_libraries ${lib})
endif()
- get_target_property(is_qt_resource ${lib} _is_qt_resource_target)
- if(is_qt_resource)
- list(APPEND resource_targets ${lib})
+ get_target_property(is_qt_propagated_object_library ${lib}
+ _is_qt_propagated_object_library
+ )
+ if(is_qt_propagated_object_library)
+ list(APPEND object_libraries ${lib})
else()
- __qt_internal_collect_resource_objects_recursively(next_level_resources
+ __qt_internal_collect_object_libraries_recursively(next_level_object_libraries
${lib}
${initial_target}
)
- list(APPEND resource_targets ${next_level_resources})
+ list(APPEND object_libraries ${next_level_object_libraries})
endif()
endif()
endforeach()
- set(${out_var} "${resource_targets}" PARENT_SCOPE)
+ set(${out_var} "${object_libraries}" PARENT_SCOPE)
endfunction()
function(__qt_internal_promote_target_to_global target)
diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake
index 3636ddecd9..88bf5052bf 100644
--- a/src/corelib/Qt6CoreMacros.cmake
+++ b/src/corelib/Qt6CoreMacros.cmake
@@ -596,7 +596,7 @@ function(_qt_internal_finalize_executable target)
get_target_property(is_immediately_finalized "${target}" _qt_is_immediately_finalized)
if(NOT is_immediately_finalized)
__qt_internal_apply_plugin_imports_finalizer_mode("${target}")
- __qt_internal_process_dependency_resource_objects("${target}")
+ __qt_internal_process_dependency_object_libraries("${target}")
endif()
set_target_properties(${target} PROPERTIES _qt_executable_is_finalized TRUE)
@@ -914,13 +914,13 @@ endif()
# It makes sense to manually disable the finalizer of the resource object if you are using
# linkers other than ld, since the dependencies between resource objects and static libraries
# are resolved correctly by them.
-function(qt6_enable_resource_objects_finalizer_mode target enabled)
- __qt_internal_enable_finalizer_mode(${target} resource_objects ${enabled})
+function(qt6_enable_object_libraries_finalizer_mode target enabled)
+ __qt_internal_enable_finalizer_mode(${target} object_libraries ${enabled})
endfunction()
if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
- function(qt_enable_resource_objects_finalizer_mode)
- qt6_enable_resource_objects_finalizer_mode(${ARGV})
+ function(qt_enable_object_libraries_finalizer_mode)
+ qt6_enable_object_libraries_finalizer_mode(${ARGV})
endfunction()
endif()
@@ -1408,6 +1408,107 @@ function(__qt_get_relative_resource_path_for_file output_alias file)
set(${output_alias} ${alias} PARENT_SCOPE)
endfunction()
+# Performs linking and propagation of the object library via the target's usage requirements.
+# Arguments:
+# NO_LINK_OBJECT_LIBRARY_REQUIREMENTS_TO_TARGET skip linking of ${object_library} to ${target}, only
+# propagate $<TARGET_OBJECTS:${object_library}> by linking it to ${target}. It's useful in case
+# if ${object_library} depends on the ${target}. E.g. resource libraries depend on the Core
+# library so linking them back to Core will cause a CMake error.
+#
+# EXTRA_CONDITIONS object library specific conditions to be checked before link the object library
+# to the end-point executable.
+function(__qt_internal_propagate_object_library target object_library)
+ set(options NO_LINK_OBJECT_LIBRARY_REQUIREMENTS_TO_TARGET)
+ set(single_args "")
+ set(multi_args EXTRA_CONDITIONS)
+ cmake_parse_arguments(arg "${options}" "${single_args}" "${multi_args}" ${ARGN})
+
+ target_link_libraries(${object_library} PRIVATE ${QT_CMAKE_EXPORT_NAMESPACE}::Platform)
+ _qt_internal_copy_dependency_properties(${object_library} ${target} PRIVATE_ONLY)
+
+ # 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.
+ # All object libraries mark themselves with the _is_qt_propagated_object_library property.
+ # Using a finalizer approach we walk through the target dependencies and look for libraries
+ # using the _is_qt_propagated_object_library property. Then, objects of the collected libraries
+ # are moved to the beginnig of the linker line using target_sources.
+ #
+ # Note: 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 objects and static
+ # libraries.
+ set_property(TARGET ${object_library} PROPERTY _is_qt_propagated_object_library TRUE)
+ set_property(TARGET ${object_library} APPEND PROPERTY
+ EXPORT_PROPERTIES _is_qt_propagated_object_library
+ )
+
+ # Keep the implicit linking if finalizers are not used.
+ set(not_finalizer_mode_condition
+ "$<NOT:$<BOOL:$<TARGET_PROPERTY:_qt_object_libraries_finalizer_mode>>>"
+ )
+
+ # Collect object library specific conditions.
+ if(arg_EXTRA_CONDITIONS)
+ list(JOIN arg_EXTRA_CONDITIONS "," extra_conditions)
+ else()
+ set(extra_conditions "$<BOOL:TRUE>")
+ endif()
+
+ # Do not litter the static libraries
+ set(not_static_condition
+ "$<NOT:$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>>"
+ )
+
+ # Check if link order matters for the Platform.
+ set(platform_link_order_property
+ "$<TARGET_PROPERTY:${QT_CMAKE_EXPORT_NAMESPACE}::Platform,_qt_link_order_matters>"
+ )
+ set(platform_link_order_condition
+ "$<BOOL:${platform_link_order_property}>"
+ )
+
+ # Use TARGET_NAME to have the correct namespaced name in the exports.
+ set(objects "$<TARGET_OBJECTS:$<TARGET_NAME:${object_library}>>")
+
+ # Collect link conditions for the target_sources call.
+ string(JOIN "" target_sources_genex
+ "$<"
+ "$<AND:"
+ "${not_finalizer_mode_condition},"
+ "${not_static_condition},"
+ "${platform_link_order_condition},"
+ "${extra_conditions}"
+ ">"
+ ":${objects}>"
+ )
+ target_sources(${target} INTERFACE
+ "${target_sources_genex}"
+ )
+
+ # Collect link conditions for the target_link_libraries call.
+ string(JOIN "" target_link_libraries_genex
+ "$<"
+ "$<AND:"
+ "${not_finalizer_mode_condition},"
+ "${not_static_condition},"
+ "$<NOT:${platform_link_order_condition}>,"
+ "${extra_conditions}"
+ ">"
+ ":${objects}>"
+ )
+ target_link_libraries(${target} INTERFACE
+ "${target_link_libraries_genex}"
+ )
+
+ if(NOT arg_NO_LINK_OBJECT_LIBRARY_REQUIREMENTS_TO_TARGET)
+ # It's necessary to link the object library target, since we want to pass the object library
+ # dependencies to the 'target'. Interface linking doesn't add the objects of the library to
+ # the end-point linker line but propagates all the dependencies of the object_library added
+ # before or AFTER the line below.
+ target_link_libraries(${target} INTERFACE ${object_library})
+ endif()
+endfunction()
+
function(__qt_propagate_generated_resource target resource_name generated_source_code output_generated_target)
get_target_property(type ${target} TYPE)
if(type STREQUAL STATIC_LIBRARY)
@@ -1424,13 +1525,10 @@ function(__qt_propagate_generated_resource target resource_name generated_source
"$<TARGET_PROPERTY:${QT_CMAKE_EXPORT_NAMESPACE}::Core,INTERFACE_COMPILE_DEFINITIONS>"
)
- target_link_libraries(${resource_target} PRIVATE ${QT_CMAKE_EXPORT_NAMESPACE}::Platform)
- _qt_internal_copy_dependency_properties(${resource_target} ${target} PRIVATE_ONLY)
-
# Special handling is required for the Core library resources. The linking of the Core
# library to the resources adds a circular dependency. This leads to the wrong
- # objects/library order in the linker command line, since the Core library target is resolved
- # first.
+ # objects/library order in the linker command line, since the Core library target is
+ # resolved first.
if(NOT target STREQUAL "Core")
target_link_libraries(${resource_target} INTERFACE ${QT_CMAKE_EXPORT_NAMESPACE}::Core)
endif()
@@ -1447,73 +1545,13 @@ function(__qt_propagate_generated_resource target resource_name generated_source
set_property(TARGET ${resource_target} APPEND PROPERTY
_qt_resource_generated_cpp_relative_path "${generated_cpp_file_relative_path}")
- # 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.
- # 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 ${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(not_finalizer_mode_condition
- "$<NOT:$<BOOL:$<TARGET_PROPERTY:_qt_resource_objects_finalizer_mode>>>"
- )
- # Do not litter the static libraries
- set(not_static_condition
- "$<NOT:$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>>"
- )
- set(resource_objects "$<TARGET_OBJECTS:$<TARGET_NAME:${resource_target}>>")
-
- set(platform_link_order_property
- "$<TARGET_PROPERTY:${QT_CMAKE_EXPORT_NAMESPACE}::Platform,_qt_link_order_matters>"
- )
- set(platform_link_order_condition
- "$<BOOL:${platform_link_order_property}>"
- )
-
- string(JOIN "" target_sources_genex
- "$<"
- "$<AND:"
- "${not_finalizer_mode_condition},"
- "${not_static_condition},"
- "${platform_link_order_condition}"
- ">"
- ":${resource_objects}>"
- )
- target_sources(${target} INTERFACE
- "${target_sources_genex}"
- )
-
- string(JOIN "" target_link_libraries_genex
- "$<"
- "$<AND:"
- "${not_finalizer_mode_condition},"
- "${not_static_condition},"
- "$<NOT:${platform_link_order_condition}>"
- ">"
- ":${resource_objects}>"
- )
- target_link_libraries(${target} INTERFACE
- "${target_link_libraries_genex}"
+ if(target STREQUAL "Core")
+ set(skip_direct_linking NO_LINK_OBJECT_LIBRARY_REQUIREMENTS_TO_TARGET)
+ endif()
+ __qt_internal_propagate_object_library(${target} ${resource_target}
+ ${skip_direct_linking}
)
- if(NOT target STREQUAL "Core")
- # It's necessary to link the object library target, since we want to pass
- # the object library dependencies to the 'target'. Interface linking doesn't
- # add the objects of the resource library to the end-point linker line
- # but propagates all the dependencies of the resource_target added before
- # or AFTER the line below.
- target_link_libraries(${target} INTERFACE ${resource_target})
- endif()
set(${output_generated_target} "${resource_target}" PARENT_SCOPE)
else()
set(${output_generated_target} "" PARENT_SCOPE)
diff --git a/tests/auto/cmake/test_static_resources/test_static_resources_propagation/CMakeLists.txt b/tests/auto/cmake/test_static_resources/test_static_resources_propagation/CMakeLists.txt
index 58a7c4147a..43363fa495 100644
--- a/tests/auto/cmake/test_static_resources/test_static_resources_propagation/CMakeLists.txt
+++ b/tests/auto/cmake/test_static_resources/test_static_resources_propagation/CMakeLists.txt
@@ -81,7 +81,7 @@ if(NOT link_order_matters)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.19)
qt_add_executable(test_static_resources_propagation_not_finalize main.cpp)
- qt6_enable_resource_objects_finalizer_mode(
+ qt6_enable_object_libraries_finalizer_mode(
test_static_resources_propagation_not_finalize FALSE
)
set_target_properties(test_static_resources_propagation_not_finalize PROPERTIES