diff options
| author | hjk <hjk@qt.io> | 2022-11-30 16:39:21 +0100 |
|---|---|---|
| committer | hjk <hjk@qt.io> | 2023-01-10 12:02:23 +0000 |
| commit | c7884a2b171470fb7f8821be7ed6a46a2db3d851 (patch) | |
| tree | 9dcb00bf7042cc68f0af5cc17d19690261925484 /src/shared | |
| parent | 0a0dd9ea31d03fcc57f51de724c32e8ca3fe3d3f (diff) | |
| download | qt-creator-c7884a2b171470fb7f8821be7ed6a46a2db3d851.tar.gz | |
Qmake: Enhance remote parsing
When parsing remote .pro files the parsers needs to pretend it runs
on the remote device.
All internal data are now "local on the remote", so that string
manipulation in .pro files "just works", and a 'device root'
string is passed around to relevant functions which then use
it to construct FilePath::toFSPathString()-style paths that
our custom FSEngineImpl can then map to the real device.
Remote $$system() calls are intercepted by the local parser and
redirected using the usual QtcProcess mechanims.
Quite a bit of the ProParser needed adjustments, so there's some
potential for regression.
Task-number: QTCREATORBUG-28242
Task-number: QTCREATORBUG-28161
Task-number: QTCREATORBUG-28355
Change-Id: I6100e7aca4e1db35f5e9689004110aab57e2c595
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Diffstat (limited to 'src/shared')
| -rw-r--r-- | src/shared/proparser/ioutils.cpp | 92 | ||||
| -rw-r--r-- | src/shared/proparser/ioutils.h | 10 | ||||
| -rw-r--r-- | src/shared/proparser/profileevaluator.cpp | 19 | ||||
| -rw-r--r-- | src/shared/proparser/proitems.cpp | 13 | ||||
| -rw-r--r-- | src/shared/proparser/proitems.h | 10 | ||||
| -rw-r--r-- | src/shared/proparser/prowriter.cpp | 12 | ||||
| -rw-r--r-- | src/shared/proparser/prowriter.h | 4 | ||||
| -rw-r--r-- | src/shared/proparser/qmakebuiltins.cpp | 107 | ||||
| -rw-r--r-- | src/shared/proparser/qmakeevaluator.cpp | 47 | ||||
| -rw-r--r-- | src/shared/proparser/qmakeevaluator.h | 25 | ||||
| -rw-r--r-- | src/shared/proparser/qmakeglobals.cpp | 25 | ||||
| -rw-r--r-- | src/shared/proparser/qmakeglobals.h | 5 | ||||
| -rw-r--r-- | src/shared/proparser/qmakeparser.cpp | 23 | ||||
| -rw-r--r-- | src/shared/proparser/qmakeparser.h | 8 | ||||
| -rw-r--r-- | src/shared/proparser/qmakevfs.cpp | 6 | ||||
| -rw-r--r-- | src/shared/proparser/qmakevfs.h | 2 |
16 files changed, 263 insertions, 145 deletions
diff --git a/src/shared/proparser/ioutils.cpp b/src/shared/proparser/ioutils.cpp index d587caea3c..f0ee2b1a03 100644 --- a/src/shared/proparser/ioutils.cpp +++ b/src/shared/proparser/ioutils.cpp @@ -24,16 +24,27 @@ QT_BEGIN_NAMESPACE using namespace QMakeInternal; -static bool isGenericPath(const QStringView fileName) +static bool startsWithSpecialRoot(const QStringView fileName) { static const QString specialRoot = QDir::rootPath() + "__qtc_devices__/"; return fileName.startsWith(specialRoot); } -IoUtils::FileType IoUtils::fileType(const QString &fileName) +static std::optional<QString> genericPath(const QString &device, const QString &fileName) { - if (isGenericPath(fileName)) { - QFileInfo fi(fileName); + if (!device.isEmpty()) + return device + fileName; + + if (startsWithSpecialRoot(fileName)) + return fileName; + + return {}; +} + +IoUtils::FileType IoUtils::fileType(const QString &device, const QString &fileName) +{ + if (std::optional<QString> devPath = genericPath(device, fileName)) { + QFileInfo fi(*devPath); if (fi.isDir()) return FileIsDir; if (fi.isFile()) @@ -41,10 +52,10 @@ IoUtils::FileType IoUtils::fileType(const QString &fileName) return FileNotFound; } - if (!QFileInfo::exists(fileName)) + if (!QFileInfo::exists(device + fileName)) return FileNotFound; - Q_ASSERT(fileName.isEmpty() || isAbsolutePath(fileName)); + Q_ASSERT(fileName.isEmpty() || isAbsolutePath(device, fileName)); #ifdef Q_OS_WIN DWORD attr = GetFileAttributesW((WCHAR*)fileName.utf16()); @@ -59,33 +70,40 @@ IoUtils::FileType IoUtils::fileType(const QString &fileName) #endif } -bool IoUtils::isRelativePath(const QString &path) +static bool isWindows(const QString &device) +{ + if (!device.isEmpty()) + return false; +#ifdef Q_OS_WIN + return true; +#else + return false; +#endif +} + +bool IoUtils::isRelativePath(const QString &device, const QString &path) { #ifdef QMAKE_BUILTIN_PRFS if (path.startsWith(QLatin1String(":/"))) return false; #endif - if (isGenericPath(path)) - return QFileInfo(path).isRelative(); - -#ifdef Q_OS_WIN - // Unlike QFileInfo, this considers only paths with both a drive prefix and - // a subsequent (back-)slash absolute: - if (path.length() >= 3 && path.at(1) == QLatin1Char(':') && path.at(0).isLetter() - && (path.at(2) == QLatin1Char('/') || path.at(2) == QLatin1Char('\\'))) { - return false; - } - // ... unless, of course, they're UNC: - if (path.length() >= 2 - && (path.at(0).unicode() == '\\' || path.at(0).unicode() == '/') - && path.at(1) == path.at(0)) { + if (isWindows(device)) { + // Unlike QFileInfo, this considers only paths with both a drive prefix and + // a subsequent (back-)slash absolute: + if (path.length() >= 3 && path.at(1) == QLatin1Char(':') && path.at(0).isLetter() + && (path.at(2) == QLatin1Char('/') || path.at(2) == QLatin1Char('\\'))) { return false; - } -#else - if (path.startsWith(QLatin1Char('/'))) + } + // ... unless, of course, they're UNC: + if (path.length() >= 2 + && (path.at(0).unicode() == '\\' || path.at(0).unicode() == '/') + && path.at(1) == path.at(0)) { + return false; + } + } else if (path.startsWith(QLatin1Char('/'))) { return false; -#endif // Q_OS_WIN + } return true; } @@ -99,22 +117,28 @@ QStringView IoUtils::fileName(const QString &fileName) return QStringView(fileName).mid(fileName.lastIndexOf(QLatin1Char('/')) + 1); } -QString IoUtils::resolvePath(const QString &baseDir, const QString &fileName) +QString IoUtils::resolvePath(const QString &device, const QString &baseDir, const QString &fileName) { if (fileName.isEmpty()) return QString(); - if (isGenericPath(fileName)) - return baseDir + '/' + fileName; + if (startsWithSpecialRoot(fileName)) + return fileName; - if (isAbsolutePath(fileName)) + if (isAbsolutePath(device, fileName)) return QDir::cleanPath(fileName); -#ifdef Q_OS_WIN // Add drive to otherwise-absolute path: - if (fileName.at(0).unicode() == '/' || fileName.at(0).unicode() == '\\') { - return isAbsolutePath(baseDir) ? QDir::cleanPath(baseDir.left(2) + fileName) - : QDir::cleanPath(fileName); + + if (isWindows(device)) { + // Add drive to otherwise-absolute path: + if (fileName.at(0).unicode() == '/' || fileName.at(0).unicode() == '\\') { + return isAbsolutePath(device, baseDir) ? QDir::cleanPath(baseDir.left(2) + fileName) + : QDir::cleanPath(fileName); + } + } else { + if (fileName.at(0).unicode() == '/' || fileName.at(0).unicode() == '\\') + return fileName; } -#endif // Q_OS_WIN + return QDir::cleanPath(baseDir + QLatin1Char('/') + fileName); } diff --git a/src/shared/proparser/ioutils.h b/src/shared/proparser/ioutils.h index bfa4ce4500..21e276df31 100644 --- a/src/shared/proparser/ioutils.h +++ b/src/shared/proparser/ioutils.h @@ -23,13 +23,13 @@ public: FileIsDir = 2 }; - static FileType fileType(const QString &fileName); - static bool exists(const QString &fileName) { return fileType(fileName) != FileNotFound; } - static bool isRelativePath(const QString &fileName); - static bool isAbsolutePath(const QString &fileName) { return !isRelativePath(fileName); } + static FileType fileType(const QString &device, const QString &fileName); + static bool exists(const QString &device, const QString &fileName) { return fileType(device, fileName) != FileNotFound; } + static bool isRelativePath(const QString &device, const QString &fileName); + static bool isAbsolutePath(const QString &device, const QString &fileName) { return !isRelativePath(device, fileName); } static QStringView pathName(const QString &fileName); // Requires normalized path static QStringView fileName(const QString &fileName); // Requires normalized path - static QString resolvePath(const QString &baseDir, const QString &fileName); + static QString resolvePath(const QString &device, const QString &baseDir, const QString &fileName); static QString shellQuoteUnix(const QString &arg); static QString shellQuoteWin(const QString &arg); static QString shellQuote(const QString &arg) diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp index 48698ad82a..bde0f1367e 100644 --- a/src/shared/proparser/profileevaluator.cpp +++ b/src/shared/proparser/profileevaluator.cpp @@ -62,12 +62,13 @@ QVector<ProFileEvaluator::SourceFile> ProFileEvaluator::fixifiedValues( bool expandWildcards) const { QVector<SourceFile> result; + QString deviceRoot = d->deviceRoot(); const ProStringList values = d->values(ProKey(variable)); for (const ProString &str : values) { const QString &el = d->m_option->expandEnvVars(str.toQString()); - const QString fn = IoUtils::isAbsolutePath(el) + const QString fn = IoUtils::isAbsolutePath(deviceRoot, el) ? QDir::cleanPath(el) : QDir::cleanPath(baseDirectory + QLatin1Char('/') + el); - if (IoUtils::exists(fn)) { + if (IoUtils::exists(deviceRoot, fn)) { result << SourceFile{fn, str.sourceFile()}; continue; } @@ -86,7 +87,7 @@ QVector<ProFileEvaluator::SourceFile> ProFileEvaluator::fixifiedValues( result << SourceFile({fullFilePath, str.sourceFile()}); } } else { - if (IoUtils::isAbsolutePath(el)) { + if (IoUtils::isAbsolutePath(deviceRoot, el)) { result << SourceFile{fn, str.sourceFile()}; } else { result << SourceFile{QDir::cleanPath(buildDirectory + QLatin1Char('/') + el), @@ -118,8 +119,8 @@ QStringList ProFileEvaluator::absolutePathValues( QStringList result; const QStringList valueList = values(variable); for (const QString &el : valueList) { - QString absEl = IoUtils::resolvePath(baseDirectory, el); - if (IoUtils::fileType(absEl) == IoUtils::FileIsDir) + QString absEl = IoUtils::resolvePath(d->deviceRoot(), baseDirectory, el); + if (IoUtils::fileType(d->deviceRoot(), absEl) == IoUtils::FileIsDir) result << absEl; } return result; @@ -139,9 +140,9 @@ QVector<ProFileEvaluator::SourceFile> ProFileEvaluator::absoluteFileValues( seen = true; const QString &el = d->m_option->expandEnvVars(str.toQString()); QString absEl; - if (IoUtils::isAbsolutePath(el)) { + if (IoUtils::isAbsolutePath(d->deviceRoot(), el)) { QString fn = QDir::cleanPath(el); - if (m_vfs->exists(fn, flags)) { + if (m_vfs->exists(d->deviceRoot(), fn, flags)) { result << SourceFile{ fn, str.sourceFile() }; goto next; } @@ -149,7 +150,7 @@ QVector<ProFileEvaluator::SourceFile> ProFileEvaluator::absoluteFileValues( } else { for (const QString &dir : searchDirs) { QString fn = QDir::cleanPath(dir + QLatin1Char('/') + el); - if (m_vfs->exists(fn, flags)) { + if (m_vfs->exists(d->deviceRoot(), fn, flags)) { result << SourceFile{fn, str.sourceFile()}; goto next; } @@ -165,7 +166,7 @@ QVector<ProFileEvaluator::SourceFile> ProFileEvaluator::absoluteFileValues( goto next; } QString absDir = d->m_tmp1.setRawData(absEl.constData(), nameOff); - if (IoUtils::exists(absDir)) { + if (IoUtils::exists(d->deviceRoot(), absDir)) { QString wildcard = d->m_tmp2.setRawData(absEl.constData() + nameOff + 1, absEl.length() - nameOff - 1); if (wildcard.contains(QLatin1Char('*')) || wildcard.contains(QLatin1Char('?'))) { diff --git a/src/shared/proparser/proitems.cpp b/src/shared/proparser/proitems.cpp index 5be4deecb3..4a5108f925 100644 --- a/src/shared/proparser/proitems.cpp +++ b/src/shared/proparser/proitems.cpp @@ -443,16 +443,21 @@ bool ProStringList::contains(const char *str, Qt::CaseSensitivity cs) const return false; } -ProFile::ProFile(int id, const QString &fileName) +ProFile::ProFile(const QString &device, int id, const QString &fileName) : m_refCount(1), m_fileName(fileName), + m_device(device), m_id(id), m_ok(true), m_hostBuild(false) { - if (!fileName.startsWith(QLatin1Char('('))) - m_directoryName = QFileInfo( // qmake sickness: canonicalize only the directory! - fileName.left(fileName.lastIndexOf(QLatin1Char('/')))).canonicalFilePath(); + if (!fileName.startsWith(QLatin1Char('('))) { + m_directoryName = fileName.left(fileName.lastIndexOf(QLatin1Char('/'))); + if (device.isEmpty()) { + // qmake sickness: canonicalize only the directory! + m_directoryName = QFileInfo(m_directoryName).canonicalFilePath(); + } + } } ProFile::~ProFile() diff --git a/src/shared/proparser/proitems.h b/src/shared/proparser/proitems.h index 054f13463e..dee7e26d85 100644 --- a/src/shared/proparser/proitems.h +++ b/src/shared/proparser/proitems.h @@ -413,12 +413,13 @@ enum ProToken { class QMAKE_EXPORT ProFile { public: - ProFile(int id, const QString &fileName); + ProFile(const QString &device, int id, const QString &fileName); ~ProFile(); int id() const { return m_id; } - QString fileName() const { return m_fileName; } - QString directoryName() const { return m_directoryName; } + const QString &fileName() const { return m_fileName; } + const QString &device() const { return m_device; } + const QString &directoryName() const { return m_directoryName; } const QString &items() const { return m_proitems; } QString *itemsRef() { return &m_proitems; } const ushort *tokPtr() const { return (const ushort *)m_proitems.constData(); } @@ -439,7 +440,8 @@ public: private: ProItemRefCount m_refCount; QString m_proitems; - QString m_fileName; + const QString m_fileName; + const QString m_device; QString m_directoryName; int m_id; bool m_ok; diff --git a/src/shared/proparser/prowriter.cpp b/src/shared/proparser/prowriter.cpp index 077facffc4..5e2e2be5f4 100644 --- a/src/shared/proparser/prowriter.cpp +++ b/src/shared/proparser/prowriter.cpp @@ -154,12 +154,12 @@ static const ushort *skipToken(ushort tok, const ushort *&tokPtr, int &lineNo) return nullptr; } -QString ProWriter::compileScope(const QString &scope) +QString ProWriter::compileScope(const QString &device, const QString &scope) { if (scope.isEmpty()) return QString(); QMakeParser parser(nullptr, nullptr, nullptr); - ProFile *includeFile = parser.parsedProBlock(QStringView(scope), 0, "no-file", 1); + ProFile *includeFile = parser.parsedProBlock(device, QStringView(scope), 0, "no-file", 1); if (!includeFile) return QString(); const QString result = includeFile->items(); @@ -181,7 +181,7 @@ static bool startsWithTokens(const ushort *that, const ushort *thatEnd, const us return true; } -bool ProWriter::locateVarValues(const ushort *tokPtr, const ushort *tokPtrEnd, +bool ProWriter::locateVarValues(const QString &device, const ushort *tokPtr, const ushort *tokPtrEnd, const QString &scope, const QString &var, int *scopeStart, int *bestLine) { const bool inScope = scope.isEmpty(); @@ -190,7 +190,7 @@ bool ProWriter::locateVarValues(const ushort *tokPtr, const ushort *tokPtrEnd, const ushort *lastXpr = nullptr; bool fresh = true; - QString compiledScope = compileScope(scope); + QString compiledScope = compileScope(device, scope); const ushort *cTokPtr = reinterpret_cast<const ushort *>(compiledScope.constData()); while (ushort tok = *tokPtr++) { @@ -206,7 +206,7 @@ bool ProWriter::locateVarValues(const ushort *tokPtr, const ushort *tokPtrEnd, && startsWithTokens(tokPtr - 1, tokPtrEnd, cTokPtr, cTokPtr + compiledScope.size()) && *(tokPtr -1 + compiledScope.size()) == TokBranch) { *scopeStart = lineNo - 1; - if (locateVarValues(tokPtr + compiledScope.size() + 2, tokPtrEnd, + if (locateVarValues(device, tokPtr + compiledScope.size() + 2, tokPtrEnd, QString(), var, scopeStart, bestLine)) return true; } @@ -298,7 +298,7 @@ void ProWriter::putVarValues(ProFile *profile, QStringList *lines, const QString return !ci.indent.isEmpty() ? ci.indent : continuationIndent + indent; }; int scopeStart = -1, lineNo; - if (locateVarValues(profile->tokPtr(), profile->tokPtrEnd(), scope, var, &scopeStart, &lineNo)) { + if (locateVarValues(profile->device(), profile->tokPtr(), profile->tokPtrEnd(), scope, var, &scopeStart, &lineNo)) { if (flags & ReplaceValues) { // remove continuation lines with old values const ContinuationInfo contInfo = skipContLines(lines, lineNo, false); diff --git a/src/shared/proparser/prowriter.h b/src/shared/proparser/prowriter.h index 6c84587d14..fa2b5391a6 100644 --- a/src/shared/proparser/prowriter.h +++ b/src/shared/proparser/prowriter.h @@ -52,9 +52,9 @@ public: VarLocations *removedLocations = nullptr); private: - static bool locateVarValues(const ushort *tokPtr, const ushort *tokPtrEnd, + static bool locateVarValues(const QString &device, const ushort *tokPtr, const ushort *tokPtrEnd, const QString &scope, const QString &var, int *scopeStart, int *bestLine); - static QString compileScope(const QString &scope); + static QString compileScope(const QString &device, const QString &scope); }; } // namespace Internal diff --git a/src/shared/proparser/qmakebuiltins.cpp b/src/shared/proparser/qmakebuiltins.cpp index b7cbb1b3a7..787d9effb9 100644 --- a/src/shared/proparser/qmakebuiltins.cpp +++ b/src/shared/proparser/qmakebuiltins.cpp @@ -419,8 +419,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode, QMakeVfs::VfsFlags flags, const QString &contents) { - int oldId = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsAccessedOnly); - int id = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsCreate); + const QString fileName = deviceRoot() + fn; + int oldId = m_vfs->idForFileName(fileName, flags | QMakeVfs::VfsAccessedOnly); + int id = m_vfs->idForFileName(fileName, flags | QMakeVfs::VfsCreate); QString errStr; if (!m_vfs->writeFile(id, mode, flags, contents, &errStr)) { evalError(fL1S("Cannot write %1file %2: %3") @@ -432,6 +433,65 @@ QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::Open return ReturnTrue; } +// This is the global callback + +QMAKE_EXPORT std::function<void(ProcessData *data)> &theProcessRunner() +{ + static std::function<void(ProcessData *)> runner; + return runner; +} + +void QMakeEvaluator::runProcessHelper(ProcessData *data) const +{ + const QString root = deviceRoot(); + if (root.isEmpty()) { + + // The "normal" setup. + QProcess proc; + + proc.setProcessChannelMode(data->processChannelMode); + + runProcess(&proc, data->command); + + data->exitCode = proc.exitCode(); + data->exitStatus = proc.exitStatus(); + data->stdOut = proc.readAllStandardOutput(); + data->stdErr = proc.readAllStandardError(); + + } else { + + // "Remote" + const std::function<void(ProcessData *data)> &runner = theProcessRunner(); + if (!runner) { + qWarning("Missing qmake process callback"); + data->exitCode = -1; + data->exitStatus = QProcess::CrashExit; + return; + } + + data->workingDirectory = currentDirectory(); +# ifdef PROEVALUATOR_SETENV + if (!m_option->environment.isEmpty()) { + QProcessEnvironment env = m_option->environment; + static const QString dummyVar = "__qtc_dummy"; + static const QString notSetValue = "not set"; + const QString oldValue = env.value(dummyVar, notSetValue); // Just in case. + env.insert(dummyVar, "QTCREATORBUG-23504"); // Force detach. + if (oldValue == notSetValue) + env.remove(dummyVar); + else + env.insert(dummyVar, oldValue); + data->environment = env; + } +# endif + + data->deviceRoot = root; + + runner(data); + + } +} + #ifndef QT_BOOTSTRAPPED void QMakeEvaluator::runProcess(QProcess *proc, const QString &command) const { @@ -485,10 +545,15 @@ QByteArray QMakeEvaluator::getCommandOutput(const QString &args, int *exitCode) { QByteArray out; #ifndef QT_BOOTSTRAPPED - QProcess proc; - runProcess(&proc, args); - *exitCode = (proc.exitStatus() == QProcess::NormalExit) ? proc.exitCode() : -1; - QByteArray errout = proc.isReadable() ? proc.readAllStandardError() : QByteArray(); + ProcessData data; + data.command = args; + + runProcessHelper(&data); + + *exitCode = data.exitStatus == QProcess::NormalExit ? data.exitCode : -1; + QByteArray errout = data.stdErr; + + # ifdef PROEVALUATOR_FULL // FIXME: Qt really should have the option to set forwarding per channel fputs(errout.constData(), stderr); @@ -501,7 +566,7 @@ QByteArray QMakeEvaluator::getCommandOutput(const QString &args, int *exitCode) QString::fromLocal8Bit(errout)); } # endif - out = proc.isReadable() ? proc.readAllStandardOutput() : QByteArray(); + out = data.stdOut; # ifdef Q_OS_WIN // FIXME: Qt's line end conversion on sequential files should really be fixed out.replace("\r\n", "\n"); @@ -1060,7 +1125,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( QString r = m_option->expandEnvVars(args.at(0).toQString(m_tmp1)) .replace(QLatin1Char('\\'), QLatin1Char('/')); QString pfx; - if (IoUtils::isRelativePath(r)) { + if (IoUtils::isRelativePath(deviceRoot(), r)) { pfx = currentDirectory(); if (!pfx.endsWith(QLatin1Char('/'))) pfx += QLatin1Char('/'); @@ -1081,12 +1146,12 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( } for (int d = 0; d < dirs.count(); d++) { QString dir = dirs[d]; - QDir qdir(pfx + dir); + QDir qdir(deviceRoot() + pfx + dir); for (int i = 0; i < (int)qdir.count(); ++i) { if (qdir[i] == statics.strDot || qdir[i] == statics.strDotDot) continue; QString fname = dir + qdir[i]; - if (IoUtils::fileType(pfx + fname) == IoUtils::FileIsDir) { + if (IoUtils::fileType(deviceRoot(), pfx + fname) == IoUtils::FileIsDir) { if (recursive) dirs.append(fname + QLatin1Char('/')); } @@ -1208,7 +1273,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( } else { QString arg = args.at(0).toQString(m_tmp1); QString baseDir = args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory(); - QString rstr = arg.isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, arg); + QString rstr = arg.isEmpty() ? baseDir : IoUtils::resolvePath(deviceRoot(), baseDir, arg); ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : args.count() > 1 && rstr.isSharedWith(m_tmp2) @@ -1222,7 +1287,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( } else { QString arg = args.at(0).toQString(m_tmp1); QString baseDir = args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory(); - QString absArg = arg.isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, arg); + QString absArg = arg.isEmpty() ? baseDir : IoUtils::resolvePath(deviceRoot(), baseDir, arg); QString rstr = QDir(baseDir).relativeFilePath(absArg); ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0))); } @@ -1405,7 +1470,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( } QString fn = resolvePath(args.at(0).toQString(m_tmp1)); QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact); - int pro = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsAccessedOnly); + int pro = m_vfs->idForFileName(deviceRoot() + fn, flags | QMakeVfs::VfsAccessedOnly); if (!pro) return ReturnFalse; ProValueMap &vmap = m_valuemapStack.front(); @@ -1481,7 +1546,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( case T_EVAL: { VisitReturn ret = ReturnFalse; QString contents = args.join(statics.field_sep); - ProFile *pro = m_parser->parsedProBlock(QStringView(contents), + ProFile *pro = m_parser->parsedProBlock(m_current.pro->device(), + QStringView(contents), 0, m_current.pro->fileName(), m_current.line); if (m_cumulative || pro->isOk()) { m_locationStack.push(m_current); @@ -1785,10 +1851,11 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( if (m_cumulative) // Anything else would be insanity return ReturnFalse; #ifndef QT_BOOTSTRAPPED - QProcess proc; - proc.setProcessChannelMode(QProcess::ForwardedChannels); - runProcess(&proc, args.at(0).toQString()); - return returnBool(proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0); + ProcessData data; + data.command = args.at(0).toQString(); + data.processChannelMode = QProcess::ForwardedChannels; + runProcessHelper(&data); + return returnBool(data.exitStatus == QProcess::NormalExit && data.exitCode == 0); #else int ec = system((QLatin1String("cd ") + IoUtils::shellQuote(QDir::toNativeSeparators(currentDirectory())) @@ -1817,7 +1884,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( // Don't use VFS here: // - it supports neither listing nor even directories // - it's unlikely that somebody would test for files they created themselves - if (IoUtils::exists(file)) + if (IoUtils::exists(deviceRoot(), file)) return ReturnTrue; int slsh = file.lastIndexOf(QLatin1Char('/')); QString fn = file.mid(slsh+1); @@ -2052,7 +2119,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( fn = m_stashfile; if (fn.isEmpty()) fn = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.stash")); - if (!m_vfs->exists(fn, flags)) { + if (!m_vfs->exists(deviceRoot(), fn, flags)) { printf("Info: creating stash file %s\n", qPrintable(QDir::toNativeSeparators(fn))); valuesRef(ProKey("_QMAKE_STASH_")) << ProString(fn); } diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp index dca187944d..ced40f106d 100644 --- a/src/shared/proparser/qmakeevaluator.cpp +++ b/src/shared/proparser/qmakeevaluator.cpp @@ -923,7 +923,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProVariable( else if (varName == statics.strQMAKESPEC) { if (!values(varName).isEmpty()) { QString spec = values(varName).constFirst().toQString(); - if (IoUtils::isAbsolutePath(spec)) { + if (IoUtils::isAbsolutePath(deviceRoot(), spec)) { m_qmakespec = spec; m_qmakespecName = IoUtils::fileName(m_qmakespec).toString(); m_featureRoots = 0; @@ -1084,6 +1084,7 @@ bool QMakeEvaluator::prepareProject(const QString &inDir) { QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact); QString superdir; + const QString device = deviceRoot(); if (m_option->do_cache) { QString conffile; QString cachefile = m_option->cachefile; @@ -1093,7 +1094,7 @@ bool QMakeEvaluator::prepareProject(const QString &inDir) superdir = m_outputDir; forever { QString superfile = superdir + QLatin1String("/.qmake.super"); - if (m_vfs->exists(superfile, flags)) { + if (m_vfs->exists(device, superfile, flags)) { m_superfile = QDir::cleanPath(superfile); break; } @@ -1108,10 +1109,10 @@ bool QMakeEvaluator::prepareProject(const QString &inDir) QString dir = m_outputDir; forever { conffile = sdir + QLatin1String("/.qmake.conf"); - if (!m_vfs->exists(conffile, flags)) + if (!m_vfs->exists(device, conffile, flags)) conffile.clear(); cachefile = dir + QLatin1String("/.qmake.cache"); - if (!m_vfs->exists(cachefile, flags)) + if (!m_vfs->exists(device, cachefile, flags)) cachefile.clear(); if (!conffile.isEmpty() || !cachefile.isEmpty()) { if (dir != sdir) @@ -1139,7 +1140,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, flags)) { + if (dir == (!superdir.isEmpty() ? superdir : m_buildRoot) || m_vfs->exists(deviceRoot(), stashfile, flags)) { m_stashfile = QDir::cleanPath(stashfile); break; } @@ -1177,7 +1178,7 @@ bool QMakeEvaluator::loadSpecInternal() const ProString &orig_spec = first(ProKey("QMAKESPEC_ORIGINAL")); if (!orig_spec.isEmpty()) { QString spec = orig_spec.toQString(); - if (IoUtils::isAbsolutePath(spec)) + if (IoUtils::isAbsolutePath(deviceRoot(), spec)) m_qmakespec = spec; } # endif @@ -1230,10 +1231,10 @@ bool QMakeEvaluator::loadSpec() if (qmakespec.isEmpty()) qmakespec = m_hostBuild ? QLatin1String("default-host") : QLatin1String("default"); #endif - if (IoUtils::isRelativePath(qmakespec)) { + if (IoUtils::isRelativePath(deviceRoot(), qmakespec)) { for (const QString &root : std::as_const(m_mkspecPaths)) { QString mkspec = root + QLatin1Char('/') + qmakespec; - if (IoUtils::exists(mkspec)) { + if (IoUtils::exists(deviceRoot(), mkspec)) { qmakespec = mkspec; goto cool; } @@ -1265,7 +1266,7 @@ bool QMakeEvaluator::loadSpec() return false; } QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact); - if (!m_stashfile.isEmpty() && m_vfs->exists(m_stashfile, flags)) { + if (!m_stashfile.isEmpty() && m_vfs->exists(deviceRoot(), m_stashfile, flags)) { valuesRef(ProKey("_QMAKE_STASH_")) << ProString(m_stashfile); if (evaluateFile( m_stashfile, QMakeHandler::EvalConfigFile, LoadProOnly) != ReturnTrue) @@ -1288,7 +1289,7 @@ void QMakeEvaluator::setupProject() void QMakeEvaluator::evaluateCommand(const QString &cmds, const QString &where) { if (!cmds.isEmpty()) { - ProFile *pro = m_parser->parsedProBlock(QStringView(cmds), 0, where, -1); + ProFile *pro = m_parser->parsedProBlock(deviceRoot(), QStringView(cmds), 0, where, -1); if (pro->isOk()) { m_locationStack.push(m_current); visitProBlock(pro, pro->tokPtr()); @@ -1462,13 +1463,17 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile( return vr; } +const QString &QMakeEvaluator::deviceRoot() const +{ + return m_option->device_root; +} void QMakeEvaluator::updateMkspecPaths() { QStringList ret; const QString concat = QLatin1String("/mkspecs"); - const auto paths = m_option->getPathListEnv(QLatin1String("QMAKEPATH")); + const QStringList paths = m_option->getPathListEnv(QLatin1String("QMAKEPATH")); for (const QString &it : paths) ret << it + concat; @@ -1480,9 +1485,8 @@ void QMakeEvaluator::updateMkspecPaths() if (!m_sourceRoot.isEmpty()) ret << m_sourceRoot + concat; - const QString root = m_option->deviceRoot(); - ret << root + m_option->propertyValue(ProKey("QT_HOST_DATA/get")) + concat; - ret << root + m_option->propertyValue(ProKey("QT_HOST_DATA/src")) + concat; + ret << m_option->propertyValue(ProKey("QT_HOST_DATA/get")) + concat; + ret << m_option->propertyValue(ProKey("QT_HOST_DATA/src")) + concat; ret.removeDuplicates(); m_mkspecPaths = ret; @@ -1526,7 +1530,7 @@ void QMakeEvaluator::updateFeaturePaths() while (!specdir.isRoot() && specdir.cdUp()) { const QString specpath = specdir.path(); if (specpath.endsWith(mkspecs_concat)) { - if (IoUtils::exists(specpath + features_concat)) + if (IoUtils::exists(deviceRoot(), specpath + features_concat)) feature_bases << specpath; break; } @@ -1551,7 +1555,7 @@ void QMakeEvaluator::updateFeaturePaths() QStringList ret; for (const QString &root : std::as_const(feature_roots)) - if (IoUtils::exists(root)) + if (IoUtils::exists(deviceRoot(), root)) ret << root; m_featureRoots = new QMakeFeatureRoots(ret); } @@ -1581,6 +1585,11 @@ int QMakeEvaluator::currentFileId() const return 0; } +QString QMakeEvaluator::resolvePath(const QString &fileName) const +{ + return QMakeInternal::IoUtils::resolvePath(deviceRoot(), currentDirectory(), fileName); +} + QString QMakeEvaluator::currentFileName() const { ProFile *pro = currentProFile(); @@ -1794,7 +1803,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditional( QStringView cond, const QString &where, int line) { VisitReturn ret = ReturnFalse; - ProFile *pro = m_parser->parsedProBlock(cond, 0, where, line, QMakeParser::TestGrammar); + ProFile *pro = m_parser->parsedProBlock(deviceRoot(), cond, 0, where, line, QMakeParser::TestGrammar); if (pro->isOk()) { m_locationStack.push(m_current); ret = visitProBlock(pro, pro->tokPtr()); @@ -1910,7 +1919,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFile( QMakeParser::ParseFlags pflags = QMakeParser::ParseUseCache; if (!(flags & LoadSilent)) pflags |= QMakeParser::ParseReportMissing; - if (ProFile *pro = m_parser->parsedProFile(fileName, pflags)) { + if (ProFile *pro = m_parser->parsedProFile(deviceRoot(), fileName, pflags)) { m_locationStack.push(m_current); VisitReturn ok = visitProFile(pro, type, flags); m_current = m_locationStack.pop(); @@ -1984,7 +1993,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFeatureFile( } for (int root = start_root; root < paths.size(); ++root) { QString fname = paths.at(root) + fn; - if (IoUtils::exists(fname)) { + if (IoUtils::exists(deviceRoot(), fname)) { fn = fname; goto cool; } diff --git a/src/shared/proparser/qmakeevaluator.h b/src/shared/proparser/qmakeevaluator.h index 7dd7e70557..8b4a9e79aa 100644 --- a/src/shared/proparser/qmakeevaluator.h +++ b/src/shared/proparser/qmakeevaluator.h @@ -29,6 +29,26 @@ #include <list> +class ProcessData +{ +public: + QString deviceRoot; + + QString command; + QString workingDirectory; + QProcessEnvironment environment; + QProcess::ProcessChannelMode processChannelMode = QProcess::SeparateChannels; + + QProcess::ExitStatus exitStatus = QProcess::NormalExit; + QByteArray stdOut; + QByteArray stdErr; + int exitCode = 0; +}; + +QMAKE_EXPORT std::function<void(ProcessData *data)> &theProcessRunner(); +QMAKE_EXPORT QString removeHostAndScheme(const QString &remotePath); + + QT_BEGIN_NAMESPACE class QMakeGlobals; @@ -159,8 +179,7 @@ public: QString currentDirectory() const; ProFile *currentProFile() const; int currentFileId() const; - QString resolvePath(const QString &fileName) const - { return QMakeInternal::IoUtils::resolvePath(currentDirectory(), fileName); } + QString resolvePath(const QString &fileName) const; VisitReturn evaluateFile(const QString &fileName, QMakeHandler::EvalFileType type, LoadFlags flags); @@ -217,6 +236,7 @@ public: #ifndef QT_BOOTSTRAPPED void runProcess(QProcess *proc, const QString &command) const; #endif + void runProcessHelper(ProcessData *processData) const; QByteArray getCommandOutput(const QString &args, int *exitCode) const; QMakeEvaluator *m_caller; @@ -229,6 +249,7 @@ public: #endif static QString quoteValue(const ProString &val); + const QString &deviceRoot() const; #ifdef PROEVALUATOR_DEBUG void debugMsgInternal(int level, const char *fmt, ...) const; diff --git a/src/shared/proparser/qmakeglobals.cpp b/src/shared/proparser/qmakeglobals.cpp index 4e6916fd02..03e0fd6055 100644 --- a/src/shared/proparser/qmakeglobals.cpp +++ b/src/shared/proparser/qmakeglobals.cpp @@ -78,7 +78,7 @@ QString QMakeGlobals::cleanSpec(QMakeCmdLineParserState &state, const QString &s { QString ret = QDir::cleanPath(spec); if (ret.contains(QLatin1Char('/'))) { - QString absRet = IoUtils::resolvePath(state.pwd, ret); + QString absRet = IoUtils::resolvePath(device_root, state.pwd, ret); if (QFile::exists(absRet)) ret = absRet; } @@ -108,10 +108,10 @@ QMakeGlobals::ArgumentReturn QMakeGlobals::addCommandLineArguments( user_template_prefix = arg; break; case ArgCache: - cachefile = args[*pos] = IoUtils::resolvePath(state.pwd, arg); + cachefile = args[*pos] = IoUtils::resolvePath(device_root, state.pwd, arg); break; case ArgQtConf: - qtconf = args[*pos] = IoUtils::resolvePath(state.pwd, arg); + qtconf = args[*pos] = IoUtils::resolvePath(device_root, state.pwd, arg); break; default: if (arg.startsWith(QLatin1Char('-'))) { @@ -204,8 +204,9 @@ void QMakeGlobals::setCommandLineArguments(const QString &pwd, const QStringList useEnvironment(); } -void QMakeGlobals::setDirectories(const QString &input_dir, const QString &output_dir) +void QMakeGlobals::setDirectories(const QString &input_dir, const QString &output_dir, const QString &device_root) { + this->device_root = device_root; if (input_dir != output_dir && !output_dir.isEmpty()) { QString srcpath = input_dir; if (!srcpath.endsWith(QLatin1Char('/'))) @@ -225,20 +226,6 @@ void QMakeGlobals::setDirectories(const QString &input_dir, const QString &outpu } } -QString QMakeGlobals::deviceRoot() const -{ - static const QString specialRoot = QDir::rootPath() + "__qtc_devices__/"; - if (!build_root.startsWith(specialRoot)) - return {}; - int pos = build_root.indexOf('/', specialRoot.size()); - if (pos == -1) - return {}; - pos = build_root.indexOf('/', pos + 1); - if (pos == -1) - return {}; - return build_root.left(pos + 1); -} - QString QMakeGlobals::shadowedPath(const QString &fileName) const { if (source_root.isEmpty()) @@ -259,7 +246,7 @@ QStringList QMakeGlobals::splitPathList(const QString &val) const const QStringList vals = val.split(dirlist_sep); ret.reserve(vals.length()); for (const QString &it : vals) - ret << IoUtils::resolvePath(cwd, it); + ret << IoUtils::resolvePath(device_root, cwd, it); } return ret; } diff --git a/src/shared/proparser/qmakeglobals.h b/src/shared/proparser/qmakeglobals.h index 210862a8d0..db840fbe1c 100644 --- a/src/shared/proparser/qmakeglobals.h +++ b/src/shared/proparser/qmakeglobals.h @@ -81,6 +81,7 @@ public: #ifdef PROEVALUATOR_SETENV QProcessEnvironment environment; #endif + QString device_root; QString qmake_abslocation; QStringList qmake_args, qmake_extra_args; @@ -102,7 +103,8 @@ public: void commitCommandLineArguments(QMakeCmdLineParserState &state); void setCommandLineArguments(const QString &pwd, const QStringList &args); void useEnvironment(); - void setDirectories(const QString &input_dir, const QString &output_dir); + void setDirectories(const QString &input_dir, const QString &output_dir, + const QString &device_root); #ifdef QT_BUILD_QMAKE void setQMakeProperty(QMakeProperty *prop) { property = prop; } void reloadProperties() { property->reload(); } @@ -120,7 +122,6 @@ public: QString expandEnvVars(const QString &str) const; QString shadowedPath(const QString &fileName) const; QStringList splitPathList(const QString &value) const; - QString deviceRoot() const; private: QString getEnv(const QString &) const; diff --git a/src/shared/proparser/qmakeparser.cpp b/src/shared/proparser/qmakeparser.cpp index aac1a69afb..758a80ce4a 100644 --- a/src/shared/proparser/qmakeparser.cpp +++ b/src/shared/proparser/qmakeparser.cpp @@ -33,12 +33,12 @@ ProFileCache::~ProFileCache() QMakeVfs::deref(); } -void ProFileCache::discardFile(const QString &fileName, QMakeVfs *vfs) +void ProFileCache::discardFile(const QString &device, const QString &fileName, QMakeVfs *vfs) { - int eid = vfs->idForFileName(fileName, QMakeVfs::VfsExact | QMakeVfs::VfsAccessedOnly); + int eid = vfs->idForFileName(device + fileName, QMakeVfs::VfsExact | QMakeVfs::VfsAccessedOnly); if (eid) discardFile(eid); - int cid = vfs->idForFileName(fileName, QMakeVfs::VfsCumulative | QMakeVfs::VfsAccessedOnly); + int cid = vfs->idForFileName(device + fileName, QMakeVfs::VfsCumulative | QMakeVfs::VfsAccessedOnly); if (cid && cid != eid) discardFile(cid); } @@ -85,17 +85,18 @@ void ProFileCache::discardFile(int id) } } -void ProFileCache::discardFiles(const QString &prefix, QMakeVfs *vfs) +void ProFileCache::discardFiles(const QString &device, const QString &prefix, QMakeVfs *vfs) { #ifdef PROPARSER_THREAD_SAFE QMutexLocker lck(&mutex); #endif auto it = parsed_files.begin(); + const QString fullPrefix = device + prefix; while (it != parsed_files.end()) { const int id = it->first; // Note: this is empty for virtual files from other VFSes. const QString fn = vfs->fileNameForId(id); - if (fn.startsWith(prefix)) { + if (fn.startsWith(prefix) || fn.startsWith(fullPrefix)) { bool continueFromScratch = false; Entry &entry = it->second; #ifdef PROPARSER_THREAD_SAFE @@ -200,12 +201,12 @@ QMakeParser::QMakeParser(ProFileCache *cache, QMakeVfs *vfs, QMakeParserHandler initialize(); } -ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags) +ProFile *QMakeParser::parsedProFile(const QString &device, const QString &fileName, ParseFlags flags) { ProFile *pro; QMakeVfs::VfsFlags vfsFlags = ((flags & ParseCumulative) ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact); - int id = m_vfs->idForFileName(fileName, vfsFlags); + int id = m_vfs->idForFileName(device + fileName, vfsFlags); if ((flags & ParseUseCache) && m_cache) { ProFileCache::Entry *ent; #ifdef PROPARSER_THREAD_SAFE @@ -260,7 +261,7 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags) #endif QString contents; if (readFile(id, flags, &contents)) { - pro = parsedProBlock(QStringView(contents), id, fileName, 1, FullGrammar); + pro = parsedProBlock(device, QStringView(contents), id, fileName, 1, FullGrammar); pro->itemsRef()->squeeze(); pro->ref(); } else { @@ -287,17 +288,17 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags) } else { QString contents; if (readFile(id, flags, &contents)) - pro = parsedProBlock(QStringView(contents), id, fileName, 1, FullGrammar); + pro = parsedProBlock(device, QStringView(contents), id, fileName, 1, FullGrammar); else pro = 0; } return pro; } -ProFile *QMakeParser::parsedProBlock( +ProFile *QMakeParser::parsedProBlock(const QString &device, QStringView contents, int id, const QString &name, int line, SubGrammar grammar) { - ProFile *pro = new ProFile(id, name); + ProFile *pro = new ProFile(device, id, name); read(pro, contents, line, grammar); return pro; } diff --git a/src/shared/proparser/qmakeparser.h b/src/shared/proparser/qmakeparser.h index 32d6724c25..58d8b21f93 100644 --- a/src/shared/proparser/qmakeparser.h +++ b/src/shared/proparser/qmakeparser.h @@ -67,8 +67,8 @@ public: enum SubGrammar { FullGrammar, TestGrammar, ValueGrammar }; // fileName is expected to be absolute and cleanPath()ed. - ProFile *parsedProFile(const QString &fileName, ParseFlags flags = ParseDefault); - ProFile *parsedProBlock(QStringView contents, int id, const QString &name, int line = 0, + ProFile *parsedProFile(const QString &device, const QString &fileName, ParseFlags flags = ParseDefault); + ProFile *parsedProBlock(const QString &device, QStringView contents, int id, const QString &name, int line = 0, SubGrammar grammar = FullGrammar); void discardFileFromCache(int id); @@ -179,8 +179,8 @@ public: ~ProFileCache(); void discardFile(int id); - void discardFile(const QString &fileName, QMakeVfs *vfs); - void discardFiles(const QString &prefix, QMakeVfs *vfs); + void discardFile(const QString &device, const QString &fileName, QMakeVfs *vfs); + void discardFiles(const QString &device, const QString &prefix, QMakeVfs *vfs); private: struct Entry { diff --git a/src/shared/proparser/qmakevfs.cpp b/src/shared/proparser/qmakevfs.cpp index cabdd5c812..0a9527542e 100644 --- a/src/shared/proparser/qmakevfs.cpp +++ b/src/shared/proparser/qmakevfs.cpp @@ -207,20 +207,20 @@ QMakeVfs::ReadResult QMakeVfs::readFile(int id, QString *contents, QString *errS return ReadOk; } -bool QMakeVfs::exists(const QString &fn, VfsFlags flags) +bool QMakeVfs::exists(const QString &device, const QString &fn, VfsFlags flags) { #ifndef PROEVALUATOR_FULL # ifdef PROEVALUATOR_THREAD_SAFE QMutexLocker locker(&m_mutex); # endif - int id = idForFileName(fn, flags); + int id = idForFileName(device + fn, flags); auto it = m_files.constFind(id); if (it != m_files.constEnd()) return it->constData() != m_magicMissing.constData(); #else Q_UNUSED(flags) #endif - bool ex = IoUtils::fileType(fn) == IoUtils::FileIsRegular; + bool ex = IoUtils::fileType(device, fn) == IoUtils::FileIsRegular; #ifndef PROEVALUATOR_FULL m_files[id] = ex ? m_magicExisting : m_magicMissing; #endif diff --git a/src/shared/proparser/qmakevfs.h b/src/shared/proparser/qmakevfs.h index 85fb68f780..6e6d5dc4d5 100644 --- a/src/shared/proparser/qmakevfs.h +++ b/src/shared/proparser/qmakevfs.h @@ -55,7 +55,7 @@ public: QString fileNameForId(int id); bool writeFile(int id, QIODevice::OpenMode mode, VfsFlags flags, const QString &contents, QString *errStr); ReadResult readFile(int id, QString *contents, QString *errStr); - bool exists(const QString &fn, QMakeVfs::VfsFlags flags); + bool exists(const QString &device, const QString &fn, QMakeVfs::VfsFlags flags); #ifndef PROEVALUATOR_FULL void invalidateCache(); |
