summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/CMakeLists.txt12
-rw-r--r--src/corelib/Qt6CoreMacros.cmake50
-rw-r--r--src/corelib/Qt6CoreResourceInit.in.cpp14
-rw-r--r--src/corelib/global/qtsymbolmacros.h65
-rw-r--r--tests/auto/cmake/CMakeLists.txt1
-rw-r--r--tests/auto/cmake/test_resource_without_obj_lib/CMakeLists.txt33
-rw-r--r--tests/auto/cmake/test_resource_without_obj_lib/helper_lib.cpp4
-rw-r--r--tests/auto/cmake/test_resource_without_obj_lib/main.cpp28
-rw-r--r--tests/auto/cmake/test_resource_without_obj_lib/resource.txt1
9 files changed, 200 insertions, 8 deletions
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index adfb67ffd6b..e7545084c13 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -87,6 +87,7 @@ qt_internal_add_module(Core
global/qtpreprocessorsupport.h
global/qtrace_p.h
global/qtresource.h
+ global/qtsymbolmacros.h
global/qttranslation.h
global/qttypetraits.h
global/qtversionchecks.h
@@ -342,11 +343,12 @@ qt_internal_add_module(Core
PUBLIC_LIBRARIES
Qt::Platform
EXTRA_CMAKE_FILES
- "${CMAKE_CURRENT_SOURCE_DIR}/Qt6CTestMacros.cmake"
- "${CMAKE_CURRENT_SOURCE_DIR}/Qt6CoreConfigureFileTemplate.in"
- "${CMAKE_CURRENT_SOURCE_DIR}/Qt6CoreDeploySupport.cmake"
- "${config_build_dir}/QtInstallPaths.cmake"
- ${corelib_extra_cmake_files}
+ "${CMAKE_CURRENT_SOURCE_DIR}/Qt6CTestMacros.cmake"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Qt6CoreConfigureFileTemplate.in"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Qt6CoreResourceInit.in.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Qt6CoreDeploySupport.cmake"
+ "${config_build_dir}/QtInstallPaths.cmake"
+ ${corelib_extra_cmake_files}
POLICIES
QTP0002
)
diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake
index cb58bbef40c..a4b1ba4c987 100644
--- a/src/corelib/Qt6CoreMacros.cmake
+++ b/src/corelib/Qt6CoreMacros.cmake
@@ -1846,11 +1846,24 @@ function(__qt_propagate_generated_resource target resource_name generated_source
math(EXPR resource_count "${resource_count} + 1")
set_target_properties(${target} PROPERTIES _qt_generated_resource_target_count ${resource_count})
+ __qt_internal_generate_init_resource_source_file(
+ resource_init_file ${target} ${resource_name})
+
set(resource_target "${target}_resources_${resource_count}")
- add_library("${resource_target}" OBJECT "${generated_source_code}")
+ add_library("${resource_target}" OBJECT "${resource_init_file}")
+ # Needed so that qtsymbolmacros.h and its dependent headers are already created / syncqt'ed.
+ if(TARGET Core_sync_headers)
+ set(headers_available_target "Core_sync_headers")
+ else()
+ set(headers_available_target "${QT_CMAKE_EXPORT_NAMESPACE}::Core")
+ endif()
+ add_dependencies(${resource_target} ${headers_available_target})
target_compile_definitions("${resource_target}" PRIVATE
"$<TARGET_PROPERTY:${QT_CMAKE_EXPORT_NAMESPACE}::Core,INTERFACE_COMPILE_DEFINITIONS>"
)
+ target_include_directories("${resource_target}" PRIVATE
+ "$<TARGET_PROPERTY:${QT_CMAKE_EXPORT_NAMESPACE}::Core,INTERFACE_INCLUDE_DIRECTORIES>"
+ )
_qt_internal_set_up_static_runtime_library("${resource_target}")
# Special handling is required for the Core library resources. The linking of the Core
@@ -1869,7 +1882,7 @@ function(__qt_propagate_generated_resource target resource_name generated_source
# .rcc/qrc_qprintdialog.cpp
file(RELATIVE_PATH generated_cpp_file_relative_path
"${CMAKE_CURRENT_BINARY_DIR}"
- "${generated_source_code}")
+ "${resource_init_file}")
set_property(TARGET ${resource_target} APPEND PROPERTY
_qt_resource_generated_cpp_relative_path "${generated_cpp_file_relative_path}")
@@ -1883,8 +1896,39 @@ function(__qt_propagate_generated_resource target resource_name generated_source
set(${output_generated_target} "${resource_target}" PARENT_SCOPE)
else()
set(${output_generated_target} "" PARENT_SCOPE)
- target_sources(${target} PRIVATE ${generated_source_code})
endif()
+
+ target_sources(${target} PRIVATE ${generated_source_code})
+endfunction()
+
+function(__qt_internal_sanitize_resource_name out_var name)
+ # The sanitized output should match RCCResourceLibrary::writeInitializer()'s
+ # isAsciiLetterOrNumber-based substituion.
+ # MAKE_C_IDENTIFIER matches that, it replaces non-alphanumeric chars with underscores.
+ string(MAKE_C_IDENTIFIER "${name}" sanitized_resource_name)
+ set(${out_var} "${sanitized_resource_name}" PARENT_SCOPE)
+endfunction()
+
+function(__qt_internal_generate_init_resource_source_file out_var target resource_name)
+ set(template_file "${__qt_core_macros_module_base_dir}/Qt6CoreResourceInit.in.cpp")
+
+ # Gets replaced in the template
+ __qt_internal_sanitize_resource_name(RESOURCE_NAME "${resource_name}")
+ set(resource_init_path "${CMAKE_CURRENT_BINARY_DIR}/.rcc/qrc_${resource_name}_init.cpp")
+
+ configure_file("${template_file}" "${resource_init_path}" @ONLY)
+
+ set(scope_args "")
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
+ set(scope_args TARGET_DIRECTORY ${target})
+ endif()
+ set_source_files_properties(${resource_init_path} ${scope_args} PROPERTIES
+ SKIP_AUTOGEN TRUE
+ SKIP_UNITY_BUILD_INCLUSION TRUE
+ SKIP_PRECOMPILE_HEADERS TRUE
+ )
+
+ set(${out_var} "${resource_init_path}" PARENT_SCOPE)
endfunction()
# Make file visible in IDEs.
diff --git a/src/corelib/Qt6CoreResourceInit.in.cpp b/src/corelib/Qt6CoreResourceInit.in.cpp
new file mode 100644
index 00000000000..0234ec8232d
--- /dev/null
+++ b/src/corelib/Qt6CoreResourceInit.in.cpp
@@ -0,0 +1,14 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: BSD-3-Clause
+
+// This file was generated by the qt_add_resources command.
+
+#include <QtCore/qtsymbolmacros.h>
+
+QT_DECLARE_EXTERN_RESOURCE(@RESOURCE_NAME@);
+
+namespace {
+ struct resourceReferenceKeeper {
+ resourceReferenceKeeper() { QT_KEEP_RESOURCE(@RESOURCE_NAME@); }
+ } resourceReferenceKeeperInstance;
+}
diff --git a/src/corelib/global/qtsymbolmacros.h b/src/corelib/global/qtsymbolmacros.h
new file mode 100644
index 00000000000..18cdc85f728
--- /dev/null
+++ b/src/corelib/global/qtsymbolmacros.h
@@ -0,0 +1,65 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QTSYMBOLMACROS_H
+#define QTSYMBOLMACROS_H
+
+#if 0
+# pragma qt_sync_stop_processing
+#endif
+
+// For GHS symbol keeping.
+#include <QtCore/qcompilerdetection.h>
+#include <QtCore/qtpreprocessorsupport.h>
+
+// For handling namespaced resources.
+#ifdef QT_NAMESPACE
+# define QT_RCC_MANGLE_NAMESPACE0(x) x
+# define QT_RCC_MANGLE_NAMESPACE1(a, b) a##_##b
+# define QT_RCC_MANGLE_NAMESPACE2(a, b) QT_RCC_MANGLE_NAMESPACE1(a,b)
+# define QT_RCC_MANGLE_NAMESPACE(name) QT_RCC_MANGLE_NAMESPACE2( \
+ QT_RCC_MANGLE_NAMESPACE0(name), QT_RCC_MANGLE_NAMESPACE0(QT_NAMESPACE))
+#else
+# define QT_RCC_MANGLE_NAMESPACE(name) name
+#endif
+
+// GHS needs special handling to keep a symbol around.
+#if defined(Q_CC_GHS)
+# define Q_GHS_KEEP_REFERENCE(S) QT_DO_PRAGMA(ghs reference S ##__Fv)
+#else
+# define Q_GHS_KEEP_REFERENCE(S)
+#endif
+
+// Macros to ensure a symbol is not dropped by the linker even if it's not used.
+#define QT_DECLARE_EXTERN_SYMBOL(NAME, RETURN_TYPE) \
+ extern RETURN_TYPE NAME(); \
+ Q_GHS_KEEP_REFERENCE(NAME)
+
+#define QT_DECLARE_EXTERN_SYMBOL_INT(NAME) \
+ QT_DECLARE_EXTERN_SYMBOL(NAME, int)
+
+#define QT_DECLARE_EXTERN_SYMBOL_VOID(NAME) \
+ QT_DECLARE_EXTERN_SYMBOL(NAME, void)
+
+#define QT_KEEP_SYMBOL_VAR_NAME(NAME) NAME ## _keep
+
+#define QT_KEEP_SYMBOL_HELPER(NAME, VAR_NAME) \
+ volatile auto VAR_NAME = &NAME; \
+ Q_UNUSED(VAR_NAME)
+
+#define QT_KEEP_SYMBOL(NAME) \
+ QT_KEEP_SYMBOL_HELPER(NAME, QT_KEEP_SYMBOL_VAR_NAME(NAME))
+
+
+// Similar to the ones above, but for rcc resource symbols specifically.
+#define QT_GET_RESOURCE_INIT_SYMBOL(NAME) \
+ QT_RCC_MANGLE_NAMESPACE(qInitResources_ ## NAME)
+
+#define QT_DECLARE_EXTERN_RESOURCE(NAME) \
+ QT_DECLARE_EXTERN_SYMBOL_INT(QT_GET_RESOURCE_INIT_SYMBOL(NAME))
+
+#define QT_KEEP_RESOURCE(NAME) \
+ QT_KEEP_SYMBOL(QT_GET_RESOURCE_INIT_SYMBOL(NAME))
+
+#endif // QTSYMBOLMACROS_H
+
diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt
index 975cc6fc7d2..1ce6f8a0202 100644
--- a/tests/auto/cmake/CMakeLists.txt
+++ b/tests/auto/cmake/CMakeLists.txt
@@ -222,6 +222,7 @@ _qt_internal_test_expect_pass(test_multiple_find_package)
_qt_internal_test_expect_pass(test_add_resources_delayed_file)
_qt_internal_test_expect_pass(test_add_binary_resources_delayed_file BINARY test_add_binary_resources_delayed_file)
_qt_internal_test_expect_pass(test_qt_add_resources_rebuild)
+_qt_internal_test_expect_pass(test_resource_without_obj_lib BINARY test_resource_without_obj_lib)
if(NOT NO_GUI)
_qt_internal_test_expect_pass(test_private_includes)
diff --git a/tests/auto/cmake/test_resource_without_obj_lib/CMakeLists.txt b/tests/auto/cmake/test_resource_without_obj_lib/CMakeLists.txt
new file mode 100644
index 00000000000..16563141f4c
--- /dev/null
+++ b/tests/auto/cmake/test_resource_without_obj_lib/CMakeLists.txt
@@ -0,0 +1,33 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.16)
+
+project(test_resource_without_obj_lib)
+
+if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/FindPackageHints.cmake")
+ include("${CMAKE_CURRENT_LIST_DIR}/FindPackageHints.cmake")
+endif()
+
+find_package(Qt6 REQUIRED
+ COMPONENTS Core Test
+ HINTS ${Qt6Tests_PREFIX_PATH}
+)
+
+qt6_add_library(helper_lib STATIC helper_lib.cpp)
+qt6_add_resources(helper_lib "helper_res" FILES resource.txt PREFIX "/")
+
+# Link to Core, to ensure both the helper_lib and the main executable
+# inherit the QT_NAMESPACE if it is set, otherwise we get undefined
+# linker errors due to the mismatch in symbol names.
+target_link_libraries(helper_lib PRIVATE Qt6::Core)
+
+set(CMAKE_AUTOMOC ON)
+
+qt6_add_executable(test_resource_without_obj_lib main.cpp)
+target_link_libraries(test_resource_without_obj_lib PRIVATE Qt6::Core Qt6::Test)
+
+# Link against the library file and not the target, so that we can confirm
+# the ability to manually initialize the resource via Q_INIT_RESOURCE.
+target_link_libraries(test_resource_without_obj_lib PRIVATE $<TARGET_FILE:helper_lib>)
+
diff --git a/tests/auto/cmake/test_resource_without_obj_lib/helper_lib.cpp b/tests/auto/cmake/test_resource_without_obj_lib/helper_lib.cpp
new file mode 100644
index 00000000000..18371786a92
--- /dev/null
+++ b/tests/auto/cmake/test_resource_without_obj_lib/helper_lib.cpp
@@ -0,0 +1,4 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+void nothing() {}
diff --git a/tests/auto/cmake/test_resource_without_obj_lib/main.cpp b/tests/auto/cmake/test_resource_without_obj_lib/main.cpp
new file mode 100644
index 00000000000..29ea0f72721
--- /dev/null
+++ b/tests/auto/cmake/test_resource_without_obj_lib/main.cpp
@@ -0,0 +1,28 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include <QtCore/qtresource.h>
+#include <QtTest/QtTest>
+
+class TestManualResourceInit : public QObject
+{
+ Q_OBJECT
+private slots:
+ void initTestCase();
+ void resourceExistsAfterManualInit();
+};
+
+void TestManualResourceInit::initTestCase()
+{
+ // Manually initialize the resource like we used to do it in qt5 + qmake times.
+ Q_INIT_RESOURCE(helper_res);
+}
+
+void TestManualResourceInit::resourceExistsAfterManualInit()
+{
+ QVERIFY(QFile::exists(":/resource.txt"));
+}
+
+QTEST_MAIN(TestManualResourceInit)
+#include "main.moc"
+
diff --git a/tests/auto/cmake/test_resource_without_obj_lib/resource.txt b/tests/auto/cmake/test_resource_without_obj_lib/resource.txt
new file mode 100644
index 00000000000..7804a324a4d
--- /dev/null
+++ b/tests/auto/cmake/test_resource_without_obj_lib/resource.txt
@@ -0,0 +1 @@
+Test resource