diff --git a/generator/abstractmetabuilder.cpp b/generator/abstractmetabuilder.cpp index d8df13e42..517c2c746 100644 --- a/generator/abstractmetabuilder.cpp +++ b/generator/abstractmetabuilder.cpp @@ -59,6 +59,7 @@ #endif #include #include +#include static QString strip_template_args(const QString &name) { @@ -413,6 +414,39 @@ AbstractMetaClass* AbstractMetaBuilder::getGlobalNamespace(const TypeEntry* type return global; } +Include AbstractMetaBuilder::getRelativeInclude(const QString& path) +{ + QString bestRelativePath; + int bestNumDirectories = 0; + // find the shortest relative path relative to all given include directories + for (QString includePath : m_include_paths) { + QDir includeDir(includePath); + QString relativePath = includeDir.relativeFilePath(path); + QFileInfo info(relativePath); + if (!info.isRelative()) { + // not relative - different drives? + continue; + } + int numDirectories = relativePath.count('/'); + if (bestRelativePath.isEmpty() || numDirectories < bestNumDirectories) { + bestRelativePath = relativePath; + bestNumDirectories = numDirectories; + if (numDirectories == 0) { + // optimal relative path + break; + } + } + } + if (bestRelativePath.isEmpty()) { + // This shouldn't happen + QFileInfo info(path); + return Include(Include::IncludePath, info.fileName()); + } + else { + return Include(Include::IncludePath, bestRelativePath); + } +} + bool AbstractMetaBuilder::build() { Q_ASSERT(!m_file_name.isEmpty()); @@ -756,13 +790,11 @@ AbstractMetaClass *AbstractMetaBuilder::traverseNamespace(NamespaceModelItem nam m_namespace_prefix = currentScope()->qualifiedName().join("::"); if (!type->include().isValid()) { - QFileInfo info(namespace_item->fileName()); - type->setInclude(Include(Include::IncludePath, info.fileName())); + type->setInclude(getRelativeInclude(namespace_item->fileName())); } // namespace items might come from different include files: for (const QString& oneIncludeFile : includeFiles) { - QFileInfo info(oneIncludeFile); - type->addExtraInclude(Include(Include::IncludePath, info.fileName())); + type->addExtraInclude(getRelativeInclude(oneIncludeFile)); } return meta_class; @@ -837,8 +869,7 @@ AbstractMetaEnum *AbstractMetaBuilder::traverseEnum(EnumModelItem enum_item, Abs m_enum_values[meta_enum_value->name()] = meta_enum_value; } - QFileInfo info(enum_item->fileName()); - meta_enum->typeEntry()->setInclude(Include(Include::IncludePath, info.fileName())); + meta_enum->typeEntry()->setInclude(getRelativeInclude(enum_item->fileName())); m_enums << meta_enum; @@ -872,8 +903,7 @@ AbstractMetaClass *AbstractMetaBuilder::traverseTypeAlias(TypeAliasModelItem typ // Set the default include file name if (!type->include().isValid()) { - QFileInfo info(typeAlias->fileName()); - type->setInclude(Include(Include::IncludePath, info.fileName())); + type->setInclude(getRelativeInclude(typeAlias->fileName())); } return meta_class; @@ -986,8 +1016,7 @@ AbstractMetaClass *AbstractMetaBuilder::traverseClass(ClassModelItem class_item) // Set the default include file name. In case we saw an template instance earlier, // overwrite the include file when we see the actual declaration. if (!type->include().isValid() || class_item->hasActualDeclaration()) { - QFileInfo info(class_item->fileName()); - type->setInclude(Include(Include::IncludePath, info.fileName())); + type->setInclude(getRelativeInclude(class_item->fileName())); } return meta_class; diff --git a/generator/abstractmetabuilder.h b/generator/abstractmetabuilder.h index f6ffacfcf..ac8f87da4 100644 --- a/generator/abstractmetabuilder.h +++ b/generator/abstractmetabuilder.h @@ -78,6 +78,9 @@ class AbstractMetaBuilder QString fileName() const { return m_file_name; } void setFileName(const QString &fileName) { m_file_name = fileName; } + //! Set list of include directories. This will be used to make absolute include paths relative. + void setIncludePaths(const QStringList& includePaths) { m_include_paths = includePaths; } + void dumpLog(); bool build(); @@ -153,7 +156,11 @@ class AbstractMetaBuilder AbstractMetaClass* getGlobalNamespace(const TypeEntry* typeEntry); + // turn absolute file path into a relative include + Include getRelativeInclude(const QString& path); + QString m_file_name; + QStringList m_include_paths; AbstractMetaClassList m_meta_classes; QHash m_templates; diff --git a/generator/generatorset.h b/generator/generatorset.h index 069835e9f..d0a125256 100644 --- a/generator/generatorset.h +++ b/generator/generatorset.h @@ -58,6 +58,7 @@ class GeneratorSet : public QObject virtual bool readParameters(const QMap args) = 0; virtual void buildModel(const QString pp_file) = 0; virtual void dumpObjectTree() = 0; + virtual void setIncludePaths(const QStringList& includePaths) = 0; virtual QString generate() = 0; static GeneratorSet *getInstance(); diff --git a/generator/generatorsetqtscript.cpp b/generator/generatorsetqtscript.cpp index 78e2d3735..404c491f1 100644 --- a/generator/generatorsetqtscript.cpp +++ b/generator/generatorsetqtscript.cpp @@ -85,6 +85,11 @@ void GeneratorSetQtScript::dumpObjectTree() { } +void GeneratorSetQtScript::setIncludePaths(const QStringList& includePaths) +{ + builder.setIncludePaths(includePaths); +} + QString GeneratorSetQtScript::generate() { AbstractMetaClassList classes = builder.classesTopologicalSorted(); QSet declaredTypeNames = builder.qtMetaTypeDeclaredTypeNames(); diff --git a/generator/generatorsetqtscript.h b/generator/generatorsetqtscript.h index 06d836906..8209bd2e4 100644 --- a/generator/generatorsetqtscript.h +++ b/generator/generatorsetqtscript.h @@ -52,13 +52,14 @@ class GeneratorSetQtScript : public GeneratorSet public: GeneratorSetQtScript(); - QString usage(); - bool readParameters(const QMap args); + QString usage() override; + bool readParameters(const QMap args) override; - void buildModel(const QString pp_file); - void dumpObjectTree(); + void buildModel(const QString pp_file) override; + void dumpObjectTree() override; + void setIncludePaths(const QStringList& includePaths) override; - QString generate( ); + QString generate() override; private: MetaQtScriptBuilder builder; diff --git a/generator/main.cpp b/generator/main.cpp index 8bac26de9..844ec7189 100644 --- a/generator/main.cpp +++ b/generator/main.cpp @@ -127,11 +127,11 @@ namespace } bool - preprocess(const QString& sourceFile, const QString& targetFile, const QString& commandLineIncludes = QString()) + preprocess(const QString& sourceFile, const QString& targetFile, const QStringList& includePaths) { simplecpp::DUI dui; // settings - for(QString include : getIncludeDirectories(commandLineIncludes)) { + for(QString include : includePaths) { dui.includePaths.push_back(QDir::toNativeSeparators(include).toStdString()); } dui.defines.push_back("__cplusplus=1"); @@ -212,10 +212,10 @@ namespace return true; } - unsigned int getQtVersion(const QString &commandLineIncludes) + unsigned int getQtVersion(const QStringList& includePaths) { QRegularExpression re("#define\\s+QTCORE_VERSION\\s+0x([0-9a-f]+)", QRegularExpression::CaseInsensitiveOption); - for (const QString &includeDir: getIncludeDirectories(commandLineIncludes)) + for (const QString &includeDir: includePaths) { QFileInfo fi(QDir(includeDir), "qtcoreversion.h"); if (fi.exists()) @@ -244,7 +244,7 @@ namespace } } printf("Error: Could not find Qt version (looked for qtcoreversion.h in %s)\n", - qPrintable(commandLineIncludes)); + qPrintable(includePaths.join(QDir::listSeparator()))); return 0; } }; @@ -348,9 +348,10 @@ int main(int argc, char *argv[]) printf("Please wait while source files are being generated...\n"); + QStringList includePaths = getIncludeDirectories(args.value("include-paths")); if (!qtVersion) { printf("Trying to determine Qt version...\n"); - qtVersion = getQtVersion(args.value("include-paths")); + qtVersion = getQtVersion(includePaths); if (!qtVersion) { fprintf(stderr, "Aborting\n"); // the error message was printed by getQtVersion @@ -372,7 +373,8 @@ int main(int argc, char *argv[]) printf("PreProcessing - Generate [%s] using [%s] and include-paths [%s]\n", qPrintable(pp_file), qPrintable(fileName), qPrintable(args.value("include-paths"))); ReportHandler::setContext("Preprocess"); - if (!preprocess(fileName, pp_file, args.value("include-paths"))) { + + if (!preprocess(fileName, pp_file, includePaths)) { fprintf(stderr, "Preprocessor failed on file: '%s'\n", qPrintable(fileName)); return 1; } @@ -387,6 +389,7 @@ int main(int argc, char *argv[]) printf("Building model using [%s]\n", qPrintable(pp_file)); ReportHandler::setContext("Build"); + gs->setIncludePaths(includePaths); gs->buildModel(pp_file); if (args.contains("dump-object-tree")) { gs->dumpObjectTree();