1// Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Volker Krause <volker.krause@kdab.com>
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
4
5#include <QCommandLineParser>
6#include <QCoreApplication>
7#include <QDir>
8#include <QFile>
9#include <QJsonDocument>
10#include <QJsonObject>
11#include <QLibrary>
12#include <QPluginLoader>
13#include <QStringList>
14
15#include <iostream>
16
17enum PrintOption {
18 PrintIID = 0x01,
19 PrintClassName = 0x02,
20 PrintQtInfo = 0x04,
21 PrintUserData = 0x08
22};
23Q_DECLARE_FLAGS(PrintOptions, PrintOption)
24Q_DECLARE_OPERATORS_FOR_FLAGS(PrintOptions)
25
26int main(int argc, char** argv)
27{
28 QCoreApplication app(argc, argv);
29 QCoreApplication::setApplicationName(QStringLiteral("qplugininfo"));
30 QCoreApplication::setApplicationVersion(QStringLiteral(QT_VERSION_STR));
31
32 QCommandLineParser parser;
33 parser.setApplicationDescription(QStringLiteral("Qt plugin meta-data dumper"));
34 QCommandLineOption jsonFormatOption(QStringList() << "f" << "json-format",
35 QStringLiteral("Print JSON data as: indented, compact"), QStringLiteral("format"));
36 QCommandLineOption fullJsonOption("full-json",
37 QStringLiteral("Print the plugin metadata in JSON format"));
38 QCommandLineOption printOption(QStringList() << "p" << QStringLiteral("print"),
39 QStringLiteral("Print detail (iid, classname, qtinfo, userdata)"), QStringLiteral("detail"));
40 jsonFormatOption.setDefaultValue(QStringLiteral("indented"));
41 printOption.setDefaultValues(QStringList() << QStringLiteral("iid") << QStringLiteral("qtinfo") << QStringLiteral("userdata"));
42
43 parser.addOption(commandLineOption: fullJsonOption);
44 parser.addOption(commandLineOption: jsonFormatOption);
45 parser.addOption(commandLineOption: printOption);
46 parser.addHelpOption();
47 parser.addVersionOption();
48 parser.addPositionalArgument(QStringLiteral("plugin"), QStringLiteral("Plug-in of which to read the meta data."), QStringLiteral("<plugin>"));
49 parser.process(app);
50
51 if (parser.positionalArguments().isEmpty())
52 parser.showHelp(exitCode: 1);
53
54 bool fullJson = parser.isSet(option: fullJsonOption);
55 QJsonDocument::JsonFormat jsonFormat = parser.value(option: jsonFormatOption) == "indented" ? QJsonDocument::Indented : QJsonDocument::Compact;
56 QStringList printOptionList = parser.values(option: printOption);
57 PrintOptions print;
58 if (printOptionList.contains(t: "iid"))
59 print |= PrintIID;
60 if (printOptionList.contains(t: "classname"))
61 print |= PrintClassName;
62 if (printOptionList.contains(t: "qtinfo"))
63 print |= PrintQtInfo;
64 if (printOptionList.contains(t: "userdata"))
65 print |= PrintUserData;
66
67 int retval = 0;
68 const QStringList positionalArguments = parser.positionalArguments();
69 for (const QString &plugin : positionalArguments) {
70 QByteArray pluginNativeName = QFile::encodeName(fileName: QDir::toNativeSeparators(pathName: plugin));
71 if (!QFile::exists(fileName: plugin)) {
72 std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": No such file or directory." << std::endl;
73 retval = 1;
74 continue;
75 }
76 if (!QLibrary::isLibrary(fileName: plugin)) {
77 std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": Not a plug-in." << std::endl;
78 retval = 1;
79 continue;
80 }
81
82 QPluginLoader loader(plugin);
83 QJsonObject metaData = loader.metaData();
84 if (metaData.isEmpty()) {
85 std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": No plug-in meta-data found: "
86 << qPrintable(loader.errorString()) << std::endl;
87 retval = 1;
88 continue;
89 }
90
91 QString iid = metaData.value(key: "IID").toString();
92 QString className = metaData.value(key: "className").toString();
93 QJsonValue debug = metaData.value(key: "debug");
94 int version = metaData.value(key: "version").toInt();
95 QJsonValue userData = metaData.value(key: "MetaData");
96
97 if ((version >> 16) != (QT_VERSION >> 16)) {
98 std::cerr << "qtplugininfo: " << pluginNativeName.constData()
99 << ": Qt version mismatch - got major version " << (version >> 16)
100 << ", expected " << (QT_VERSION >> 16) << std::endl;
101 retval = 1;
102 continue;
103 }
104 if (iid.isEmpty() || className.isEmpty() || debug.isNull()) {
105 std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": invalid metadata, missing required fields:";
106 if (iid.isEmpty())
107 std::cerr << " iid";
108 if (className.isEmpty())
109 std::cerr << " className";
110 if (debug.isNull())
111 std::cerr << " debug";
112 std::cerr << std::endl;
113 retval = 1;
114 continue;
115 }
116
117 if (parser.positionalArguments().size() != 1)
118 std::cout << pluginNativeName.constData() << ": ";
119 if (fullJson) {
120 std::cout << QJsonDocument(metaData).toJson(format: jsonFormat).constData();
121 if (jsonFormat == QJsonDocument::Compact)
122 std::cout << std::endl;
123 } else {
124 if (print & PrintIID)
125 std::cout << "IID \"" << qPrintable(iid) << "\" ";
126 if (print & PrintClassName)
127 std::cout << "class " << qPrintable(className) << ' ';
128 if (print & PrintQtInfo)
129 std::cout << "Qt " << (version >> 16) << '.' << ((version >> 8) & 0xFF) << '.' << (version & 0xFF)
130 << (debug.toBool() ? " (debug)" : " (release)");
131 std::cout << std::endl;
132 if (print & PrintUserData) {
133 if (userData.isObject())
134 std::cout << "User Data: " << QJsonDocument(userData.toObject()).toJson().constData();
135 else if (!userData.isNull()) {
136 std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": invalid metadata, user data is not a JSON object" << std::endl;
137 retval = 1;
138 }
139 }
140 }
141 }
142
143 return retval;
144}
145

source code of qttools/src/qtplugininfo/qtplugininfo.cpp