aboutsummaryrefslogtreecommitdiffstats
path: root/src/shared
diff options
context:
space:
mode:
authorOrgad Shaneh <orgad.shaneh@audiocodes.com>2016-11-02 16:52:58 +0200
committerOrgad Shaneh <orgad.shaneh@audiocodes.com>2016-11-02 16:52:58 +0200
commit410211e0907f5d31c8fd3bceb362801bb4d108d5 (patch)
tree186ed812fddc8ff5e6337acc6161e66e226e39a2 /src/shared
parent7b70c307501771bd26d189d43156dc308b7217c5 (diff)
parent63bed77178786091a3a490220582a23520352816 (diff)
Merge remote-tracking branch 'origin/4.2'
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/proparser/ioutils.cpp2
-rw-r--r--src/shared/proparser/ioutils.h4
-rw-r--r--src/shared/proparser/objective_c.prf12
-rw-r--r--src/shared/proparser/profileevaluator.cpp90
-rw-r--r--src/shared/proparser/profileevaluator.h26
-rw-r--r--src/shared/proparser/proparser.pri2
-rw-r--r--src/shared/proparser/proparser.qrc3
-rw-r--r--src/shared/proparser/qmakebuiltins.cpp15
-rw-r--r--src/shared/proparser/qmakeevaluator.cpp51
-rw-r--r--src/shared/proparser/qmakeevaluator.h3
-rw-r--r--src/shared/proparser/qmakeparser.cpp51
-rw-r--r--src/shared/proparser/qmakeparser.h10
-rw-r--r--src/shared/proparser/qmakevfs.cpp93
-rw-r--r--src/shared/proparser/qmakevfs.h35
14 files changed, 274 insertions, 123 deletions
diff --git a/src/shared/proparser/ioutils.cpp b/src/shared/proparser/ioutils.cpp
index 57b2812c8f..4239d6ba5c 100644
--- a/src/shared/proparser/ioutils.cpp
+++ b/src/shared/proparser/ioutils.cpp
@@ -52,7 +52,7 @@ IoUtils::FileType IoUtils::fileType(const QString &fileName)
struct ::stat st;
if (::stat(fileName.toLocal8Bit().constData(), &st))
return FileNotFound;
- return S_ISDIR(st.st_mode) ? FileIsDir : FileIsRegular;
+ return S_ISDIR(st.st_mode) ? FileIsDir : S_ISREG(st.st_mode) ? FileIsRegular : FileNotFound;
#endif
}
diff --git a/src/shared/proparser/ioutils.h b/src/shared/proparser/ioutils.h
index f4fd79f32d..d7fc596b0d 100644
--- a/src/shared/proparser/ioutils.h
+++ b/src/shared/proparser/ioutils.h
@@ -25,6 +25,8 @@
#pragma once
+#include "qmake_global.h"
+
#include <qstring.h>
QT_BEGIN_NAMESPACE
@@ -35,7 +37,7 @@ namespace QMakeInternal {
This class provides replacement functionality for QFileInfo, QFile & QDir,
as these are abysmally slow.
*/
-class IoUtils {
+class QMAKE_EXPORT IoUtils {
public:
enum FileType {
FileNotFound = 0,
diff --git a/src/shared/proparser/objective_c.prf b/src/shared/proparser/objective_c.prf
new file mode 100644
index 0000000000..ed1ad8ad38
--- /dev/null
+++ b/src/shared/proparser/objective_c.prf
@@ -0,0 +1,12 @@
+
+# Objective-C/C++ sources go in SOURCES, like all other sources
+SOURCES += $$OBJECTIVE_SOURCES
+unset(OBJECTIVE_SOURCES)
+
+# Strip C/C++ flags from QMAKE_OBJECTIVE_CFLAGS just in case
+QMAKE_OBJECTIVE_CFLAGS -= $$QMAKE_CFLAGS $$QMAKE_CXXFLAGS
+
+# Add Objective-C/C++ flags to C/C++ flags, the compiler can handle it
+QMAKE_CFLAGS += $$QMAKE_OBJECTIVE_CFLAGS
+QMAKE_CXXFLAGS += $$QMAKE_OBJECTIVE_CFLAGS
+unset(QMAKE_OBJECTIVE_CFLAGS)
diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp
index 50bf4a89cf..f60c6afa2c 100644
--- a/src/shared/proparser/profileevaluator.cpp
+++ b/src/shared/proparser/profileevaluator.cpp
@@ -26,6 +26,7 @@
#include "profileevaluator.h"
#include "qmakeglobals.h"
+#include "qmakevfs.h"
#include "ioutils.h"
#include <QDir>
@@ -39,9 +40,10 @@ void ProFileEvaluator::initialize()
QMakeEvaluator::initStatics();
}
-ProFileEvaluator::ProFileEvaluator(ProFileGlobals *option, QMakeParser *parser, QMakeVfs *vfs,
+ProFileEvaluator::ProFileEvaluator(QMakeGlobals *option, QMakeParser *parser, QMakeVfs *vfs,
QMakeHandler *handler)
- : d(new QMakeEvaluator(option, parser, vfs, handler))
+ : d(new QMakeEvaluator(option, parser, vfs, handler)),
+ m_vfs(vfs)
{
}
@@ -74,75 +76,80 @@ QStringList ProFileEvaluator::values(const QString &variableName) const
return ret;
}
-QStringList ProFileEvaluator::values(const QString &variableName, const ProFile *pro) const
+QVector<ProFileEvaluator::SourceFile> ProFileEvaluator::fixifiedValues(
+ const QString &variable, const QString &baseDirectory, const QString &buildDirectory) 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;
+ 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 << SourceFile{ el, str.sourceFile() };
+ } else {
+ QString fn = QDir::cleanPath(baseDirectory + QLatin1Char('/') + el);
+ if (IoUtils::exists(fn))
+ result << SourceFile{ fn, str.sourceFile() };
+ else
+ result << SourceFile{ QDir::cleanPath(buildDirectory + QLatin1Char('/') + el),
+ str.sourceFile() };
+ }
+ }
+ return result;
}
-QString ProFileEvaluator::sysrootify(const QString &path, const QString &baseDir) const
+QStringList ProFileEvaluator::sourcesToFiles(const QVector<ProFileEvaluator::SourceFile> &sources)
{
- ProFileGlobals *option = static_cast<ProFileGlobals *>(d->m_option);
-#ifdef Q_OS_WIN
- Qt::CaseSensitivity cs = Qt::CaseInsensitive;
-#else
- Qt::CaseSensitivity cs = Qt::CaseSensitive;
-#endif
- const bool isHostSystemPath =
- option->sysroot.isEmpty() || path.startsWith(option->sysroot, cs)
- || path.startsWith(baseDir, cs) || path.startsWith(d->m_outputDir, cs)
- || !QFileInfo::exists(option->sysroot + path);
-
- return isHostSystemPath ? path : option->sysroot + path;
+ 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
{
QStringList result;
foreach (const QString &el, values(variable)) {
- QString absEl = IoUtils::isAbsolutePath(el)
- ? sysrootify(el, baseDirectory) : IoUtils::resolvePath(baseDirectory, el);
+ QString absEl = IoUtils::resolvePath(baseDirectory, el);
if (IoUtils::fileType(absEl) == IoUtils::FileIsDir)
- result << QDir::cleanPath(absEl);
+ result << absEl;
}
return result;
}
-QStringList ProFileEvaluator::absoluteFileValues(
+QVector<ProFileEvaluator::SourceFile> ProFileEvaluator::absoluteFileValues(
const QString &variable, const QString &baseDirectory, const QStringList &searchDirs,
- const ProFile *pro) const
+ QHash<ProString, bool> *handled) const
{
- QStringList result;
- foreach (const QString &el, pro ? values(variable, pro) : values(variable)) {
+ QMakeVfs::VfsFlags flags = (d->m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
+ QVector<SourceFile> result;
+ foreach (const ProString &str, d->values(ProKey(variable))) {
+ bool &seen = (*handled)[str];
+ if (seen)
+ continue;
+ seen = true;
+ const QString &el = d->m_option->expandEnvVars(str.toQString());
QString absEl;
if (IoUtils::isAbsolutePath(el)) {
- const QString elWithSysroot = sysrootify(el, baseDirectory);
- if (IoUtils::exists(elWithSysroot)) {
- result << QDir::cleanPath(elWithSysroot);
+ if (m_vfs->exists(el, flags)) {
+ result << SourceFile{ el, str.sourceFile() };
goto next;
}
- absEl = elWithSysroot;
+ absEl = el;
} else {
foreach (const QString &dir, searchDirs) {
- QString fn = dir + QLatin1Char('/') + el;
- if (IoUtils::exists(fn)) {
- result << QDir::cleanPath(fn);
+ QString fn = QDir::cleanPath(dir + QLatin1Char('/') + el);
+ if (m_vfs->exists(fn, flags)) {
+ result << SourceFile{ QDir::cleanPath(fn), str.sourceFile() };
goto next;
}
}
if (baseDirectory.isEmpty())
goto next;
- absEl = baseDirectory + QLatin1Char('/') + el;
+ absEl = QDir::cleanPath(baseDirectory + QLatin1Char('/') + el);
}
{
- absEl = QDir::cleanPath(absEl);
int nameOff = absEl.lastIndexOf(QLatin1Char('/'));
QString absDir = d->m_tmp1.setRawData(absEl.constData(), nameOff);
if (IoUtils::exists(absDir)) {
@@ -151,9 +158,10 @@ QStringList ProFileEvaluator::absoluteFileValues(
if (wildcard.contains(QLatin1Char('*')) || wildcard.contains(QLatin1Char('?'))) {
wildcard.detach(); // Keep m_tmp out of QRegExp's cache
QDir theDir(absDir);
+ theDir.setFilter(theDir.filter() & ~QDir::AllDirs);
foreach (const QString &fn, theDir.entryList(QStringList(wildcard)))
if (fn != QLatin1String(".") && fn != QLatin1String(".."))
- result << absDir + QLatin1Char('/') + fn;
+ result << SourceFile{ absDir + QLatin1Char('/') + fn, str.sourceFile() };
} // else if (acceptMissing)
}
}
diff --git a/src/shared/proparser/profileevaluator.h b/src/shared/proparser/profileevaluator.h
index 27b26081b0..d001c9d7b0 100644
--- a/src/shared/proparser/profileevaluator.h
+++ b/src/shared/proparser/profileevaluator.h
@@ -40,12 +40,6 @@ class QMakeParser;
class QMakeEvaluator;
class QMakeHandler;
-class QMAKE_EXPORT ProFileGlobals : public QMakeGlobals
-{
-public:
- QString sysroot;
-};
-
class QMAKE_EXPORT ProFileEvaluator
{
public:
@@ -59,10 +53,15 @@ public:
TT_Subdirs
};
+ struct SourceFile {
+ QString fileName;
+ const ProFile *proFile;
+ };
+
// Call this from a concurrency-free context
static void initialize();
- ProFileEvaluator(ProFileGlobals *option, QMakeParser *parser, QMakeVfs *vfs,
+ ProFileEvaluator(QMakeGlobals *option, QMakeParser *parser, QMakeVfs *vfs,
QMakeHandler *handler);
~ProFileEvaluator();
@@ -81,17 +80,20 @@ 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;
+ QVector<SourceFile> fixifiedValues(
+ const QString &variable, const QString &baseDirectory, const QString &buildDirectory) const;
QStringList absolutePathValues(const QString &variable, const QString &baseDirectory) const;
- QStringList absoluteFileValues(
+ QVector<SourceFile> absoluteFileValues(
const QString &variable, const QString &baseDirectory, const QStringList &searchDirs,
- const ProFile *pro) const;
+ QHash<ProString, bool> *handled) const;
QString propertyValue(const QString &val) const;
+ static QStringList sourcesToFiles(const QVector<SourceFile> &sources);
private:
- QString sysrootify(const QString &path, const QString &baseDir) const;
-
QMakeEvaluator *d;
+ QMakeVfs *m_vfs;
};
+Q_DECLARE_TYPEINFO(ProFileEvaluator::SourceFile, Q_MOVABLE_TYPE);
+
QT_END_NAMESPACE
diff --git a/src/shared/proparser/proparser.pri b/src/shared/proparser/proparser.pri
index a3667e5291..53ab86cf57 100644
--- a/src/shared/proparser/proparser.pri
+++ b/src/shared/proparser/proparser.pri
@@ -29,4 +29,4 @@ SOURCES += \
ioutils.cpp
RESOURCES += proparser.qrc
-DEFINES += QMAKE_BUILTIN_PRFS
+DEFINES += QMAKE_BUILTIN_PRFS QMAKE_OVERRIDE_PRFS
diff --git a/src/shared/proparser/proparser.qrc b/src/shared/proparser/proparser.qrc
index 9193eaa31c..10f360fa49 100644
--- a/src/shared/proparser/proparser.qrc
+++ b/src/shared/proparser/proparser.qrc
@@ -3,4 +3,7 @@
<file>spec_pre.prf</file>
<file>spec_post.prf</file>
</qresource>
+ <qresource prefix="/qmake/override_features" >
+ <file>objective_c.prf</file>
+ </qresource>
</RCC>
diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp
index 3a8e3b110e..852c40d55d 100644
--- a/src/shared/proparser/qmakebuiltins.cpp
+++ b/src/shared/proparser/qmakebuiltins.cpp
@@ -414,10 +414,10 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::parseJsonInto(const QByteArray &json
QMakeEvaluator::VisitReturn
QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode,
- bool exe, const QString &contents)
+ QMakeVfs::VfsFlags flags, const QString &contents)
{
QString errStr;
- if (!m_vfs->writeFile(fn, mode, exe, contents, &errStr)) {
+ if (!m_vfs->writeFile(fn, mode, flags, contents, &errStr)) {
evalError(fL1S("Cannot write %1file %2: %3")
.arg(ctx, QDir::toNativeSeparators(fn), errStr));
return ReturnFalse;
@@ -1714,7 +1714,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ReturnFalse;
}
QIODevice::OpenMode mode = QIODevice::Truncate;
- bool exe = false;
+ QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
QString contents;
if (args.count() >= 2) {
const ProStringList &vals = values(args.at(1).toKey());
@@ -1727,7 +1727,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
if (m_tmp3 == QLatin1String("append")) {
mode = QIODevice::Append;
} else if (m_tmp3 == QLatin1String("exe")) {
- exe = true;
+ flags |= QMakeVfs::VfsExecutable;
} else {
evalError(fL1S("write_file(): invalid flag %1.").arg(m_tmp3));
return ReturnFalse;
@@ -1737,7 +1737,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
}
QString path = resolvePath(args.at(0).toQString(m_tmp1));
path.detach(); // make sure to not leak m_tmp1 into the map of written files.
- return writeFile(QString(), path, mode, exe, contents);
+ return writeFile(QString(), path, mode, flags, contents);
}
case T_TOUCH: {
if (args.count() != 2) {
@@ -1921,6 +1921,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
varstr += QLatin1Char('\n');
}
QString fn;
+ QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
if (target == TargetSuper) {
if (m_superfile.isEmpty()) {
m_superfile = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.super"));
@@ -1944,12 +1945,12 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
fn = m_stashfile;
if (fn.isEmpty())
fn = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.stash"));
- if (!m_vfs->exists(fn)) {
+ if (!m_vfs->exists(fn, flags)) {
printf("Info: creating stash file %s\n", qPrintable(QDir::toNativeSeparators(fn)));
valuesRef(ProKey("_QMAKE_STASH_")) << ProString(fn);
}
}
- return writeFile(fL1S("cache "), fn, QIODevice::Append, false, varstr);
+ return writeFile(fL1S("cache "), fn, QIODevice::Append, flags, varstr);
}
default:
evalError(fL1S("Function '%1' is not implemented.").arg(function.toQString(m_tmp1)));
diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp
index 3f78878e63..5e318b170d 100644
--- a/src/shared/proparser/qmakeevaluator.cpp
+++ b/src/shared/proparser/qmakeevaluator.cpp
@@ -1082,6 +1082,7 @@ void QMakeEvaluator::loadDefaults()
bool QMakeEvaluator::prepareProject(const QString &inDir)
{
+ QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
QString superdir;
if (m_option->do_cache) {
QString conffile;
@@ -1092,7 +1093,7 @@ bool QMakeEvaluator::prepareProject(const QString &inDir)
superdir = m_outputDir;
forever {
QString superfile = superdir + QLatin1String("/.qmake.super");
- if (m_vfs->exists(superfile)) {
+ if (m_vfs->exists(superfile, flags)) {
m_superfile = QDir::cleanPath(superfile);
break;
}
@@ -1107,10 +1108,10 @@ bool QMakeEvaluator::prepareProject(const QString &inDir)
QString dir = m_outputDir;
forever {
conffile = sdir + QLatin1String("/.qmake.conf");
- if (!m_vfs->exists(conffile))
+ if (!m_vfs->exists(conffile, flags))
conffile.clear();
cachefile = dir + QLatin1String("/.qmake.cache");
- if (!m_vfs->exists(cachefile))
+ if (!m_vfs->exists(cachefile, flags))
cachefile.clear();
if (!conffile.isEmpty() || !cachefile.isEmpty()) {
if (dir != sdir)
@@ -1138,7 +1139,7 @@ bool QMakeEvaluator::prepareProject(const QString &inDir)
QString dir = m_outputDir;
forever {
QString stashfile = dir + QLatin1String("/.qmake.stash");
- if (dir == (!superdir.isEmpty() ? superdir : m_buildRoot) || m_vfs->exists(stashfile)) {
+ if (dir == (!superdir.isEmpty() ? superdir : m_buildRoot) || m_vfs->exists(stashfile, flags)) {
m_stashfile = QDir::cleanPath(stashfile);
break;
}
@@ -1265,7 +1266,8 @@ bool QMakeEvaluator::loadSpec()
m_cachefile, QMakeHandler::EvalConfigFile, LoadProOnly) != ReturnTrue)
return false;
}
- if (!m_stashfile.isEmpty() && m_vfs->exists(m_stashfile)) {
+ QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
+ if (!m_stashfile.isEmpty() && m_vfs->exists(m_stashfile, flags)) {
valuesRef(ProKey("_QMAKE_STASH_")) << ProString(m_stashfile);
if (evaluateFile(
m_stashfile, QMakeHandler::EvalConfigFile, LoadProOnly) != ReturnTrue)
@@ -1951,23 +1953,34 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFeatureFile(
// 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;
+#ifdef QMAKE_OVERRIDE_PRFS
+ {
+ QString ovrfn(QLatin1String(":/qmake/override_features/") + fn);
+ if (QFileInfo::exists(ovrfn)) {
+ fn = ovrfn;
goto cool;
}
}
+#endif
+ {
+ 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;
+ }
+ }
+ }
#ifdef QMAKE_BUILTIN_PRFS
fn.prepend(QLatin1String(":/qmake/features/"));
if (QFileInfo::exists(fn))
diff --git a/src/shared/proparser/qmakeevaluator.h b/src/shared/proparser/qmakeevaluator.h
index 8f7a2072b5..d1e734346b 100644
--- a/src/shared/proparser/qmakeevaluator.h
+++ b/src/shared/proparser/qmakeevaluator.h
@@ -30,6 +30,7 @@
#endif
#include "qmakeparser.h"
+#include "qmakevfs.h"
#include "ioutils.h"
#include <qlist.h>
@@ -232,7 +233,7 @@ public:
VisitReturn parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value);
VisitReturn writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode,
- bool exe, const QString &contents);
+ QMakeVfs::VfsFlags flags, const QString &contents);
#ifndef QT_BOOTSTRAPPED
void runProcess(QProcess *proc, const QString &command) const;
#endif
diff --git a/src/shared/proparser/qmakeparser.cpp b/src/shared/proparser/qmakeparser.cpp
index 429ef3b500..5d1bd71043 100644
--- a/src/shared/proparser/qmakeparser.cpp
+++ b/src/shared/proparser/qmakeparser.cpp
@@ -167,7 +167,13 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
#ifdef PROPARSER_THREAD_SAFE
QMutexLocker locker(&m_cache->mutex);
#endif
- QHash<QString, ProFileCache::Entry>::Iterator it = m_cache->parsed_files.find(fileName);
+ QHash<QString, ProFileCache::Entry>::Iterator it;
+#ifdef PROEVALUATOR_DUAL_VFS
+ QString virtFileName = ((flags & ParseCumulative) ? '-' : '+') + fileName;
+ it = m_cache->parsed_files.find(virtFileName);
+ if (it == m_cache->parsed_files.end())
+#endif
+ it = m_cache->parsed_files.find(fileName);
if (it != m_cache->parsed_files.end()) {
ent = &*it;
#ifdef PROPARSER_THREAD_SAFE
@@ -185,18 +191,27 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
if ((pro = ent->pro))
pro->ref();
} else if (!(flags & ParseOnlyCached)) {
- ent = &m_cache->parsed_files[fileName];
+ QString contents;
+ QMakeVfs::VfsFlags vfsFlags =
+ ((flags & ParseCumulative) ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
+ bool virt = false;
+#ifdef PROEVALUATOR_DUAL_VFS
+ virt = m_vfs->readVirtualFile(fileName, vfsFlags, &contents);
+ if (virt)
+ ent = &m_cache->parsed_files[virtFileName];
+ else
+#endif
+ ent = &m_cache->parsed_files[fileName];
#ifdef PROPARSER_THREAD_SAFE
ent->locker = new ProFileCache::Entry::Locker;
locker.unlock();
#endif
- pro = new ProFile(fileName);
- if (!read(pro, flags)) {
- delete pro;
- pro = 0;
- } else {
+ if (virt || readFile(fileName, vfsFlags | QMakeVfs::VfsNoVirtual, flags, &contents)) {
+ pro = parsedProBlock(QStringRef(&contents), fileName, 1, FullGrammar);
pro->itemsRef()->squeeze();
pro->ref();
+ } else {
+ pro = 0;
}
ent->pro = pro;
#ifdef PROPARSER_THREAD_SAFE
@@ -213,11 +228,13 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
pro = 0;
}
} else if (!(flags & ParseOnlyCached)) {
- pro = new ProFile(fileName);
- if (!read(pro, flags)) {
- delete pro;
+ QString contents;
+ QMakeVfs::VfsFlags vfsFlags =
+ ((flags & ParseCumulative) ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
+ if (readFile(fileName, vfsFlags, flags, &contents))
+ pro = parsedProBlock(QStringRef(&contents), fileName, 1, FullGrammar);
+ else
pro = 0;
- }
} else {
pro = 0;
}
@@ -238,17 +255,17 @@ void QMakeParser::discardFileFromCache(const QString &fileName)
m_cache->discardFile(fileName);
}
-bool QMakeParser::read(ProFile *pro, ParseFlags flags)
+bool QMakeParser::readFile(
+ const QString &fn, QMakeVfs::VfsFlags vfsFlags, ParseFlags flags, QString *contents)
{
- QString content;
QString errStr;
- if (!m_vfs->readFile(pro->fileName(), &content, &errStr)) {
- if (m_handler && ((flags & ParseReportMissing) || m_vfs->exists(pro->fileName())))
+ QMakeVfs::ReadResult result = m_vfs->readFile(fn, vfsFlags, contents, &errStr);
+ if (result != QMakeVfs::ReadOk) {
+ if (m_handler && ((flags & ParseReportMissing) || result != QMakeVfs::ReadNotFound))
m_handler->message(QMakeParserHandler::ParserIoError,
- fL1S("Cannot read %1: %2").arg(pro->fileName(), errStr));
+ fL1S("Cannot read %1: %2").arg(fn, errStr));
return false;
}
- read(pro, QStringRef(&content), 1, FullGrammar);
return true;
}
diff --git a/src/shared/proparser/qmakeparser.h b/src/shared/proparser/qmakeparser.h
index 07a9f07753..43fa354b9e 100644
--- a/src/shared/proparser/qmakeparser.h
+++ b/src/shared/proparser/qmakeparser.h
@@ -26,6 +26,7 @@
#pragma once
#include "qmake_global.h"
+#include "qmakevfs.h"
#include "proitems.h"
#include <qhash.h>
@@ -75,7 +76,12 @@ public:
ParseDefault = 0,
ParseUseCache = 1,
ParseOnlyCached = 2,
- ParseReportMissing = 4
+ ParseReportMissing = 4,
+#ifdef PROEVALUATOR_DUAL_VFS
+ ParseCumulative = 8
+#else
+ ParseCumulative = 0
+#endif
};
Q_DECLARE_FLAGS(ParseFlags, ParseFlag)
@@ -126,7 +132,7 @@ private:
ushort terminator; // '}' if replace function call is braced, ':' if test function
};
- bool read(ProFile *pro, ParseFlags flags);
+ bool readFile(const QString &fn, QMakeVfs::VfsFlags vfsFlags, QMakeParser::ParseFlags flags, QString *contents);
void read(ProFile *pro, const QStringRef &content, int line, SubGrammar grammar);
ALWAYS_INLINE void putTok(ushort *&tokPtr, ushort tok);
diff --git a/src/shared/proparser/qmakevfs.cpp b/src/shared/proparser/qmakevfs.cpp
index 0231fa9a46..6115a02457 100644
--- a/src/shared/proparser/qmakevfs.cpp
+++ b/src/shared/proparser/qmakevfs.cpp
@@ -44,20 +44,24 @@ QMakeVfs::QMakeVfs()
{
}
-bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe,
+bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, VfsFlags flags,
const QString &contents, QString *errStr)
{
#ifndef PROEVALUATOR_FULL
# ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&m_mutex);
# endif
+#ifdef PROEVALUATOR_DUAL_VFS
+ QString *cont = &m_files[((flags & VfsCumulative) ? '-' : '+') + fn];
+#else
QString *cont = &m_files[fn];
+ Q_UNUSED(flags)
+#endif
if (mode & QIODevice::Append)
*cont += contents;
else
*cont = contents;
Q_UNUSED(errStr)
- Q_UNUSED(exe)
return true;
#else
QFileInfo qfi(fn);
@@ -69,7 +73,7 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe,
QFile cfile(fn);
if (!(mode & QIODevice::Append) && cfile.open(QIODevice::ReadOnly | QIODevice::Text)) {
if (cfile.readAll() == bytes) {
- if (exe) {
+ if (flags & VfsExecutable) {
cfile.setPermissions(cfile.permissions()
| QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther);
} else {
@@ -90,42 +94,85 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe,
*errStr = cfile.errorString();
return false;
}
- if (exe)
+ if (flags & VfsExecutable)
cfile.setPermissions(cfile.permissions()
| QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther);
return true;
#endif
}
-bool QMakeVfs::readFile(const QString &fn, QString *contents, QString *errStr)
+#ifndef PROEVALUATOR_FULL
+bool QMakeVfs::readVirtualFile(const QString &fn, VfsFlags flags, QString *contents)
+{
+# ifdef PROEVALUATOR_THREAD_SAFE
+ QMutexLocker locker(&m_mutex);
+# endif
+ QHash<QString, QString>::ConstIterator it;
+# ifdef PROEVALUATOR_DUAL_VFS
+ it = m_files.constFind(((flags & VfsCumulative) ? '-' : '+') + fn);
+ if (it != m_files.constEnd()) {
+ *contents = *it;
+ return true;
+ }
+# else
+ it = m_files.constFind(fn);
+ if (it != m_files.constEnd()
+ && it->constData() != m_magicMissing.constData()
+ && it->constData() != m_magicExisting.constData()) {
+ *contents = *it;
+ return true;
+ }
+ Q_UNUSED(flags)
+# endif
+ return false;
+}
+#endif
+
+QMakeVfs::ReadResult QMakeVfs::readFile(
+ const QString &fn, VfsFlags flags, QString *contents, QString *errStr)
{
#ifndef PROEVALUATOR_FULL
# ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&m_mutex);
# endif
- QHash<QString, QString>::ConstIterator it = m_files.constFind(fn);
+ QHash<QString, QString>::ConstIterator it;
+# ifdef PROEVALUATOR_DUAL_VFS
+ if (!(flags & VfsNoVirtual)) {
+ it = m_files.constFind(((flags & VfsCumulative) ? '-' : '+') + fn);
+ if (it != m_files.constEnd()) {
+ *contents = *it;
+ return ReadOk;
+ }
+ }
+# else
+ Q_UNUSED(flags)
+# endif
+ it = m_files.constFind(fn);
if (it != m_files.constEnd()) {
if (it->constData() == m_magicMissing.constData()) {
*errStr = fL1S("No such file or directory");
- return false;
+ return ReadNotFound;
}
if (it->constData() != m_magicExisting.constData()) {
*contents = *it;
- return true;
+ return ReadOk;
}
}
+#else
+ Q_UNUSED(flags)
#endif
QFile file(fn);
if (!file.open(QIODevice::ReadOnly)) {
+ if (!file.exists()) {
#ifndef PROEVALUATOR_FULL
- if (!IoUtils::exists(fn)) {
m_files[fn] = m_magicMissing;
- *errStr = fL1S("No such file or directory");
- } else
#endif
- *errStr = file.errorString();
- return false;
+ *errStr = fL1S("No such file or directory");
+ return ReadNotFound;
+ }
+ *errStr = file.errorString();
+ return ReadOtherError;
}
#ifndef PROEVALUATOR_FULL
m_files[fn] = m_magicExisting;
@@ -135,23 +182,33 @@ bool QMakeVfs::readFile(const QString &fn, QString *contents, QString *errStr)
if (bcont.startsWith("\xef\xbb\xbf")) {
// UTF-8 BOM will cause subtle errors
*errStr = fL1S("Unexpected UTF-8 BOM");
- return false;
+ return ReadOtherError;
}
*contents = QString::fromLocal8Bit(bcont);
- return true;
+ return ReadOk;
}
-bool QMakeVfs::exists(const QString &fn)
+bool QMakeVfs::exists(const QString &fn, VfsFlags flags)
{
#ifndef PROEVALUATOR_FULL
# ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&m_mutex);
# endif
- QHash<QString, QString>::ConstIterator it = m_files.constFind(fn);
+ QHash<QString, QString>::ConstIterator it;
+# ifdef PROEVALUATOR_DUAL_VFS
+ it = m_files.constFind(((flags & VfsCumulative) ? '-' : '+') + fn);
+ if (it != m_files.constEnd())
+ return true;
+# else
+ Q_UNUSED(flags)
+# endif
+ it = m_files.constFind(fn);
if (it != m_files.constEnd())
return it->constData() != m_magicMissing.constData();
+#else
+ Q_UNUSED(flags)
#endif
- bool ex = IoUtils::exists(fn);
+ bool ex = IoUtils::fileType(fn) == IoUtils::FileIsRegular;
#ifndef PROEVALUATOR_FULL
m_files[fn] = ex ? m_magicExisting : m_magicMissing;
#endif
diff --git a/src/shared/proparser/qmakevfs.h b/src/shared/proparser/qmakevfs.h
index 3ffe67c1ba..02c0a6406b 100644
--- a/src/shared/proparser/qmakevfs.h
+++ b/src/shared/proparser/qmakevfs.h
@@ -36,18 +36,45 @@
# endif
#endif
+#ifdef PROEVALUATOR_DUAL_VFS
+# ifndef PROEVALUATOR_CUMULATIVE
+# error PROEVALUATOR_DUAL_VFS requires PROEVALUATOR_CUMULATIVE
+# endif
+#endif
+
QT_BEGIN_NAMESPACE
class QMAKE_EXPORT QMakeVfs
{
public:
+ enum ReadResult {
+ ReadOk,
+ ReadNotFound,
+ ReadOtherError
+ };
+
+ enum VfsFlag {
+ VfsExecutable = 1,
+ VfsExact = 0,
+#ifdef PROEVALUATOR_DUAL_VFS
+ VfsCumulative = 2,
+ VfsNoVirtual = 4
+#else
+ VfsCumulative = 0,
+ VfsNoVirtual = 0
+#endif
+ };
+ Q_DECLARE_FLAGS(VfsFlags, VfsFlag)
+
QMakeVfs();
- bool writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe, const QString &contents, QString *errStr);
- bool readFile(const QString &fn, QString *contents, QString *errStr);
- bool exists(const QString &fn);
+ bool writeFile(const QString &fn, QIODevice::OpenMode mode, VfsFlags flags, const QString &contents, QString *errStr);
+ ReadResult readFile(const QString &fn, VfsFlags flags, QString *contents, QString *errStr);
+ bool exists(const QString &fn, VfsFlags flags);
#ifndef PROEVALUATOR_FULL
+ bool readVirtualFile(const QString &fn, VfsFlags flags, QString *contents);
+
void invalidateCache();
void invalidateContents();
#endif
@@ -63,4 +90,6 @@ private:
#endif
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QMakeVfs::VfsFlags)
+
QT_END_NAMESPACE