diff --git a/mkspecs/features/resources.prf b/mkspecs/features/resources.prf index ff45446219..7ae78d021e 100644 --- a/mkspecs/features/resources.prf +++ b/mkspecs/features/resources.prf @@ -72,6 +72,38 @@ for(resource, RESOURCES) { RESOURCES += $$resource_file } +!isEmpty(RESOURCES):contains(TEMPLATE, .*lib):plugin:static { + resource_init_function = $$lower($$basename(TARGET))_plugin_resource_init + DEFINES += "QT_PLUGIN_RESOURCE_INIT_FUNCTION=$$resource_init_function" + + RESOURCE_INIT_CPP = $$OUT_PWD/$$lower($$basename(TARGET))_plugin_resources.cpp + + GENERATED_SOURCES += $$RESOURCE_INIT_CPP + QMAKE_DISTCLEAN += $$RESOURCE_INIT_CPP + + !build_pass { + RESOURCE_INIT_CONT = \ + "// This file is autogenerated by qmake. It contains a function that" \ + "// references all resources the plugin includes and the function is" \ + "// referenced by Qt_(MOC_)EXPORT_PLUGIN to ensure the inclusion in" \ + "// the statically linked plugin." \ + "$${LITERAL_HASH}include " \ + "void $${resource_init_function}() " \ + "{" \ + + for (resource, RESOURCES) { + resource_name = $$section($$list($$basename(resource)), ., 0, 0) + resource_name = $$replace(resource_name, [^a-zA-Z0-9_], _) + RESOURCE_INIT_CONT += " Q_INIT_RESOURCE($$resource_name);" + } + + RESOURCE_INIT_CONT += \ + "}" + + write_file($$RESOURCE_INIT_CPP, RESOURCE_INIT_CONT)|error() + } +} + rcc.input = RESOURCES rcc.name = RCC ${QMAKE_FILE_IN} rcc.depend_command = $$QMAKE_RCC_DEP -list $$QMAKE_RESOURCE_FLAGS ${QMAKE_FILE_IN} diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h index b644d47856..07edc616df 100644 --- a/src/corelib/plugin/qplugin.h +++ b/src/corelib/plugin/qplugin.h @@ -105,11 +105,21 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin); }; \ static Static##PLUGIN##PluginInstance static##PLUGIN##Instance; +#if defined(QT_PLUGIN_RESOURCE_INIT_FUNCTION) +# define QT_PLUGIN_RESOURCE_INIT \ + extern void QT_PLUGIN_RESOURCE_INIT_FUNCTION(); \ + QT_PLUGIN_RESOURCE_INIT_FUNCTION(); +#else +# define QT_PLUGIN_RESOURCE_INIT +#endif + #define Q_PLUGIN_INSTANCE(IMPLEMENTATION) \ { \ static QT_PREPEND_NAMESPACE(QPointer) _instance; \ - if (!_instance) \ + if (!_instance) { \ + QT_PLUGIN_RESOURCE_INIT \ _instance = new IMPLEMENTATION; \ + } \ return _instance; \ } diff --git a/tests/auto/corelib/io/qresourceengine/qresourceengine.pro b/tests/auto/corelib/io/qresourceengine/qresourceengine.pro index f937d23fe2..1e12a41dea 100644 --- a/tests/auto/corelib/io/qresourceengine/qresourceengine.pro +++ b/tests/auto/corelib/io/qresourceengine/qresourceengine.pro @@ -1,23 +1,2 @@ -CONFIG += testcase -TARGET = tst_qresourceengine - -QT = core testlib -SOURCES = tst_qresourceengine.cpp -RESOURCES += testqrc/test.qrc - -qtPrepareTool(QMAKE_RCC, rcc, _DEP) -runtime_resource.target = runtime_resource.rcc -runtime_resource.depends = $$PWD/testqrc/test.qrc $$QMAKE_RCC_EXE -runtime_resource.commands = $$QMAKE_RCC -root /runtime_resource/ -binary $$PWD/testqrc/test.qrc -o $${runtime_resource.target} -QMAKE_EXTRA_TARGETS = runtime_resource -PRE_TARGETDEPS += $${runtime_resource.target} -QMAKE_DISTCLEAN += $${runtime_resource.target} - -TESTDATA += \ - parentdir.txt \ - testqrc/* -GENERATED_TESTDATA = $${runtime_resource.target} - -android:!android-embedded { - RESOURCES += android_testdata.qrc -} +TEMPLATE = subdirs +SUBDIRS = staticplugin qresourceengine_test.pro diff --git a/tests/auto/corelib/io/qresourceengine/qresourceengine_test.pro b/tests/auto/corelib/io/qresourceengine/qresourceengine_test.pro new file mode 100644 index 0000000000..9478595df6 --- /dev/null +++ b/tests/auto/corelib/io/qresourceengine/qresourceengine_test.pro @@ -0,0 +1,31 @@ +CONFIG += testcase +TARGET = tst_qresourceengine + +QT = core testlib +SOURCES = tst_qresourceengine.cpp +RESOURCES += testqrc/test.qrc + +qtPrepareTool(QMAKE_RCC, rcc, _DEP) +runtime_resource.target = runtime_resource.rcc +runtime_resource.depends = $$PWD/testqrc/test.qrc $$QMAKE_RCC_EXE +runtime_resource.commands = $$QMAKE_RCC -root /runtime_resource/ -binary $$PWD/testqrc/test.qrc -o $${runtime_resource.target} +QMAKE_EXTRA_TARGETS = runtime_resource +PRE_TARGETDEPS += $${runtime_resource.target} +QMAKE_DISTCLEAN += $${runtime_resource.target} + +TESTDATA += \ + parentdir.txt \ + testqrc/* +GENERATED_TESTDATA = $${runtime_resource.target} + +android:!android-embedded { + RESOURCES += android_testdata.qrc +} + +win32 { + CONFIG(debug, debug|release): LIBS += -Lstaticplugin/debug + else: LIBS += -Lstaticplugin/release +} else { + LIBS += -Lstaticplugin +} +LIBS += -lmoctestplugin diff --git a/tests/auto/corelib/io/qresourceengine/staticplugin/.gitignore b/tests/auto/corelib/io/qresourceengine/staticplugin/.gitignore new file mode 100644 index 0000000000..c397dde6a5 --- /dev/null +++ b/tests/auto/corelib/io/qresourceengine/staticplugin/.gitignore @@ -0,0 +1 @@ +moctestplugin_plugin_resources.cpp diff --git a/tests/auto/corelib/io/qresourceengine/staticplugin/main.cpp b/tests/auto/corelib/io/qresourceengine/staticplugin/main.cpp new file mode 100644 index 0000000000..39a3a1e012 --- /dev/null +++ b/tests/auto/corelib/io/qresourceengine/staticplugin/main.cpp @@ -0,0 +1,9 @@ +#include + +class PluginClass : public QObject +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.tests.moc" FILE "staticplugin.json") +}; + +#include "main.moc" diff --git a/tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.json b/tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.json new file mode 100644 index 0000000000..4103ecb18c --- /dev/null +++ b/tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.json @@ -0,0 +1 @@ +{ "Keys": [ "staticplugin" ] } diff --git a/tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.pro b/tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.pro new file mode 100644 index 0000000000..e19d884548 --- /dev/null +++ b/tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.pro @@ -0,0 +1,8 @@ +TEMPLATE = lib +TARGET = moctestplugin +CONFIG += plugin static +SOURCES = main.cpp +plugin_resource.files = main.cpp +plugin_resource.prefix = /staticplugin +RESOURCES += plugin_resource +QT = core diff --git a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp index ab1866fb2d..3f0e68c1b8 100644 --- a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp +++ b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp @@ -56,6 +56,7 @@ private slots: void doubleSlashInRoot(); void setLocale(); void lastModified(); + void resourcesInStaticPlugins(); private: const QString m_runtimeResourceRcc; @@ -118,6 +119,7 @@ void tst_QResourceEngine::checkStructure_data() << QLatin1String("searchpath1") << QLatin1String("searchpath2") << QLatin1String("secondary_root") + << QLatin1String("staticplugin") << QLatin1String("test") << QLatin1String("withoutslashes"); @@ -504,6 +506,16 @@ void tst_QResourceEngine::lastModified() } } +Q_IMPORT_PLUGIN(PluginClass) +void tst_QResourceEngine::resourcesInStaticPlugins() +{ + // We built a separate static plugin and attempted linking against + // it. That should successfully register the resources linked into + // the plugin via moc generated Q_INIT_RESOURCE calls in a + // Q_CONSTRUCTOR_FUNCTION. + QVERIFY(QFile::exists(":/staticplugin/main.cpp")); +} + QTEST_MAIN(tst_QResourceEngine) #include "tst_qresourceengine.moc"