diff options
author | Hugo Lima <hugo.lima@openbossa.org> | 2009-08-20 21:24:45 -0300 |
---|---|---|
committer | Hugo Lima <hugo.lima@openbossa.org> | 2009-08-25 16:23:11 -0300 |
commit | 425c1eba27766b4382ace8f10daeaa548c9eb0d6 (patch) | |
tree | dfdf37ebca0fd2b1b26f8e598410f35eb1e6c12e /main.cpp | |
parent | 252ff87489c02fe1b26d650ad855d111042c6490 (diff) |
The current generators will be just plugins and all generator stuff in APIExtractor were moved
to this project.
So we need to re-think if boostpythongenerator still a good name for the project, because
boostpythongenerator will be the name of the plugin to generate bindings for boost::python.
Also the generators were just moved to a subdirectory (generators) and the boostpython generators
to a sub-subdirectory (generators/boostpython), transform them in plugins will be a second milestone.
Diffstat (limited to 'main.cpp')
-rw-r--r-- | main.cpp | 200 |
1 files changed, 180 insertions, 20 deletions
@@ -21,32 +21,192 @@ * */ -#include <QtCore/QCoreApplication> +#include <QCoreApplication> +#include <QLinkedList> +#include <QLibrary> +#include <iostream> #include <apiextractor/apiextractor.h> -#include "hppgenerator.h" -#include "cppgenerator.h" -#include "hppgenerator.h" -#include "convertergenerator.h" -#include "docgenerator.h" #include "boostpythongeneratorversion.h" -#include <iostream> +#include "generator.h" -void showVersion(const char* apiextractor_version) { - using namespace std; +#if defined(Q_OS_WIN32) + #define PATH_SPLITTER ";" +#else + #define PATH_SPLITTER ":" +#endif - cout << "BoostPythonGenerator v" BOOSTPYTHONGENERATOR_VERSION << " using " << apiextractor_version << endl; - cout << "Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)" << endl; + +static void printOptions(QTextStream& s, const QMap<QString, QString>& options) { + QMap<QString, QString>::const_iterator it = options.constBegin(); + s.setFieldAlignment(QTextStream::AlignLeft); + for (; it != options.constEnd(); ++it) { + s << " --"; + s.setFieldWidth(38); + s << it.key() << it.value(); + s.setFieldWidth(0); + s << endl; + } +} + +typedef QLinkedList<Generator*> (*getGeneratorsFunc)(); +typedef QLinkedList<Generator*> GeneratorList; + +QMap<QString, QString> getCommandLineArgs(int argc, char** argv) +{ + QMap<QString, QString> args; + int argNum = 0; + for (int i = 1; i < argc; ++i) { + QString arg(argv[i]); + arg = arg.trimmed(); + if (arg.startsWith("--")) { + int split = arg.indexOf("="); + 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("-")) { + args[arg.mid(1)] = QString(); + } else { + argNum++; + args[QString("arg-%1").arg(argNum)] = arg; + } + } + return args; +} + +void printUsage(const GeneratorList& generators) +{ + #if defined(Q_OS_WIN32) + #define PATHSPLITTER ";" + #else + #define PATHSPLITTER ":" + #endif + QTextStream s(stdout); + s << "Usage:\n " + << "generator [options] header-file typesystem-file\n\n" + "General options:\n"; + QMap<QString, QString> generalOptions; + generalOptions.insert("debug-level=[sparse|medium|full]", "Set the debug level"); + generalOptions.insert("silent", "Avoid printing any message"); + generalOptions.insert("help", "Display this help and exit"); + generalOptions.insert("no-suppress-warnings", "Show all warnings"); + generalOptions.insert("output-directory=[dir]", "The directory where the generated files will be written"); + generalOptions.insert("include-paths=<path>[" PATHSPLITTER "<path>" PATHSPLITTER "...]", "Include paths used by the C++ parser"); + generalOptions.insert("typesystem-paths=<path>[" PATHSPLITTER "<path>" PATHSPLITTER "...]", "Paths used when searching for typesystems"); + generalOptions.insert("documentation-only", "Do not generates any code, just the documentation"); + generalOptions.insert("license-file=[licensefile]", "File used for copyright headers of generated files"); + generalOptions.insert("version", "Output version information and exit"); + generalOptions.insert("generatorSet", "generatorSet to be used. e.g. boostpython"); + printOptions(s, generalOptions); + + foreach (Generator* generator, generators) { + QMap<QString, QString> options = generator->options(); + if (!options.isEmpty()) { + s << endl << generator->name() << " options:\n"; + printOptions(s, generator->options()); + } + } } int main(int argc, char *argv[]) { - QCoreApplication app(argc, argv); // needed by qxmlpatterns - - ApiExtractor extractor(argc, argv); - extractor.addGenerator(new HppGenerator); - extractor.addGenerator(new CppGenerator); - extractor.addGenerator(new ConverterGenerator); - extractor.addGenerator(new DocGenerator); - extractor.setVersionHandler(&showVersion); - return extractor.exec(); + // needed by qxmlpatterns + QCoreApplication app(argc, argv); + + // Store command arguments in a map + QMap<QString, QString> args = getCommandLineArgs(argc, argv); + GeneratorList generators; + + if (args.contains("version")) { + std::cout << "generator v" BOOSTPYTHONGENERATOR_VERSION << std::endl; + std::cout << "Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)" << std::endl; + return EXIT_SUCCESS; + } + + // Try to load a generator + QString generatorSet = args.value("generatorSet"); + if (!generatorSet.isEmpty()) { + QLibrary plugin(generatorSet); + getGeneratorsFunc getGenerators = reinterpret_cast<getGeneratorsFunc>(plugin.resolve("getGenerators")); + if (getGenerators) + generators = getGenerators(); + else { + std::cerr << argv[0] << ": Error loading generatorset plugin: " << qPrintable(plugin.errorString()) << std::endl; + return EXIT_FAILURE; + } + } else if (!args.contains("help")) { + std::cerr << argv[0] << ": You need to specify a generator with --generatorSet=GENERATOR_NAME" << std::endl; + return EXIT_FAILURE; + } + + if (args.contains("help")) { + printUsage(generators); + return EXIT_SUCCESS; + } + + + QString licenseComment; + if (args.contains("license-file") && !args.value("license-file").isEmpty()) { + QString licenseFileName = args.value("license-file"); + if (QFile::exists(licenseFileName)) { + QFile licenseFile(licenseFileName); + if (licenseFile.open(QIODevice::ReadOnly)) + licenseComment = licenseFile.readAll(); + } else { + std::cerr << "Couldn't find the file containing the license heading: "; + std::cerr << qPrintable(licenseFileName) << std::endl; + return EXIT_FAILURE; + } + } + + // Create and set-up API Extractor + ApiExtractor extractor; + + if (args.contains("silent")) { + extractor.setSilent(true); + } else if (args.contains("debug-level")) { + QString level = args.value("debug-level"); + if (level == "sparse") + extractor.setDebugLevel(ReportHandler::SparseDebug); + else if (level == "medium") + extractor.setDebugLevel(ReportHandler::MediumDebug); + else if (level == "full") + extractor.setDebugLevel(ReportHandler::FullDebug); + } + if (args.contains("no-suppress-warnings")) + extractor.setSuppressWarnings(false); + + if (args.contains("typesystem-paths")) + extractor.addTypesystemSearchPath(args.value("typesystem-paths").split(PATH_SPLITTER)); + if (!args.value("include-paths").isEmpty()) + extractor.addIncludePath(args.value("include-paths").split(PATH_SPLITTER)); + + + QString cppFileName = args.value("arg-1"); + QString typeSystemFileName = args.value("arg-2"); + if (args.contains("arg-3")) { + std::cerr << "Too many arguments!" << std::endl; + return EXIT_FAILURE; + } + extractor.setCppFileName(cppFileName); + extractor.setTypeSystem(typeSystemFileName); + extractor.run(); + + if (!extractor.classCount()) { + std::cerr << "No C++ classes found!" << std::endl; + return EXIT_FAILURE; + } + + + QString outputDirectory = args.contains("output-directory") ? args["output-directory"] : "out"; + foreach (Generator* g, generators) { + g->setOutputDirectory(outputDirectory); + g->setLicenseComment(licenseComment); + if (g->setup(extractor, args)) + g->generate(); + } + + std::cout << "Done, " << ReportHandler::warningCount(); + std::cout << " warnings (" << ReportHandler::suppressedCount() << " known issues)"; + std::cout << std::endl; } |