support a cache that is really just a cache
authorOswald Buddenhagen <oswald.buddenhagen@digia.com>
Thu, 7 Nov 2013 19:40:00 +0000 (20:40 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Mon, 18 Nov 2013 11:12:24 +0000 (12:12 +0100)
unlike .qmake.cache & co., the presence of this file has no magic
effects on where mkspecs, modules and other things are searched.

as the obvious name "cache" is of course already taken, we call it
"stash".

the file is searched up to the super cache (if present), otherwise up to
the normal cache/conf (if present), otherwise up to the root.
if it's not found, it is created next to the super cache (if present),
otherwise next to the cache/conf (if present), otherwise in the current
output directory.

note that the cache really should be created and populated by the
top-level project if there are subprojects: otherwise, if there is an
"anchor" (super/cache/conf), subprojects would race for updating the
cache and make a mess. without an "anchor", each subproject would just
create its own cache, kind of defeating its purpose. this is no
different from the existing "cache", but it's worth mentioning that
removing the "anchoring" function does not remove the "nesting order"
constraint.

Task-number: QTBUG-31340
Change-Id: I786d40cef40d14582a0dd4a9407863001bec4c98
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
(cherry picked from qtbase/ff31d87cc883dcf17ab459a15eac04e074d9614a)
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@digia.com>
src/linguist/shared/qmakebuiltins.cpp
src/linguist/shared/qmakeevaluator.cpp
src/linguist/shared/qmakeevaluator.h
src/linguist/shared/qmakeglobals.h

index 99232d1..4bfe5c0 100644 (file)
@@ -1596,11 +1596,11 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
     }
     case T_CACHE: {
         if (args.count() > 3) {
-            evalError(fL1S("cache(var, [set|add|sub] [transient] [super], [srcvar]) requires one to three arguments."));
+            evalError(fL1S("cache(var, [set|add|sub] [transient] [super|stash], [srcvar]) requires one to three arguments."));
             return ReturnFalse;
         }
         bool persist = true;
-        bool super = false;
+        enum { TargetStash, TargetCache, TargetSuper } target = TargetCache;
         enum { CacheSet, CacheAdd, CacheSub } mode = CacheSet;
         ProKey srcvar;
         if (args.count() >= 2) {
@@ -1609,7 +1609,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
                 if (m_tmp3 == QLatin1String("transient")) {
                     persist = false;
                 } else if (m_tmp3 == QLatin1String("super")) {
-                    super = true;
+                    target = TargetSuper;
+                } else if (m_tmp3 == QLatin1String("stash")) {
+                    target = TargetStash;
                 } else if (m_tmp3 == QLatin1String("set")) {
                     mode = CacheSet;
                 } else if (m_tmp3 == QLatin1String("add")) {
@@ -1648,7 +1650,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
                 m_option->mutex.lock();
 #endif
                 QMakeBaseEnv *baseEnv =
-                        m_option->baseEnvs.value(QMakeBaseKey(m_buildRoot, hostBuild));
+                        m_option->baseEnvs.value(QMakeBaseKey(m_buildRoot, m_stashfile, hostBuild));
 #ifdef PROEVALUATOR_THREAD_SAFE
                 // It's ok to unlock this before locking baseEnv,
                 // as we have no intention to initialize the env.
@@ -1681,21 +1683,23 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
                             removeEach(&newval, diffval);
                     }
                     if (oldval != newval) {
-                        baseEval->valuesRef(dstvar) = newval;
-                        if (super) {
-                            do {
-                                if (dstvar == QLatin1String("QMAKEPATH")) {
-                                    baseEval->m_qmakepath = newval.toQStringList();
-                                    baseEval->updateMkspecPaths();
-                                } else if (dstvar == QLatin1String("QMAKEFEATURES")) {
-                                    baseEval->m_qmakefeatures = newval.toQStringList();
-                                } else {
-                                    break;
-                                }
-                                baseEval->updateFeaturePaths();
-                                if (hostBuild == m_hostBuild)
-                                    m_featureRoots = baseEval->m_featureRoots;
-                            } while (false);
+                        if (target != TargetStash || !m_stashfile.isEmpty()) {
+                            baseEval->valuesRef(dstvar) = newval;
+                            if (target == TargetSuper) {
+                                do {
+                                    if (dstvar == QLatin1String("QMAKEPATH")) {
+                                        baseEval->m_qmakepath = newval.toQStringList();
+                                        baseEval->updateMkspecPaths();
+                                    } else if (dstvar == QLatin1String("QMAKEFEATURES")) {
+                                        baseEval->m_qmakefeatures = newval.toQStringList();
+                                    } else {
+                                        break;
+                                    }
+                                    baseEval->updateFeaturePaths();
+                                    if (hostBuild == m_hostBuild)
+                                        m_featureRoots = baseEval->m_featureRoots;
+                                } while (false);
+                            }
                         }
                         changed = true;
                     }
@@ -1726,14 +1730,14 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
             varstr += QLatin1Char('\n');
         }
         QString fn;
-        if (super) {
+        if (target == TargetSuper) {
             if (m_superfile.isEmpty()) {
                 m_superfile = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.super"));
                 printf("Info: creating super cache file %s\n", qPrintable(m_superfile));
                 valuesRef(ProKey("_QMAKE_SUPER_CACHE_")) << ProString(m_superfile);
             }
             fn = m_superfile;
-        } else {
+        } else if (target == TargetCache) {
             if (m_cachefile.isEmpty()) {
                 m_cachefile = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.cache"));
                 printf("Info: creating cache file %s\n", qPrintable(m_cachefile));
@@ -1745,6 +1749,14 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
                 // The sub-projects will find the new cache all by themselves.
             }
             fn = m_cachefile;
+        } else {
+            fn = m_stashfile;
+            if (fn.isEmpty())
+                fn = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.stash"));
+            if (!m_vfs->exists(fn)) {
+                printf("Info: creating stash file %s\n", qPrintable(fn));
+                valuesRef(ProKey("_QMAKE_STASH_")) << ProString(fn);
+            }
         }
         return writeFile(fL1S("cache "), fn, QIODevice::Append, varstr);
     }
index 3985362..2707553 100644 (file)
@@ -79,19 +79,19 @@ QT_BEGIN_NAMESPACE
 #define fL1S(s) QString::fromLatin1(s)
 
 
-QMakeBaseKey::QMakeBaseKey(const QString &_root, bool _hostBuild)
-    : root(_root), hostBuild(_hostBuild)
+QMakeBaseKey::QMakeBaseKey(const QString &_root, const QString &_stash, bool _hostBuild)
+    : root(_root), stash(_stash), hostBuild(_hostBuild)
 {
 }
 
 uint qHash(const QMakeBaseKey &key)
 {
-    return qHash(key.root) ^ (uint)key.hostBuild;
+    return qHash(key.root) ^ qHash(key.stash) ^ (uint)key.hostBuild;
 }
 
 bool operator==(const QMakeBaseKey &one, const QMakeBaseKey &two)
 {
-    return one.root == two.root && one.hostBuild == two.hostBuild;
+    return one.root == two.root && one.stash == two.stash && one.hostBuild == two.hostBuild;
 }
 
 QMakeBaseEnv::QMakeBaseEnv()
@@ -1144,6 +1144,19 @@ bool QMakeEvaluator::prepareProject(const QString &inDir)
         dir = qdfi.path();
     }
 
+    dir = m_outputDir;
+    forever {
+        QString stashfile = dir + QLatin1String("/.qmake.stash");
+        if (dir == (!superdir.isEmpty() ? superdir : m_buildRoot) || m_vfs->exists(stashfile)) {
+            m_stashfile = QDir::cleanPath(stashfile);
+            break;
+        }
+        QFileInfo qdfi(dir);
+        if (qdfi.isRoot())
+            break;
+        dir = qdfi.path();
+    }
+
     return true;
 }
 
@@ -1258,6 +1271,12 @@ bool QMakeEvaluator::loadSpec()
                 m_cachefile, QMakeHandler::EvalConfigFile, LoadProOnly) != ReturnTrue)
             return false;
     }
+    if (!m_stashfile.isEmpty() && m_vfs->exists(m_stashfile)) {
+        valuesRef(ProKey("_QMAKE_STASH_")) << ProString(m_stashfile);
+        if (evaluateFile(
+                m_stashfile, QMakeHandler::EvalConfigFile, LoadProOnly) != ReturnTrue)
+            return false;
+    }
     return true;
 }
 
@@ -1335,7 +1354,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile(
 #ifdef PROEVALUATOR_THREAD_SAFE
         m_option->mutex.lock();
 #endif
-        QMakeBaseEnv **baseEnvPtr = &m_option->baseEnvs[QMakeBaseKey(m_buildRoot, m_hostBuild)];
+        QMakeBaseEnv **baseEnvPtr = &m_option->baseEnvs[QMakeBaseKey(m_buildRoot, m_stashfile, m_hostBuild)];
         if (!*baseEnvPtr)
             *baseEnvPtr = new QMakeBaseEnv;
         QMakeBaseEnv *baseEnv = *baseEnvPtr;
@@ -1362,6 +1381,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile(
             baseEval->m_superfile = m_superfile;
             baseEval->m_conffile = m_conffile;
             baseEval->m_cachefile = m_cachefile;
+            baseEval->m_stashfile = m_stashfile;
             baseEval->m_sourceRoot = m_sourceRoot;
             baseEval->m_buildRoot = m_buildRoot;
             baseEval->m_hostBuild = m_hostBuild;
index c1ba65e..0cb2ccf 100644 (file)
@@ -300,6 +300,7 @@ public:
     QString m_superfile;
     QString m_conffile;
     QString m_cachefile;
+    QString m_stashfile;
     QString m_sourceRoot;
     QString m_buildRoot;
     QStringList m_qmakepath;
index 8fcffab..6a7b437 100644 (file)
@@ -66,9 +66,10 @@ class QMakeEvaluator;
 class QMakeBaseKey
 {
 public:
-    QMakeBaseKey(const QString &_root, bool _hostBuild);
+    QMakeBaseKey(const QString &_root, const QString &_stash, bool _hostBuild);
 
     QString root;
+    QString stash;
     bool hostBuild;
 };