diff options
-rw-r--r-- | qmake/library/qmakeevaluator.cpp | 66 | ||||
-rw-r--r-- | qmake/library/qmakeevaluator.h | 20 |
2 files changed, 62 insertions, 24 deletions
diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp index 85e08095a5..25e4e8511d 100644 --- a/qmake/library/qmakeevaluator.cpp +++ b/qmake/library/qmakeevaluator.cpp @@ -1503,7 +1503,7 @@ void QMakeEvaluator::updateFeaturePaths() foreach (const QString &root, feature_roots) if (IoUtils::exists(root)) ret << root; - m_featureRoots = ret; + m_featureRoots = new QMakeFeatureRoots(ret); } ProString QMakeEvaluator::propertyValue(const ProKey &name) const @@ -1861,35 +1861,55 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFeatureFile( if (!fn.endsWith(QLatin1String(".prf"))) fn += QLatin1String(".prf"); - if (m_featureRoots.isEmpty()) + if (!m_featureRoots) updateFeaturePaths(); - int start_root = 0; +#ifdef PROEVALUATOR_THREAD_SAFE + m_featureRoots->mutex.lock(); +#endif QString currFn = currentFileName(); - if (IoUtils::fileName(currFn) == IoUtils::fileName(fn)) { - QStringRef currPath = IoUtils::pathName(currFn); - for (int root = 0; root < m_featureRoots.size(); ++root) - if (currPath == m_featureRoots.at(root)) { - start_root = root + 1; - break; + if (IoUtils::fileName(currFn) != IoUtils::fileName(fn)) + currFn.clear(); + // Null values cannot regularly exist in the hash, so they indicate that the value still + // needs to be determined. Failed lookups are represented via non-null empty strings. + QString *fnp = &m_featureRoots->cache[qMakePair(fn, currFn)]; + if (fnp->isNull()) { + int start_root = 0; + const QStringList &paths = m_featureRoots->paths; + if (!currFn.isEmpty()) { + QStringRef currPath = IoUtils::pathName(currFn); + for (int root = 0; root < paths.size(); ++root) + if (currPath == paths.at(root)) { + start_root = root + 1; + break; + } + } + for (int root = start_root; root < paths.size(); ++root) { + QString fname = paths.at(root) + fn; + if (IoUtils::exists(fname)) { + fn = fname; + goto cool; } - } - for (int root = start_root; root < m_featureRoots.size(); ++root) { - QString fname = m_featureRoots.at(root) + fn; - if (IoUtils::exists(fname)) { - fn = fname; - goto cool; } - } #ifdef QMAKE_BUILTIN_PRFS - fn.prepend(QLatin1String(":/qmake/features/")); - if (QFileInfo(fn).exists()) - goto cool; + fn.prepend(QLatin1String(":/qmake/features/")); + if (QFileInfo(fn).exists()) + goto cool; #endif - if (!silent) - evalError(fL1S("Cannot find feature %1").arg(fileName)); - return ReturnFalse; + fn = QLatin1String(""); // Indicate failed lookup. See comment above. - cool: + cool: + *fnp = fn; + } else { + fn = *fnp; + } +#ifdef PROEVALUATOR_THREAD_SAFE + m_featureRoots->mutex.unlock(); +#endif + if (fn.isEmpty()) { + if (!silent) + evalError(fL1S("Cannot find feature %1").arg(fileName)); + return ReturnFalse; + } ProStringList &already = valuesRef(ProKey("QMAKE_INTERNAL_INCLUDED_FEATURES")); ProString afn(fn); if (already.contains(afn)) { diff --git a/qmake/library/qmakeevaluator.h b/qmake/library/qmakeevaluator.h index 09617ba019..91433302d0 100644 --- a/qmake/library/qmakeevaluator.h +++ b/qmake/library/qmakeevaluator.h @@ -55,9 +55,13 @@ #include <qstack.h> #include <qstring.h> #include <qstringlist.h> +#include <qshareddata.h> #ifndef QT_BOOTSTRAPPED # include <qprocess.h> #endif +#ifdef PROEVALUATOR_THREAD_SAFE +# include <qmutex.h> +#endif QT_BEGIN_NAMESPACE @@ -83,6 +87,20 @@ public: virtual void doneWithEval(ProFile *parent) = 0; }; +typedef QPair<QString, QString> QMakeFeatureKey; // key, parent +typedef QHash<QMakeFeatureKey, QString> QMakeFeatureHash; + +class QMAKE_EXPORT QMakeFeatureRoots : public QSharedData +{ +public: + QMakeFeatureRoots(const QStringList &_paths) : paths(_paths) {} + const QStringList paths; + mutable QMakeFeatureHash cache; +#ifdef PROEVALUATOR_THREAD_SAFE + mutable QMutex mutex; +#endif +}; + // We use a QLinkedList based stack instead of a QVector based one (QStack), so that // the addresses of value maps stay constant. The qmake generators rely on that. class QMAKE_EXPORT ProValueMapStack : public QLinkedList<ProValueMap> @@ -284,7 +302,7 @@ public: QStringList m_qmakepath; QStringList m_qmakefeatures; QStringList m_mkspecPaths; - QStringList m_featureRoots; + QExplicitlySharedDataPointer<QMakeFeatureRoots> m_featureRoots; ProString m_dirSep; ProFunctionDefs m_functionDefs; ProStringList m_returnValue; |