add discard_from() function
this function discards all values that come from a specific file. it will be needed for configure bootstrapping, but is too obscure to document it for general use. Change-Id: I62c18aeb1847712e33d0599dbb0b90ffa1722438 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
parent
6a9f38a11d
commit
12bb328bb0
@ -52,6 +52,8 @@
|
|||||||
# include <qthreadpool.h>
|
# include <qthreadpool.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <utime.h>
|
#include <utime.h>
|
||||||
@ -97,7 +99,7 @@ enum ExpandFunc {
|
|||||||
enum TestFunc {
|
enum TestFunc {
|
||||||
T_INVALID = 0, T_REQUIRES, T_GREATERTHAN, T_LESSTHAN, T_EQUALS,
|
T_INVALID = 0, T_REQUIRES, T_GREATERTHAN, T_LESSTHAN, T_EQUALS,
|
||||||
T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM,
|
T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM,
|
||||||
T_DEFINED, T_CONTAINS, T_INFILE,
|
T_DEFINED, T_DISCARD_FROM, T_CONTAINS, T_INFILE,
|
||||||
T_COUNT, T_ISEMPTY, T_PARSE_JSON, T_INCLUDE, T_LOAD, T_DEBUG, T_LOG, T_MESSAGE, T_WARNING, T_ERROR, T_IF,
|
T_COUNT, T_ISEMPTY, T_PARSE_JSON, T_INCLUDE, T_LOAD, T_DEBUG, T_LOG, T_MESSAGE, T_WARNING, T_ERROR, T_IF,
|
||||||
T_MKPATH, T_WRITE_FILE, T_TOUCH, T_CACHE
|
T_MKPATH, T_WRITE_FILE, T_TOUCH, T_CACHE
|
||||||
};
|
};
|
||||||
@ -178,6 +180,7 @@ void QMakeEvaluator::initFunctionStatics()
|
|||||||
{ "if", T_IF },
|
{ "if", T_IF },
|
||||||
{ "isActiveConfig", T_CONFIG },
|
{ "isActiveConfig", T_CONFIG },
|
||||||
{ "system", T_SYSTEM },
|
{ "system", T_SYSTEM },
|
||||||
|
{ "discard_from", T_DISCARD_FROM },
|
||||||
{ "defined", T_DEFINED },
|
{ "defined", T_DEFINED },
|
||||||
{ "contains", T_CONTAINS },
|
{ "contains", T_CONTAINS },
|
||||||
{ "infile", T_INFILE },
|
{ "infile", T_INFILE },
|
||||||
@ -1292,6 +1295,38 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
|||||||
}
|
}
|
||||||
return ReturnTrue;
|
return ReturnTrue;
|
||||||
}
|
}
|
||||||
|
case T_DISCARD_FROM: {
|
||||||
|
if (args.count() != 1 || args.at(0).isEmpty()) {
|
||||||
|
evalError(fL1S("discard_from(file) requires one argument."));
|
||||||
|
return ReturnFalse;
|
||||||
|
}
|
||||||
|
if (m_valuemapStack.count() != 1) {
|
||||||
|
evalError(fL1S("discard_from() cannot be called from functions."));
|
||||||
|
return ReturnFalse;
|
||||||
|
}
|
||||||
|
QString fn = resolvePath(args.at(0).toQString(m_tmp1));
|
||||||
|
ProFile *pro = m_parser->parsedProFile(fn, QMakeParser::ParseOnlyCached);
|
||||||
|
if (!pro)
|
||||||
|
return ReturnFalse;
|
||||||
|
ProValueMap &vmap = m_valuemapStack.first();
|
||||||
|
for (auto vit = vmap.begin(); vit != vmap.end(); ) {
|
||||||
|
if (!vit->isEmpty()) {
|
||||||
|
auto isFrom = [pro](const ProString &s) {
|
||||||
|
return s.sourceFile() == pro;
|
||||||
|
};
|
||||||
|
vit->erase(std::remove_if(vit->begin(), vit->end(), isFrom), vit->end());
|
||||||
|
if (vit->isEmpty()) {
|
||||||
|
// When an initially non-empty variable becomes entirely empty,
|
||||||
|
// undefine it altogether.
|
||||||
|
vit = vmap.erase(vit);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++vit;
|
||||||
|
}
|
||||||
|
pro->deref();
|
||||||
|
return ReturnTrue;
|
||||||
|
}
|
||||||
case T_INFILE:
|
case T_INFILE:
|
||||||
if (args.count() < 2 || args.count() > 3) {
|
if (args.count() < 2 || args.count() > 3) {
|
||||||
evalError(fL1S("infile(file, var, [values]) requires two or three arguments."));
|
evalError(fL1S("infile(file, var, [values]) requires two or three arguments."));
|
||||||
|
@ -165,7 +165,7 @@ QMakeParser::QMakeParser(ProFileCache *cache, QMakeVfs *vfs, QMakeParserHandler
|
|||||||
ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
|
ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
|
||||||
{
|
{
|
||||||
ProFile *pro;
|
ProFile *pro;
|
||||||
if ((flags & ParseUseCache) && m_cache) {
|
if ((flags & (ParseUseCache|ParseOnlyCached)) && m_cache) {
|
||||||
ProFileCache::Entry *ent;
|
ProFileCache::Entry *ent;
|
||||||
#ifdef PROPARSER_THREAD_SAFE
|
#ifdef PROPARSER_THREAD_SAFE
|
||||||
QMutexLocker locker(&m_cache->mutex);
|
QMutexLocker locker(&m_cache->mutex);
|
||||||
@ -187,7 +187,7 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
|
|||||||
#endif
|
#endif
|
||||||
if ((pro = ent->pro))
|
if ((pro = ent->pro))
|
||||||
pro->ref();
|
pro->ref();
|
||||||
} else {
|
} else if (!(flags & ParseOnlyCached)) {
|
||||||
ent = &m_cache->parsed_files[fileName];
|
ent = &m_cache->parsed_files[fileName];
|
||||||
#ifdef PROPARSER_THREAD_SAFE
|
#ifdef PROPARSER_THREAD_SAFE
|
||||||
ent->locker = new ProFileCache::Entry::Locker;
|
ent->locker = new ProFileCache::Entry::Locker;
|
||||||
@ -212,13 +212,17 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
|
|||||||
ent->locker = 0;
|
ent->locker = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
pro = 0;
|
||||||
|
}
|
||||||
|
} else if (!(flags & ParseOnlyCached)) {
|
||||||
pro = new ProFile(fileName);
|
pro = new ProFile(fileName);
|
||||||
if (!read(pro, flags)) {
|
if (!read(pro, flags)) {
|
||||||
delete pro;
|
delete pro;
|
||||||
pro = 0;
|
pro = 0;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
pro = 0;
|
||||||
}
|
}
|
||||||
return pro;
|
return pro;
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,8 @@ public:
|
|||||||
enum ParseFlag {
|
enum ParseFlag {
|
||||||
ParseDefault = 0,
|
ParseDefault = 0,
|
||||||
ParseUseCache = 1,
|
ParseUseCache = 1,
|
||||||
ParseReportMissing = 2
|
ParseOnlyCached = 2,
|
||||||
|
ParseReportMissing = 4
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(ParseFlags, ParseFlag)
|
Q_DECLARE_FLAGS(ParseFlags, ParseFlag)
|
||||||
|
|
||||||
|
@ -2325,6 +2325,18 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
|
|||||||
<< "##:1: load(feature) requires one or two arguments."
|
<< "##:1: load(feature) requires one or two arguments."
|
||||||
<< true;
|
<< true;
|
||||||
|
|
||||||
|
QTest::newRow("discard_from()")
|
||||||
|
<< "HERE = 1\nPLUS = one\ninclude(include/inc.pri)\ndiscard_from(include/inc.pri): OK = 1"
|
||||||
|
<< "OK = 1\nHERE = 1\nPLUS = one\nVAR = UNDEF"
|
||||||
|
<< ""
|
||||||
|
<< true;
|
||||||
|
|
||||||
|
QTest::newRow("discard_from(): bad number of arguments")
|
||||||
|
<< "discard_from(1, 2): OK = 1"
|
||||||
|
<< "OK = UNDEF"
|
||||||
|
<< "##:1: discard_from(file) requires one argument."
|
||||||
|
<< true;
|
||||||
|
|
||||||
// We don't test debug() and log(), because they print directly to stderr.
|
// We don't test debug() and log(), because they print directly to stderr.
|
||||||
|
|
||||||
QTest::newRow("message()")
|
QTest::newRow("message()")
|
||||||
@ -2744,7 +2756,8 @@ void tst_qmakelib::proEval()
|
|||||||
QMakeTestHandler handler;
|
QMakeTestHandler handler;
|
||||||
handler.setExpectedMessages(msgs.replace("##:", infile + ':').split('\n', QString::SkipEmptyParts));
|
handler.setExpectedMessages(msgs.replace("##:", infile + ':').split('\n', QString::SkipEmptyParts));
|
||||||
QMakeVfs vfs;
|
QMakeVfs vfs;
|
||||||
QMakeParser parser(0, &vfs, &handler);
|
ProFileCache cache;
|
||||||
|
QMakeParser parser(&cache, &vfs, &handler);
|
||||||
QMakeGlobals globals;
|
QMakeGlobals globals;
|
||||||
globals.do_cache = false;
|
globals.do_cache = false;
|
||||||
globals.xqmakespec = "fake-g++";
|
globals.xqmakespec = "fake-g++";
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
VAR = val
|
VAR = val
|
||||||
.VAR = nope
|
.VAR = nope
|
||||||
|
|
||||||
|
PLUS += more
|
||||||
|
|
||||||
fake-*: MATCH = 1
|
fake-*: MATCH = 1
|
||||||
|
|
||||||
defineTest(func) {
|
defineTest(func) {
|
||||||
|
Loading…
Reference in New Issue
Block a user