From a2f40fce2a1cf3c19a13fa27eea08192493ab76e Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen <oswald.buddenhagen@nokia.com> Date: Fri, 10 Jul 2009 13:37:02 +0200 Subject: [PATCH] implement proper vpath handling for qt4 projects this also removes the bogus special casing of various filename-containing variables inside the pro parser. --- .../qt4projectmanager/profilereader.cpp | 48 ------ src/plugins/qt4projectmanager/profilereader.h | 5 - src/plugins/qt4projectmanager/qt4nodes.cpp | 33 +++- src/shared/proparser/profileevaluator.cpp | 158 ++++++------------ src/shared/proparser/profileevaluator.h | 5 +- 5 files changed, 81 insertions(+), 168 deletions(-) diff --git a/src/plugins/qt4projectmanager/profilereader.cpp b/src/plugins/qt4projectmanager/profilereader.cpp index e8f8e833994..5bef6ecd6ce 100644 --- a/src/plugins/qt4projectmanager/profilereader.cpp +++ b/src/plugins/qt4projectmanager/profilereader.cpp @@ -107,54 +107,6 @@ QString ProFileReader::value(const QString &variable) const } -// Construct QFileInfo from path value and base directory -// Truncate trailing slashs and make absolute -static inline QFileInfo infoFromPath(QString path, - const QString &baseDirectory) -{ - if (path.size() > 1 && path.endsWith(QLatin1Char('/'))) - path.truncate(path.size() - 1); - QFileInfo info(path); - if (info.isAbsolute()) - return info; - return QFileInfo(baseDirectory, path); -} - -/*! - Returns a list of absolute paths - */ -QStringList ProFileReader::absolutePathValues(const QString &variable, - const QString &baseDirectory, - PathValuesMode mode, - const ProFile *pro) const -{ - QStringList rawList; - if (!pro) - rawList = values(variable); - else - rawList = values(variable, pro); - - if (rawList.isEmpty()) - return QStringList(); - - // Normalize list of paths, kill trailing slashes, - // remove duplicates while maintaining order - const QChar slash = QLatin1Char('/'); - QStringList result; - const QStringList::const_iterator rcend = rawList.constEnd(); - for (QStringList::const_iterator it = rawList.constBegin(); it != rcend; ++it) { - const QFileInfo info = infoFromPath(*it, baseDirectory); - if (mode == AllPaths || info.exists()) { - if (mode != ExistingFilePaths || info.isFile()) { - const QString absPath = info.absoluteFilePath(); - if (!result.contains(absPath)) - result.push_back(absPath); - } - } - } - return result; -} - void ProFileReader::fileMessage(const QString &message) { Q_UNUSED(message); diff --git a/src/plugins/qt4projectmanager/profilereader.h b/src/plugins/qt4projectmanager/profilereader.h index cded457cdf3..74a8745ac60 100644 --- a/src/plugins/qt4projectmanager/profilereader.h +++ b/src/plugins/qt4projectmanager/profilereader.h @@ -53,11 +53,6 @@ public: QString value(const QString &variable) const; - enum PathValuesMode { AllPaths, ExistingPaths, ExistingFilePaths }; - QStringList absolutePathValues(const QString &variable, - const QString &baseDirectory, - PathValuesMode mode, - const ProFile *pro = 0) const; ProFile *proFileFor(const QString &name); signals: void errorFound(const QString &error); diff --git a/src/plugins/qt4projectmanager/qt4nodes.cpp b/src/plugins/qt4projectmanager/qt4nodes.cpp index f1556eb5ff0..e8b3de82965 100644 --- a/src/plugins/qt4projectmanager/qt4nodes.cpp +++ b/src/plugins/qt4projectmanager/qt4nodes.cpp @@ -132,14 +132,30 @@ void Qt4PriFileNode::update(ProFile *includeFile, ProFileReader *reader) << ProjectExplorer::ResourceType << ProjectExplorer::UnknownFileType); + const QString &projectDir = m_qt4ProFileNode->m_projectDir; + + QStringList baseVPaths; + baseVPaths += reader->absolutePathValues("VPATH", projectDir); + baseVPaths << projectDir; // QMAKE_ABSOLUTE_SOURCE_PATH + baseVPaths += reader->absolutePathValues("DEPENDPATH", projectDir); + baseVPaths.removeDuplicates(); + // update files - const QDir projectDir = QFileInfo(m_projectFilePath).dir(); foreach (FileType type, fileTypes) { const QStringList qmakeVariables = varNames(type); QStringList newFilePaths; - foreach (const QString &qmakeVariable, qmakeVariables) - newFilePaths += reader->absolutePathValues(qmakeVariable, projectDir.path(), ProFileReader::ExistingFilePaths, includeFile); + foreach (const QString &qmakeVariable, qmakeVariables) { + QStringList vPaths; + if (type == ProjectExplorer::SourceType) + vPaths = reader->absolutePathValues("VPATH_" + qmakeVariable, projectDir); + vPaths += baseVPaths; + if (type == ProjectExplorer::HeaderType) + vPaths += reader->absolutePathValues("INCLUDEPATH", projectDir); + vPaths.removeDuplicates(); + newFilePaths += reader->absoluteFileValues(qmakeVariable, projectDir, vPaths, includeFile); + } + newFilePaths.removeDuplicates(); QList<FileNode*> existingFileNodes; foreach (FileNode *fileNode, fileNodes()) { @@ -896,16 +912,16 @@ Qt4ProFileNode *Qt4ProFileNode::createSubProFileNode(const QString &path) QStringList Qt4ProFileNode::uiDirPaths(ProFileReader *reader) const { QStringList candidates = reader->absolutePathValues(QLatin1String("UI_DIR"), - buildDir(), - ProFileReader::ExistingPaths); + buildDir()); + candidates.removeDuplicates(); return candidates; } QStringList Qt4ProFileNode::mocDirPaths(ProFileReader *reader) const { QStringList candidates = reader->absolutePathValues(QLatin1String("MOC_DIR"), - buildDir(), - ProFileReader::ExistingPaths); + buildDir()); + candidates.removeDuplicates(); return candidates; } @@ -913,8 +929,7 @@ QStringList Qt4ProFileNode::includePaths(ProFileReader *reader) const { QStringList paths; paths = reader->absolutePathValues(QLatin1String("INCLUDEPATH"), - m_projectDir, - ProFileReader::ExistingPaths); + m_projectDir); paths << uiDirPaths(reader) << mocDirPaths(reader); paths.removeDuplicates(); return paths; diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp index 295e094a9ce..27e3932cb95 100644 --- a/src/shared/proparser/profileevaluator.cpp +++ b/src/shared/proparser/profileevaluator.cpp @@ -182,9 +182,6 @@ public: QString propertyValue(const QString &val) const; bool isActiveConfig(const QString &config, bool regex = false); - QStringList expandPattern(const QString &pattern); - void expandPatternHelper(const QString &relName, const QString &absName, - QStringList &sources_out); QStringList expandVariableReferences(const QString &value); void doVariableReplace(QString *str); QStringList evaluateExpandFunction(const QString &function, const QString &arguments); @@ -844,32 +841,6 @@ void ProFileEvaluator::Private::visitProValue(ProValue *value) m_prevLineNo = m_lineNo; m_prevProFile = currentProFile(); - // The following two blocks fix bug 180128 by making all "interesting" - // file name absolute in each .pro file, not just the top most one - if (varName == QLatin1String("SOURCES") - || varName == QLatin1String("OBJECTIVE_SOURCES") - || varName == QLatin1String("HEADERS") - || varName == QLatin1String("INTERFACES") - || varName == QLatin1String("FORMS") - || varName == QLatin1String("FORMS3") - || varName == QLatin1String("RESOURCES") - || varName == QLatin1String("LEXSOURCES") - || varName == QLatin1String("YACCSOURCES")){ - // matches only existent files, expand certain(?) patterns - QStringList vv; - for (int i = v.count(); --i >= 0; ) - vv << expandPattern(v[i]); - v = vv; - } - - if (varName == QLatin1String("TRANSLATIONS")) { - // also matches non-existent files, but does not expand pattern - QString dir = QFileInfo(currentFileName()).absolutePath(); - dir += QLatin1Char('/'); - for (int i = v.count(); --i >= 0; ) - v[i] = QFileInfo(dir, v[i]).absoluteFilePath(); - } - switch (m_variableOperator) { case ProVariable::SetOperator: // = if (!m_cumulative) { @@ -2495,82 +2466,6 @@ bool ProFileEvaluator::Private::evaluateFeatureFile(const QString &fileName) return ok; } -void ProFileEvaluator::Private::expandPatternHelper(const QString &relName, const QString &absName, - QStringList &sources_out) -{ - const QStringList vpaths = values(QLatin1String("VPATH")) - + values(QLatin1String("QMAKE_ABSOLUTE_SOURCE_PATH")) - + values(QLatin1String("DEPENDPATH")) - + values(QLatin1String("VPATH_SOURCES")); - - QFileInfo fi(absName); - bool found = fi.exists(); - // Search in all vpaths - if (!found) { - foreach (const QString &vpath, vpaths) { - fi.setFile(vpath + QDir::separator() + relName); - if (fi.exists()) { - found = true; - break; - } - } - } - - if (found) { - sources_out += fi.absoluteFilePath(); // Not resolving symlinks - } else { - QString val = relName; - QString dir; - QString wildcard = val; - QString real_dir; - if (wildcard.lastIndexOf(QLatin1Char('/')) != -1) { - dir = wildcard.left(wildcard.lastIndexOf(QLatin1Char('/')) + 1); - real_dir = dir; - wildcard = wildcard.right(wildcard.length() - dir.length()); - } - - if (real_dir.isEmpty() || QFileInfo(real_dir).exists()) { - QStringList files = QDir(real_dir).entryList(QStringList(wildcard)); - if (files.isEmpty()) { - q->logMessage(format("Failure to find %1").arg(val)); - } else { - QString a; - for (int i = files.count() - 1; i >= 0; --i) { - if (files[i] == QLatin1String(".") || files[i] == QLatin1String("..")) - continue; - a = dir + files[i]; - sources_out += a; - } - } - } else { - q->logMessage(format("Cannot match %1/%2, as %3 does not exist.") - .arg(real_dir).arg(wildcard).arg(real_dir)); - } - } -} - - -/* - * Lookup of files are done in this order: - * 1. look in pwd - * 2. look in vpaths - * 3. expand wild card files relative from the profiles folder - **/ - -// FIXME: This code supports something that I'd consider a flaw in .pro file syntax -// which is not even documented. So arguably this can be ditched completely... -QStringList ProFileEvaluator::Private::expandPattern(const QString& pattern) -{ - if (!currentProFile()) - return QStringList(); - - QStringList sources_out; - const QString absName = QDir::cleanPath(QDir::current().absoluteFilePath(pattern)); - - expandPatternHelper(pattern, absName, sources_out); - return sources_out; -} - QString ProFileEvaluator::Private::format(const char *fmt) const { ProFile *pro = currentProFile(); @@ -2621,6 +2516,59 @@ QStringList ProFileEvaluator::values(const QString &variableName, const ProFile return fixEnvVariables(d->values(variableName, pro)); } +QStringList ProFileEvaluator::absolutePathValues( + const QString &variable, const QString &baseDirectory) const +{ + QStringList result; + foreach (const QString &el, values(variable)) { + const QFileInfo info = QFileInfo(baseDirectory, el); + if (info.isDir()) + result << QDir::cleanPath(info.absoluteFilePath()); + } + return result; +} + +QStringList ProFileEvaluator::absoluteFileValues( + const QString &variable, const QString &baseDirectory, const QStringList &searchDirs, + const ProFile *pro) const +{ + QStringList result; + foreach (const QString &el, pro ? values(variable, pro) : values(variable)) { + QFileInfo info(el); + if (info.isAbsolute()) { + if (info.exists()) { + result << QDir::cleanPath(el); + goto next; + } + } else { + foreach (const QString &dir, searchDirs) { + QFileInfo info(dir, el); + if (info.isFile()) { + result << QDir::cleanPath(info.filePath()); + goto next; + } + } + if (baseDirectory.isEmpty()) + goto next; + info = QFileInfo(baseDirectory, el); + } + { + QFileInfo baseInfo(info.absolutePath()); + if (baseInfo.exists()) { + QString wildcard = info.fileName(); + if (wildcard.contains(QLatin1Char('*')) || wildcard.contains(QLatin1Char('?'))) { + QDir theDir(QDir::cleanPath(baseInfo.filePath())); + foreach (const QString &fn, theDir.entryList(QStringList(wildcard))) + if (fn != QLatin1String(".") && fn != QLatin1String("..")) + result << theDir.absoluteFilePath(fn); + } // else if (acceptMissing) + } + } + next: ; + } + return result; +} + ProFileEvaluator::TemplateType ProFileEvaluator::templateType() { QStringList templ = values(QLatin1String("TEMPLATE")); diff --git a/src/shared/proparser/profileevaluator.h b/src/shared/proparser/profileevaluator.h index 9bd88c0c03d..55a5c53776c 100644 --- a/src/shared/proparser/profileevaluator.h +++ b/src/shared/proparser/profileevaluator.h @@ -40,7 +40,6 @@ QT_BEGIN_NAMESPACE -class ProFile; class ProFileEvaluator; void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringList> *varMap); @@ -76,6 +75,10 @@ public: void addProperties(const QHash<QString, QString> &properties); QStringList values(const QString &variableName) const; QStringList values(const QString &variableName, const ProFile *pro) const; + QStringList absolutePathValues(const QString &variable, const QString &baseDirectory) const; + QStringList absoluteFileValues( + const QString &variable, const QString &baseDirectory, const QStringList &searchDirs, + const ProFile *pro) const; QString propertyValue(const QString &val) const; // for our descendents -- GitLab