forked from qt-creator/qt-creator
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>
This commit is contained in:
@@ -299,7 +299,11 @@ bool AbstractProcessStep::setupProcessParameters(ProcessParameters *params) cons
|
||||
|
||||
const FilePath executable = params->effectiveCommand();
|
||||
|
||||
QTC_ASSERT(executable.ensureReachable(workingDirectory), return false);
|
||||
// E.g. the QMakeStep doesn't have set up anything when this is called
|
||||
// as it doesn't set a command line provider, so executable might be empty.
|
||||
const bool looksGood = executable.isEmpty() || executable.ensureReachable(workingDirectory);
|
||||
QTC_ASSERT(looksGood, return false);
|
||||
|
||||
params->setWorkingDirectory(workingDirectory.onDevice(executable));
|
||||
|
||||
return true;
|
||||
|
@@ -164,17 +164,17 @@ static void createTree(QmakeBuildSystem *buildSystem,
|
||||
|| type == FileType::Form);
|
||||
|
||||
if (type == FileType::Resource) {
|
||||
for (const auto &file : newFilePaths) {
|
||||
for (const SourceFile &file : newFilePaths) {
|
||||
auto vfs = buildSystem->qmakeVfs();
|
||||
QString contents;
|
||||
QString errorMessage;
|
||||
// Prefer the cumulative file if it's non-empty, based on the assumption
|
||||
// that it contains more "stuff".
|
||||
int cid = vfs->idForFileName(file.first.toString(), QMakeVfs::VfsCumulative);
|
||||
int cid = vfs->idForFileName(file.first.toFSPathString(), QMakeVfs::VfsCumulative);
|
||||
vfs->readFile(cid, &contents, &errorMessage);
|
||||
// If the cumulative evaluation botched the file too much, try the exact one.
|
||||
if (contents.isEmpty()) {
|
||||
int eid = vfs->idForFileName(file.first.toString(), QMakeVfs::VfsExact);
|
||||
int eid = vfs->idForFileName(file.first.toFSPathString(), QMakeVfs::VfsExact);
|
||||
vfs->readFile(eid, &contents, &errorMessage);
|
||||
}
|
||||
auto topLevel = std::make_unique<ResourceEditor::ResourceTopLevelNode>
|
||||
|
@@ -138,16 +138,18 @@ void QmakePriFile::finishInitialization(QmakeBuildSystem *buildSystem, QmakeProF
|
||||
m_qmakeProFile = qmakeProFile;
|
||||
}
|
||||
|
||||
FilePath QmakePriFile::filePath() const
|
||||
{
|
||||
return m_filePath;
|
||||
}
|
||||
|
||||
FilePath QmakePriFile::directoryPath() const
|
||||
{
|
||||
return filePath().parentDir();
|
||||
}
|
||||
|
||||
QString QmakePriFile::deviceRoot() const
|
||||
{
|
||||
if (m_filePath.needsDevice())
|
||||
return m_filePath.withNewPath("/").toFSPathString();
|
||||
return {};
|
||||
}
|
||||
|
||||
QString QmakePriFile::displayName() const
|
||||
{
|
||||
return filePath().completeBaseName();
|
||||
@@ -205,7 +207,7 @@ const QSet<FilePath> QmakePriFile::collectFiles(const FileType &type) const
|
||||
{
|
||||
QSet<FilePath> allFiles = transform(files(type),
|
||||
[](const SourceFile &sf) { return sf.first; });
|
||||
for (const QmakePriFile * const priFile : std::as_const(m_children)) {
|
||||
for (const QmakePriFile * const priFile : m_children) {
|
||||
if (!dynamic_cast<const QmakeProFile *>(priFile))
|
||||
allFiles.unite(priFile->collectFiles(type));
|
||||
}
|
||||
@@ -222,7 +224,7 @@ void QmakePriFile::scheduleUpdate()
|
||||
{
|
||||
QTC_ASSERT(m_buildSystem, return);
|
||||
QtSupport::ProFileCacheManager::instance()->discardFile(
|
||||
filePath().toString(), m_buildSystem->qmakeVfs());
|
||||
deviceRoot(), filePath().path(), m_buildSystem->qmakeVfs());
|
||||
m_qmakeProFile->scheduleUpdate(QmakeProFile::ParseLater);
|
||||
}
|
||||
|
||||
@@ -277,20 +279,20 @@ static QStringList fileListForVar(
|
||||
return result;
|
||||
}
|
||||
|
||||
void QmakePriFile::extractSources(
|
||||
static void extractSources(const QString &device,
|
||||
QHash<int, QmakePriFileEvalResult *> proToResult, QmakePriFileEvalResult *fallback,
|
||||
QVector<ProFileEvaluator::SourceFile> sourceFiles, FileType type, bool cumulative)
|
||||
const QVector<ProFileEvaluator::SourceFile> &sourceFiles, FileType type, bool cumulative)
|
||||
{
|
||||
for (const ProFileEvaluator::SourceFile &source : std::as_const(sourceFiles)) {
|
||||
for (const ProFileEvaluator::SourceFile &source : sourceFiles) {
|
||||
auto *result = proToResult.value(source.proFileId);
|
||||
if (!result)
|
||||
result = fallback;
|
||||
auto &foundFiles = cumulative ? result->foundFilesCumulative : result->foundFilesExact;
|
||||
foundFiles[type].insert(FilePath::fromString(source.fileName));
|
||||
foundFiles[type].insert(FilePath::fromUserInput(device + source.fileName));
|
||||
}
|
||||
}
|
||||
|
||||
void QmakePriFile::extractInstalls(
|
||||
static void extractInstalls(const QString &device,
|
||||
QHash<int, QmakePriFileEvalResult *> proToResult, QmakePriFileEvalResult *fallback,
|
||||
const InstallsList &installList)
|
||||
{
|
||||
@@ -299,7 +301,7 @@ void QmakePriFile::extractInstalls(
|
||||
auto *result = proToResult.value(source.proFileId);
|
||||
if (!result)
|
||||
result = fallback;
|
||||
result->folders.insert(FilePath::fromString(source.fileName));
|
||||
result->folders.insert(FilePath::fromUserInput(device + source.fileName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -675,7 +677,7 @@ bool QmakePriFile::saveModifiedEditors()
|
||||
|
||||
// force instant reload of ourselves
|
||||
QtSupport::ProFileCacheManager::instance()->discardFile(
|
||||
filePath().toString(), m_buildSystem->qmakeVfs());
|
||||
deviceRoot(), filePath().path(), m_buildSystem->qmakeVfs());
|
||||
|
||||
m_buildSystem->notifyChanged(filePath());
|
||||
return true;
|
||||
@@ -760,7 +762,8 @@ QPair<ProFile *, QStringList> QmakePriFile::readProFile()
|
||||
QMakeVfs vfs;
|
||||
QtSupport::ProMessageHandler handler;
|
||||
QMakeParser parser(nullptr, &vfs, &handler);
|
||||
includeFile = parser.parsedProBlock(QStringView(contents),
|
||||
includeFile = parser.parsedProBlock(deviceRoot(),
|
||||
QStringView(contents),
|
||||
0,
|
||||
filePath().toString(),
|
||||
1);
|
||||
@@ -785,12 +788,12 @@ bool QmakePriFile::renameFile(const FilePath &oldFilePath, const FilePath &newFi
|
||||
if (!includeFile)
|
||||
return false;
|
||||
|
||||
QDir priFileDir = QDir(m_qmakeProFile->directoryPath().toString());
|
||||
QDir priFileDir = QDir(m_qmakeProFile->directoryPath().toFSPathString());
|
||||
ProWriter::VarLocations removedLocations;
|
||||
const QStringList notChanged = ProWriter::removeFiles(includeFile,
|
||||
&lines,
|
||||
priFileDir,
|
||||
{oldFilePath.toString()},
|
||||
{oldFilePath.path()},
|
||||
varNamesForRemoving(),
|
||||
&removedLocations);
|
||||
|
||||
@@ -807,9 +810,10 @@ bool QmakePriFile::renameFile(const FilePath &oldFilePath, const FilePath &newFi
|
||||
|
||||
// Reparse necessary due to changed contents.
|
||||
QMakeParser parser(nullptr, nullptr, nullptr);
|
||||
ProFile *const proFile = parser.parsedProBlock(QStringView(currentContents),
|
||||
ProFile *const proFile = parser.parsedProBlock(deviceRoot(),
|
||||
QStringView(currentContents),
|
||||
0,
|
||||
filePath().toString(),
|
||||
filePath().path(),
|
||||
1,
|
||||
QMakeParser::FullGrammar);
|
||||
QTC_ASSERT(proFile, return); // The file should still be valid after what we did.
|
||||
@@ -1057,11 +1061,11 @@ QSet<FilePath> QmakePriFile::filterFilesProVariables(FileType fileType, const QS
|
||||
QSet<FilePath> result;
|
||||
if (fileType == FileType::QML) {
|
||||
for (const FilePath &file : files)
|
||||
if (file.toString().endsWith(QLatin1String(".qml")))
|
||||
if (file.endsWith(QLatin1String(".qml")))
|
||||
result << file;
|
||||
} else {
|
||||
for (const FilePath &file : files)
|
||||
if (!file.toString().endsWith(QLatin1String(".qml")))
|
||||
if (!file.endsWith(QLatin1String(".qml")))
|
||||
result << file;
|
||||
}
|
||||
return result;
|
||||
@@ -1074,11 +1078,11 @@ QSet<FilePath> QmakePriFile::filterFilesRecursiveEnumerata(FileType fileType, co
|
||||
return result;
|
||||
if (fileType == FileType::QML) {
|
||||
for (const FilePath &file : files)
|
||||
if (file.toString().endsWith(QLatin1String(".qml")))
|
||||
if (file.endsWith(QLatin1String(".qml")))
|
||||
result << file;
|
||||
} else {
|
||||
for (const FilePath &file : files)
|
||||
if (!file.toString().endsWith(QLatin1String(".qml")))
|
||||
if (!file.endsWith(QLatin1String(".qml")))
|
||||
result << file;
|
||||
}
|
||||
return result;
|
||||
@@ -1298,7 +1302,7 @@ bool QmakeProFile::isFileFromWildcard(const QString &filePath) const
|
||||
QmakeEvalInput QmakeProFile::evalInput() const
|
||||
{
|
||||
QmakeEvalInput input;
|
||||
input.projectDir = directoryPath().toFSPathString();
|
||||
input.projectDir = directoryPath().path();
|
||||
input.projectFilePath = filePath();
|
||||
input.buildDirectory = m_buildSystem->buildDir(m_filePath);
|
||||
input.sysroot = m_buildSystem->qmakeSysroot();
|
||||
@@ -1367,8 +1371,8 @@ QmakeEvalResultPtr QmakeProFile::evaluate(const QmakeEvalInput &input)
|
||||
QmakeEvalResultPtr result(new QmakeEvalResult);
|
||||
QtSupport::ProFileReader *exactBuildPassReader = nullptr;
|
||||
QtSupport::ProFileReader *cumulativeBuildPassReader = nullptr;
|
||||
ProFile *pro;
|
||||
if ((pro = input.readerExact->parsedProFile(input.projectFilePath.toFSPathString()))) {
|
||||
ProFile *pro = input.readerExact->parsedProFile(input.qmakeGlobals->device_root, input.projectFilePath.path());
|
||||
if (pro) {
|
||||
bool exactOk = evaluateOne(input, pro, input.readerExact, false, &exactBuildPassReader);
|
||||
bool cumulOk = evaluateOne(input, pro, input.readerCumulative, true, &cumulativeBuildPassReader);
|
||||
pro->deref();
|
||||
@@ -1471,10 +1475,11 @@ QmakeEvalResultPtr QmakeProFile::evaluate(const QmakeEvalInput &input)
|
||||
QHash<QString, QVector<ProFileEvaluator::SourceFile>> exactSourceFiles;
|
||||
QHash<QString, QVector<ProFileEvaluator::SourceFile>> cumulativeSourceFiles;
|
||||
|
||||
const QString &device = input.qmakeGlobals->device_root;
|
||||
const QStringList baseVPathsExact
|
||||
= baseVPaths(exactReader, input.projectDir, input.buildDirectory.toFSPathString());
|
||||
= baseVPaths(exactReader, input.projectDir, input.buildDirectory.path());
|
||||
const QStringList baseVPathsCumulative
|
||||
= baseVPaths(cumulativeReader, input.projectDir, input.buildDirectory.toFSPathString());
|
||||
= baseVPaths(cumulativeReader, input.projectDir, input.buildDirectory.path());
|
||||
|
||||
for (int i = 0; i < static_cast<int>(FileType::FileTypeSize); ++i) {
|
||||
const auto type = static_cast<FileType>(i);
|
||||
@@ -1487,14 +1492,14 @@ QmakeEvalResultPtr QmakeProFile::evaluate(const QmakeEvalInput &input)
|
||||
auto sourceFiles = exactReader->absoluteFileValues(
|
||||
qmakeVariable, input.projectDir, vPathsExact, &handled, result->directoriesWithWildcards);
|
||||
exactSourceFiles[qmakeVariable] = sourceFiles;
|
||||
extractSources(proToResult, &result->includedFiles.result, sourceFiles, type, false);
|
||||
extractSources(device, proToResult, &result->includedFiles.result, sourceFiles, type, false);
|
||||
}
|
||||
const QStringList vPathsCumulative = fullVPaths(
|
||||
baseVPathsCumulative, cumulativeReader, qmakeVariable, input.projectDir);
|
||||
auto sourceFiles = cumulativeReader->absoluteFileValues(
|
||||
qmakeVariable, input.projectDir, vPathsCumulative, &handled, result->directoriesWithWildcards);
|
||||
cumulativeSourceFiles[qmakeVariable] = sourceFiles;
|
||||
extractSources(proToResult, &result->includedFiles.result, sourceFiles, type, true);
|
||||
extractSources(device, proToResult, &result->includedFiles.result, sourceFiles, type, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1504,10 +1509,10 @@ QmakeEvalResultPtr QmakeProFile::evaluate(const QmakeEvalInput &input)
|
||||
// watching bogus paths. However, we accept the values even if the evaluation
|
||||
// failed, to at least have a best-effort result.
|
||||
result->installsList = installsList(exactBuildPassReader,
|
||||
input.projectFilePath.toFSPathString(),
|
||||
input.projectFilePath.path(),
|
||||
input.projectDir,
|
||||
input.buildDirectory.toFSPathString());
|
||||
extractInstalls(proToResult, &result->includedFiles.result, result->installsList);
|
||||
input.buildDirectory.path());
|
||||
extractInstalls(device, proToResult, &result->includedFiles.result, result->installsList);
|
||||
|
||||
if (result->state == QmakeEvalResult::EvalOk) {
|
||||
result->targetInformation = targetInformation(input.readerExact, exactBuildPassReader,
|
||||
@@ -1535,7 +1540,7 @@ QmakeEvalResultPtr QmakeProFile::evaluate(const QmakeEvalInput &input)
|
||||
result->newVarValues[Variable::CumulativeResource] = fileListForVar(cumulativeSourceFiles, QLatin1String("RESOURCES"));
|
||||
result->newVarValues[Variable::PkgConfig] = exactReader->values(QLatin1String("PKGCONFIG"));
|
||||
result->newVarValues[Variable::PrecompiledHeader] = ProFileEvaluator::sourcesToFiles(exactReader->fixifiedValues(
|
||||
QLatin1String("PRECOMPILED_HEADER"), input.projectDir, input.buildDirectory.toFSPathString(), false));
|
||||
QLatin1String("PRECOMPILED_HEADER"), input.projectDir, input.buildDirectory.path(), false));
|
||||
result->newVarValues[Variable::LibDirectories] = libDirectories(exactReader);
|
||||
result->newVarValues[Variable::Config] = exactReader->values(QLatin1String("CONFIG"));
|
||||
result->newVarValues[Variable::QmlImportPath] = exactReader->absolutePathValues(
|
||||
@@ -1808,7 +1813,7 @@ QString QmakeProFile::sysrootify(const QString &path, const QString &sysroot,
|
||||
return path;
|
||||
}
|
||||
QString sysrooted = QDir::cleanPath(sysroot + path);
|
||||
return !IoUtils::exists(sysrooted) ? path : sysrooted;
|
||||
return !IoUtils::exists({}, sysrooted) ? path : sysrooted;
|
||||
}
|
||||
|
||||
QStringList QmakeProFile::includePaths(QtSupport::ProFileReader *reader, const FilePath &sysroot,
|
||||
@@ -1836,13 +1841,13 @@ QStringList QmakeProFile::includePaths(QtSupport::ProFileReader *reader, const F
|
||||
const QString uiDir = uiDirPath(reader, buildDir);
|
||||
|
||||
const QVector<ProFileEvaluator::SourceFile> elList = reader->fixifiedValues(
|
||||
QLatin1String("INCLUDEPATH"), projectDir, buildDir.toFSPathString(), false);
|
||||
QLatin1String("INCLUDEPATH"), projectDir, buildDir.path(), false);
|
||||
for (const ProFileEvaluator::SourceFile &el : elList) {
|
||||
const QString sysrootifiedPath = sysrootify(el.fileName, sysroot.toFSPathString(),
|
||||
const QString sysrootifiedPath = sysrootify(el.fileName, sysroot.path(),
|
||||
projectDir,
|
||||
buildDir.toFSPathString());
|
||||
if (IoUtils::isAbsolutePath(sysrootifiedPath)
|
||||
&& (IoUtils::exists(sysrootifiedPath) || sysrootifiedPath == mocDir
|
||||
buildDir.path());
|
||||
if (IoUtils::isAbsolutePath({}, sysrootifiedPath)
|
||||
&& (IoUtils::exists({}, sysrootifiedPath) || sysrootifiedPath == mocDir
|
||||
|| sysrootifiedPath == uiDir)) {
|
||||
paths << sysrootifiedPath;
|
||||
} else {
|
||||
@@ -1857,7 +1862,7 @@ QStringList QmakeProFile::includePaths(QtSupport::ProFileReader *reader, const F
|
||||
for (const QString &p : rawValues) {
|
||||
const QString sysrootifiedPath = sysrootify(QDir::cleanPath(p), sysroot.toString(),
|
||||
projectDir, buildDir.toString());
|
||||
if (IoUtils::isAbsolutePath(sysrootifiedPath) && IoUtils::exists(sysrootifiedPath))
|
||||
if (IoUtils::isAbsolutePath({}, sysrootifiedPath) && IoUtils::exists({}, sysrootifiedPath))
|
||||
paths << sysrootifiedPath;
|
||||
}
|
||||
}
|
||||
|
@@ -115,8 +115,10 @@ public:
|
||||
virtual ~QmakePriFile();
|
||||
|
||||
void finishInitialization(QmakeBuildSystem *buildSystem, QmakeProFile *qmakeProFile);
|
||||
Utils::FilePath filePath() const;
|
||||
|
||||
const Utils::FilePath &filePath() const { return m_filePath; }
|
||||
Utils::FilePath directoryPath() const;
|
||||
QString deviceRoot() const;
|
||||
virtual QString displayName() const;
|
||||
|
||||
QmakePriFile *parent() const;
|
||||
@@ -205,13 +207,6 @@ private:
|
||||
Utils::FilePaths formResources(const Utils::FilePath &formFile) const;
|
||||
static QStringList baseVPaths(QtSupport::ProFileReader *reader, const QString &projectDir, const QString &buildDir);
|
||||
static QStringList fullVPaths(const QStringList &baseVPaths, QtSupport::ProFileReader *reader, const QString &qmakeVariable, const QString &projectDir);
|
||||
static void extractSources(QHash<int, Internal::QmakePriFileEvalResult *> proToResult,
|
||||
Internal::QmakePriFileEvalResult *fallback,
|
||||
QVector<ProFileEvaluator::SourceFile> sourceFiles, ProjectExplorer::FileType type, bool cumulative);
|
||||
static void extractInstalls(
|
||||
QHash<int, Internal::QmakePriFileEvalResult *> proToResult,
|
||||
Internal::QmakePriFileEvalResult *fallback,
|
||||
const InstallsList &installList);
|
||||
static void processValues(Internal::QmakePriFileEvalResult &result);
|
||||
void watchFolders(const QSet<Utils::FilePath> &folders);
|
||||
|
||||
|
@@ -416,6 +416,7 @@ void QmakeBuildSystem::updateQmlJSCodeModel()
|
||||
project()->files(Project::HiddenRccFolders));
|
||||
|
||||
const QList<QmakeProFile *> proFiles = rootProFile()->allProFiles();
|
||||
const QString device = rootProFile()->deviceRoot();
|
||||
|
||||
projectInfo.importPaths.clear();
|
||||
|
||||
@@ -433,7 +434,7 @@ void QmakeBuildSystem::updateQmlJSCodeModel()
|
||||
projectInfo.activeResourceFiles.append(rcPath);
|
||||
projectInfo.allResourceFiles.append(rcPath);
|
||||
QString contents;
|
||||
int id = m_qmakeVfs->idForFileName(rc, QMakeVfs::VfsExact);
|
||||
int id = m_qmakeVfs->idForFileName(device + rc, QMakeVfs::VfsExact);
|
||||
if (m_qmakeVfs->readFile(id, &contents, &errorMessage) == QMakeVfs::ReadOk)
|
||||
projectInfo.resourceFileContents[rcPath] = contents;
|
||||
}
|
||||
@@ -441,7 +442,7 @@ void QmakeBuildSystem::updateQmlJSCodeModel()
|
||||
FilePath rcPath = FilePath::fromString(rc);
|
||||
projectInfo.allResourceFiles.append(rcPath);
|
||||
QString contents;
|
||||
int id = m_qmakeVfs->idForFileName(rc, QMakeVfs::VfsCumulative);
|
||||
int id = m_qmakeVfs->idForFileName(device + rc, QMakeVfs::VfsCumulative);
|
||||
if (m_qmakeVfs->readFile(id, &contents, &errorMessage) == QMakeVfs::ReadOk)
|
||||
projectInfo.resourceFileContents[rcPath] = contents;
|
||||
}
|
||||
@@ -856,12 +857,14 @@ QtSupport::ProFileReader *QmakeBuildSystem::createProFileReader(const QmakeProFi
|
||||
|
||||
if (qtVersion && qtVersion->isValid()) {
|
||||
m_qmakeGlobals->qmake_abslocation =
|
||||
QDir::cleanPath(qtVersion->qmakeFilePath().toFSPathString());
|
||||
QDir::cleanPath(qtVersion->qmakeFilePath().path());
|
||||
qtVersion->applyProperties(m_qmakeGlobals.get());
|
||||
}
|
||||
|
||||
QString rootProFileName = buildDir(rootProFile()->filePath()).toFSPathString();
|
||||
m_qmakeGlobals->setDirectories(rootProFile()->sourceDir().toFSPathString(), rootProFileName);
|
||||
QString rootProFileName = buildDir(rootProFile()->filePath()).path();
|
||||
m_qmakeGlobals->setDirectories(rootProFile()->sourceDir().path(),
|
||||
rootProFileName,
|
||||
deviceRoot());
|
||||
|
||||
Environment::const_iterator eit = env.constBegin(), eend = env.constEnd();
|
||||
for (; eit != eend; ++eit)
|
||||
@@ -891,7 +894,7 @@ QtSupport::ProFileReader *QmakeBuildSystem::createProFileReader(const QmakeProFi
|
||||
auto reader = new QtSupport::ProFileReader(m_qmakeGlobals.get(), m_qmakeVfs);
|
||||
|
||||
// Core parts of the ProParser hard-assert on non-local items
|
||||
reader->setOutputDir(buildDir(qmakeProFile->filePath()).toFSPathString());
|
||||
reader->setOutputDir(buildDir(qmakeProFile->filePath()).path());
|
||||
|
||||
return reader;
|
||||
}
|
||||
@@ -926,10 +929,10 @@ void QmakeBuildSystem::destroyProFileReader(QtSupport::ProFileReader *reader)
|
||||
|
||||
void QmakeBuildSystem::deregisterFromCacheManager()
|
||||
{
|
||||
QString dir = projectFilePath().toFSPathString();
|
||||
QString dir = projectFilePath().path();
|
||||
if (!dir.endsWith(QLatin1Char('/')))
|
||||
dir += QLatin1Char('/');
|
||||
QtSupport::ProFileCacheManager::instance()->discardFiles(dir, qmakeVfs());
|
||||
QtSupport::ProFileCacheManager::instance()->discardFiles(deviceRoot(), dir, qmakeVfs());
|
||||
QtSupport::ProFileCacheManager::instance()->decRefCount();
|
||||
}
|
||||
|
||||
@@ -947,7 +950,7 @@ static void notifyChangedHelper(const FilePath &fileName, QmakeProFile *file)
|
||||
{
|
||||
if (file->filePath() == fileName) {
|
||||
QtSupport::ProFileCacheManager::instance()->discardFile(
|
||||
fileName.toString(), file->buildSystem()->qmakeVfs());
|
||||
file->deviceRoot(), fileName.path(), file->buildSystem()->qmakeVfs());
|
||||
file->scheduleUpdate(QmakeProFile::ParseNow);
|
||||
}
|
||||
|
||||
@@ -1439,6 +1442,13 @@ void QmakeBuildSystem::testToolChain(ToolChain *tc, const FilePath &path) const
|
||||
m_toolChainWarnings.insert(pair);
|
||||
}
|
||||
|
||||
QString QmakeBuildSystem::deviceRoot() const
|
||||
{
|
||||
if (projectFilePath().needsDevice())
|
||||
return projectFilePath().withNewPath("/").toFSPathString();
|
||||
return {};
|
||||
}
|
||||
|
||||
void QmakeBuildSystem::warnOnToolChainMismatch(const QmakeProFile *pro) const
|
||||
{
|
||||
const BuildConfiguration *bc = buildConfiguration();
|
||||
|
@@ -113,6 +113,8 @@ public:
|
||||
void warnOnToolChainMismatch(const QmakeProFile *pro) const;
|
||||
void testToolChain(ProjectExplorer::ToolChain *tc, const Utils::FilePath &path) const;
|
||||
|
||||
QString deviceRoot() const;
|
||||
|
||||
/// \internal
|
||||
QtSupport::ProFileReader *createProFileReader(const QmakeProFile *qmakeProFile);
|
||||
/// \internal
|
||||
|
@@ -1123,12 +1123,11 @@ void QtVersion::ensureMkSpecParsed() const
|
||||
Environment env = d->m_qmakeCommand.deviceEnvironment();
|
||||
setupQmakeRunEnvironment(env);
|
||||
option.environment = env.toProcessEnvironment();
|
||||
option.device_root = d->m_qmakeCommand.withNewPath("/").toFSPathString();
|
||||
ProMessageHandler msgHandler(true);
|
||||
ProFileCacheManager::instance()->incRefCount();
|
||||
QMakeParser parser(ProFileCacheManager::instance()->cache(), &vfs, &msgHandler);
|
||||
ProFileEvaluator evaluator(&option, &parser, &vfs, &msgHandler);
|
||||
// FIXME: toString() would be better, but the pro parser Q_ASSERTs on anything
|
||||
// non-local.
|
||||
evaluator.loadNamedSpec(mkspecPath().path(), false);
|
||||
|
||||
parseMkSpec(&evaluator);
|
||||
@@ -1165,7 +1164,7 @@ void QtVersion::setId(int id)
|
||||
QString QtVersion::mkspec() const
|
||||
{
|
||||
d->updateMkspec();
|
||||
return d->m_mkspec.toString();
|
||||
return d->m_mkspec.toFSPathString();
|
||||
}
|
||||
|
||||
QString QtVersion::mkspecFor(ToolChain *tc) const
|
||||
|
@@ -170,14 +170,14 @@ void ProFileCacheManager::clear()
|
||||
m_cache = nullptr;
|
||||
}
|
||||
|
||||
void ProFileCacheManager::discardFiles(const QString &prefix, QMakeVfs *vfs)
|
||||
void ProFileCacheManager::discardFiles(const QString &device, const QString &prefix, QMakeVfs *vfs)
|
||||
{
|
||||
if (m_cache)
|
||||
m_cache->discardFiles(prefix, vfs);
|
||||
m_cache->discardFiles(device, prefix, vfs);
|
||||
}
|
||||
|
||||
void ProFileCacheManager::discardFile(const QString &fileName, QMakeVfs *vfs)
|
||||
void ProFileCacheManager::discardFile(const QString &device, const QString &fileName, QMakeVfs *vfs)
|
||||
{
|
||||
if (m_cache)
|
||||
m_cache->discardFile(fileName, vfs);
|
||||
m_cache->discardFile(device, fileName, vfs);
|
||||
}
|
||||
|
@@ -67,8 +67,8 @@ class QTSUPPORT_EXPORT ProFileCacheManager : public QObject
|
||||
public:
|
||||
static ProFileCacheManager *instance() { return s_instance; }
|
||||
ProFileCache *cache();
|
||||
void discardFiles(const QString &prefix, QMakeVfs *vfs);
|
||||
void discardFile(const QString &fileName, QMakeVfs *vfs);
|
||||
void discardFiles(const QString &device, const QString &prefix, QMakeVfs *vfs);
|
||||
void discardFile(const QString &device, const QString &fileName, QMakeVfs *vfs);
|
||||
void incRefCount();
|
||||
void decRefCount();
|
||||
|
||||
|
@@ -27,9 +27,12 @@
|
||||
#include <projectexplorer/session.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <proparser/qmakeevaluator.h>
|
||||
|
||||
#include <utils/filepath.h>
|
||||
#include <utils/infobar.h>
|
||||
#include <utils/macroexpander.h>
|
||||
#include <utils/qtcprocess.h>
|
||||
|
||||
using namespace Core;
|
||||
using namespace Utils;
|
||||
@@ -65,8 +68,28 @@ QtSupportPlugin::~QtSupportPlugin()
|
||||
delete d;
|
||||
}
|
||||
|
||||
static void processRunnerCallback(ProcessData *data)
|
||||
{
|
||||
FilePath rootPath = FilePath::fromString(data->deviceRoot);
|
||||
|
||||
QtcProcess proc;
|
||||
proc.setProcessChannelMode(data->processChannelMode);
|
||||
proc.setCommand({rootPath.withNewPath("/bin/sh"), {QString("-c"), data->command}});
|
||||
proc.setWorkingDirectory(FilePath::fromString(data->workingDirectory));
|
||||
proc.setEnvironment(Environment(data->environment.toStringList(), OsTypeLinux));
|
||||
|
||||
proc.runBlocking();
|
||||
|
||||
data->exitCode = proc.exitCode();
|
||||
data->exitStatus = proc.exitStatus();
|
||||
data->stdErr = proc.readAllStandardError();
|
||||
data->stdOut = proc.readAllStandardOutput();
|
||||
}
|
||||
|
||||
bool QtSupportPlugin::initialize(const QStringList &arguments, QString *errorMessage)
|
||||
{
|
||||
theProcessRunner() = processRunnerCallback;
|
||||
|
||||
Q_UNUSED(arguments)
|
||||
Q_UNUSED(errorMessage)
|
||||
QMakeParser::initialize();
|
||||
|
@@ -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,17 +70,25 @@ 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
|
||||
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()
|
||||
@@ -82,10 +101,9 @@ bool IoUtils::isRelativePath(const QString &path)
|
||||
&& path.at(1) == path.at(0)) {
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if (path.startsWith(QLatin1Char('/')))
|
||||
} 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 (isWindows(device)) {
|
||||
// Add drive to otherwise-absolute path:
|
||||
if (fileName.at(0).unicode() == '/' || fileName.at(0).unicode() == '\\') {
|
||||
return isAbsolutePath(baseDir) ? QDir::cleanPath(baseDir.left(2) + fileName)
|
||||
return isAbsolutePath(device, baseDir) ? QDir::cleanPath(baseDir.left(2) + fileName)
|
||||
: QDir::cleanPath(fileName);
|
||||
}
|
||||
#endif // Q_OS_WIN
|
||||
} else {
|
||||
if (fileName.at(0).unicode() == '/' || fileName.at(0).unicode() == '\\')
|
||||
return fileName;
|
||||
}
|
||||
|
||||
return QDir::cleanPath(baseDir + QLatin1Char('/') + fileName);
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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('?'))) {
|
||||
|
@@ -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()
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
@@ -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
|
||||
|
@@ -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();
|
||||
|
@@ -454,7 +454,8 @@ void tst_ProFileWriter::adds()
|
||||
|
||||
QMakeVfs vfs;
|
||||
QMakeParser parser(0, &vfs, &parseHandler);
|
||||
ProFile *proFile = parser.parsedProBlock(QStringView(input),
|
||||
ProFile *proFile = parser.parsedProBlock(QString(), // device
|
||||
QStringView(input),
|
||||
0,
|
||||
QLatin1String(BASE_DIR "/test.pro"),
|
||||
1);
|
||||
@@ -628,7 +629,8 @@ void tst_ProFileWriter::removes()
|
||||
|
||||
QMakeVfs vfs;
|
||||
QMakeParser parser(0, &vfs, &parseHandler);
|
||||
ProFile *proFile = parser.parsedProBlock(QStringView(input),
|
||||
ProFile *proFile = parser.parsedProBlock(QString(), // device
|
||||
QStringView(input),
|
||||
0,
|
||||
QLatin1String(BASE_DIR "/test.pro"),
|
||||
1);
|
||||
@@ -660,7 +662,8 @@ void tst_ProFileWriter::multiVar()
|
||||
|
||||
QMakeVfs vfs;
|
||||
QMakeParser parser(0, &vfs, &parseHandler);
|
||||
ProFile *proFile = parser.parsedProBlock(QStringView(input),
|
||||
ProFile *proFile = parser.parsedProBlock(QString(), // device
|
||||
QStringView(input),
|
||||
0,
|
||||
QLatin1String(BASE_DIR "/test.pro"),
|
||||
1);
|
||||
@@ -683,7 +686,8 @@ void tst_ProFileWriter::addFiles()
|
||||
|
||||
QMakeVfs vfs;
|
||||
QMakeParser parser(0, &vfs, &parseHandler);
|
||||
ProFile *proFile = parser.parsedProBlock(QStringView(input),
|
||||
ProFile *proFile = parser.parsedProBlock(QString(), // device
|
||||
QStringView(input),
|
||||
0,
|
||||
BASE_DIR "/test.pro",
|
||||
1);
|
||||
@@ -709,7 +713,8 @@ void tst_ProFileWriter::removeFiles()
|
||||
|
||||
QMakeVfs vfs;
|
||||
QMakeParser parser(0, &vfs, &parseHandler);
|
||||
ProFile *proFile = parser.parsedProBlock(QStringView(input),
|
||||
ProFile *proFile = parser.parsedProBlock(QString(), // device
|
||||
QStringView(input),
|
||||
0,
|
||||
QLatin1String(BASE_DIR "/test.pro"),
|
||||
1);
|
||||
|
@@ -58,9 +58,9 @@ static int evaluate(const QString &fileName, const QString &in_pwd, const QStrin
|
||||
#endif
|
||||
visitor.setOutputDir(out_pwd);
|
||||
|
||||
ProFile *pro;
|
||||
if (!(pro = parser->parsedProFile(fileName))) {
|
||||
if (!QFile::exists(fileName)) {
|
||||
ProFile *pro = parser->parsedProFile(option->device_root, fileName);
|
||||
if (!pro) {
|
||||
if (!QFileInfo::exists(option->device_root + fileName)) {
|
||||
qCritical("Input file %s does not exist.", qPrintable(fileName));
|
||||
return 3;
|
||||
}
|
||||
@@ -171,7 +171,7 @@ int main(int argc, char **argv)
|
||||
option.useEnvironment();
|
||||
if (out_pwd.isEmpty())
|
||||
out_pwd = in_pwd;
|
||||
option.setDirectories(in_pwd, out_pwd);
|
||||
option.setDirectories(in_pwd, out_pwd, {});
|
||||
|
||||
QMakeVfs vfs;
|
||||
QMakeParser parser(0, &vfs, &evalHandler);
|
||||
|
Reference in New Issue
Block a user