diff options
author | Orgad Shaneh <orgad.shaneh@audiocodes.com> | 2016-11-02 16:52:58 +0200 |
---|---|---|
committer | Orgad Shaneh <orgad.shaneh@audiocodes.com> | 2016-11-02 16:52:58 +0200 |
commit | 410211e0907f5d31c8fd3bceb362801bb4d108d5 (patch) | |
tree | 186ed812fddc8ff5e6337acc6161e66e226e39a2 /src/shared | |
parent | 7b70c307501771bd26d189d43156dc308b7217c5 (diff) | |
parent | 63bed77178786091a3a490220582a23520352816 (diff) |
Merge remote-tracking branch 'origin/4.2'
Change-Id: Ibb932efece05a5f5613823fbc79c5b7601c73905
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/proparser/ioutils.cpp | 2 | ||||
-rw-r--r-- | src/shared/proparser/ioutils.h | 4 | ||||
-rw-r--r-- | src/shared/proparser/objective_c.prf | 12 | ||||
-rw-r--r-- | src/shared/proparser/profileevaluator.cpp | 90 | ||||
-rw-r--r-- | src/shared/proparser/profileevaluator.h | 26 | ||||
-rw-r--r-- | src/shared/proparser/proparser.pri | 2 | ||||
-rw-r--r-- | src/shared/proparser/proparser.qrc | 3 | ||||
-rw-r--r-- | src/shared/proparser/qmakebuiltins.cpp | 15 | ||||
-rw-r--r-- | src/shared/proparser/qmakeevaluator.cpp | 51 | ||||
-rw-r--r-- | src/shared/proparser/qmakeevaluator.h | 3 | ||||
-rw-r--r-- | src/shared/proparser/qmakeparser.cpp | 51 | ||||
-rw-r--r-- | src/shared/proparser/qmakeparser.h | 10 | ||||
-rw-r--r-- | src/shared/proparser/qmakevfs.cpp | 93 | ||||
-rw-r--r-- | src/shared/proparser/qmakevfs.h | 35 |
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 |