diff options
Diffstat (limited to 'sources/shiboken2/generator/main.cpp')
-rw-r--r-- | sources/shiboken2/generator/main.cpp | 290 |
1 files changed, 138 insertions, 152 deletions
diff --git a/sources/shiboken2/generator/main.cpp b/sources/shiboken2/generator/main.cpp index 7ee43710e..c996c7cc3 100644 --- a/sources/shiboken2/generator/main.cpp +++ b/sources/shiboken2/generator/main.cpp @@ -34,6 +34,7 @@ #include <QtCore/QDir> #include <iostream> #include <apiextractor.h> +#include <fileout.h> #include "generator.h" #include "shibokenconfig.h" #include "cppgenerator.h" @@ -52,87 +53,19 @@ static inline QString frameworkIncludePathOption() { return QStringLiteral("fram 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 const char helpHint[] = "Note: use --help or -h for more information.\n"; - -namespace { - -class ArgsHandler -{ -public: - explicit ArgsHandler(const QMap<QString, QString>& other); - virtual ~ArgsHandler(); - - inline QMap<QString, QString>& args() const - { - return *m_args; - } - - inline bool argExists(const QString& s) const - { - return m_args->contains(s); - } - - QString removeArg(const QString& s); - bool argExistsRemove(const QString& s); - - inline QString argValue(const QString& s) const - { - return m_args->value(s); - } - - inline bool noArgs() const - { - return m_args->isEmpty(); - } - - QString errorMessage() const; - -private: - QMap<QString, QString>* m_args; -}; +static inline QString diffOption() { return QStringLiteral("diff"); } +static inline QString dryrunOption() { return QStringLiteral("dry-run"); } -ArgsHandler::ArgsHandler(const QMap<QString, QString>& other) - : m_args(new QMap<QString, QString>(other)) -{ -} - -ArgsHandler::~ArgsHandler() -{ - delete m_args; -} - -QString ArgsHandler::removeArg(const QString& s) -{ - QString retval; - - if (argExists(s)) { - retval = argValue(s); - m_args->remove(s); - } - - return retval; -} - -bool ArgsHandler::argExistsRemove(const QString& s) -{ - bool retval = false; - - if (argExists(s)) { - retval = true; - m_args->remove(s); - } +static const char helpHint[] = "Note: use --help or -h for more information.\n"; - return retval; -} +typedef QMap<QString, QString> CommandArgumentMap; -QString ArgsHandler::errorMessage() const +static QString msgLeftOverArguments(const CommandArgumentMap &remainingArgs) { - typedef QMap<QString, QString>::ConstIterator StringMapConstIt; - QString message; QTextStream str(&message); str << "shiboken: Called with wrong arguments:"; - for (StringMapConstIt it = m_args->cbegin(), end = m_args->cend(); it != end; ++it) { + for (auto it = remainingArgs.cbegin(), end = remainingArgs.cend(); it != end; ++it) { str << ' ' << it.key(); if (!it.value().isEmpty()) str << ' ' << it.value(); @@ -140,7 +73,6 @@ QString ArgsHandler::errorMessage() const str << "\nCommand line: " << QCoreApplication::arguments().join(QLatin1Char(' ')); return message; } -} typedef Generator::OptionDescriptions OptionDescriptions; @@ -233,9 +165,9 @@ static bool processProjectFile(QFile& projectFile, QMap<QString, QString>& args) return true; } -static QMap<QString, QString> getInitializedArguments() +static CommandArgumentMap getInitializedArguments() { - QMap<QString, QString> args; + CommandArgumentMap args; QStringList arguments = QCoreApplication::arguments(); QString appName = arguments.constFirst(); arguments.removeFirst(); @@ -277,9 +209,9 @@ static QMap<QString, QString> getInitializedArguments() // 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) + CommandArgumentMap &args) { - const QMap<QString, QString>::iterator it = args.find(option); + const CommandArgumentMap::iterator it = args.find(option); if (it != args.end()) it.value().append(QLatin1String(PATH_SPLITTER) + value); else @@ -380,18 +312,22 @@ void printUsage() << 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") + pathSyntax, QString()) + << qMakePair(QLatin1String("-F<path>"), QString()) << qMakePair(QLatin1String("framework-include-paths=") + pathSyntax, QLatin1String("Framework include paths used by the C++ parser")) - << qMakePair(QLatin1String("-isystem") + pathSyntax, QString()) + << 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(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") + pathSyntax, QString()) + << qMakePair(QLatin1String("-I<path>"), QString()) << qMakePair(QLatin1String("include-paths=") + pathSyntax, QLatin1String("Include paths used by the C++ parser")) << qMakePair(languageLevelOption() + QLatin1String("=, -std=<level>"), @@ -407,7 +343,7 @@ void printUsage() "Replaces and overrides command line arguments")) << qMakePair(QLatin1String("silent"), QLatin1String("Avoid printing any message")) - << qMakePair(QLatin1String("-T") + pathSyntax, QString()) + << qMakePair(QLatin1String("-T<path>"), QString()) << qMakePair(QLatin1String("typesystem-paths=") + pathSyntax, QLatin1String("Paths used when searching for typesystems")) << qMakePair(QLatin1String("version"), @@ -445,12 +381,14 @@ static QString msgInvalidVersion(const QString &package, const QString &version) } static void parseIncludePathOption(const QString &option, HeaderType headerType, - ArgsHandler &args, + CommandArgumentMap &args, ApiExtractor &extractor) { - const QString path = args.removeArg(option); - if (!path.isEmpty()) { - const QStringList includePathListList = path.split(QLatin1String(PATH_SPLITTER)); + const CommandArgumentMap::iterator it = args.find(option); + if (it != args.end()) { + const QStringList includePathListList = + it.value().split(QLatin1String(PATH_SPLITTER), QString::SkipEmptyParts); + args.erase(it); for (const QString &s : includePathListList) extractor.addIncludePath(HeaderPath{QFile::encodeName(s), headerType}); } @@ -466,19 +404,24 @@ int main(int argc, char *argv[]) qCDebug(lcShiboken()).noquote().nospace() << QCoreApplication::arguments().join(QLatin1Char(' ')); // Store command arguments in a map - QMap<QString, QString> args = getCommandLineArgs(); - ArgsHandler argsHandler(args); + CommandArgumentMap args = getCommandLineArgs(); Generators generators; - if (argsHandler.argExistsRemove(QLatin1String("version"))) { + CommandArgumentMap::iterator ait = args.find(QLatin1String("version")); + if (ait != args.end()) { + args.erase(ait); printVerAndBanner(); return EXIT_SUCCESS; } - QString generatorSet = argsHandler.removeArg(QLatin1String("generator-set")); - // Also check QLatin1String("generatorSet") command line argument for backward compatibility. - if (generatorSet.isEmpty()) - generatorSet = argsHandler.removeArg(QLatin1String("generatorSet")); + QString generatorSet; + ait = args.find(QLatin1String("generator-set")); + if (ait == args.end()) // Also check QLatin1String("generatorSet") command line argument for backward compatibility. + ait = args.find(QLatin1String("generatorSet")); + if (ait != args.end()) { + generatorSet = ait.value(); + args.erase(ait); + } // Pre-defined generator sets. if (generatorSet == QLatin1String("qtdoc")) { @@ -494,28 +437,45 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - if (argsHandler.argExistsRemove(QLatin1String("help"))) { + ait = args.find(QLatin1String("help")); + if (ait != args.end()) { + args.erase(ait); printUsage(); return EXIT_SUCCESS; } + ait = args.find(diffOption()); + if (ait != args.end()) { + args.erase(ait); + FileOut::diff = true; + } + + ait = args.find(dryrunOption()); + if (ait != args.end()) { + args.erase(ait); + FileOut::dummy = true; + } + QString licenseComment; - QString licenseFileName = argsHandler.removeArg(QLatin1String("license-file")); - if (!licenseFileName.isEmpty()) { - if (QFile::exists(licenseFileName)) { - QFile licenseFile(licenseFileName); - if (licenseFile.open(QIODevice::ReadOnly)) - licenseComment = QString::fromUtf8(licenseFile.readAll()); + ait = args.find(QLatin1String("license-file")); + if (ait != args.end()) { + QFile licenseFile(ait.value()); + args.erase(ait); + if (licenseFile.open(QIODevice::ReadOnly)) { + licenseComment = QString::fromUtf8(licenseFile.readAll()); } else { - errorPrint(QStringLiteral("Couldn't find the file containing the license heading: %1"). - arg(licenseFileName)); + 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 = argsHandler.removeArg(QLatin1String("output-directory")); - if (outputDirectory.isEmpty()) - outputDirectory = QLatin1String("out"); + QString outputDirectory = QLatin1String("out"); + ait = args.find(QLatin1String("output-directory")); + if (ait != args.end()) { + outputDirectory = ait.value(); + args.erase(ait); + } if (!QDir(outputDirectory).exists()) { if (!QDir().mkpath(outputDirectory)) { @@ -529,11 +489,15 @@ int main(int argc, char *argv[]) ApiExtractor extractor; extractor.setLogDirectory(outputDirectory); - if (argsHandler.argExistsRemove(QLatin1String("silent"))) { + ait = args.find(QLatin1String("silent")); + if (ait != args.end()) { extractor.setSilent(true); + args.erase(ait); } else { - QString level = argsHandler.removeArg(QLatin1String("debug-level")); - if (!level.isEmpty()) { + ait = args.find(QLatin1String("debug-level")); + if (ait != args.end()) { + const QString level = ait.value(); + args.erase(ait); if (level == QLatin1String("sparse")) extractor.setDebugLevel(ReportHandler::SparseDebug); else if (level == QLatin1String("medium")) @@ -542,11 +506,15 @@ int main(int argc, char *argv[]) extractor.setDebugLevel(ReportHandler::FullDebug); } } - if (argsHandler.argExistsRemove(QLatin1String("no-suppress-warnings"))) + ait = args.find(QLatin1String("no-suppress-warnings")); + if (ait != args.end()) { + args.erase(ait); extractor.setSuppressWarnings(false); - - if (argsHandler.argExists(QLatin1String("api-version"))) { - const QStringList &versions = argsHandler.removeArg(QLatin1String("api-version")).split(QLatin1Char('|')); + } + ait = args.find(QLatin1String("api-version")); + if (ait != args.end()) { + const QStringList &versions = ait.value().split(QLatin1Char('|')); + args.erase(ait); for (const QString &fullVersion : versions) { QStringList parts = fullVersion.split(QLatin1Char(',')); QString package; @@ -560,54 +528,65 @@ int main(int argc, char *argv[]) } } - if (argsHandler.argExists(QLatin1String("drop-type-entries"))) - extractor.setDropTypeEntries(argsHandler.removeArg(QLatin1String("drop-type-entries"))); + ait = args.find(QLatin1String("drop-type-entries")); + if (ait != args.end()) { + extractor.setDropTypeEntries(ait.value()); + args.erase(ait); + } - QString path = argsHandler.removeArg(QLatin1String("typesystem-paths")); - if (!path.isEmpty()) - extractor.addTypesystemSearchPath(path.split(QLatin1String(PATH_SPLITTER))); + ait = args.find(QLatin1String("typesystem-paths")); + if (ait != args.end()) { + extractor.addTypesystemSearchPath(ait.value().split(QLatin1String(PATH_SPLITTER))); + args.erase(ait); + } parseIncludePathOption(includePathOption(), HeaderType::Standard, - argsHandler, extractor); + args, extractor); parseIncludePathOption(frameworkIncludePathOption(), HeaderType::Framework, - argsHandler, extractor); + args, extractor); parseIncludePathOption(systemIncludePathOption(), HeaderType::System, - argsHandler, extractor); + args, extractor); - QString cppFileName = argsHandler.removeArg(QLatin1String("arg-1")); + ait = args.find(QLatin1String("arg-1")); + if (ait == args.end()) { + errorPrint(QLatin1String("Required argument header-file is missing.")); + return EXIT_FAILURE; + } + const QString cppFileName = ait.value(); + args.erase(ait); const QFileInfo cppFileNameFi(cppFileName); if (!cppFileNameFi.isFile() && !cppFileNameFi.isSymLink()) { errorPrint(QLatin1Char('"') + cppFileName + QLatin1String("\" does not exist.")); return EXIT_FAILURE; } - QString typeSystemFileName = argsHandler.removeArg(QLatin1String("arg-2")); + ait = args.find(QLatin1String("arg-2")); + if (ait == args.end()) { + errorPrint(QLatin1String("Required argument typesystem-file is missing.")); + return EXIT_FAILURE; + } + const QString typeSystemFileName = ait.value(); + args.erase(ait); 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 - * checking if there isn't any existing arguments in argsHandler. - */ - argsHandler.removeArg(QLatin1String("project-file")); - QMap<QString, QString> projectFileArgs = getInitializedArguments(); - if (!projectFileArgs.isEmpty()) { - QMap<QString, QString>::const_iterator it = - projectFileArgs.constBegin(); - for ( ; it != projectFileArgs.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); - } - - const QString languageLevel = argsHandler.removeArg(languageLevelOption()); - if (!languageLevel.isEmpty()) { - const QByteArray languageLevelBA = languageLevel.toLatin1(); + // Pass option to all generators (Cpp/Header generator have the same options) + for (ait = args.begin(); ait != args.end(); ) { + bool found = false; + for (const GeneratorPtr &generator : qAsConst(generators)) + found |= generator->handleOption(ait.key(), ait.value()); + if (found) + ait = args.erase(ait); + else + ++ait; + } + + ait = args.find(languageLevelOption()); + if (ait != args.end()) { + const QByteArray languageLevelBA = ait.value().toLatin1(); + args.erase(ait); const LanguageLevel level = clang::languageLevelFromOption(languageLevelBA.constData()); if (level == LanguageLevel::Default) { std::cout << "Invalid argument for language level: \"" @@ -617,8 +596,17 @@ int main(int argc, char *argv[]) extractor.setLanguageLevel(level); } - if (!argsHandler.noArgs()) { - errorPrint(argsHandler.errorMessage()); + /* 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.remove(QLatin1String("project-file")); + CommandArgumentMap projectFileArgs = getInitializedArguments(); + for (auto it = projectFileArgs.cbegin(), end = projectFileArgs.cend(); it != end; ++it) + args.remove(it.key()); + + if (!args.isEmpty()) { + errorPrint(msgLeftOverArguments(args)); std::cout << helpHint; return EXIT_FAILURE; } @@ -644,12 +632,10 @@ int main(int argc, char *argv[]) for (const GeneratorPtr &g : qAsConst(generators)) { g->setOutputDirectory(outputDirectory); g->setLicenseComment(licenseComment); - if (g->setup(extractor, args)) { - if (!g->generate()) { - errorPrint(QLatin1String("Error running generator: ") - + QLatin1String(g->name()) + QLatin1Char('.')); - return EXIT_FAILURE; - } + if (!g->setup(extractor) || !g->generate()) { + errorPrint(QLatin1String("Error running generator: ") + + QLatin1String(g->name()) + QLatin1Char('.')); + return EXIT_FAILURE; } } |