2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2020 Alexis Jeandet.
|
2022-12-21 10:12:09 +01:00
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
2020-10-29 10:20:14 +01:00
|
|
|
|
2020-05-01 18:20:56 +02:00
|
|
|
#include "mesonprojectparser.h"
|
2020-10-29 10:20:14 +01:00
|
|
|
|
2022-10-06 16:58:18 +02:00
|
|
|
#include "mesoninfoparser.h"
|
2023-09-27 18:03:18 +02:00
|
|
|
#include "mesonprojectmanagertr.h"
|
2022-10-06 16:58:18 +02:00
|
|
|
#include "mesonprojectnodes.h"
|
|
|
|
|
#include "mesontools.h"
|
|
|
|
|
#include "projecttree.h"
|
2020-05-01 18:20:56 +02:00
|
|
|
|
2023-09-27 18:03:18 +02:00
|
|
|
#include <coreplugin/messagemanager.h>
|
2020-05-01 18:20:56 +02:00
|
|
|
#include <coreplugin/messagemanager.h>
|
2020-10-29 10:20:14 +01:00
|
|
|
|
2020-05-01 18:20:56 +02:00
|
|
|
#include <projectexplorer/projectexplorer.h>
|
2023-09-27 18:03:18 +02:00
|
|
|
#include <projectexplorer/projectexplorerconstants.h>
|
|
|
|
|
#include <projectexplorer/taskhub.h>
|
2020-10-29 10:20:14 +01:00
|
|
|
|
2023-05-03 15:05:47 +02:00
|
|
|
#include <utils/async.h>
|
2023-09-27 18:03:18 +02:00
|
|
|
#include <utils/environment.h>
|
2020-05-01 18:20:56 +02:00
|
|
|
#include <utils/fileinprojectfinder.h>
|
2023-09-27 18:03:18 +02:00
|
|
|
#include <utils/stringutils.h>
|
2020-05-01 18:20:56 +02:00
|
|
|
|
2022-08-26 10:30:00 +02:00
|
|
|
#include <optional>
|
|
|
|
|
|
2023-09-27 18:03:18 +02:00
|
|
|
#include <coreplugin/progressmanager/processprogress.h>
|
|
|
|
|
|
|
|
|
|
using namespace Core;
|
|
|
|
|
using namespace ProjectExplorer;
|
|
|
|
|
using namespace Utils;
|
|
|
|
|
|
2020-05-01 18:20:56 +02:00
|
|
|
namespace MesonProjectManager {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2023-09-27 18:03:18 +02:00
|
|
|
static Q_LOGGING_CATEGORY(mesonProcessLog, "qtc.meson.buildsystem", QtWarningMsg);
|
|
|
|
|
|
2020-05-01 18:20:56 +02:00
|
|
|
struct CompilerArgs
|
|
|
|
|
{
|
|
|
|
|
QStringList args;
|
|
|
|
|
QStringList includePaths;
|
2023-09-27 18:31:52 +02:00
|
|
|
Macros macros;
|
2020-05-01 18:20:56 +02:00
|
|
|
};
|
|
|
|
|
|
2023-09-27 18:03:18 +02:00
|
|
|
static std::optional<QString> extractValueIfMatches(const QString &arg,
|
|
|
|
|
const QStringList &candidates)
|
2020-05-01 18:20:56 +02:00
|
|
|
{
|
|
|
|
|
for (const auto &flag : candidates) {
|
|
|
|
|
if (arg.startsWith(flag))
|
|
|
|
|
return arg.mid(flag.length());
|
|
|
|
|
}
|
2022-08-26 10:30:00 +02:00
|
|
|
return std::nullopt;
|
2020-05-01 18:20:56 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-27 18:03:18 +02:00
|
|
|
static std::optional<QString> extractInclude(const QString &arg)
|
2020-05-01 18:20:56 +02:00
|
|
|
{
|
|
|
|
|
return extractValueIfMatches(arg, {"-I", "/I", "-isystem", "-imsvc", "/imsvc"});
|
|
|
|
|
}
|
2023-09-27 18:03:18 +02:00
|
|
|
|
2023-09-27 18:31:52 +02:00
|
|
|
static std::optional<Macro> extractMacro(const QString &arg)
|
2020-05-01 18:20:56 +02:00
|
|
|
{
|
|
|
|
|
auto define = extractValueIfMatches(arg, {"-D", "/D"});
|
|
|
|
|
if (define)
|
2023-09-27 18:31:52 +02:00
|
|
|
return Macro::fromKeyValue(define->toLatin1());
|
2020-05-01 18:20:56 +02:00
|
|
|
auto undef = extractValueIfMatches(arg, {"-U", "/U"});
|
|
|
|
|
if (undef)
|
2023-09-27 18:31:52 +02:00
|
|
|
return Macro(undef->toLatin1(), MacroType::Undefine);
|
2022-08-26 10:30:00 +02:00
|
|
|
return std::nullopt;
|
2020-05-01 18:20:56 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-27 18:31:52 +02:00
|
|
|
static CompilerArgs splitArgs(const QStringList &args)
|
2020-05-01 18:20:56 +02:00
|
|
|
{
|
|
|
|
|
CompilerArgs splited;
|
2020-10-27 17:58:55 +01:00
|
|
|
for (const QString &arg : args) {
|
2020-05-01 18:20:56 +02:00
|
|
|
auto inc = extractInclude(arg);
|
|
|
|
|
if (inc) {
|
|
|
|
|
splited.includePaths << *inc;
|
|
|
|
|
} else {
|
|
|
|
|
auto macro = extractMacro(arg);
|
|
|
|
|
if (macro) {
|
|
|
|
|
splited.macros << *macro;
|
|
|
|
|
} else {
|
|
|
|
|
splited.args << arg;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-10-27 17:58:55 +01:00
|
|
|
}
|
2020-05-01 18:20:56 +02:00
|
|
|
return splited;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-27 18:31:52 +02:00
|
|
|
static QStringList toAbsolutePath(const FilePath &refPath, QStringList &pathList)
|
2020-05-01 18:20:56 +02:00
|
|
|
{
|
|
|
|
|
QStringList allAbs;
|
|
|
|
|
std::transform(std::cbegin(pathList),
|
|
|
|
|
std::cend(pathList),
|
|
|
|
|
std::back_inserter(allAbs),
|
|
|
|
|
[refPath](const QString &path) {
|
2022-11-30 13:59:42 +01:00
|
|
|
return refPath.resolvePath(path).toString();
|
2020-05-01 18:20:56 +02:00
|
|
|
});
|
|
|
|
|
return allAbs;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-27 18:31:52 +02:00
|
|
|
MesonProjectParser::MesonProjectParser(const Id &meson, const Environment &env, Project *project)
|
2020-05-01 18:20:56 +02:00
|
|
|
: m_env{env}
|
|
|
|
|
, m_meson{meson}
|
|
|
|
|
, m_projectName{project->displayName()}
|
|
|
|
|
{
|
|
|
|
|
// TODO re-think the way all BuildSystem/ProjectParser are tied
|
|
|
|
|
// I take project info here, I also take build and src dir later from
|
|
|
|
|
// functions args.
|
2023-09-27 18:31:52 +02:00
|
|
|
auto fileFinder = new FileInProjectFinder;
|
2020-05-01 18:20:56 +02:00
|
|
|
fileFinder->setProjectDirectory(project->projectDirectory());
|
2023-09-27 18:03:18 +02:00
|
|
|
fileFinder->setProjectFiles(project->files(Project::AllFiles));
|
2020-05-01 18:20:56 +02:00
|
|
|
m_outputParser.setFileFinder(fileFinder);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-27 18:31:52 +02:00
|
|
|
bool MesonProjectParser::configure(const FilePath &sourcePath,
|
|
|
|
|
const FilePath &buildPath,
|
2020-05-01 18:20:56 +02:00
|
|
|
const QStringList &args)
|
|
|
|
|
{
|
|
|
|
|
m_introType = IntroDataType::file;
|
|
|
|
|
m_srcDir = sourcePath;
|
|
|
|
|
m_buildDir = buildPath;
|
|
|
|
|
m_outputParser.setSourceDirectory(sourcePath);
|
|
|
|
|
auto cmd = MesonTools::mesonWrapper(m_meson)->configure(sourcePath, buildPath, args);
|
|
|
|
|
// see comment near m_pendingCommands declaration
|
|
|
|
|
m_pendingCommands.enqueue(
|
2020-06-10 16:17:28 +02:00
|
|
|
std::make_tuple(MesonTools::mesonWrapper(m_meson)->regenerate(sourcePath, buildPath),
|
|
|
|
|
false));
|
2023-09-27 18:03:18 +02:00
|
|
|
return run(cmd, m_env, m_projectName);
|
2020-05-01 18:20:56 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-27 18:31:52 +02:00
|
|
|
bool MesonProjectParser::wipe(const FilePath &sourcePath,
|
|
|
|
|
const FilePath &buildPath,
|
2020-05-01 18:20:56 +02:00
|
|
|
const QStringList &args)
|
|
|
|
|
{
|
|
|
|
|
return setup(sourcePath, buildPath, args, true);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-27 18:31:52 +02:00
|
|
|
bool MesonProjectParser::setup(const FilePath &sourcePath,
|
|
|
|
|
const FilePath &buildPath,
|
2020-05-01 18:20:56 +02:00
|
|
|
const QStringList &args,
|
|
|
|
|
bool forceWipe)
|
|
|
|
|
{
|
|
|
|
|
m_introType = IntroDataType::file;
|
|
|
|
|
m_srcDir = sourcePath;
|
|
|
|
|
m_buildDir = buildPath;
|
|
|
|
|
m_outputParser.setSourceDirectory(sourcePath);
|
|
|
|
|
auto cmdArgs = args;
|
|
|
|
|
if (forceWipe || isSetup(buildPath))
|
|
|
|
|
cmdArgs << "--wipe";
|
|
|
|
|
auto cmd = MesonTools::mesonWrapper(m_meson)->setup(sourcePath, buildPath, cmdArgs);
|
2023-09-27 18:03:18 +02:00
|
|
|
return run(cmd, m_env, m_projectName);
|
2020-05-01 18:20:56 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-27 18:31:52 +02:00
|
|
|
bool MesonProjectParser::parse(const FilePath &sourcePath, const FilePath &buildPath)
|
2020-05-01 18:20:56 +02:00
|
|
|
{
|
|
|
|
|
m_srcDir = sourcePath;
|
|
|
|
|
m_buildDir = buildPath;
|
|
|
|
|
m_outputParser.setSourceDirectory(sourcePath);
|
|
|
|
|
if (!isSetup(buildPath)) {
|
|
|
|
|
return parse(sourcePath);
|
|
|
|
|
} else {
|
|
|
|
|
m_introType = IntroDataType::file;
|
|
|
|
|
return startParser();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-27 18:31:52 +02:00
|
|
|
bool MesonProjectParser::parse(const FilePath &sourcePath)
|
2020-05-01 18:20:56 +02:00
|
|
|
{
|
|
|
|
|
m_srcDir = sourcePath;
|
|
|
|
|
m_introType = IntroDataType::stdo;
|
|
|
|
|
m_outputParser.setSourceDirectory(sourcePath);
|
2023-09-27 18:03:18 +02:00
|
|
|
return run(MesonTools::mesonWrapper(m_meson)->introspect(sourcePath),
|
|
|
|
|
m_env,
|
|
|
|
|
m_projectName,
|
|
|
|
|
true);
|
2020-05-01 18:20:56 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-27 18:03:18 +02:00
|
|
|
QList<BuildTargetInfo> MesonProjectParser::appsTargets() const
|
2020-05-01 18:20:56 +02:00
|
|
|
{
|
2023-09-27 18:03:18 +02:00
|
|
|
QList<BuildTargetInfo> apps;
|
2020-10-27 17:58:55 +01:00
|
|
|
for (const Target &target : m_parserResult.targets) {
|
|
|
|
|
if (target.type == Target::Type::executable) {
|
2023-09-27 18:03:18 +02:00
|
|
|
BuildTargetInfo bti;
|
2020-10-27 17:58:55 +01:00
|
|
|
bti.displayName = target.name;
|
2023-07-10 13:05:52 +02:00
|
|
|
bti.buildKey = Target::fullName(m_buildDir, target);
|
2020-10-27 17:58:55 +01:00
|
|
|
bti.displayNameUniquifier = bti.buildKey;
|
2023-09-27 18:31:52 +02:00
|
|
|
bti.targetFilePath = FilePath::fromString(target.fileName.first());
|
|
|
|
|
bti.workingDirectory = FilePath::fromString(target.fileName.first()).absolutePath();
|
|
|
|
|
bti.projectFilePath = FilePath::fromString(target.definedIn);
|
2020-10-27 17:58:55 +01:00
|
|
|
bti.usesTerminal = true;
|
|
|
|
|
apps.append(bti);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-05-01 18:20:56 +02:00
|
|
|
return apps;
|
|
|
|
|
}
|
2022-10-12 08:26:39 +02:00
|
|
|
|
2020-05-01 18:20:56 +02:00
|
|
|
bool MesonProjectParser::startParser()
|
|
|
|
|
{
|
2023-03-03 22:11:44 +01:00
|
|
|
m_parserFutureResult = Utils::asyncRun(
|
2023-09-27 18:03:18 +02:00
|
|
|
ProjectExplorerPlugin::sharedThreadPool(),
|
|
|
|
|
[processOutput = m_stdo, introType = m_introType,
|
2023-06-13 14:51:48 +02:00
|
|
|
buildDir = m_buildDir, srcDir = m_srcDir] {
|
2022-10-12 08:26:39 +02:00
|
|
|
if (introType == IntroDataType::file)
|
|
|
|
|
return extractParserResults(srcDir, MesonInfoParser::parse(buildDir));
|
|
|
|
|
else
|
|
|
|
|
return extractParserResults(srcDir, MesonInfoParser::parse(processOutput));
|
|
|
|
|
});
|
2020-05-01 18:20:56 +02:00
|
|
|
|
|
|
|
|
Utils::onFinished(m_parserFutureResult, this, &MesonProjectParser::update);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MesonProjectParser::ParserData *MesonProjectParser::extractParserResults(
|
2023-09-27 18:31:52 +02:00
|
|
|
const FilePath &srcDir, MesonInfoParser::Result &&parserResult)
|
2020-05-01 18:20:56 +02:00
|
|
|
{
|
|
|
|
|
auto rootNode = ProjectTree::buildTree(srcDir,
|
|
|
|
|
parserResult.targets,
|
|
|
|
|
parserResult.buildSystemFiles);
|
|
|
|
|
return new ParserData{std::move(parserResult), std::move(rootNode)};
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-27 18:31:52 +02:00
|
|
|
static void addMissingTargets(QStringList &targetList)
|
2020-05-01 18:20:56 +02:00
|
|
|
{
|
|
|
|
|
// Not all targets are listed in introspection data
|
2023-09-27 18:31:52 +02:00
|
|
|
static const QString additionalTargets[] {
|
|
|
|
|
Constants::Targets::all,
|
|
|
|
|
Constants::Targets::clean,
|
|
|
|
|
Constants::Targets::install,
|
|
|
|
|
Constants::Targets::benchmark,
|
|
|
|
|
Constants::Targets::scan_build
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (const QString &target : additionalTargets) {
|
|
|
|
|
if (!targetList.contains(target))
|
2020-05-01 18:20:56 +02:00
|
|
|
targetList.append(target);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MesonProjectParser::update(const QFuture<MesonProjectParser::ParserData *> &data)
|
|
|
|
|
{
|
|
|
|
|
auto parserData = data.result();
|
|
|
|
|
m_parserResult = std::move(parserData->data);
|
|
|
|
|
m_rootNode = std::move(parserData->rootNode);
|
|
|
|
|
m_targetsNames.clear();
|
2020-06-24 09:44:55 +02:00
|
|
|
for (const Target &target : m_parserResult.targets) {
|
2023-07-10 13:05:52 +02:00
|
|
|
m_targetsNames.push_back(Target::fullName(m_buildDir, target));
|
2020-06-24 09:44:55 +02:00
|
|
|
}
|
2020-05-01 18:20:56 +02:00
|
|
|
addMissingTargets(m_targetsNames);
|
|
|
|
|
m_targetsNames.sort();
|
2020-07-31 11:17:14 +02:00
|
|
|
delete parserData;
|
2020-05-01 18:20:56 +02:00
|
|
|
emit parsingCompleted(true);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-27 18:03:18 +02:00
|
|
|
RawProjectPart MesonProjectParser::buildRawPart(
|
2020-05-01 18:20:56 +02:00
|
|
|
const Target &target,
|
|
|
|
|
const Target::SourceGroup &sources,
|
2024-01-22 17:46:28 +01:00
|
|
|
const Toolchain *cxxToolchain,
|
|
|
|
|
const Toolchain *cToolchain)
|
2020-05-01 18:20:56 +02:00
|
|
|
{
|
2023-09-27 18:03:18 +02:00
|
|
|
RawProjectPart part;
|
2020-05-01 18:20:56 +02:00
|
|
|
part.setDisplayName(target.name);
|
2023-07-10 13:05:52 +02:00
|
|
|
part.setBuildSystemTarget(Target::fullName(m_buildDir, target));
|
2020-05-01 18:20:56 +02:00
|
|
|
part.setFiles(sources.sources + sources.generatedSources);
|
2023-09-27 18:31:52 +02:00
|
|
|
CompilerArgs flags = splitArgs(sources.parameters);
|
2020-05-01 18:20:56 +02:00
|
|
|
part.setMacros(flags.macros);
|
2020-06-24 09:44:55 +02:00
|
|
|
part.setIncludePaths(toAbsolutePath(m_buildDir, flags.includePaths));
|
2020-05-01 18:20:56 +02:00
|
|
|
part.setProjectFileLocation(target.definedIn);
|
|
|
|
|
if (sources.language == "cpp")
|
2024-01-22 17:46:28 +01:00
|
|
|
part.setFlagsForCxx({cxxToolchain, flags.args, {}});
|
2020-05-01 18:20:56 +02:00
|
|
|
else if (sources.language == "c")
|
2024-01-22 17:46:28 +01:00
|
|
|
part.setFlagsForC({cToolchain, flags.args, {}});
|
2020-05-01 18:20:56 +02:00
|
|
|
part.setQtVersion(m_qtVersion);
|
|
|
|
|
return part;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-27 18:31:52 +02:00
|
|
|
RawProjectParts MesonProjectParser::buildProjectParts(
|
2024-01-22 17:46:28 +01:00
|
|
|
const Toolchain *cxxToolchain, const Toolchain *cToolchain)
|
2020-05-01 18:20:56 +02:00
|
|
|
{
|
2023-09-27 18:31:52 +02:00
|
|
|
RawProjectParts parts;
|
2020-05-01 18:20:56 +02:00
|
|
|
for_each_source_group(m_parserResult.targets,
|
|
|
|
|
[&parts,
|
2024-01-22 17:46:28 +01:00
|
|
|
&cxxToolchain,
|
|
|
|
|
&cToolchain,
|
2020-05-01 18:20:56 +02:00
|
|
|
this](const Target &target, const Target::SourceGroup &sourceList) {
|
|
|
|
|
parts.push_back(
|
2024-01-22 17:46:28 +01:00
|
|
|
buildRawPart(target, sourceList, cxxToolchain, cToolchain));
|
2020-05-01 18:20:56 +02:00
|
|
|
});
|
|
|
|
|
return parts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool sourceGroupMatchesKit(const KitData &kit, const Target::SourceGroup &group)
|
|
|
|
|
{
|
|
|
|
|
if (group.language == "c")
|
|
|
|
|
return kit.cCompilerPath == group.compiler[0];
|
|
|
|
|
if (group.language == "cpp")
|
|
|
|
|
return kit.cxxCompilerPath == group.compiler[0];
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MesonProjectParser::matchesKit(const KitData &kit)
|
|
|
|
|
{
|
|
|
|
|
bool matches = true;
|
|
|
|
|
for_each_source_group(m_parserResult.targets,
|
|
|
|
|
[&matches, &kit](const Target &, const Target::SourceGroup &sourceGroup) {
|
|
|
|
|
matches = matches && sourceGroupMatchesKit(kit, sourceGroup);
|
|
|
|
|
});
|
|
|
|
|
return matches;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-27 18:31:52 +02:00
|
|
|
bool MesonProjectParser::usesSameMesonVersion(const FilePath &buildPath)
|
2020-05-01 18:20:56 +02:00
|
|
|
{
|
2023-06-13 14:51:48 +02:00
|
|
|
auto info = MesonInfoParser::mesonInfo(buildPath);
|
2020-05-01 18:20:56 +02:00
|
|
|
auto meson = MesonTools::mesonWrapper(m_meson);
|
|
|
|
|
return info && meson && info->mesonVersion == meson->version();
|
|
|
|
|
}
|
2023-09-27 18:03:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
bool MesonProjectParser::run(const Command &command,
|
|
|
|
|
const Environment &env,
|
|
|
|
|
const QString &projectName,
|
|
|
|
|
bool captureStdo)
|
|
|
|
|
{
|
|
|
|
|
if (!sanityCheck(command))
|
|
|
|
|
return false;
|
|
|
|
|
m_stdo.clear();
|
2023-09-27 18:31:52 +02:00
|
|
|
TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
|
2023-09-27 18:03:18 +02:00
|
|
|
setupProcess(command, env, projectName, captureStdo);
|
|
|
|
|
m_elapsed.start();
|
|
|
|
|
m_process->start();
|
2024-07-22 13:17:46 +02:00
|
|
|
qCDebug(mesonProcessLog()) << "Starting:" << command.cmdLine.toUserOutput();
|
2023-09-27 18:03:18 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MesonProjectParser::handleProcessDone()
|
|
|
|
|
{
|
2023-09-27 18:31:52 +02:00
|
|
|
if (m_process->result() != ProcessResult::FinishedWithSuccess)
|
|
|
|
|
TaskHub::addTask(BuildSystemTask{Task::TaskType::Error, m_process->exitMessage()});
|
|
|
|
|
|
2023-09-27 18:03:18 +02:00
|
|
|
m_stdo = m_process->readAllRawStandardOutput();
|
|
|
|
|
m_stderr = m_process->readAllRawStandardError();
|
|
|
|
|
const QString elapsedTime = formatElapsedTime(m_elapsed.elapsed());
|
|
|
|
|
MessageManager::writeSilently(elapsedTime);
|
2023-09-27 18:31:52 +02:00
|
|
|
|
|
|
|
|
if (m_process->exitCode() == 0 && m_process->exitStatus() == QProcess::NormalExit) {
|
|
|
|
|
if (m_pendingCommands.isEmpty())
|
|
|
|
|
startParser();
|
|
|
|
|
else {
|
|
|
|
|
// see comment near m_pendingCommands declaration
|
|
|
|
|
std::tuple<Command, bool> args = m_pendingCommands.dequeue();
|
|
|
|
|
run(std::get<0>(args), m_env, m_projectName, std::get<1>(args));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (m_introType == IntroDataType::stdo) {
|
|
|
|
|
MessageManager::writeSilently(QString::fromLocal8Bit(m_stderr));
|
|
|
|
|
m_outputParser.readStdo(m_stderr);
|
|
|
|
|
}
|
|
|
|
|
emit parsingCompleted(false);
|
|
|
|
|
}
|
2023-09-27 18:03:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MesonProjectParser::setupProcess(const Command &command, const Environment &env,
|
|
|
|
|
const QString &projectName, bool captureStdo)
|
|
|
|
|
{
|
|
|
|
|
if (m_process)
|
|
|
|
|
m_process.release()->deleteLater();
|
|
|
|
|
m_process.reset(new Process);
|
|
|
|
|
connect(m_process.get(), &Process::done, this, &MesonProjectParser::handleProcessDone);
|
|
|
|
|
if (!captureStdo) {
|
|
|
|
|
connect(m_process.get(), &Process::readyReadStandardOutput,
|
|
|
|
|
this, &MesonProjectParser::processStandardOutput);
|
|
|
|
|
connect(m_process.get(), &Process::readyReadStandardError,
|
|
|
|
|
this, &MesonProjectParser::processStandardError);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-22 13:17:46 +02:00
|
|
|
m_process->setWorkingDirectory(command.workDir);
|
2023-09-27 18:03:18 +02:00
|
|
|
m_process->setEnvironment(env);
|
|
|
|
|
MessageManager::writeFlashing(Tr::tr("Running %1 in %2.")
|
2024-07-22 13:17:46 +02:00
|
|
|
.arg(command.cmdLine.toUserOutput(), command.workDir.toUserOutput()));
|
|
|
|
|
m_process->setCommand(command.cmdLine);
|
2023-09-27 18:03:18 +02:00
|
|
|
ProcessProgress *progress = new ProcessProgress(m_process.get());
|
|
|
|
|
progress->setDisplayName(Tr::tr("Configuring \"%1\".").arg(projectName));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MesonProjectParser::sanityCheck(const Command &command) const
|
|
|
|
|
{
|
2024-07-22 13:17:46 +02:00
|
|
|
const auto &exe = command.cmdLine.executable();
|
2023-09-27 18:03:18 +02:00
|
|
|
if (!exe.exists()) {
|
|
|
|
|
//Should only reach this point if Meson exe is removed while a Meson project is opened
|
2023-09-27 18:31:52 +02:00
|
|
|
TaskHub::addTask(
|
|
|
|
|
BuildSystemTask{Task::TaskType::Error,
|
|
|
|
|
Tr::tr("Executable does not exist: %1").arg(exe.toUserOutput())});
|
2023-09-27 18:03:18 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (!exe.toFileInfo().isExecutable()) {
|
2023-09-27 18:31:52 +02:00
|
|
|
TaskHub::addTask(
|
|
|
|
|
BuildSystemTask{Task::TaskType::Error,
|
|
|
|
|
Tr::tr("Command is not executable: %1").arg(exe.toUserOutput())});
|
2023-09-27 18:03:18 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MesonProjectParser::processStandardOutput()
|
|
|
|
|
{
|
|
|
|
|
const auto data = m_process->readAllRawStandardOutput();
|
|
|
|
|
MessageManager::writeSilently(QString::fromLocal8Bit(data));
|
|
|
|
|
m_outputParser.readStdo(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MesonProjectParser::processStandardError()
|
|
|
|
|
{
|
|
|
|
|
MessageManager::writeSilently(QString::fromLocal8Bit(m_process->readAllRawStandardError()));
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-01 18:20:56 +02:00
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace MesonProjectManager
|