diff options
-rw-r--r-- | CMakeLists.txt | 15 | ||||
-rw-r--r-- | generator.cpp | 143 | ||||
-rw-r--r-- | generator.h | 334 | ||||
-rw-r--r-- | generators/boostpython/boostpythongenerator.cpp (renamed from boostpythongenerator.cpp) | 0 | ||||
-rw-r--r-- | generators/boostpython/boostpythongenerator.h (renamed from boostpythongenerator.h) | 0 | ||||
-rw-r--r-- | generators/boostpython/convertergenerator.cpp (renamed from convertergenerator.cpp) | 0 | ||||
-rw-r--r-- | generators/boostpython/convertergenerator.h (renamed from convertergenerator.h) | 0 | ||||
-rw-r--r-- | generators/boostpython/cppgenerator.cpp (renamed from cppgenerator.cpp) | 0 | ||||
-rw-r--r-- | generators/boostpython/cppgenerator.h (renamed from cppgenerator.h) | 0 | ||||
-rw-r--r-- | generators/boostpython/hppgenerator.cpp (renamed from hppgenerator.cpp) | 0 | ||||
-rw-r--r-- | generators/boostpython/hppgenerator.h (renamed from hppgenerator.h) | 0 | ||||
-rw-r--r-- | main.cpp | 200 |
12 files changed, 662 insertions, 30 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e385494f..2eeb84ca1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,11 +12,8 @@ configure_file(boostpythongeneratorversion.h.in ${CMAKE_CURRENT_BINARY_DIR}/boos set(CMAKE_BUILD_TYPE Debug) set(boostpythongenerator_SRC -boostpythongenerator.cpp -convertergenerator.cpp -docgenerator.cpp -hppgenerator.cpp -cppgenerator.cpp +main.cpp +generator.cpp ) include_directories(${CMAKE_CURRENT_SOURCE_DIR} @@ -26,13 +23,11 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${QT_INCLUDE_DIR} ${QT_QTCORE_INCLUDE_DIR}) -add_library(libboostpythongenerator STATIC ${boostpythongenerator_SRC}) -target_link_libraries(libboostpythongenerator +add_executable(boostpythongenerator ${boostpythongenerator_SRC}) +target_link_libraries(boostpythongenerator ${APIEXTRACTOR_LIBRARY} ${QT_QTCORE_LIBRARY} ${QT_QTXML_LIBRARY}) -add_executable(boostpythongenerator main.cpp) -target_link_libraries(boostpythongenerator libboostpythongenerator) # uninstall target configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake" @@ -58,5 +53,5 @@ install(TARGETS boostpythongenerator DESTINATION bin) enable_testing() #add_subdirectory(libbindgen) -add_subdirectory(tests) +# add_subdirectory(tests) diff --git a/generator.cpp b/generator.cpp new file mode 100644 index 000000000..343ebc63e --- /dev/null +++ b/generator.cpp @@ -0,0 +1,143 @@ +/* + * This file is part of the API Extractor project. + * + * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team <contact@pyside.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include "generator.h" +#include "reporthandler.h" +#include "fileout.h" +#include "apiextractor.h" + +#include <QtCore/QDir> +#include <QtCore/QFile> +#include <QtCore/QFileInfo> +#include <QDebug> + +Generator::Generator() : m_numGenerated(0), m_numGeneratedWritten(0) +{} + +Generator::~Generator() +{ +} + +bool Generator::setup(const ApiExtractor& extractor, const QMap< QString, QString > args) +{ + m_globalEnums = extractor.globalEnums(); + m_globalFunctions = extractor.globalFunctions(); + m_classes = extractor.classes(); + m_primitiveTypes = extractor.primitiveTypes(); + m_containerTypes = extractor.containerTypes(); + + // FIXME: Avoid this ugly hack to get the package name.. and... why the name "package"!? + foreach (const AbstractMetaClass* cppClass, m_classes) { + if (m_packageName.isEmpty() + && cppClass->typeEntry()->generateCode() + && !cppClass->package().isEmpty()) { + m_packageName = cppClass->package(); + break; + } + } + // does anyone use this? + m_qmetatypeDeclaredTypenames = extractor.qtMetaTypeDeclaredTypeNames(); + return doSetup(args); +} + +void Generator::generate() +{ + foreach (AbstractMetaClass *cls, m_classes) { + if (!shouldGenerate(cls)) + continue; + + QString fileName = fileNameForClass(cls); + if (fileName.isNull()) + continue; + ReportHandler::debugSparse(QString("generating: %1").arg(fileName)); + + FileOut fileOut(outputDirectory() + '/' + subDirectoryForClass(cls) + '/' + fileName); + generateClass(fileOut.stream, cls); + + if (fileOut.done()) + ++m_numGeneratedWritten; + ++m_numGenerated; + } + finishGeneration(); +} + +bool Generator::shouldGenerate(const AbstractMetaClass* metaClass) const +{ + return metaClass->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang; +} + +void Generator::verifyDirectoryFor(const QFile &file) +{ + QDir dir = QFileInfo(file).dir(); + if (!dir.exists()) { + if (!dir.mkpath(dir.absolutePath())) + ReportHandler::warning(QString("unable to create directory '%1'") + .arg(dir.absolutePath())); + } +} + +bool Generator::hasDefaultConstructor(const AbstractMetaType *type) +{ + QString full_name = type->typeEntry()->qualifiedTargetLangName(); + QString class_name = type->typeEntry()->targetLangName(); + + foreach (const AbstractMetaClass *cls, m_classes) { + if (cls->typeEntry()->qualifiedTargetLangName() == full_name) { + AbstractMetaFunctionList functions = cls->functions(); + foreach (const AbstractMetaFunction *function, functions) { + if (function->arguments().isEmpty() && function->name() == class_name) + return true; + } + return false; + } + } + return false; +} + +void Generator::replaceTemplateVariables(QString &code, const AbstractMetaFunction *func) +{ + const AbstractMetaClass *cpp_class = func->ownerClass(); + code.replace("%TYPE", cpp_class->name()); + + foreach (AbstractMetaArgument *arg, func->arguments()) + code.replace("%" + QString::number(arg->argumentIndex() + 1), arg->argumentName()); + + //template values + code.replace("%RETURN_TYPE", translateType(func->type(), cpp_class)); + code.replace("%FUNCTION_NAME", func->originalName()); + + if (code.contains("%ARGUMENT_NAMES")) { + QString str; + QTextStream aux_stream(&str); + writeArgumentNames(aux_stream, func, Generator::SkipRemovedArguments); + code.replace("%ARGUMENT_NAMES", str); + } + + if (code.contains("%ARGUMENTS")) { + QString str; + QTextStream aux_stream(&str); + writeFunctionArguments(aux_stream, func, Generator::SkipDefaultValues | Generator::SkipRemovedArguments); + code.replace("%ARGUMENTS", str); + } +} + diff --git a/generator.h b/generator.h new file mode 100644 index 000000000..14526d7f0 --- /dev/null +++ b/generator.h @@ -0,0 +1,334 @@ +/* + * This file is part of the API Extractor project. + * + * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team <contact@pyside.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef GENERATOR_H +#define GENERATOR_H + +#include <QtCore/QObject> +#include <QtCore/QDir> +#include "abstractmetalang.h" + +class ApiExtractor; +class AbstractMetaBuilder; +class QFile; + +/** + * Base class for all generators. The default implementations does nothing, + * you must subclass this to create your own generators. + */ +class Generator +{ +public: + /// Optiosn used around the generator code + enum Option { + NoOption = 0x00000000, + BoxedPrimitive = 0x00000001, + ExcludeConst = 0x00000002, + ExcludeReference = 0x00000004, + UseNativeIds = 0x00000008, + + EnumAsInts = 0x00000010, + SkipName = 0x00000020, + NoCasts = 0x00000040, + SkipReturnType = 0x00000080, + OriginalName = 0x00000100, + ShowStatic = 0x00000200, + UnderscoreSpaces = 0x00000400, + ForceEnumCast = 0x00000800, + ArrayAsPointer = 0x00001000, + VirtualCall = 0x00002000, + SkipTemplateParameters = 0x00004000, + SkipAttributes = 0x00008000, + OriginalTypeDescription = 0x00010000, + SkipRemovedArguments = 0x00020000, + IncludeDefaultExpression = 0x00040000, + NoReturnStatement = 0x00080000, + NoBlockedSlot = 0x00100000, + + SuperCall = 0x00200000, + + GlobalRefJObject = 0x00100000, + + SkipDefaultValues = 0x00400000, + + WriteSelf = 0x00800000, + ExcludeMethodConst = 0x01000000, + + ForceValueType = ExcludeReference | ExcludeConst + }; + + Generator(); + virtual ~Generator(); + + bool setup(const ApiExtractor& extractor, const QMap<QString, QString> args); + + virtual QMap<QString, QString> options() const + { + return QMap<QString, QString>(); + } + + /// Returns the classes used to generate the binding code. + AbstractMetaClassList classes() const + { + return m_classes; + } + + AbstractMetaFunctionList globalFunctions() const + { + return m_globalFunctions; + } + + AbstractMetaEnumList globalEnums() const + { + return m_globalEnums; + } + + QList<const PrimitiveTypeEntry*> primitiveTypes() const + { + return m_primitiveTypes; + } + + QList<const ContainerTypeEntry*> containerTypes() const + { + return m_containerTypes; + } + + /// Returns the output directory + QString outputDirectory() const + { + return m_outDir; + } + + /// Set the output directory + void setOutputDirectory(const QString &outDir) + { + m_outDir = outDir; + } + + /** + * Start the code generation, be sure to call setClasses before callign this method. + * For each class it creates a QTextStream, call the write method with the current + * class and the associated text stream, then write the text stream contents if needed. + * \see #write + */ + void generate(); + + /// Returns the number of generated items + int numGenerated() + { + return m_numGenerated; + } + + /// Returns the number of generated items written + int numGeneratedAndWritten() + { + return m_numGeneratedWritten; + } + + virtual const char* name() const = 0; + + /// Returns true if the generator should generate any code for the AbstractMetaClass + virtual bool shouldGenerate(const AbstractMetaClass *) const; + + /// Returns the subdirectory used to write the binding code of an AbstractMetaClass. + virtual QString subDirectoryForClass(const AbstractMetaClass* clazz) const = 0; + + /** + * Translate metatypes to binding source format. + * \param metatype a pointer to metatype + * \param context the current meta class + * \param option some extra options + * \return the metatype translated to binding source format + */ + virtual QString translateType(const AbstractMetaType *metatype, + const AbstractMetaClass *context, + int option = NoOption) const = 0; + + /** + * Function used to write the fucntion arguments on the class buffer. + * \param s the class output buffer + * \param metafunction the pointer to metafunction information + * \param count the number of function arguments + * \param options some extra options used during the parser + */ + virtual void writeFunctionArguments(QTextStream &s, + const AbstractMetaFunction *metafunction, + uint options = 0) const = 0; + + virtual void writeArgumentNames(QTextStream &s, + const AbstractMetaFunction *metafunction, + uint options = 0) const = 0; + + void replaceTemplateVariables(QString &code, const AbstractMetaFunction *func); + + bool hasDefaultConstructor(const AbstractMetaType *type); + + // QtScript + QSet<QString> qtMetaTypeDeclaredTypeNames() const + { + return m_qmetatypeDeclaredTypenames; + } + + /** + * Returns the license comment to be prepended to each source file generated. + */ + QString licenseComment() + { + return m_licenseComment; + } + + /** + * Sets the license comment to be prepended to each source file generated. + */ + void setLicenseComment(const QString &licenseComment) + { + m_licenseComment = licenseComment; + } + + /** + * Returns the package name. + */ + QString packageName() + { + return m_packageName; + } + + /** + * Sets the package name. + */ + void setPackageName(const QString &packageName) + { + m_packageName = packageName; + } + + /** + * Retrieves the name of the currently processed module. While package name + * is a complete package idetification, e.g. 'PySide.QtCore', a module name + * represents the last part of the package, e.g. 'QtCore'. + * If the target language separates the modules with characters other than + * dots ('.') the generator subclass must overload this method. + * /return a string representing the last part of a package name + */ + virtual QString moduleName() + { + return QString(m_packageName).remove(0, m_packageName.lastIndexOf('.') + 1); + } + +protected: + QString m_packageName; + + /** + * Returns the file name used to write the binding code of an AbstractMetaClass. + * /param metaClass the AbstractMetaClass for which the file name must be + * returned + * /return the file name used to write the binding code for the class + */ + virtual QString fileNameForClass(const AbstractMetaClass* metaClass) const = 0; + + virtual bool doSetup(QMap<QString, QString> args) = 0; + + /** + * Returns the subdirectory path for a given package + * (aka module, aka library) name. + * If the target language separates the package modules with characters other + * than dots ('.') the generator subclass must overload this method. + * /param packageName complete package name for which to return the subdirectory path + * or nothing the use the name of the currently processed package + * /return a string representing the subdirectory path for the given package + */ + virtual QString subDirectoryForPackage(QString packageName = QString()) const + { + if (packageName.isEmpty()) + packageName = m_packageName; + return QString(packageName).replace(".", QDir::separator()); + } + + /** + * Write the bindding code for an AbstractMetaClass. + * This is called by the default implementation of generate method. + * \param s text stream to write the generated output + * \param metaClass the class that should be generated + */ + virtual void generateClass(QTextStream& s, const AbstractMetaClass* metaClass) = 0; + virtual void finishGeneration() = 0; + + void verifyDirectoryFor(const QFile &file); + + int m_numGenerated; + int m_numGeneratedWritten; + +private: + AbstractMetaClassList m_classes; + AbstractMetaFunctionList m_globalFunctions; + AbstractMetaEnumList m_globalEnums; + QString m_outDir; + + QList<const PrimitiveTypeEntry*> m_primitiveTypes; + QList<const ContainerTypeEntry*> m_containerTypes; + + // QtScript + QSet<QString> m_qmetatypeDeclaredTypenames; + + // License comment + QString m_licenseComment; +}; + +/** +* Utility class to store the identation level, use it in a QTextStream. +*/ +class Indentor +{ +public: + Indentor(): + indent(0) {} + int indent; +}; + +/** +* Class that use the RAII idiom to set and unset the identation level. +*/ +class Indentation +{ +public: + Indentation(Indentor &indentor) : indentor(indentor) + { + indentor.indent++; + } + ~Indentation() + { + indentor.indent--; + } + +private: + Indentor &indentor; +}; + +inline QTextStream &operator <<(QTextStream &s, const Indentor &indentor) +{ + for (int i = 0; i < indentor.indent; ++i) + s << " "; + return s; +} + +#endif // GENERATOR_H + diff --git a/boostpythongenerator.cpp b/generators/boostpython/boostpythongenerator.cpp index 70ce4a5ed..70ce4a5ed 100644 --- a/boostpythongenerator.cpp +++ b/generators/boostpython/boostpythongenerator.cpp diff --git a/boostpythongenerator.h b/generators/boostpython/boostpythongenerator.h index 4ad191b50..4ad191b50 100644 --- a/boostpythongenerator.h +++ b/generators/boostpython/boostpythongenerator.h diff --git a/convertergenerator.cpp b/generators/boostpython/convertergenerator.cpp index ea52b9193..ea52b9193 100644 --- a/convertergenerator.cpp +++ b/generators/boostpython/convertergenerator.cpp diff --git a/convertergenerator.h b/generators/boostpython/convertergenerator.h index 8f91377c0..8f91377c0 100644 --- a/convertergenerator.h +++ b/generators/boostpython/convertergenerator.h diff --git a/cppgenerator.cpp b/generators/boostpython/cppgenerator.cpp index 36bd067cf..36bd067cf 100644 --- a/cppgenerator.cpp +++ b/generators/boostpython/cppgenerator.cpp diff --git a/cppgenerator.h b/generators/boostpython/cppgenerator.h index bd41fe114..bd41fe114 100644 --- a/cppgenerator.h +++ b/generators/boostpython/cppgenerator.h diff --git a/hppgenerator.cpp b/generators/boostpython/hppgenerator.cpp index f6d576d08..f6d576d08 100644 --- a/hppgenerator.cpp +++ b/generators/boostpython/hppgenerator.cpp diff --git a/hppgenerator.h b/generators/boostpython/hppgenerator.h index 8e0f5f03b..8e0f5f03b 100644 --- a/hppgenerator.h +++ b/generators/boostpython/hppgenerator.h @@ -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; } |