summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Edelev <alexey.edelev@qt.io>2021-06-03 13:51:48 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-06-10 15:30:09 +0000
commit9278be7f3922a1919af11659f3adf793b342c742 (patch)
treecd2a9c9904532ad6555bc5790982490c8faffc1c
parenta3065c1f4d5c384378d7e0cb43086b4ae6da67b1 (diff)
Add the check for linker capabilities to resolve circular dependencies
'ld' only capable to resolve circular dependencies by wrapping the suspected static libraries and objects using --start/end-group arguments. We want to detect if linker is 'ld' at configure time to decide how to link the resource objects if finalizers are not enabled. The qt_config_compile_test function is extended with an extra argument since it's required to pass custom cmake flags to the ld-related test. Change-Id: I484fcc99e2886952d8b0232f37e4e6a35d072931 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io> (cherry picked from commit 4e901a2f99cbfda3b479253ea54b16f02e1c3aa5) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--cmake/QtBaseGlobalTargets.cmake7
-rw-r--r--cmake/QtBuildInternals/QtBuildInternalsConfig.cmake38
-rw-r--r--cmake/QtFeature.cmake8
-rw-r--r--cmake/config.tests/static_link_order/CMakeLists.txt22
-rw-r--r--cmake/config.tests/static_link_order/main.cpp33
-rw-r--r--cmake/config.tests/static_link_order/objlib.cpp33
-rw-r--r--cmake/config.tests/static_link_order/staticlib1.cpp33
-rw-r--r--cmake/config.tests/static_link_order/staticlib2.cpp30
-rw-r--r--src/corelib/Qt6CoreMacros.cmake16
-rw-r--r--tests/auto/cmake/test_static_resources/test_static_resources_propagation/CMakeLists.txt4
10 files changed, 219 insertions, 5 deletions
diff --git a/cmake/QtBaseGlobalTargets.cmake b/cmake/QtBaseGlobalTargets.cmake
index 17d5cd6c05..3b770e79ff 100644
--- a/cmake/QtBaseGlobalTargets.cmake
+++ b/cmake/QtBaseGlobalTargets.cmake
@@ -139,6 +139,7 @@ qt_internal_setup_public_platform_target()
# defines PlatformCommonInternal PlatformModuleInternal PlatformPluginInternal PlatformToolInternal
include(QtInternalTargets)
+qt_internal_run_common_config_tests()
set(__export_targets Platform
GlobalConfig
@@ -237,6 +238,12 @@ qt_copy_or_install(FILES
DESTINATION "${__GlobalConfig_install_dir}"
)
+# Install public config.tests files.
+qt_copy_or_install(DIRECTORY
+ "cmake/config.tests"
+ DESTINATION "${__GlobalConfig_install_dir}"
+)
+
# Install public CMake files.
# The functions defined inside can be used in both public projects and while building Qt.
# Usually we put such functions into Qt6CoreMacros.cmake, but that's getting bloated.
diff --git a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
index 2ed51f5685..ad0025da7c 100644
--- a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
+++ b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
@@ -372,6 +372,11 @@ macro(qt_build_repo_begin)
qt_build_internals_set_up_private_api()
qt_enable_cmake_languages()
+ # QtBase has own call right after definition of internal platform-specific targets.
+ if(NOT PROJECT_NAME STREQUAL "QtBase")
+ qt_internal_run_common_config_tests()
+ endif()
+
# Add global docs targets that will work both for per-repo builds, and super builds.
if(NOT TARGET docs)
add_custom_target(docs)
@@ -941,3 +946,36 @@ if ("STANDALONE_TEST" IN_LIST Qt6BuildInternals_FIND_COMPONENTS)
list(GET _qt_core_version_list 2 PROJECT_VERSION_PATCH)
endif()
endif()
+
+function(qt_internal_static_link_order_test)
+ if(TARGET ${QT_CMAKE_EXPORT_NAMESPACE}::PlatformCommonInternal)
+ get_target_property(linker_options
+ ${QT_CMAKE_EXPORT_NAMESPACE}::PlatformCommonInternal INTERFACE_LINK_OPTIONS
+ )
+ string(JOIN " " linker_options ${linker_options})
+ endif()
+
+ qt_config_compile_test(static_link_order
+ LABEL "Check if linker can resolve circular dependencies"
+ PROJECT_PATH "${QT_CMAKE_DIR}/config.tests/static_link_order"
+ CMAKE_FLAGS "-DCMAKE_EXE_LINKER_FLAGS:STRING=${linker_options}"
+ )
+
+ if(TEST_static_link_order)
+ set_property(GLOBAL PROPERTY QT_LINK_ORDER_MATTERS FALSE)
+ set(summary_message "no")
+ else()
+ set_property(GLOBAL PROPERTY QT_LINK_ORDER_MATTERS TRUE)
+ set(summary_message "yes")
+ endif()
+ qt_configure_add_summary_entry(TYPE "message"
+ ARGS "Linker can resolve circular dependencies"
+ MESSAGE "${summary_message}"
+ )
+endfunction()
+
+function(qt_internal_run_common_config_tests)
+ qt_configure_add_summary_section(NAME "Common build options")
+ qt_internal_static_link_order_test()
+ qt_configure_end_summary_section()
+endfunction()
diff --git a/cmake/QtFeature.cmake b/cmake/QtFeature.cmake
index 5603051342..747e0e9405 100644
--- a/cmake/QtFeature.cmake
+++ b/cmake/QtFeature.cmake
@@ -736,7 +736,7 @@ function(qt_config_compile_test name)
endif()
cmake_parse_arguments(arg "" "LABEL;PROJECT_PATH;C_STANDARD;CXX_STANDARD"
- "COMPILE_OPTIONS;LIBRARIES;CODE;PACKAGES" ${ARGN})
+ "COMPILE_OPTIONS;LIBRARIES;CODE;PACKAGES;CMAKE_FLAGS" ${ARGN})
if(arg_PROJECT_PATH)
message(STATUS "Performing Test ${arg_LABEL}")
@@ -815,8 +815,12 @@ function(qt_config_compile_test name)
endif()
endif()
+ if(NOT arg_CMAKE_FLAGS)
+ set(arg_CMAKE_FLAGS "")
+ endif()
+
try_compile(HAVE_${name} "${CMAKE_BINARY_DIR}/config.tests/${name}" "${arg_PROJECT_PATH}"
- "${name}" CMAKE_FLAGS ${flags})
+ "${name}" CMAKE_FLAGS ${flags} ${arg_CMAKE_FLAGS})
if(${HAVE_${name}})
set(status_label "Success")
diff --git a/cmake/config.tests/static_link_order/CMakeLists.txt b/cmake/config.tests/static_link_order/CMakeLists.txt
new file mode 100644
index 0000000000..36ce10e87c
--- /dev/null
+++ b/cmake/config.tests/static_link_order/CMakeLists.txt
@@ -0,0 +1,22 @@
+# The test represents the order-related issue that we have with the ld linker.
+#
+# CMake versions < 3.21.0 produce the following linker line:
+# <binary_name> main.cpp -o static_link_order_test libstaticLib.a objlib.cpp.o
+# Since 'static_link_order_test' doesn't have direct use of 'staticlib2.cpp.o' symbols
+# the translation unit is not linked. When we link objlib.cpp.o it cannot resolve symbols from
+# staticlib2.cpp.o.
+#
+# For now it's only applicable for ld-like linkers. 'lld' has no such issue.
+cmake_minimum_required(VERSION 3.14)
+
+project(static_link_order_test LANGUAGES CXX)
+
+add_library(objLib OBJECT objlib.cpp)
+add_library(staticLib STATIC staticlib1.cpp staticlib2.cpp)
+
+target_link_libraries(staticLib
+ INTERFACE objLib "$<TARGET_OBJECTS:objLib>"
+)
+
+add_executable(static_link_order_test main.cpp)
+target_link_libraries(static_link_order_test PRIVATE staticLib)
diff --git a/cmake/config.tests/static_link_order/main.cpp b/cmake/config.tests/static_link_order/main.cpp
new file mode 100644
index 0000000000..02f10d1620
--- /dev/null
+++ b/cmake/config.tests/static_link_order/main.cpp
@@ -0,0 +1,33 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the utils of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+void staticLibFunc1();
+
+int main() {
+ staticLibFunc1();
+}
diff --git a/cmake/config.tests/static_link_order/objlib.cpp b/cmake/config.tests/static_link_order/objlib.cpp
new file mode 100644
index 0000000000..c3889e04d7
--- /dev/null
+++ b/cmake/config.tests/static_link_order/objlib.cpp
@@ -0,0 +1,33 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the utils of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+void staticLibFunc2();
+
+void objLibFunc() {
+ staticLibFunc2();
+}
diff --git a/cmake/config.tests/static_link_order/staticlib1.cpp b/cmake/config.tests/static_link_order/staticlib1.cpp
new file mode 100644
index 0000000000..b2e933e510
--- /dev/null
+++ b/cmake/config.tests/static_link_order/staticlib1.cpp
@@ -0,0 +1,33 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the utils of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+void objLibFunc();
+
+void staticLibFunc1() {
+ objLibFunc();
+}
diff --git a/cmake/config.tests/static_link_order/staticlib2.cpp b/cmake/config.tests/static_link_order/staticlib2.cpp
new file mode 100644
index 0000000000..7e84289797
--- /dev/null
+++ b/cmake/config.tests/static_link_order/staticlib2.cpp
@@ -0,0 +1,30 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the utils of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+void staticLibFunc2() {
+}
diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake
index 819fbbfb9c..3c154f4587 100644
--- a/src/corelib/Qt6CoreMacros.cmake
+++ b/src/corelib/Qt6CoreMacros.cmake
@@ -1479,10 +1479,24 @@ function(__qt_propagate_generated_resource target resource_name generated_source
"$<NOT:$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>>"
)
set(resource_objects "$<TARGET_OBJECTS:$<TARGET_NAME:${resource_target}>>")
- target_link_libraries(${target} INTERFACE
+
+ set(resource_linking_args ${target} INTERFACE
"$<$<AND:${finalizer_mode_condition},${not_static_condition}>:${resource_objects}>"
)
+ # TODO: The QT_LINK_ORDER_MATTERS flag is not defined for user projects.
+ # It makes sense to disable finalizers if linker may resolve circular dependencies
+ # between objects and static libraries.
+ # Follow-up changes should set _qt_resource_objects_finalizer_mode to FALSE by default
+ # and use target_link_libraries for user projects if the order doesn't affect the
+ # linker work.
+ get_property(link_order_matters GLOBAL PROPERTY QT_LINK_ORDER_MATTERS)
+ if(link_order_matters)
+ target_sources(${resource_linking_args})
+ else()
+ target_link_libraries(${resource_linking_args})
+ endif()
+
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
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 40c922fd8b..f8f46e14f4 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
@@ -58,8 +58,8 @@ add_test(NAME test_static_resources_propagation_non_qt
COMMAND test_static_resources_propagation_non_qt
)
-
-if(NOT GCC AND NOT MINGW AND NOT CLANG)
+get_property(link_order_matters GLOBAL PROPERTY QT_LINK_ORDER_MATTERS)
+if(NOT link_order_matters)
## Add the executable using add_executable, expecting resources to be linked regardless of order.
add_executable(test_static_resources_propagation_non_ld main.cpp)
set_target_properties(test_static_resources_propagation_non_ld PROPERTIES