diff options
Diffstat (limited to 'sources/shiboken2/generator/main.cpp')
-rw-r--r-- | sources/shiboken2/generator/main.cpp | 275 |
1 files changed, 141 insertions, 134 deletions
diff --git a/sources/shiboken2/generator/main.cpp b/sources/shiboken2/generator/main.cpp index 25daea99e..8d819c763 100644 --- a/sources/shiboken2/generator/main.cpp +++ b/sources/shiboken2/generator/main.cpp @@ -33,6 +33,7 @@ #include <iostream> #include <apiextractor.h> #include <fileout.h> +#include <reporthandler.h> #include <typedatabase.h> #include <messages.h> #include "generator.h" @@ -41,7 +42,7 @@ #include "headergenerator.h" #include "qtdocgenerator.h" -#ifdef _WINDOWS +#ifdef Q_OS_WIN static const QChar pathSplitter = QLatin1Char(';'); #else static const QChar pathSplitter = QLatin1Char(':'); @@ -59,10 +60,14 @@ static inline QString skipDeprecatedOption() { return QStringLiteral("skip-depre static const char helpHint[] = "Note: use --help or -h for more information.\n"; -using CommandArgumentMap = QMap<QString, QString>; - using OptionDescriptions = Generator::OptionDescriptions; +struct CommandLineArguments +{ + QMap<QString, QString> options; + QStringList positionalArguments; +}; + static void printOptions(QTextStream &s, const OptionDescriptions &options) { s.setFieldAlignment(QTextStream::AlignLeft); @@ -73,16 +78,16 @@ static void printOptions(QTextStream &s, const OptionDescriptions &options) if (od.second.isEmpty()) { s << ", "; } else { - s << endl; + s << Qt::endl; const auto lines = od.second.splitRef(QLatin1Char('\n')); for (const auto &line : lines) - s << " " << line << endl; - s << endl; + s << " " << line << Qt::endl; + s << Qt::endl; } } } -static bool processProjectFile(QFile &projectFile, QMap<QString, QString> &args) +static bool processProjectFile(QFile &projectFile, CommandLineArguments &args) { QByteArray line = projectFile.readLine().trimmed(); if (line.isEmpty() || line != "[generator-project]") @@ -123,36 +128,36 @@ static bool processProjectFile(QFile &projectFile, QMap<QString, QString> &args) else if (key == "api-version") apiVersions << value; else if (key == "header-file") - args.insert(QLatin1String("arg-1"), value); + args.positionalArguments.prepend(value); else if (key == "typesystem-file") - args.insert(QLatin1String("arg-2"), value); + args.positionalArguments.append(value); else - args.insert(QString::fromUtf8(key), value); + args.options.insert(QString::fromUtf8(key), value); } if (!includePaths.isEmpty()) - args.insert(includePathOption(), includePaths.join(pathSplitter)); + args.options.insert(includePathOption(), includePaths.join(pathSplitter)); if (!frameworkIncludePaths.isEmpty()) - args.insert(frameworkIncludePathOption(), - frameworkIncludePaths.join(pathSplitter)); + args.options.insert(frameworkIncludePathOption(), + frameworkIncludePaths.join(pathSplitter)); if (!systemIncludePaths.isEmpty()) { - args.insert(systemIncludePathOption(), - systemIncludePaths.join(pathSplitter)); + args.options.insert(systemIncludePathOption(), + systemIncludePaths.join(pathSplitter)); } if (!typesystemPaths.isEmpty()) - args.insert(typesystemPathOption(), typesystemPaths.join(pathSplitter)); + args.options.insert(typesystemPathOption(), typesystemPaths.join(pathSplitter)); if (!apiVersions.isEmpty()) - args.insert(QLatin1String("api-version"), apiVersions.join(QLatin1Char('|'))); + args.options.insert(QLatin1String("api-version"), apiVersions.join(QLatin1Char('|'))); if (!languageLevel.isEmpty()) - args.insert(languageLevelOption(), languageLevel); + args.options.insert(languageLevelOption(), languageLevel); return true; } -static CommandArgumentMap getInitializedArguments() +static CommandLineArguments getProjectFileArguments() { - CommandArgumentMap args; + CommandLineArguments args; QStringList arguments = QCoreApplication::arguments(); QString appName = arguments.constFirst(); arguments.removeFirst(); @@ -194,22 +199,22 @@ static CommandArgumentMap getInitializedArguments() // Concatenate values of path arguments that can occur multiple times on the // command line. static void addPathOptionValue(const QString &option, const QString &value, - CommandArgumentMap &args) + CommandLineArguments &args) { - const CommandArgumentMap::iterator it = args.find(option); - if (it != args.end()) + auto it = args.options.find(option); + if (it != args.options.end()) it.value().append(pathSplitter + value); else - args.insert(option, value); + args.options.insert(option, value); } -static void getCommandLineArg(QString arg, int &argNum, QMap<QString, QString> &args) +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.insert(arg, QString()); + args.options.insert(arg, QString()); return; } const QString option = arg.left(split); @@ -218,7 +223,7 @@ static void getCommandLineArg(QString arg, int &argNum, QMap<QString, QString> & || option == systemIncludePathOption() || option == typesystemPathOption()) { addPathOptionValue(option, value, args); } else { - args.insert(option, value); + args.options.insert(option, value); } return; } @@ -233,28 +238,26 @@ static void getCommandLineArg(QString arg, int &argNum, QMap<QString, QString> & else if (arg.startsWith(QLatin1Char('T'))) addPathOptionValue(typesystemPathOption(), arg.mid(1), args); else if (arg == QLatin1String("h")) - args.insert(helpOption(), QString()); + args.options.insert(helpOption(), QString()); else if (arg.startsWith(QLatin1String("std="))) - args.insert(languageLevelOption(), arg.mid(4)); + args.options.insert(languageLevelOption(), arg.mid(4)); else - args.insert(arg, QString()); + args.options.insert(arg, QString()); return; } - argNum++; - args.insert(QStringLiteral("arg-") + QString::number(argNum), arg); + if (argNum < args.positionalArguments.size()) + args.positionalArguments[argNum] = arg; + else + args.positionalArguments.append(arg); + ++argNum; } -static QMap<QString, QString> getCommandLineArgs() +static void getCommandLineArgs(CommandLineArguments &args) { - QMap<QString, QString> args = getInitializedArguments(); - QStringList arguments = QCoreApplication::arguments(); - arguments.removeFirst(); - + const QStringList arguments = QCoreApplication::arguments(); int argNum = 0; - for (const QString &carg : qAsConst(arguments)) - getCommandLineArg(carg.trimmed(), argNum, args); - - return args; + for (int i = 1, size = arguments.size(); i < size; ++i) + getCommandLineArg(arguments.at(i).trimmed(), argNum, args); } static inline Generators docGenerators() @@ -284,7 +287,7 @@ void printUsage() { QTextStream s(stdout); s << "Usage:\n " - << "shiboken [options] header-file typesystem-file\n\n" + << "shiboken [options] header-file(s) typesystem-file\n\n" << "General options:\n"; QString pathSyntax; QTextStream(&pathSyntax) << "<path>[" << pathSplitter << "<path>" @@ -343,7 +346,7 @@ void printUsage() for (const GeneratorPtr &generator : generators) { const OptionDescriptions options = generator->options(); if (!options.isEmpty()) { - s << endl << generator->name() << " options:\n\n"; + s << Qt::endl << generator->name() << " options:\n\n"; printOptions(s, generator->options()); } } @@ -364,14 +367,14 @@ static inline void errorPrint(const QString &s) } static void parseIncludePathOption(const QString &option, HeaderType headerType, - CommandArgumentMap &args, + CommandLineArguments &args, ApiExtractor &extractor) { - const CommandArgumentMap::iterator it = args.find(option); - if (it != args.end()) { + const auto it = args.options.find(option); + if (it != args.options.end()) { const QStringList includePathListList = - it.value().split(pathSplitter, QString::SkipEmptyParts); - args.erase(it); + 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}); @@ -387,26 +390,29 @@ int main(int argc, char *argv[]) // needed by qxmlpatterns QCoreApplication app(argc, argv); ReportHandler::install(); - qCDebug(lcShiboken()).noquote().nospace() << QCoreApplication::arguments().join(QLatin1Char(' ')); + if (ReportHandler::isDebug(ReportHandler::SparseDebug)) + qCInfo(lcShiboken()).noquote().nospace() << QCoreApplication::arguments().join(QLatin1Char(' ')); // Store command arguments in a map - CommandArgumentMap args = getCommandLineArgs(); + const CommandLineArguments projectFileArguments = getProjectFileArguments(); + CommandLineArguments args = projectFileArguments; + getCommandLineArgs(args); Generators generators; - CommandArgumentMap::iterator ait = args.find(QLatin1String("version")); - if (ait != args.end()) { - args.erase(ait); + auto ait = args.options.find(QLatin1String("version")); + if (ait != args.options.end()) { + args.options.erase(ait); printVerAndBanner(); return EXIT_SUCCESS; } 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()) { + 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.erase(ait); + args.options.erase(ait); } // Pre-defined generator sets. @@ -423,30 +429,30 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - ait = args.find(QLatin1String("help")); - if (ait != args.end()) { - args.erase(ait); + ait = args.options.find(QLatin1String("help")); + if (ait != args.options.end()) { + args.options.erase(ait); printUsage(); return EXIT_SUCCESS; } - ait = args.find(diffOption()); - if (ait != args.end()) { - args.erase(ait); + ait = args.options.find(diffOption()); + if (ait != args.options.end()) { + args.options.erase(ait); FileOut::diff = true; } - ait = args.find(dryrunOption()); - if (ait != args.end()) { - args.erase(ait); + ait = args.options.find(dryrunOption()); + if (ait != args.options.end()) { + args.options.erase(ait); FileOut::dummy = true; } QString licenseComment; - ait = args.find(QLatin1String("license-file")); - if (ait != args.end()) { + ait = args.options.find(QLatin1String("license-file")); + if (ait != args.options.end()) { QFile licenseFile(ait.value()); - args.erase(ait); + args.options.erase(ait); if (licenseFile.open(QIODevice::ReadOnly)) { licenseComment = QString::fromUtf8(licenseFile.readAll()); } else { @@ -457,10 +463,10 @@ int main(int argc, char *argv[]) } QString outputDirectory = QLatin1String("out"); - ait = args.find(QLatin1String("output-directory")); - if (ait != args.end()) { + ait = args.options.find(QLatin1String("output-directory")); + if (ait != args.options.end()) { outputDirectory = ait.value(); - args.erase(ait); + args.options.erase(ait); } if (!QDir(outputDirectory).exists()) { @@ -474,38 +480,35 @@ int main(int argc, char *argv[]) // Create and set-up API Extractor ApiExtractor extractor; extractor.setLogDirectory(outputDirectory); - ait = args.find(skipDeprecatedOption()); - if (ait != args.end()) { + ait = args.options.find(skipDeprecatedOption()); + if (ait != args.options.end()) { extractor.setSkipDeprecated(true); - args.erase(ait); + args.options.erase(ait); } - ait = args.find(QLatin1String("silent")); - if (ait != args.end()) { + ait = args.options.find(QLatin1String("silent")); + if (ait != args.options.end()) { extractor.setSilent(true); - args.erase(ait); + args.options.erase(ait); } else { - 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")) - extractor.setDebugLevel(ReportHandler::MediumDebug); - else if (level == QLatin1String("full")) - extractor.setDebugLevel(ReportHandler::FullDebug); + 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.find(QLatin1String("no-suppress-warnings")); - if (ait != args.end()) { - args.erase(ait); + ait = args.options.find(QLatin1String("no-suppress-warnings")); + if (ait != args.options.end()) { + args.options.erase(ait); extractor.setSuppressWarnings(false); } - ait = args.find(QLatin1String("api-version")); - if (ait != args.end()) { + ait = args.options.find(QLatin1String("api-version")); + if (ait != args.options.end()) { const QStringList &versions = ait.value().split(QLatin1Char('|')); - args.erase(ait); + args.options.erase(ait); for (const QString &fullVersion : versions) { QStringList parts = fullVersion.split(QLatin1Char(',')); QString package; @@ -519,16 +522,16 @@ int main(int argc, char *argv[]) } } - ait = args.find(QLatin1String("drop-type-entries")); - if (ait != args.end()) { + ait = args.options.find(QLatin1String("drop-type-entries")); + if (ait != args.options.end()) { extractor.setDropTypeEntries(ait.value()); - args.erase(ait); + args.options.erase(ait); } - ait = args.find(QLatin1String("typesystem-paths")); - if (ait != args.end()) { + ait = args.options.find(QLatin1String("typesystem-paths")); + if (ait != args.options.end()) { extractor.addTypesystemSearchPath(ait.value().split(pathSplitter)); - args.erase(ait); + args.options.erase(ait); } parseIncludePathOption(includePathOption(), HeaderType::Standard, @@ -538,46 +541,44 @@ int main(int argc, char *argv[]) parseIncludePathOption(systemIncludePathOption(), HeaderType::System, args, extractor); - 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.")); + if (args.positionalArguments.size() < 2) { + errorPrint(QLatin1String("Insufficient positional arguments, specify header-file and typesystem-file.")); + std::cout << '\n'; + printUsage(); return EXIT_FAILURE; } - 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); + 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.begin(); ait != args.end(); ) { + 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.erase(ait); + ait = args.options.erase(ait); else ++ait; } - ait = args.find(languageLevelOption()); - if (ait != args.end()) { + ait = args.options.find(languageLevelOption()); + if (ait != args.options.end()) { const QByteArray languageLevelBA = ait.value().toLatin1(); - args.erase(ait); + args.options.erase(ait); const LanguageLevel level = clang::languageLevelFromOption(languageLevelBA.constData()); if (level == LanguageLevel::Default) { std::cout << "Invalid argument for language level: \"" @@ -591,13 +592,14 @@ int main(int argc, char *argv[]) * --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()); + 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.isEmpty()) { - errorPrint(msgLeftOverArguments(args)); + if (!args.options.isEmpty()) { + errorPrint(msgLeftOverArguments(args.options)); std::cout << helpHint; return EXIT_FAILURE; } @@ -607,10 +609,13 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - extractor.setCppFileName(cppFileNameFi.absoluteFilePath()); + extractor.setCppFileNames(cppFileNames); extractor.setTypeSystem(typeSystemFileName); - if (!extractor.run()) { + 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; } @@ -618,8 +623,11 @@ int main(int argc, char *argv[]) if (!extractor.classCount()) qCWarning(lcShiboken) << "No C++ classes found!"; - qCDebug(lcShiboken) << extractor << '\n' - << *TypeDatabase::instance(); + 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); @@ -635,7 +643,6 @@ int main(int argc, char *argv[]) } const QByteArray doneMessage = ReportHandler::doneMessage(); - qCDebug(lcShiboken, "%s", doneMessage.constData()); std::cout << doneMessage.constData() << std::endl; return EXIT_SUCCESS; |