aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/generator/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken6/generator/main.cpp')
-rw-r--r--sources/shiboken6/generator/main.cpp649
1 files changed, 649 insertions, 0 deletions
diff --git a/sources/shiboken6/generator/main.cpp b/sources/shiboken6/generator/main.cpp
new file mode 100644
index 000000000..3c5c5876c
--- /dev/null
+++ b/sources/shiboken6/generator/main.cpp
@@ -0,0 +1,649 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $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$
+**
+****************************************************************************/
+
+#include <QCoreApplication>
+#include <QLibrary>
+#include <QtCore/QFile>
+#include <QtCore/QDir>
+#include <iostream>
+#include <apiextractor.h>
+#include <fileout.h>
+#include <reporthandler.h>
+#include <typedatabase.h>
+#include <messages.h>
+#include "generator.h"
+#include "shibokenconfig.h"
+#include "cppgenerator.h"
+#include "headergenerator.h"
+#include "qtdocgenerator.h"
+
+#ifdef Q_OS_WIN
+static const QChar pathSplitter = QLatin1Char(';');
+#else
+static const QChar pathSplitter = QLatin1Char(':');
+#endif
+
+static inline QString languageLevelOption() { return QStringLiteral("language-level"); }
+static inline QString includePathOption() { return QStringLiteral("include-paths"); }
+static inline QString frameworkIncludePathOption() { return QStringLiteral("framework-include-paths"); }
+static inline QString systemIncludePathOption() { return QStringLiteral("system-include-paths"); }
+static inline QString typesystemPathOption() { return QStringLiteral("typesystem-paths"); }
+static inline QString helpOption() { return QStringLiteral("help"); }
+static inline QString diffOption() { return QStringLiteral("diff"); }
+static inline QString dryrunOption() { return QStringLiteral("dry-run"); }
+static inline QString skipDeprecatedOption() { return QStringLiteral("skip-deprecated"); }
+
+static const char helpHint[] = "Note: use --help or -h for more information.\n";
+
+using OptionDescriptions = Generator::OptionDescriptions;
+
+struct CommandLineArguments
+{
+ QMap<QString, QString> options;
+ QStringList positionalArguments;
+};
+
+static void printOptions(QTextStream &s, const OptionDescriptions &options)
+{
+ s.setFieldAlignment(QTextStream::AlignLeft);
+ for (const auto &od : options) {
+ if (!od.first.startsWith(QLatin1Char('-')))
+ s << "--";
+ s << od.first;
+ if (od.second.isEmpty()) {
+ s << ", ";
+ } else {
+ s << Qt::endl;
+ const auto lines = QStringView{od.second}.split(QLatin1Char('\n'));
+ for (const auto &line : lines)
+ s << " " << line << Qt::endl;
+ s << Qt::endl;
+ }
+ }
+}
+
+static bool processProjectFile(QFile &projectFile, CommandLineArguments &args)
+{
+ QByteArray line = projectFile.readLine().trimmed();
+ if (line.isEmpty() || line != "[generator-project]")
+ return false;
+
+ QStringList includePaths;
+ QStringList frameworkIncludePaths;
+ QStringList systemIncludePaths;
+ QStringList typesystemPaths;
+ QStringList apiVersions;
+ QString languageLevel;
+
+ while (!projectFile.atEnd()) {
+ line = projectFile.readLine().trimmed();
+ if (line.isEmpty())
+ continue;
+
+ int split = line.indexOf('=');
+ QByteArray key;
+ QString value;
+ if (split > 0) {
+ key = line.left(split - 1).trimmed();
+ value = QString::fromUtf8(line.mid(split + 1).trimmed());
+ } else {
+ key = line;
+ }
+
+ if (key == "include-path")
+ includePaths << QDir::toNativeSeparators(value);
+ else if (key == "framework-include-path")
+ frameworkIncludePaths << QDir::toNativeSeparators(value);
+ else if (key == "system-include-paths")
+ systemIncludePaths << QDir::toNativeSeparators(value);
+ else if (key == "typesystem-path")
+ typesystemPaths << QDir::toNativeSeparators(value);
+ else if (key == "language-level")
+ languageLevel = value;
+ else if (key == "api-version")
+ apiVersions << value;
+ else if (key == "header-file")
+ args.positionalArguments.prepend(value);
+ else if (key == "typesystem-file")
+ args.positionalArguments.append(value);
+ else
+ args.options.insert(QString::fromUtf8(key), value);
+ }
+
+ if (!includePaths.isEmpty())
+ args.options.insert(includePathOption(), includePaths.join(pathSplitter));
+
+ if (!frameworkIncludePaths.isEmpty())
+ args.options.insert(frameworkIncludePathOption(),
+ frameworkIncludePaths.join(pathSplitter));
+ if (!systemIncludePaths.isEmpty()) {
+ args.options.insert(systemIncludePathOption(),
+ systemIncludePaths.join(pathSplitter));
+ }
+
+ if (!typesystemPaths.isEmpty())
+ args.options.insert(typesystemPathOption(), typesystemPaths.join(pathSplitter));
+ if (!apiVersions.isEmpty())
+ args.options.insert(QLatin1String("api-version"), apiVersions.join(QLatin1Char('|')));
+ if (!languageLevel.isEmpty())
+ args.options.insert(languageLevelOption(), languageLevel);
+ return true;
+}
+
+static CommandLineArguments getProjectFileArguments()
+{
+ CommandLineArguments args;
+ QStringList arguments = QCoreApplication::arguments();
+ QString appName = arguments.constFirst();
+ arguments.removeFirst();
+
+ QString projectFileName;
+ for (const QString &arg : qAsConst(arguments)) {
+ if (arg.startsWith(QLatin1String("--project-file"))) {
+ int split = arg.indexOf(QLatin1Char('='));
+ if (split > 0)
+ projectFileName = arg.mid(split + 1).trimmed();
+ break;
+ }
+ }
+
+ if (projectFileName.isEmpty())
+ return args;
+
+ if (!QFile::exists(projectFileName)) {
+ std::cerr << qPrintable(appName) << ": Project file \"";
+ std::cerr << qPrintable(projectFileName) << "\" not found.";
+ std::cerr << std::endl;
+ return args;
+ }
+
+ QFile projectFile(projectFileName);
+ if (!projectFile.open(QIODevice::ReadOnly))
+ return args;
+
+ if (!processProjectFile(projectFile, args)) {
+ std::cerr << qPrintable(appName) << ": first line of project file \"";
+ std::cerr << qPrintable(projectFileName) << "\" must be the string \"[generator-project]\"";
+ std::cerr << std::endl;
+ return args;
+ }
+
+ return args;
+}
+
+// Concatenate values of path arguments that can occur multiple times on the
+// command line.
+static void addPathOptionValue(const QString &option, const QString &value,
+ CommandLineArguments &args)
+{
+ auto it = args.options.find(option);
+ if (it != args.options.end())
+ it.value().append(pathSplitter + value);
+ else
+ args.options.insert(option, value);
+}
+
+static void getCommandLineArg(QString arg, int &argNum, CommandLineArguments &args)
+{
+ if (arg.startsWith(QLatin1String("--"))) {
+ arg.remove(0, 2);
+ const int split = arg.indexOf(QLatin1Char('='));
+ if (split < 0) {
+ args.options.insert(arg, QString());
+ return;
+ }
+ const QString option = arg.left(split);
+ const QString value = arg.mid(split + 1).trimmed();
+ if (option == includePathOption() || option == frameworkIncludePathOption()
+ || option == systemIncludePathOption() || option == typesystemPathOption()) {
+ addPathOptionValue(option, value, args);
+ } else {
+ args.options.insert(option, value);
+ }
+ return;
+ }
+ if (arg.startsWith(QLatin1Char('-'))) {
+ arg.remove(0, 1);
+ if (arg.startsWith(QLatin1Char('I'))) // Shorthand path arguments -I/usr/include...
+ addPathOptionValue(includePathOption(), arg.mid(1), args);
+ else if (arg.startsWith(QLatin1Char('F')))
+ addPathOptionValue(frameworkIncludePathOption(), arg.mid(1), args);
+ else if (arg.startsWith(QLatin1String("isystem")))
+ addPathOptionValue(systemIncludePathOption(), arg.mid(7), args);
+ else if (arg.startsWith(QLatin1Char('T')))
+ addPathOptionValue(typesystemPathOption(), arg.mid(1), args);
+ else if (arg == QLatin1String("h"))
+ args.options.insert(helpOption(), QString());
+ else if (arg.startsWith(QLatin1String("std=")))
+ args.options.insert(languageLevelOption(), arg.mid(4));
+ else
+ args.options.insert(arg, QString());
+ return;
+ }
+ if (argNum < args.positionalArguments.size())
+ args.positionalArguments[argNum] = arg;
+ else
+ args.positionalArguments.append(arg);
+ ++argNum;
+}
+
+static void getCommandLineArgs(CommandLineArguments &args)
+{
+ const QStringList arguments = QCoreApplication::arguments();
+ int argNum = 0;
+ for (int i = 1, size = arguments.size(); i < size; ++i)
+ getCommandLineArg(arguments.at(i).trimmed(), argNum, args);
+}
+
+static inline Generators docGenerators()
+{
+ Generators result;
+#ifdef DOCSTRINGS_ENABLED
+ result.append(GeneratorPtr(new QtDocGenerator));
+#endif
+ return result;
+}
+
+static inline Generators shibokenGenerators()
+{
+ Generators result;
+ result << GeneratorPtr(new CppGenerator) << GeneratorPtr(new HeaderGenerator);
+ return result;
+}
+
+static inline QString languageLevelDescription()
+{
+ return QLatin1String("C++ Language level (c++11..c++17, default=")
+ + QLatin1String(clang::languageLevelOption(clang::emulatedCompilerLanguageLevel()))
+ + QLatin1Char(')');
+}
+
+void printUsage()
+{
+ QTextStream s(stdout);
+ s << "Usage:\n "
+ << "shiboken [options] header-file(s) typesystem-file\n\n"
+ << "General options:\n";
+ QString pathSyntax;
+ QTextStream(&pathSyntax) << "<path>[" << pathSplitter << "<path>"
+ << pathSplitter << "...]";
+ OptionDescriptions generalOptions = OptionDescriptions()
+ << qMakePair(QLatin1String("api-version=<\"package mask\">,<\"version\">"),
+ QLatin1String("Specify the supported api version used to generate the bindings"))
+ << qMakePair(QLatin1String("debug-level=[sparse|medium|full]"),
+ QLatin1String("Set the debug level"))
+ << qMakePair(QLatin1String("documentation-only"),
+ QLatin1String("Do not generates any code, just the documentation"))
+ << qMakePair(QLatin1String("drop-type-entries=\"<TypeEntry0>[;TypeEntry1;...]\""),
+ QLatin1String("Semicolon separated list of type system entries (classes, namespaces,\n"
+ "global functions and enums) to be dropped from generation."))
+ << qMakePair(QLatin1String("-F<path>"), QString())
+ << qMakePair(QLatin1String("framework-include-paths=") + pathSyntax,
+ QLatin1String("Framework include paths used by the C++ parser"))
+ << qMakePair(QLatin1String("-isystem<path>"), QString())
+ << qMakePair(QLatin1String("system-include-paths=") + pathSyntax,
+ QLatin1String("System include paths used by the C++ parser"))
+ << qMakePair(QLatin1String("generator-set=<\"generator module\">"),
+ QLatin1String("generator-set to be used. e.g. qtdoc"))
+ << qMakePair(skipDeprecatedOption(),
+ QLatin1String("Skip deprecated functions"))
+ << qMakePair(diffOption(),
+ QLatin1String("Print a diff of wrapper files"))
+ << qMakePair(dryrunOption(),
+ QLatin1String("Dry run, do not generate wrapper files"))
+ << qMakePair(QLatin1String("-h"), QString())
+ << qMakePair(helpOption(),
+ QLatin1String("Display this help and exit"))
+ << qMakePair(QLatin1String("-I<path>"), QString())
+ << qMakePair(QLatin1String("include-paths=") + pathSyntax,
+ QLatin1String("Include paths used by the C++ parser"))
+ << qMakePair(languageLevelOption() + QLatin1String("=, -std=<level>"),
+ languageLevelDescription())
+ << qMakePair(QLatin1String("license-file=<license-file>"),
+ QLatin1String("File used for copyright headers of generated files"))
+ << qMakePair(QLatin1String("no-suppress-warnings"),
+ QLatin1String("Show all warnings"))
+ << qMakePair(QLatin1String("output-directory=<path>"),
+ QLatin1String("The directory where the generated files will be written"))
+ << qMakePair(QLatin1String("project-file=<file>"),
+ QLatin1String("text file containing a description of the binding project.\n"
+ "Replaces and overrides command line arguments"))
+ << qMakePair(QLatin1String("silent"),
+ QLatin1String("Avoid printing any message"))
+ << qMakePair(QLatin1String("-T<path>"), QString())
+ << qMakePair(QLatin1String("typesystem-paths=") + pathSyntax,
+ QLatin1String("Paths used when searching for typesystems"))
+ << qMakePair(QLatin1String("version"),
+ QLatin1String("Output version information and exit"));
+ printOptions(s, generalOptions);
+
+ const Generators generators = shibokenGenerators() + docGenerators();
+ for (const GeneratorPtr &generator : generators) {
+ const OptionDescriptions options = generator->options();
+ if (!options.isEmpty()) {
+ s << Qt::endl << generator->name() << " options:\n\n";
+ printOptions(s, generator->options());
+ }
+ }
+}
+
+static inline void printVerAndBanner()
+{
+ std::cout << "shiboken v" SHIBOKEN_VERSION << std::endl;
+ std::cout << "Copyright (C) 2016 The Qt Company Ltd." << std::endl;
+}
+
+static inline void errorPrint(const QString &s)
+{
+ QStringList arguments = QCoreApplication::arguments();
+ arguments.pop_front();
+ std::cerr << "shiboken: " << qPrintable(s)
+ << "\nCommand line: " << qPrintable(arguments.join(QLatin1Char(' '))) << '\n';
+}
+
+static void parseIncludePathOption(const QString &option, HeaderType headerType,
+ CommandLineArguments &args,
+ ApiExtractor &extractor)
+{
+ const auto it = args.options.find(option);
+ if (it != args.options.end()) {
+ const QStringList includePathListList =
+ it.value().split(pathSplitter, Qt::SkipEmptyParts);
+ args.options.erase(it);
+ for (const QString &s : includePathListList) {
+ auto path = QFile::encodeName(QDir::cleanPath(s));
+ extractor.addIncludePath(HeaderPath{path, headerType});
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ // PYSIDE-757: Request a deterministic ordering of QHash in the code model
+ // and type system.
+ qSetGlobalQHashSeed(0);
+ // needed by qxmlpatterns
+ QCoreApplication app(argc, argv);
+ ReportHandler::install();
+ if (ReportHandler::isDebug(ReportHandler::SparseDebug))
+ qCInfo(lcShiboken()).noquote().nospace() << QCoreApplication::arguments().join(QLatin1Char(' '));
+
+ // Store command arguments in a map
+ const CommandLineArguments projectFileArguments = getProjectFileArguments();
+ CommandLineArguments args = projectFileArguments;
+ getCommandLineArgs(args);
+ Generators generators;
+
+ auto ait = args.options.find(QLatin1String("version"));
+ if (ait != args.options.end()) {
+ args.options.erase(ait);
+ printVerAndBanner();
+ return EXIT_SUCCESS;
+ }
+
+ QString generatorSet;
+ ait = args.options.find(QLatin1String("generator-set"));
+ if (ait == args.options.end()) // Also check QLatin1String("generatorSet") command line argument for backward compatibility.
+ ait = args.options.find(QLatin1String("generatorSet"));
+ if (ait != args.options.end()) {
+ generatorSet = ait.value();
+ args.options.erase(ait);
+ }
+
+ // Pre-defined generator sets.
+ if (generatorSet == QLatin1String("qtdoc")) {
+ generators = docGenerators();
+ if (generators.isEmpty()) {
+ errorPrint(QLatin1String("Doc strings extractions was not enabled in this shiboken build."));
+ return EXIT_FAILURE;
+ }
+ } else if (generatorSet.isEmpty() || generatorSet == QLatin1String("shiboken")) {
+ generators = shibokenGenerators();
+ } else {
+ errorPrint(QLatin1String("Unknown generator set, try \"shiboken\" or \"qtdoc\"."));
+ return EXIT_FAILURE;
+ }
+
+ ait = args.options.find(QLatin1String("help"));
+ if (ait != args.options.end()) {
+ args.options.erase(ait);
+ printUsage();
+ return EXIT_SUCCESS;
+ }
+
+ ait = args.options.find(diffOption());
+ if (ait != args.options.end()) {
+ args.options.erase(ait);
+ FileOut::diff = true;
+ }
+
+ ait = args.options.find(dryrunOption());
+ if (ait != args.options.end()) {
+ args.options.erase(ait);
+ FileOut::dummy = true;
+ }
+
+ QString licenseComment;
+ ait = args.options.find(QLatin1String("license-file"));
+ if (ait != args.options.end()) {
+ QFile licenseFile(ait.value());
+ args.options.erase(ait);
+ if (licenseFile.open(QIODevice::ReadOnly)) {
+ licenseComment = QString::fromUtf8(licenseFile.readAll());
+ } else {
+ errorPrint(QStringLiteral("Could not open the file \"%1\" containing the license heading: %2").
+ arg(QDir::toNativeSeparators(licenseFile.fileName()), licenseFile.errorString()));
+ return EXIT_FAILURE;
+ }
+ }
+
+ QString outputDirectory = QLatin1String("out");
+ ait = args.options.find(QLatin1String("output-directory"));
+ if (ait != args.options.end()) {
+ outputDirectory = ait.value();
+ args.options.erase(ait);
+ }
+
+ if (!QDir(outputDirectory).exists()) {
+ if (!QDir().mkpath(outputDirectory)) {
+ qCWarning(lcShiboken).noquote().nospace()
+ << "Can't create output directory: " << QDir::toNativeSeparators(outputDirectory);
+ return EXIT_FAILURE;
+ }
+ }
+
+ // Create and set-up API Extractor
+ ApiExtractor extractor;
+ extractor.setLogDirectory(outputDirectory);
+ ait = args.options.find(skipDeprecatedOption());
+ if (ait != args.options.end()) {
+ extractor.setSkipDeprecated(true);
+ args.options.erase(ait);
+ }
+
+ ait = args.options.find(QLatin1String("silent"));
+ if (ait != args.options.end()) {
+ extractor.setSilent(true);
+ args.options.erase(ait);
+ } else {
+ ait = args.options.find(QLatin1String("debug-level"));
+ if (ait != args.options.end()) {
+ if (!ReportHandler::setDebugLevelFromArg(ait.value())) {
+ errorPrint(QLatin1String("Invalid debug level: ") + ait.value());
+ return EXIT_FAILURE;
+ }
+ args.options.erase(ait);
+ }
+ }
+ ait = args.options.find(QLatin1String("no-suppress-warnings"));
+ if (ait != args.options.end()) {
+ args.options.erase(ait);
+ extractor.setSuppressWarnings(false);
+ }
+ ait = args.options.find(QLatin1String("api-version"));
+ if (ait != args.options.end()) {
+ const QStringList &versions = ait.value().split(QLatin1Char('|'));
+ args.options.erase(ait);
+ for (const QString &fullVersion : versions) {
+ QStringList parts = fullVersion.split(QLatin1Char(','));
+ QString package;
+ QString version;
+ package = parts.count() == 1 ? QLatin1String("*") : parts.constFirst();
+ version = parts.constLast();
+ if (!extractor.setApiVersion(package, version)) {
+ errorPrint(msgInvalidVersion(package, version));
+ return EXIT_FAILURE;
+ }
+ }
+ }
+
+ ait = args.options.find(QLatin1String("drop-type-entries"));
+ if (ait != args.options.end()) {
+ extractor.setDropTypeEntries(ait.value());
+ args.options.erase(ait);
+ }
+
+ ait = args.options.find(QLatin1String("typesystem-paths"));
+ if (ait != args.options.end()) {
+ extractor.addTypesystemSearchPath(ait.value().split(pathSplitter));
+ args.options.erase(ait);
+ }
+
+ parseIncludePathOption(includePathOption(), HeaderType::Standard,
+ args, extractor);
+ parseIncludePathOption(frameworkIncludePathOption(), HeaderType::Framework,
+ args, extractor);
+ parseIncludePathOption(systemIncludePathOption(), HeaderType::System,
+ args, extractor);
+
+ if (args.positionalArguments.size() < 2) {
+ errorPrint(QLatin1String("Insufficient positional arguments, specify header-file and typesystem-file."));
+ std::cout << '\n';
+ printUsage();
+ return EXIT_FAILURE;
+ }
+
+ const QString typeSystemFileName = args.positionalArguments.takeLast();
+ QString messagePrefix = QFileInfo(typeSystemFileName).baseName();
+ if (messagePrefix.startsWith(QLatin1String("typesystem_")))
+ messagePrefix.remove(0, 11);
+ ReportHandler::setPrefix(QLatin1Char('(') + messagePrefix + QLatin1Char(')'));
+
+ QFileInfoList cppFileNames;
+ for (const QString &cppFileName : qAsConst(args.positionalArguments)) {
+ const QFileInfo cppFileNameFi(cppFileName);
+ if (!cppFileNameFi.isFile() && !cppFileNameFi.isSymLink()) {
+ errorPrint(QLatin1Char('"') + cppFileName + QLatin1String("\" does not exist."));
+ return EXIT_FAILURE;
+ }
+ cppFileNames.append(cppFileNameFi);
+ }
+
+ // Pass option to all generators (Cpp/Header generator have the same options)
+ for (ait = args.options.begin(); ait != args.options.end(); ) {
+ bool found = false;
+ for (const GeneratorPtr &generator : qAsConst(generators))
+ found |= generator->handleOption(ait.key(), ait.value());
+ if (found)
+ ait = args.options.erase(ait);
+ else
+ ++ait;
+ }
+
+ ait = args.options.find(languageLevelOption());
+ if (ait != args.options.end()) {
+ const QByteArray languageLevelBA = ait.value().toLatin1();
+ args.options.erase(ait);
+ const LanguageLevel level = clang::languageLevelFromOption(languageLevelBA.constData());
+ if (level == LanguageLevel::Default) {
+ std::cout << "Invalid argument for language level: \""
+ << languageLevelBA.constData() << "\"\n" << helpHint;
+ return EXIT_FAILURE;
+ }
+ extractor.setLanguageLevel(level);
+ }
+
+ /* Make sure to remove the project file's arguments (if any) and
+ * --project-file, also the arguments of each generator before
+ * checking if there isn't any existing arguments in argsHandler.
+ */
+ args.options.remove(QLatin1String("project-file"));
+ for (auto it = projectFileArguments.options.cbegin(), end = projectFileArguments.options.cend();
+ it != end; ++it) {
+ args.options.remove(it.key());
+ }
+
+ if (!args.options.isEmpty()) {
+ errorPrint(msgLeftOverArguments(args.options));
+ std::cout << helpHint;
+ return EXIT_FAILURE;
+ }
+
+ if (typeSystemFileName.isEmpty()) {
+ std::cout << "You must specify a Type System file." << std::endl << helpHint;
+ return EXIT_FAILURE;
+ }
+
+ extractor.setCppFileNames(cppFileNames);
+ extractor.setTypeSystem(typeSystemFileName);
+
+ auto shibokenGenerator = dynamic_cast<const ShibokenGenerator *>(generators.constFirst().data());
+ const bool usePySideExtensions = shibokenGenerator && shibokenGenerator->usePySideExtensions();
+
+ if (!extractor.run(usePySideExtensions)) {
+ errorPrint(QLatin1String("Error running ApiExtractor."));
+ return EXIT_FAILURE;
+ }
+
+ if (!extractor.classCount())
+ qCWarning(lcShiboken) << "No C++ classes found!";
+
+ if (ReportHandler::isDebug(ReportHandler::FullDebug)
+ || qEnvironmentVariableIsSet("SHIBOKEN_DUMP_CODEMODEL")) {
+ qCInfo(lcShiboken) << "API Extractor:\n" << extractor
+ << "\n\nType datase:\n" << *TypeDatabase::instance();
+ }
+
+ for (const GeneratorPtr &g : qAsConst(generators)) {
+ g->setOutputDirectory(outputDirectory);
+ g->setLicenseComment(licenseComment);
+ ReportHandler::startProgress(QByteArray("Running ") + g->name() + "...");
+ const bool ok = g->setup(extractor) && g->generate();
+ ReportHandler::endProgress();
+ if (!ok) {
+ errorPrint(QLatin1String("Error running generator: ")
+ + QLatin1String(g->name()) + QLatin1Char('.'));
+ return EXIT_FAILURE;
+ }
+ }
+
+ const QByteArray doneMessage = ReportHandler::doneMessage();
+ std::cout << doneMessage.constData() << std::endl;
+
+ return EXIT_SUCCESS;
+}