diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 50da6d2e54..cb18c2c4a5 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -1462,6 +1462,10 @@ void Generator::generatePluginMetaData() data.insert(debugKey, QJsonValue(false)); data.insert(QStringLiteral("MetaData"), cdef->pluginData.metaData.object()); + // Add -M args from the command line: + foreach (const QString &key, cdef->pluginData.metaArgs.keys()) + data.insert(key, cdef->pluginData.metaArgs.value(key)); + fputs("\nQT_PLUGIN_METADATA_SECTION const uint qt_section_alignment_dummy = 42;\n\n" "#ifdef QT_NO_DEBUG\n", out); writePluginMetaData(out, data); diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp index 999cae0e60..98472792f8 100644 --- a/src/tools/moc/main.cpp +++ b/src/tools/moc/main.cpp @@ -242,6 +242,11 @@ int runMoc(int argc, char **argv) undefineOption.setValueName(QStringLiteral("macro")); parser.addOption(undefineOption); + QCommandLineOption metadataOption(QStringLiteral("M")); + metadataOption.setDescription(QStringLiteral("Add key/value pair to plugin meta data")); + metadataOption.setValueName(QStringLiteral("key=value")); + parser.addOption(metadataOption); + QCommandLineOption noIncludeOption(QStringLiteral("i")); noIncludeOption.setDescription(QStringLiteral("Do not generate an #include statement.")); parser.addOption(noIncludeOption); @@ -385,6 +390,24 @@ int runMoc(int argc, char **argv) moc.filename = filename.toLocal8Bit(); } + foreach (const QString &md, parser.values(metadataOption)) { + int split = md.indexOf(QLatin1Char('=')); + QString key = md.left(split); + QString value = md.mid(split + 1); + + if (split == -1 || key.isEmpty() || value.isEmpty()) { + error("missing key or value for option '-M'"); + } else if (key.indexOf(QLatin1Char('.')) != -1) { + // Don't allow keys with '.' for now, since we might need this + // format later for more advanced meta data API + error("A key cannot contain the letter '.' for option '-M'"); + } else { + QJsonArray array = moc.metaArgs.value(key); + array.append(value); + moc.metaArgs.insert(key, array); + } + } + moc.currentFilenames.push(filename.toLocal8Bit()); moc.includes = pp.includes; diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 648723ebc1..8ff481d5b1 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -787,6 +787,10 @@ void Moc::parse() if (!def.hasQObject && !def.hasQGadget) error("Class declarations lacks Q_OBJECT macro."); + // Add meta tags to the plugin meta data: + if (!def.pluginData.iid.isEmpty()) + def.pluginData.metaArgs = metaArgs; + checkSuperClasses(&def); checkProperties(&def); diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index f97a537215..2e22435653 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -47,6 +47,8 @@ #include #include #include +#include +#include #include #include @@ -171,6 +173,7 @@ struct ClassDef { struct PluginData { QByteArray iid; + QMap metaArgs; QJsonDocument metaData; } pluginData; @@ -213,6 +216,7 @@ public: QMap interface2IdMap; QList metaTypes; QSet knownQObjectClasses; + QMap metaArgs; void parse(); void generate(FILE *out); diff --git a/tests/auto/tools/moc/moc.pro b/tests/auto/tools/moc/moc.pro index 5ea8c06f02..0d25131c47 100644 --- a/tests/auto/tools/moc/moc.pro +++ b/tests/auto/tools/moc/moc.pro @@ -22,7 +22,8 @@ HEADERS += using-namespaces.h no-keywords.h task87883.h c-comments.h backslash-n cxx11-explicit-override-control.h \ forward-declared-param.h \ parse-defines.h \ - function-with-attributes.h + function-with-attributes.h \ + plugin_metadata.h if(*-g++*|*-icc*|*-clang*|*-llvm):!irix-*:!win32-*: HEADERS += os9-newlines.h win-newlines.h @@ -35,3 +36,8 @@ qtHaveModule(dbus) { QT += dbus } DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 + +# tst_Moc::specifyMetaTagsFromCmdline() +# Ensure that plugin_metadata.h are moc-ed with some extra -M arguments: +QMAKE_MOC_OPTIONS += -Muri=com.company.app -Muri=com.company.app.private + diff --git a/tests/auto/tools/moc/plugin_metadata.h b/tests/auto/tools/moc/plugin_metadata.h new file mode 100644 index 0000000000..7172617f00 --- /dev/null +++ b/tests/auto/tools/moc/plugin_metadata.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTPLUGINMETADATA +#define TESTPLUGINMETADATA + +#include + +class TestPluginMetaData : public QObject +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "test.meta.tags") +}; + +#endif diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index a6cd85ade5..7fae29e5ca 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -531,6 +531,7 @@ private slots: void frameworkSearchPath(); void cstyleEnums(); void defineMacroViaCmdline(); + void specifyMetaTagsFromCmdline(); void invokable(); void singleFunctionKeywordSignalAndSlot(); void templateGtGt(); @@ -1170,6 +1171,37 @@ void tst_Moc::defineMacroViaCmdline() #endif } +// tst_Moc::specifyMetaTagsFromCmdline() +// plugin_metadata.h contains a plugin which we register here. Since we're not building this +// application as a plugin, we need top copy some of the initializer code found in qplugin.h: +extern "C" QObject *qt_plugin_instance(); +extern "C" const char *qt_plugin_query_metadata(); +class StaticPluginInstance{ +public: + StaticPluginInstance() { + QStaticPlugin plugin = { &qt_plugin_instance, &qt_plugin_query_metadata }; + qRegisterStaticPluginFunction(plugin); + } +}; +static StaticPluginInstance staticInstance; + +void tst_Moc::specifyMetaTagsFromCmdline() { + foreach (const QStaticPlugin &plugin, QPluginLoader::staticPlugins()) { + const QString iid = plugin.metaData().value(QLatin1String("IID")).toString(); + if (iid == QLatin1String("test.meta.tags")) { + const QJsonArray metaTagsUriList = plugin.metaData().value("uri").toArray(); + QCOMPARE(metaTagsUriList.size(), 2); + + // The following uri-s are set in the pro file using + // -Muri=com.company.app -Muri=com.company.app.private + QCOMPARE(metaTagsUriList[0].toString(), QLatin1String("com.company.app")); + QCOMPARE(metaTagsUriList[1].toString(), QLatin1String("com.company.app.private")); + return; + } + } + QFAIL("Could not find plugin with IID 'test.meta.tags'"); +} + void tst_Moc::invokable() { {