Meson: De-noise project parser a bit

Change-Id: Ic0b19e5a1e10057f750c2ad13f61c09f1105d05d
Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
hjk
2023-09-27 18:31:52 +02:00
parent 895f8e7396
commit 7bf1b6e586
2 changed files with 76 additions and 92 deletions

View File

@@ -38,7 +38,7 @@ struct CompilerArgs
{ {
QStringList args; QStringList args;
QStringList includePaths; QStringList includePaths;
ProjectExplorer::Macros macros; Macros macros;
}; };
static std::optional<QString> extractValueIfMatches(const QString &arg, static std::optional<QString> extractValueIfMatches(const QString &arg,
@@ -56,18 +56,18 @@ static std::optional<QString> extractInclude(const QString &arg)
return extractValueIfMatches(arg, {"-I", "/I", "-isystem", "-imsvc", "/imsvc"}); return extractValueIfMatches(arg, {"-I", "/I", "-isystem", "-imsvc", "/imsvc"});
} }
static std::optional<ProjectExplorer::Macro> extractMacro(const QString &arg) static std::optional<Macro> extractMacro(const QString &arg)
{ {
auto define = extractValueIfMatches(arg, {"-D", "/D"}); auto define = extractValueIfMatches(arg, {"-D", "/D"});
if (define) if (define)
return ProjectExplorer::Macro::fromKeyValue(define->toLatin1()); return Macro::fromKeyValue(define->toLatin1());
auto undef = extractValueIfMatches(arg, {"-U", "/U"}); auto undef = extractValueIfMatches(arg, {"-U", "/U"});
if (undef) if (undef)
return ProjectExplorer::Macro(undef->toLatin1(), ProjectExplorer::MacroType::Undefine); return Macro(undef->toLatin1(), MacroType::Undefine);
return std::nullopt; return std::nullopt;
} }
CompilerArgs splitArgs(const QStringList &args) static CompilerArgs splitArgs(const QStringList &args)
{ {
CompilerArgs splited; CompilerArgs splited;
for (const QString &arg : args) { for (const QString &arg : args) {
@@ -86,7 +86,7 @@ CompilerArgs splitArgs(const QStringList &args)
return splited; return splited;
} }
QStringList toAbsolutePath(const Utils::FilePath &refPath, QStringList &pathList) static QStringList toAbsolutePath(const FilePath &refPath, QStringList &pathList)
{ {
QStringList allAbs; QStringList allAbs;
std::transform(std::cbegin(pathList), std::transform(std::cbegin(pathList),
@@ -98,9 +98,7 @@ QStringList toAbsolutePath(const Utils::FilePath &refPath, QStringList &pathList
return allAbs; return allAbs;
} }
MesonProjectParser::MesonProjectParser(const Utils::Id &meson, MesonProjectParser::MesonProjectParser(const Id &meson, const Environment &env, Project *project)
Utils::Environment env,
ProjectExplorer::Project *project)
: m_env{env} : m_env{env}
, m_meson{meson} , m_meson{meson}
, m_projectName{project->displayName()} , m_projectName{project->displayName()}
@@ -108,19 +106,14 @@ MesonProjectParser::MesonProjectParser(const Utils::Id &meson,
// TODO re-think the way all BuildSystem/ProjectParser are tied // TODO re-think the way all BuildSystem/ProjectParser are tied
// I take project info here, I also take build and src dir later from // I take project info here, I also take build and src dir later from
// functions args. // functions args.
auto fileFinder = new Utils::FileInProjectFinder; auto fileFinder = new FileInProjectFinder;
fileFinder->setProjectDirectory(project->projectDirectory()); fileFinder->setProjectDirectory(project->projectDirectory());
fileFinder->setProjectFiles(project->files(Project::AllFiles)); fileFinder->setProjectFiles(project->files(Project::AllFiles));
m_outputParser.setFileFinder(fileFinder); m_outputParser.setFileFinder(fileFinder);
} }
void MesonProjectParser::setMesonTool(const Utils::Id &meson) bool MesonProjectParser::configure(const FilePath &sourcePath,
{ const FilePath &buildPath,
m_meson = meson;
}
bool MesonProjectParser::configure(const Utils::FilePath &sourcePath,
const Utils::FilePath &buildPath,
const QStringList &args) const QStringList &args)
{ {
m_introType = IntroDataType::file; m_introType = IntroDataType::file;
@@ -135,15 +128,15 @@ bool MesonProjectParser::configure(const Utils::FilePath &sourcePath,
return run(cmd, m_env, m_projectName); return run(cmd, m_env, m_projectName);
} }
bool MesonProjectParser::wipe(const Utils::FilePath &sourcePath, bool MesonProjectParser::wipe(const FilePath &sourcePath,
const Utils::FilePath &buildPath, const FilePath &buildPath,
const QStringList &args) const QStringList &args)
{ {
return setup(sourcePath, buildPath, args, true); return setup(sourcePath, buildPath, args, true);
} }
bool MesonProjectParser::setup(const Utils::FilePath &sourcePath, bool MesonProjectParser::setup(const FilePath &sourcePath,
const Utils::FilePath &buildPath, const FilePath &buildPath,
const QStringList &args, const QStringList &args,
bool forceWipe) bool forceWipe)
{ {
@@ -158,7 +151,7 @@ bool MesonProjectParser::setup(const Utils::FilePath &sourcePath,
return run(cmd, m_env, m_projectName); return run(cmd, m_env, m_projectName);
} }
bool MesonProjectParser::parse(const Utils::FilePath &sourcePath, const Utils::FilePath &buildPath) bool MesonProjectParser::parse(const FilePath &sourcePath, const FilePath &buildPath)
{ {
m_srcDir = sourcePath; m_srcDir = sourcePath;
m_buildDir = buildPath; m_buildDir = buildPath;
@@ -171,7 +164,7 @@ bool MesonProjectParser::parse(const Utils::FilePath &sourcePath, const Utils::F
} }
} }
bool MesonProjectParser::parse(const Utils::FilePath &sourcePath) bool MesonProjectParser::parse(const FilePath &sourcePath)
{ {
m_srcDir = sourcePath; m_srcDir = sourcePath;
m_introType = IntroDataType::stdo; m_introType = IntroDataType::stdo;
@@ -191,9 +184,9 @@ QList<BuildTargetInfo> MesonProjectParser::appsTargets() const
bti.displayName = target.name; bti.displayName = target.name;
bti.buildKey = Target::fullName(m_buildDir, target); bti.buildKey = Target::fullName(m_buildDir, target);
bti.displayNameUniquifier = bti.buildKey; bti.displayNameUniquifier = bti.buildKey;
bti.targetFilePath = Utils::FilePath::fromString(target.fileName.first()); bti.targetFilePath = FilePath::fromString(target.fileName.first());
bti.workingDirectory = Utils::FilePath::fromString(target.fileName.first()).absolutePath(); bti.workingDirectory = FilePath::fromString(target.fileName.first()).absolutePath();
bti.projectFilePath = Utils::FilePath::fromString(target.definedIn); bti.projectFilePath = FilePath::fromString(target.definedIn);
bti.usesTerminal = true; bti.usesTerminal = true;
apps.append(bti); apps.append(bti);
} }
@@ -218,7 +211,7 @@ bool MesonProjectParser::startParser()
} }
MesonProjectParser::ParserData *MesonProjectParser::extractParserResults( MesonProjectParser::ParserData *MesonProjectParser::extractParserResults(
const Utils::FilePath &srcDir, MesonInfoParser::Result &&parserResult) const FilePath &srcDir, MesonInfoParser::Result &&parserResult)
{ {
auto rootNode = ProjectTree::buildTree(srcDir, auto rootNode = ProjectTree::buildTree(srcDir,
parserResult.targets, parserResult.targets,
@@ -226,13 +219,20 @@ MesonProjectParser::ParserData *MesonProjectParser::extractParserResults(
return new ParserData{std::move(parserResult), std::move(rootNode)}; return new ParserData{std::move(parserResult), std::move(rootNode)};
} }
void MesonProjectParser::addMissingTargets(QStringList &targetList) static void addMissingTargets(QStringList &targetList)
{ {
// Not all targets are listed in introspection data // Not all targets are listed in introspection data
for (const auto &target : additionalTargets()) { static const QString additionalTargets[] {
if (!targetList.contains(target)) { 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))
targetList.append(target); targetList.append(target);
}
} }
} }
@@ -261,7 +261,7 @@ RawProjectPart MesonProjectParser::buildRawPart(
part.setDisplayName(target.name); part.setDisplayName(target.name);
part.setBuildSystemTarget(Target::fullName(m_buildDir, target)); part.setBuildSystemTarget(Target::fullName(m_buildDir, target));
part.setFiles(sources.sources + sources.generatedSources); part.setFiles(sources.sources + sources.generatedSources);
auto flags = splitArgs(sources.parameters); CompilerArgs flags = splitArgs(sources.parameters);
part.setMacros(flags.macros); part.setMacros(flags.macros);
part.setIncludePaths(toAbsolutePath(m_buildDir, flags.includePaths)); part.setIncludePaths(toAbsolutePath(m_buildDir, flags.includePaths));
part.setProjectFileLocation(target.definedIn); part.setProjectFileLocation(target.definedIn);
@@ -273,29 +273,10 @@ RawProjectPart MesonProjectParser::buildRawPart(
return part; return part;
} }
void MesonProjectParser::processFinished(int exitCode, QProcess::ExitStatus exitStatus) RawProjectParts MesonProjectParser::buildProjectParts(
const ToolChain *cxxToolChain, const ToolChain *cToolChain)
{ {
if (exitCode == 0 && exitStatus == QProcess::NormalExit) { RawProjectParts parts;
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) {
Core::MessageManager::writeSilently(QString::fromLocal8Bit(m_stderr));
m_outputParser.readStdo(m_stderr);
}
emit parsingCompleted(false);
}
}
ProjectExplorer::RawProjectParts MesonProjectParser::buildProjectParts(
const ProjectExplorer::ToolChain *cxxToolChain, const ProjectExplorer::ToolChain *cToolChain)
{
ProjectExplorer::RawProjectParts parts;
for_each_source_group(m_parserResult.targets, for_each_source_group(m_parserResult.targets,
[&parts, [&parts,
&cxxToolChain, &cxxToolChain,
@@ -326,7 +307,7 @@ bool MesonProjectParser::matchesKit(const KitData &kit)
return matches; return matches;
} }
bool MesonProjectParser::usesSameMesonVersion(const Utils::FilePath &buildPath) bool MesonProjectParser::usesSameMesonVersion(const FilePath &buildPath)
{ {
auto info = MesonInfoParser::mesonInfo(buildPath); auto info = MesonInfoParser::mesonInfo(buildPath);
auto meson = MesonTools::mesonWrapper(m_meson); auto meson = MesonTools::mesonWrapper(m_meson);
@@ -342,7 +323,7 @@ bool MesonProjectParser::run(const Command &command,
if (!sanityCheck(command)) if (!sanityCheck(command))
return false; return false;
m_stdo.clear(); m_stdo.clear();
ProjectExplorer::TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM); TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
setupProcess(command, env, projectName, captureStdo); setupProcess(command, env, projectName, captureStdo);
m_elapsed.start(); m_elapsed.start();
m_process->start(); m_process->start();
@@ -352,15 +333,29 @@ bool MesonProjectParser::run(const Command &command,
void MesonProjectParser::handleProcessDone() void MesonProjectParser::handleProcessDone()
{ {
if (m_process->result() != ProcessResult::FinishedWithSuccess) { if (m_process->result() != ProcessResult::FinishedWithSuccess)
ProjectExplorer::TaskHub::addTask(ProjectExplorer::BuildSystemTask{ TaskHub::addTask(BuildSystemTask{Task::TaskType::Error, m_process->exitMessage()});
ProjectExplorer::Task::TaskType::Error, m_process->exitMessage()});
}
m_stdo = m_process->readAllRawStandardOutput(); m_stdo = m_process->readAllRawStandardOutput();
m_stderr = m_process->readAllRawStandardError(); m_stderr = m_process->readAllRawStandardError();
const QString elapsedTime = formatElapsedTime(m_elapsed.elapsed()); const QString elapsedTime = formatElapsedTime(m_elapsed.elapsed());
MessageManager::writeSilently(elapsedTime); MessageManager::writeSilently(elapsedTime);
processFinished(m_process->exitCode(), m_process->exitStatus());
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);
}
} }
void MesonProjectParser::setupProcess(const Command &command, const Environment &env, void MesonProjectParser::setupProcess(const Command &command, const Environment &env,
@@ -392,17 +387,15 @@ bool MesonProjectParser::sanityCheck(const Command &command) const
const auto &exe = command.cmdLine().executable(); const auto &exe = command.cmdLine().executable();
if (!exe.exists()) { if (!exe.exists()) {
//Should only reach this point if Meson exe is removed while a Meson project is opened //Should only reach this point if Meson exe is removed while a Meson project is opened
ProjectExplorer::TaskHub::addTask( TaskHub::addTask(
ProjectExplorer::BuildSystemTask{ProjectExplorer::Task::TaskType::Error, BuildSystemTask{Task::TaskType::Error,
Tr::tr("Executable does not exist: %1") Tr::tr("Executable does not exist: %1").arg(exe.toUserOutput())});
.arg(exe.toUserOutput())});
return false; return false;
} }
if (!exe.toFileInfo().isExecutable()) { if (!exe.toFileInfo().isExecutable()) {
ProjectExplorer::TaskHub::addTask( TaskHub::addTask(
ProjectExplorer::BuildSystemTask{ProjectExplorer::Task::TaskType::Error, BuildSystemTask{Task::TaskType::Error,
Tr::tr("Command is not executable: %1") Tr::tr("Command is not executable: %1").arg(exe.toUserOutput())});
.arg(exe.toUserOutput())});
return false; return false;
} }
return true; return true;

View File

@@ -13,9 +13,6 @@
#include <projectexplorer/kit.h> #include <projectexplorer/kit.h>
#include <projectexplorer/rawprojectpart.h> #include <projectexplorer/rawprojectpart.h>
#include <utils/environment.h>
#include <utils/fileutils.h>
#include <QFuture> #include <QFuture>
#include <QQueue> #include <QQueue>
@@ -25,6 +22,7 @@ namespace Internal {
class MesonProjectParser : public QObject class MesonProjectParser : public QObject
{ {
Q_OBJECT Q_OBJECT
enum class IntroDataType { file, stdo }; enum class IntroDataType { file, stdo };
struct ParserData struct ParserData
{ {
@@ -33,8 +31,10 @@ class MesonProjectParser : public QObject
}; };
public: public:
MesonProjectParser(const Utils::Id &meson, Utils::Environment env, ProjectExplorer::Project* project); MesonProjectParser(const Utils::Id &meson,
void setMesonTool(const Utils::Id &meson); const Utils::Environment &env,
ProjectExplorer::Project *project);
bool configure(const Utils::FilePath &sourcePath, bool configure(const Utils::FilePath &sourcePath,
const Utils::FilePath &buildPath, const Utils::FilePath &buildPath,
const QStringList &args); const QStringList &args);
@@ -48,22 +48,11 @@ public:
bool parse(const Utils::FilePath &sourcePath, const Utils::FilePath &buildPath); bool parse(const Utils::FilePath &sourcePath, const Utils::FilePath &buildPath);
bool parse(const Utils::FilePath &sourcePath); bool parse(const Utils::FilePath &sourcePath);
Q_SIGNAL void parsingCompleted(bool success);
std::unique_ptr<MesonProjectNode> takeProjectNode() { return std::move(m_rootNode); } std::unique_ptr<MesonProjectNode> takeProjectNode() { return std::move(m_rootNode); }
inline const BuildOptionsList &buildOptions() const { return m_parserResult.buildOptions; }; const BuildOptionsList &buildOptions() const { return m_parserResult.buildOptions; };
inline const TargetsList &targets() const { return m_parserResult.targets; } const TargetsList &targets() const { return m_parserResult.targets; }
inline const QStringList &targetsNames() const { return m_targetsNames; } const QStringList &targetsNames() const { return m_targetsNames; }
static inline QStringList additionalTargets()
{
return QStringList{Constants::Targets::all,
Constants::Targets::clean,
Constants::Targets::install,
Constants::Targets::benchmark,
Constants::Targets::scan_build};
}
QList<ProjectExplorer::BuildTargetInfo> appsTargets() const; QList<ProjectExplorer::BuildTargetInfo> appsTargets() const;
@@ -71,25 +60,27 @@ public:
const ProjectExplorer::ToolChain *cxxToolChain, const ProjectExplorer::ToolChain *cxxToolChain,
const ProjectExplorer::ToolChain *cToolChain); const ProjectExplorer::ToolChain *cToolChain);
inline void setEnvironment(const Utils::Environment &environment) { m_env = environment; } void setEnvironment(const Utils::Environment &environment) { m_env = environment; }
inline void setQtVersion(Utils::QtMajorVersion v) { m_qtVersion = v; } void setQtVersion(Utils::QtMajorVersion v) { m_qtVersion = v; }
bool matchesKit(const KitData &kit); bool matchesKit(const KitData &kit);
bool usesSameMesonVersion(const Utils::FilePath &buildPath); bool usesSameMesonVersion(const Utils::FilePath &buildPath);
signals:
void parsingCompleted(bool success);
private: private:
bool startParser(); bool startParser();
static ParserData *extractParserResults(const Utils::FilePath &srcDir, static ParserData *extractParserResults(const Utils::FilePath &srcDir,
MesonInfoParser::Result &&parserResult); MesonInfoParser::Result &&parserResult);
static void addMissingTargets(QStringList &targetList);
void update(const QFuture<ParserData *> &data); void update(const QFuture<ParserData *> &data);
ProjectExplorer::RawProjectPart buildRawPart(const Target &target, ProjectExplorer::RawProjectPart buildRawPart(const Target &target,
const Target::SourceGroup &sources, const Target::SourceGroup &sources,
const ProjectExplorer::ToolChain *cxxToolChain, const ProjectExplorer::ToolChain *cxxToolChain,
const ProjectExplorer::ToolChain *cToolChain); const ProjectExplorer::ToolChain *cToolChain);
void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
MesonOutputParser m_outputParser; MesonOutputParser m_outputParser;
Utils::Environment m_env; Utils::Environment m_env;
Utils::Id m_meson; Utils::Id m_meson;