diff options
author | Oswald Buddenhagen <oswald.buddenhagen@qt.io> | 2016-10-25 21:25:25 +0200 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@qt.io> | 2016-11-01 17:37:17 +0000 |
commit | 5f17c280ec2f077670b82cfd9d255449ceedee7e (patch) | |
tree | cf1e993681284c6c690d6a3b73b9ff5cf1de37e0 | |
parent | 4a59a7d714bdfdf54e279d6dc8de11383fff7ccd (diff) |
de-duplicate INSTALLS resolution
don't resolve the source files once for deployment and once for the
project tree.
Change-Id: Ifddf8fc7883bf025d3640de0d6676b5930991088
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
-rw-r--r-- | src/plugins/qmakeprojectmanager/qmakenodes.cpp | 78 | ||||
-rw-r--r-- | src/plugins/qmakeprojectmanager/qmakenodes.h | 16 | ||||
-rw-r--r-- | src/plugins/qmakeprojectmanager/qmakeproject.cpp | 6 | ||||
-rw-r--r-- | src/shared/proparser/profileevaluator.cpp | 35 | ||||
-rw-r--r-- | src/shared/proparser/profileevaluator.h | 4 |
5 files changed, 70 insertions, 69 deletions
diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.cpp b/src/plugins/qmakeprojectmanager/qmakenodes.cpp index 9f20ebeead4..e802968c9ab 100644 --- a/src/plugins/qmakeprojectmanager/qmakenodes.cpp +++ b/src/plugins/qmakeprojectmanager/qmakenodes.cpp @@ -660,24 +660,22 @@ void QmakePriFileNode::extractSources( } } -void QmakePriFileNode::extractValues( - const EvalInput &input, ProFile *proFile, PriFileEvalResult &result) -{ - // Figure out DEPLOYMENT and INSTALL folders. - // Ignore stuff from cumulative parse, as we are recursively enumerating - // all the files from those folders and add watchers for them. That's too - // dangerous if we get the folders wrong and enumerate the whole project - // tree multiple times. - QStringList dynamicVariables = dynamicVarNames(input.readerExact); - foreach (const QString &dynamicVar, dynamicVariables) - result.folders += input.readerExact->values(dynamicVar, proFile); - - for (int i=0; i < result.folders.size(); ++i) { - const QFileInfo fi(result.folders.at(i)); - if (fi.isRelative()) - result.folders[i] = QDir::cleanPath(input.projectDir + QLatin1Char('/') + result.folders.at(i)); +void QmakePriFileNode::extractInstalls( + QHash<const ProFile *, PriFileEvalResult *> proToResult, PriFileEvalResult *fallback, + const InstallsList &installList) +{ + for (const InstallsItem &item : installList.items) { + for (const ProFileEvaluator::SourceFile &source : item.files) { + auto *result = proToResult.value(source.proFile); + if (!result) + result = fallback; + result->folders << source.fileName; + } } +} +void QmakePriFileNode::processValues(PriFileEvalResult &result) +{ result.folders.removeDuplicates(); // Remove non existing items and non folders @@ -1456,19 +1454,6 @@ QStringList QmakePriFileNode::varNamesForRemoving() return vars; } -QStringList QmakePriFileNode::dynamicVarNames(QtSupport::ProFileReader *reader) -{ - QStringList result; - - // Figure out INSTALLS (and DEPLOYMENT, as it's aliased) - const QString installs = QLatin1String("INSTALLS"); - const QString files = QLatin1String(".files"); - foreach (const QString &var, reader->values(installs)) - result << (var + files); - result.removeDuplicates(); - return result; -} - QSet<FileName> QmakePriFileNode::filterFilesProVariables(FileType fileType, const QSet<FileName> &files) { if (fileType != QMLType && fileType != UnknownFileType) @@ -1952,11 +1937,18 @@ EvalResult *QmakeProFileNode::evaluate(const EvalInput &input) } } + // This is used for two things: + // - Actual deployment, in which case we need exact values. + // - The project tree, in which case we also want exact values to avoid recursively + // watching bogus paths. However, we accept the values even if the evaluation + // failed, to at least have a best-effort result. + result->installsList = installsList(exactBuildPassReader, input.projectFilePath.toString(), + input.projectDir, input.buildDirectory); + extractInstalls(proToResult, &result->includedFiles.result, result->installsList); + if (result->state == EvalResult::EvalOk) { result->targetInformation = targetInformation(input.readerExact, exactBuildPassReader, input.buildDirectory, input.projectFilePath.toString()); - result->installsList = installsList(exactBuildPassReader, input.projectFilePath.toString(), - input.projectDir, input.buildDirectory); // update other variables result->newVarValues[DefinesVar] = exactReader->values(QLatin1String("DEFINES")); @@ -1977,8 +1969,8 @@ EvalResult *QmakeProFileNode::evaluate(const EvalInput &input) result->newVarValues[ExactResourceVar] = fileListForVar(exactSourceFiles, QLatin1String("RESOURCES")); result->newVarValues[CumulativeResourceVar] = fileListForVar(cumulativeSourceFiles, QLatin1String("RESOURCES")); result->newVarValues[PkgConfigVar] = exactReader->values(QLatin1String("PKGCONFIG")); - result->newVarValues[PrecompiledHeaderVar] = exactReader->fixifiedValues( - QLatin1String("PRECOMPILED_HEADER"), input.projectDir, input.buildDirectory); + result->newVarValues[PrecompiledHeaderVar] = ProFileEvaluator::sourcesToFiles(exactReader->fixifiedValues( + QLatin1String("PRECOMPILED_HEADER"), input.projectDir, input.buildDirectory)); result->newVarValues[LibDirectoriesVar] = libDirectories(exactReader); result->newVarValues[ConfigVar] = exactReader->values(QLatin1String("CONFIG")); result->newVarValues[QmlImportPathVar] = exactReader->absolutePathValues( @@ -2007,11 +1999,10 @@ EvalResult *QmakeProFileNode::evaluate(const EvalInput &input) if (result->state == EvalResult::EvalOk || result->state == EvalResult::EvalPartial) { - // extract values for each .pri file and add it to IncludedPriFiles structure QList<IncludedPriFile *> toExtract = { &result->includedFiles }; while (!toExtract.isEmpty()) { IncludedPriFile *current = toExtract.takeFirst(); - extractValues(input, current->proFile, current->result); + processValues(current->result); toExtract.append(current->children.values()); } } @@ -2295,8 +2286,10 @@ QStringList QmakeProFileNode::includePaths(QtSupport::ProFileReader *reader, con paths.append(cxxflags.mid(2)); } - foreach (const QString &el, reader->fixifiedValues(QLatin1String("INCLUDEPATH"), projectDir, buildDir)) - paths << sysrootify(el, sysroot, projectDir, buildDir); + foreach (const ProFileEvaluator::SourceFile &el, + reader->fixifiedValues(QLatin1String("INCLUDEPATH"), projectDir, buildDir)) { + paths << sysrootify(el.fileName, sysroot, projectDir, buildDir); + } // paths already contains moc dir and ui dir, due to corrrectly parsing uic.prf and moc.prf // except if those directories don't exist at the time of parsing // thus we add those directories manually (without checking for existence) @@ -2411,8 +2404,8 @@ InstallsList QmakeProFileNode::installsList(const QtSupport::ProFileReader *read return result; const QStringList &itemList = reader->values(QLatin1String("INSTALLS")); foreach (const QString &item, itemList) { - if (reader->values(item + QLatin1String(".CONFIG")).contains(QLatin1String("no_default_install"))) - continue; + bool active = !reader->values(item + QLatin1String(".CONFIG")) + .contains(QLatin1String("no_default_install")); QString itemPath; const QString pathVar = item + QLatin1String(".path"); const QStringList &itemPaths = reader->values(pathVar); @@ -2428,11 +2421,12 @@ InstallsList QmakeProFileNode::installsList(const QtSupport::ProFileReader *read itemPath = itemPaths.last(); if (item == QLatin1String("target")) { - result.targetPath = itemPath; + if (active) + result.targetPath = itemPath; } else { - const QStringList &itemFiles = reader->fixifiedValues( + const auto &itemFiles = reader->fixifiedValues( item + QLatin1String(".files"), projectDir, buildDir); - result.items << InstallsItem(itemPath, itemFiles); + result.items << InstallsItem(itemPath, itemFiles, active); } } return result; diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.h b/src/plugins/qmakeprojectmanager/qmakenodes.h index 4dd307b4ad2..e7d3a3f8b25 100644 --- a/src/plugins/qmakeprojectmanager/qmakenodes.h +++ b/src/plugins/qmakeprojectmanager/qmakenodes.h @@ -115,6 +115,8 @@ class EvalResult; class PriFileEvalResult; } +struct InstallsList; + // Implements ProjectNode for qmake .pri files class QMAKEPROJECTMANAGER_EXPORT QmakePriFileNode : public ProjectExplorer::ProjectNode { @@ -164,7 +166,6 @@ protected: static QStringList varNames(ProjectExplorer::FileType type, QtSupport::ProFileReader *readerExact); static QStringList varNamesForRemoving(); static QString varNameForAdding(const QString &mimeType); - static QStringList dynamicVarNames(QtSupport::ProFileReader *readerExact); static QSet<Utils::FileName> filterFilesProVariables(ProjectExplorer::FileType fileType, const QSet<Utils::FileName> &files); static QSet<Utils::FileName> filterFilesRecursiveEnumerata(ProjectExplorer::FileType fileType, const QSet<Utils::FileName> &files); @@ -201,8 +202,11 @@ private: QHash<const ProFile *, Internal::PriFileEvalResult *> proToResult, Internal::PriFileEvalResult *fallback, QVector<ProFileEvaluator::SourceFile> sourceFiles, ProjectExplorer::FileType type); - static void extractValues( - const Internal::EvalInput &input, ProFile *proFile, Internal::PriFileEvalResult &result); + static void extractInstalls( + QHash<const ProFile *, Internal::PriFileEvalResult *> proToResult, + Internal::PriFileEvalResult *fallback, + const InstallsList &installList); + static void processValues(Internal::PriFileEvalResult &result); void watchFolders(const QSet<QString> &folders); QmakeProject *m_project; @@ -294,9 +298,11 @@ public: struct QMAKEPROJECTMANAGER_EXPORT InstallsItem { InstallsItem() = default; - InstallsItem(QString p, QStringList f) : path(p), files(f) {} + InstallsItem(QString p, QVector<ProFileEvaluator::SourceFile> f, bool a) + : path(p), files(f), active(a) {} QString path; - QStringList files; + QVector<ProFileEvaluator::SourceFile> files; + bool active; }; struct QMAKEPROJECTMANAGER_EXPORT InstallsList { diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index f3cd7dbffa3..4a06be86ade 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -1388,8 +1388,10 @@ void QmakeProject::collectData(const QmakeProFileNode *node, DeploymentData &dep const InstallsList &installsList = node->installsList(); foreach (const InstallsItem &item, installsList.items) { - foreach (const QString &localFile, item.files) - deploymentData.addFile(localFile, item.path); + if (!item.active) + continue; + foreach (const auto &localFile, item.files) + deploymentData.addFile(localFile.fileName, item.path); } switch (node->projectType()) { diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp index 3124b273319..f60c6afa2c8 100644 --- a/src/shared/proparser/profileevaluator.cpp +++ b/src/shared/proparser/profileevaluator.cpp @@ -76,36 +76,35 @@ QStringList ProFileEvaluator::values(const QString &variableName) const return ret; } -QStringList ProFileEvaluator::values(const QString &variableName, const ProFile *pro) const -{ - // It makes no sense to put any kind of magic into expanding these - const ProStringList &values = d->m_valuemapStack.first().value(ProKey(variableName)); - QStringList ret; - ret.reserve(values.size()); - foreach (const ProString &str, values) - if (str.sourceFile() == pro) - ret << d->m_option->expandEnvVars(str.toQString()); - return ret; -} - -QStringList ProFileEvaluator::fixifiedValues( +QVector<ProFileEvaluator::SourceFile> ProFileEvaluator::fixifiedValues( const QString &variable, const QString &baseDirectory, const QString &buildDirectory) const { - QStringList result; - foreach (const QString &el, values(variable)) { + QVector<SourceFile> result; + foreach (const ProString &str, d->values(ProKey(variable))) { + const QString &el = d->m_option->expandEnvVars(str.toQString()); if (IoUtils::isAbsolutePath(el)) { - result << el; + result << SourceFile{ el, str.sourceFile() }; } else { QString fn = QDir::cleanPath(baseDirectory + QLatin1Char('/') + el); if (IoUtils::exists(fn)) - result << fn; + result << SourceFile{ fn, str.sourceFile() }; else - result << QDir::cleanPath(buildDirectory + QLatin1Char('/') + el); + result << SourceFile{ QDir::cleanPath(buildDirectory + QLatin1Char('/') + el), + str.sourceFile() }; } } return result; } +QStringList ProFileEvaluator::sourcesToFiles(const QVector<ProFileEvaluator::SourceFile> &sources) +{ + QStringList result; + result.reserve(sources.size()); + for (const auto &src : sources) + result << src.fileName; + return result; +} + // VFS note: all search paths are assumed to be real. QStringList ProFileEvaluator::absolutePathValues( const QString &variable, const QString &baseDirectory) const diff --git a/src/shared/proparser/profileevaluator.h b/src/shared/proparser/profileevaluator.h index a356dadaf7a..d001c9d7b0d 100644 --- a/src/shared/proparser/profileevaluator.h +++ b/src/shared/proparser/profileevaluator.h @@ -80,14 +80,14 @@ public: bool contains(const QString &variableName) const; QString value(const QString &variableName) const; QStringList values(const QString &variableName) const; - QStringList values(const QString &variableName, const ProFile *pro) const; - QStringList fixifiedValues( + QVector<SourceFile> fixifiedValues( const QString &variable, const QString &baseDirectory, const QString &buildDirectory) const; QStringList absolutePathValues(const QString &variable, const QString &baseDirectory) const; QVector<SourceFile> absoluteFileValues( const QString &variable, const QString &baseDirectory, const QStringList &searchDirs, QHash<ProString, bool> *handled) const; QString propertyValue(const QString &val) const; + static QStringList sourcesToFiles(const QVector<SourceFile> &sources); private: QMakeEvaluator *d; |