Commit 5bd33a79 authored by Oswald Buddenhagen's avatar Oswald Buddenhagen
Browse files

add cache() function



follow suit with qmake ...

Change-Id: I8be9b0ecdc45c6358fe00d03ea5d9e77c631c3bb
Reviewed-by: default avatarJoerg Bornemann <joerg.bornemann@nokia.com>
Reviewed-by: default avatarOswald Buddenhagen <oswald.buddenhagen@nokia.com>
parent 48e09230
......@@ -90,7 +90,7 @@ enum TestFunc {
T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM,
T_RETURN, T_BREAK, T_NEXT, T_DEFINED, T_CONTAINS, T_INFILE,
T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_LOG, T_MESSAGE, T_WARNING, T_ERROR, T_IF,
T_MKPATH, T_WRITE_FILE, T_TOUCH
T_MKPATH, T_WRITE_FILE, T_TOUCH, T_CACHE
};
void QMakeEvaluator::initFunctionStatics()
......@@ -178,6 +178,7 @@ void QMakeEvaluator::initFunctionStatics()
{ "mkpath", T_MKPATH },
{ "write_file", T_WRITE_FILE },
{ "touch", T_TOUCH },
{ "cache", T_CACHE },
};
for (unsigned i = 0; i < sizeof(testInits)/sizeof(testInits[0]); ++i)
statics.functions.insert(ProString(testInits[i].name), testInits[i].func);
......@@ -1525,6 +1526,137 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction(
#endif
return ReturnTrue;
}
case T_CACHE: {
if (args.count() > 3) {
evalError(fL1S("cache(var, [set|add|sub] [transient] [super], [srcvar]) requires one to three arguments."));
return ReturnFalse;
}
bool persist = true;
bool super = false;
enum { CacheSet, CacheAdd, CacheSub } mode = CacheSet;
ProString srcvar;
if (args.count() >= 2) {
foreach (const ProString &opt, split_value_list(args.at(1).toQString(m_tmp2))) {
opt.toQString(m_tmp3);
if (m_tmp3 == QLatin1String("transient")) {
persist = false;
} else if (m_tmp3 == QLatin1String("super")) {
super = true;
} else if (m_tmp3 == QLatin1String("set")) {
mode = CacheSet;
} else if (m_tmp3 == QLatin1String("add")) {
mode = CacheAdd;
} else if (m_tmp3 == QLatin1String("sub")) {
mode = CacheSub;
} else {
evalError(fL1S("cache(): invalid flag %1.").arg(m_tmp3));
return ReturnFalse;
}
}
if (args.count() >= 3) {
srcvar = args.at(2);
} else if (mode != CacheSet) {
evalError(fL1S("cache(): modes other than 'set' require a source variable."));
return ReturnFalse;
}
}
QString varstr;
ProString dstvar = args.at(0);
if (!dstvar.isEmpty()) {
if (srcvar.isEmpty())
srcvar = dstvar;
ProValueMap::Iterator srcvarIt;
if (!findValues(srcvar, &srcvarIt)) {
evalError(fL1S("Variable %1 is not defined.").arg(srcvar.toQString(m_tmp1)));
return ReturnFalse;
}
// The caches for the host and target may differ (e.g., when we are manipulating
// CONFIG), so we cannot compute a common new value for both.
const ProStringList &diffval = *srcvarIt;
ProStringList newval;
bool changed = false;
for (bool hostBuild = false; ; hostBuild = true) {
if (QMakeBaseEnv *baseEnv = m_option->baseEnvs.value(
QMakeBaseKey(m_buildRoot, hostBuild))) {
QMakeEvaluator *baseEval = baseEnv->evaluator;
const ProStringList &oldval = baseEval->values(dstvar);
if (mode == CacheSet) {
newval = diffval;
} else {
newval = oldval;
if (mode == CacheAdd)
newval += diffval;
else
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);
}
changed = true;
}
}
if (hostBuild)
break;
}
// We assume that whatever got the cached value to be what it is now will do so
// the next time as well, so we just skip the persisting if nothing changed.
if (!persist || !changed)
return ReturnTrue;
varstr = dstvar.toQString();
if (mode == CacheAdd)
varstr += QLatin1String(" +=");
else if (mode == CacheSub)
varstr += QLatin1String(" -=");
else
varstr += QLatin1String(" =");
if (diffval.count() == 1) {
varstr += QLatin1Char(' ');
varstr += quoteValue(diffval.at(0));
} else if (!diffval.isEmpty()) {
foreach (const ProString &vval, diffval) {
varstr += QLatin1String(" \\\n ");
varstr += quoteValue(vval);
}
}
varstr += QLatin1Char('\n');
}
QString fn;
if (super) {
if (m_superfile.isEmpty()) {
m_superfile = m_outputDir + QLatin1String("/.qmake.super");
printf("Info: creating super cache file %s\n", qPrintable(m_superfile));
valuesRef(ProString("_QMAKE_SUPER_CACHE_")) << ProString(m_superfile, NoHash);
}
fn = m_superfile;
} else {
if (m_cachefile.isEmpty()) {
m_cachefile = m_outputDir + QLatin1String("/.qmake.cache");
printf("Info: creating cache file %s\n", qPrintable(m_cachefile));
valuesRef(ProString("_QMAKE_CACHE_")) << ProString(m_cachefile, NoHash);
// We could update m_{source,build}Root and m_featureRoots here, or even
// "re-home" our rootEnv, but this doesn't sound too useful - if somebody
// wanted qmake to find something in the build directory, he could have
// done so "from the outside".
// The sub-projects will find the new cache all by themselves.
}
fn = m_cachefile;
}
return writeFile(fL1S("cache "), fn, QIODevice::Append, varstr);
}
#endif
case T_INVALID:
evalError(fL1S("'%1' is not a recognized test function.")
......
......@@ -315,7 +315,7 @@ static void removeAll(ProStringList *varlist, const ProString &value)
varlist->remove(i);
}
static void removeEach(ProStringList *varlist, const ProStringList &value)
void QMakeEvaluator::removeEach(ProStringList *varlist, const ProStringList &value)
{
foreach (const ProString &str, value)
if (!str.isEmpty())
......
......@@ -31,6 +31,10 @@
#ifndef QMAKEEVALUATOR_H
#define QMAKEEVALUATOR_H
#if defined(PROEVALUATOR_FULL) && defined(PROEVALUATOR_THREAD_SAFE)
# error PROEVALUATOR_FULL is incompatible with PROEVALUATOR_THREAD_SAFE due to cache() implementation
#endif
#include "qmakeparser.h"
#include "ioutils.h"
......@@ -188,6 +192,8 @@ public:
#endif
QByteArray getCommandOutput(const QString &args) const;
static void removeEach(ProStringList *varlist, const ProStringList &value);
int m_loopLevel; // To report unexpected break() and next()s
#ifdef PROEVALUATOR_CUMULATIVE
bool m_cumulative;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment