diff options
Diffstat (limited to 'sources/shiboken2/generator/main.cpp')
-rw-r--r-- | sources/shiboken2/generator/main.cpp | 221 |
1 files changed, 150 insertions, 71 deletions
diff --git a/sources/shiboken2/generator/main.cpp b/sources/shiboken2/generator/main.cpp index 874540e54..774775fb0 100644 --- a/sources/shiboken2/generator/main.cpp +++ b/sources/shiboken2/generator/main.cpp @@ -46,6 +46,12 @@ #define PATH_SPLITTER ":" #endif +static inline QString includePathOption() { return QStringLiteral("include-paths"); } +static inline QString frameworkIncludePathOption() { return QStringLiteral("framework-include-paths"); } +static inline QString typesystemPathOption() { return QStringLiteral("typesystem-paths"); } +static inline QString helpOption() { return QStringLiteral("help"); } +static const char helpHint[] = "Note: use --help or -h for more information.\n"; + namespace { class ArgsHandler @@ -134,14 +140,17 @@ QString ArgsHandler::errorMessage() const } } -static void printOptions(QTextStream& s, const QMap<QString, QString>& options) +typedef Generator::OptionDescriptions OptionDescriptions; + +static void printOptions(QTextStream& s, const OptionDescriptions& options) { - QMap<QString, QString>::const_iterator it = options.constBegin(); s.setFieldAlignment(QTextStream::AlignLeft); - for (; it != options.constEnd(); ++it) { - s << " --"; + for (const auto &od : options) { + s << ' '; + if (!od.first.startsWith(QLatin1Char('-'))) + s << "--"; s.setFieldWidth(38); - s << it.key() << it.value(); + s << od.first << od.second; s.setFieldWidth(0); s << endl; } @@ -156,6 +165,7 @@ static bool processProjectFile(QFile& projectFile, QMap<QString, QString>& args) return false; QStringList includePaths; + QStringList frameworkIncludePaths; QStringList typesystemPaths; QStringList apiVersions; @@ -176,6 +186,8 @@ static bool processProjectFile(QFile& projectFile, QMap<QString, QString>& args) if (key == "include-path") includePaths << QDir::toNativeSeparators(value); + else if (key == "framework-include-path") + frameworkIncludePaths << QDir::toNativeSeparators(value); else if (key == "typesystem-path") typesystemPaths << QDir::toNativeSeparators(value); else if (key == "api-version") @@ -189,10 +201,14 @@ static bool processProjectFile(QFile& projectFile, QMap<QString, QString>& args) } if (!includePaths.isEmpty()) - args.insert(QLatin1String("include-paths"), includePaths.join(QLatin1String(PATH_SPLITTER))); + args.insert(includePathOption(), includePaths.join(QLatin1String(PATH_SPLITTER))); + + if (!frameworkIncludePaths.isEmpty()) + args.insert(frameworkIncludePathOption(), + frameworkIncludePaths.join(QLatin1String(PATH_SPLITTER))); if (!typesystemPaths.isEmpty()) - args.insert(QLatin1String("typesystem-paths"), typesystemPaths.join(QLatin1String(PATH_SPLITTER))); + args.insert(typesystemPathOption(), typesystemPaths.join(QLatin1String(PATH_SPLITTER))); if (!apiVersions.isEmpty()) args.insert(QLatin1String("api-version"), apiVersions.join(QLatin1Char('|'))); return true; @@ -202,11 +218,11 @@ static QMap<QString, QString> getInitializedArguments() { QMap<QString, QString> args; QStringList arguments = QCoreApplication::arguments(); - QString appName = arguments.first(); + QString appName = arguments.constFirst(); arguments.removeFirst(); QString projectFileName; - foreach (const QString& arg, arguments) { + for (const QString &arg : qAsConst(arguments)) { if (arg.startsWith(QLatin1String("--project-file"))) { int split = arg.indexOf(QLatin1Char('=')); if (split > 0) @@ -239,6 +255,55 @@ static QMap<QString, QString> getInitializedArguments() 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, + QMap<QString, QString> &args) +{ + const QMap<QString, QString>::iterator it = args.find(option); + if (it != args.end()) + it.value().append(QLatin1String(PATH_SPLITTER) + value); + else + args.insert(option, value); +} + +static void getCommandLineArg(QString arg, int &argNum, QMap<QString, QString> &args) +{ + if (arg.startsWith(QLatin1String("--"))) { + arg.remove(0, 2); + const int split = arg.indexOf(QLatin1Char('=')); + if (split < 0) { + args.insert(arg, QString()); + return; + } + const QString option = arg.left(split); + const QString value = arg.mid(split + 1).trimmed(); + if (option == includePathOption() || option == frameworkIncludePathOption() + || option == typesystemPathOption()) { + addPathOptionValue(option, value, args); + } else { + args.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(QLatin1Char('T'))) + addPathOptionValue(typesystemPathOption(), arg.mid(1), args); + else if (arg == QLatin1String("h")) + args.insert(helpOption(), QString()); + else + args.insert(arg, QString()); + return; + } + argNum++; + args.insert(QStringLiteral("arg-") + QString::number(argNum), arg); +} + static QMap<QString, QString> getCommandLineArgs() { QMap<QString, QString> args = getInitializedArguments(); @@ -246,21 +311,9 @@ static QMap<QString, QString> getCommandLineArgs() arguments.removeFirst(); int argNum = 0; - foreach (const QString &carg, arguments) { - const QString &arg = carg.trimmed(); - if (arg.startsWith(QLatin1String("--"))) { - int split = arg.indexOf(QLatin1Char('=')); - if (split > 0) - args[arg.mid(2).left(split-2)] = arg.mid(split + 1).trimmed(); - else - args[arg.mid(2)] = QString(); - } else if (arg.startsWith(QLatin1Char('-'))) { - args[arg.mid(1)] = QString(); - } else { - argNum++; - args[QString::fromLatin1("arg-%1").arg(argNum)] = arg; - } - } + for (const QString &carg : qAsConst(arguments)) + getCommandLineArg(carg.trimmed(), argNum, args); + return args; } @@ -286,40 +339,47 @@ void printUsage() s << "Usage:\n " << "shiboken [options] header-file typesystem-file\n\n" << "General options:\n"; - QMap<QString, QString> generalOptions; - generalOptions.insert(QLatin1String("project-file=<file>"), - QLatin1String("text file containing a description of the binding project. Replaces and overrides command line arguments")); - generalOptions.insert(QLatin1String("debug-level=[sparse|medium|full]"), - QLatin1String("Set the debug level")); - generalOptions.insert(QLatin1String("silent"), - QLatin1String("Avoid printing any message")); - generalOptions.insert(QLatin1String("help"), - QLatin1String("Display this help and exit")); - generalOptions.insert(QLatin1String("no-suppress-warnings"), - QLatin1String("Show all warnings")); - generalOptions.insert(QLatin1String("output-directory=<path>"), - QLatin1String("The directory where the generated files will be written")); - generalOptions.insert(QLatin1String("include-paths=<path>[" PATH_SPLITTER "<path>" PATH_SPLITTER "...]"), - QLatin1String("Include paths used by the C++ parser")); - generalOptions.insert(QLatin1String("typesystem-paths=<path>[" PATH_SPLITTER "<path>" PATH_SPLITTER "...]"), - QLatin1String("Paths used when searching for typesystems")); - generalOptions.insert(QLatin1String("documentation-only"), - QLatin1String("Do not generates any code, just the documentation")); - generalOptions.insert(QLatin1String("license-file=<license-file>"), - QLatin1String("File used for copyright headers of generated files")); - generalOptions.insert(QLatin1String("version"), - QLatin1String("Output version information and exit")); - generalOptions.insert(QLatin1String("generator-set=<\"generator module\">"), - QLatin1String("generator-set to be used. e.g. qtdoc")); - generalOptions.insert(QLatin1String("api-version=<\"package mask\">,<\"version\">"), - QLatin1String("Specify the supported api version used to generate the bindings")); - generalOptions.insert(QLatin1String("drop-type-entries=\"<TypeEntry0>[;TypeEntry1;...]\""), - QLatin1String("Semicolon separated list of type system entries (classes, namespaces, global functions and enums) to be dropped from generation.")); + const QString pathSyntax = QLatin1String("<path>[" PATH_SPLITTER "<path>" PATH_SPLITTER "...]"); + 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, global functions and enums) to be dropped from generation.")) + << qMakePair(QLatin1String("-F") + pathSyntax, QString()) + << qMakePair(QLatin1String("framework-include-paths=") + pathSyntax, + QLatin1String("Framework include paths used by the C++ parser")) + << qMakePair(QLatin1String("generator-set=<\"generator module\">"), + QLatin1String("generator-set to be used. e.g. qtdoc")) + << qMakePair(QLatin1String("-h"), QString()) + << qMakePair(helpOption(), + QLatin1String("Display this help and exit")) + << qMakePair(QLatin1String("-I") + pathSyntax, QString()) + << qMakePair(QLatin1String("include-paths=") + pathSyntax, + QLatin1String("Include paths used by the C++ parser")) + << 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. Replaces and overrides command line arguments")) + << qMakePair(QLatin1String("silent"), + QLatin1String("Avoid printing any message")) + << qMakePair(QLatin1String("-T") + pathSyntax, 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(); - foreach (const GeneratorPtr &generator, generators) { - QMap<QString, QString> options = generator->options(); + for (const GeneratorPtr &generator : generators) { + const OptionDescriptions options = generator->options(); if (!options.isEmpty()) { s << endl << generator->name() << " options:\n"; printOptions(s, generator->options()); @@ -437,14 +497,13 @@ int main(int argc, char *argv[]) extractor.setSuppressWarnings(false); if (argsHandler.argExists(QLatin1String("api-version"))) { - QStringList versions = argsHandler.removeArg(QLatin1String("api-version")).split(QLatin1Char('|')); - foreach (const QString &fullVersion, versions) { + const QStringList &versions = argsHandler.removeArg(QLatin1String("api-version")).split(QLatin1Char('|')); + for (const QString &fullVersion : versions) { QStringList parts = fullVersion.split(QLatin1Char(',')); QString package; QString version; - // avoid constFirst to stay Qt 5.5 compatible - package = parts.count() == 1 ? QLatin1String("*") : parts.first(); - version = parts.last(); + package = parts.count() == 1 ? QLatin1String("*") : parts.constFirst(); + version = parts.constLast(); if (!extractor.setApiVersion(package, version)) { errorPrint(msgInvalidVersion(package, version)); return EXIT_FAILURE; @@ -460,11 +519,29 @@ int main(int argc, char *argv[]) extractor.addTypesystemSearchPath(path.split(QLatin1String(PATH_SPLITTER))); path = argsHandler.removeArg(QLatin1String("include-paths")); - if (!path.isEmpty()) - extractor.addIncludePath(path.split(QLatin1String(PATH_SPLITTER))); + if (!path.isEmpty()) { + const QStringList includePathListList = path.split(QLatin1String(PATH_SPLITTER)); + for (const QString &s : qAsConst(includePathListList)) { + const bool isFramework = false; + extractor.addIncludePath(HeaderPath(s, isFramework)); + } + } + + path = argsHandler.removeArg(QLatin1String("framework-include-paths")); + if (!path.isEmpty()) { + const QStringList frameworkPathList = path.split(QLatin1String(PATH_SPLITTER)); + const bool isFramework = true; + for (const QString &s : qAsConst(frameworkPathList)) { + extractor.addIncludePath(HeaderPath(s, isFramework)); + } + } QString cppFileName = argsHandler.removeArg(QLatin1String("arg-1")); QString typeSystemFileName = argsHandler.removeArg(QLatin1String("arg-2")); + QString messagePrefix = QFileInfo(typeSystemFileName).baseName(); + if (messagePrefix.startsWith(QLatin1String("typesystem_"))) + messagePrefix.remove(0, 11); + ReportHandler::setPrefix(QLatin1Char('(') + messagePrefix + QLatin1Char(')')); /* Make sure to remove the project file's arguments (if any) and * --project-file, also the arguments of each generator before @@ -478,18 +555,20 @@ int main(int argc, char *argv[]) for ( ; it != projectFileArgs.constEnd(); ++it) argsHandler.removeArg(it.key()); } - foreach (const GeneratorPtr &generator, generators) { - QMap<QString, QString> options = generator->options(); - if (!options.isEmpty()) { - QMap<QString, QString>::const_iterator it = options.constBegin(); - for ( ; it != options.constEnd(); ++it) - argsHandler.removeArg(it.key()); - } + for (const GeneratorPtr &generator : qAsConst(generators)) { + const OptionDescriptions &options = generator->options(); + for (const auto &od : options) + argsHandler.removeArg(od.first); } if (!argsHandler.noArgs()) { errorPrint(argsHandler.errorMessage()); - std::cout << "Note: use --help option for more information." << std::endl; + std::cout << helpHint; + return EXIT_FAILURE; + } + + if (typeSystemFileName.isEmpty()) { + std::cout << "You must specify a Type System file." << std::endl << helpHint; return EXIT_FAILURE; } @@ -505,7 +584,7 @@ int main(int argc, char *argv[]) qCDebug(lcShiboken) << extractor; - foreach (const GeneratorPtr &g, generators) { + for (const GeneratorPtr &g : qAsConst(generators)) { g->setOutputDirectory(outputDirectory); g->setLicenseComment(licenseComment); if (g->setup(extractor, args)) { |