ProjectExplorer: Add BuildSystem class

Add a class to abstract out the BuildSystem from the Project.

Thie idea is to make a Project have-a BuildSystem, so that
it can stop being one.

The Projects in the different ProjectManagers will get much
simpler that way (and many will only consist of a constructor
with some setter calls) and handles all the interactions
between the rest of Qt Creator and the project.

The complex code to interact with the build systems is then
separate from that.

Change-Id: I3bbb000bb1aed91f0b547ac493f743ede8afb8cd
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
Tobias Hunger
2019-08-09 11:22:49 +02:00
parent f4c1c0e441
commit b7e4046a17
15 changed files with 324 additions and 253 deletions

View File

@@ -47,6 +47,7 @@
#include <QDir>
#include <QLoggingCategory>
#include <QMessageBox>
#include <QPointer>
#include <QPushButton>
#include <QSet>
@@ -95,6 +96,18 @@ Utils::FilePath BuildDirManager::workDirectory(const BuildDirParameters &paramet
return Utils::FilePath::fromString(tmpDirIt->second->path());
}
void BuildDirManager::updateReparseParameters(const int parameters)
{
m_reparseParameters |= parameters;
}
int BuildDirManager::takeReparseParameters()
{
int result = m_reparseParameters;
m_reparseParameters = REPARSE_DEFAULT;
return result;
}
void BuildDirManager::emitDataAvailable()
{
if (!isParsing())
@@ -108,6 +121,14 @@ void BuildDirManager::emitErrorOccured(const QString &message) const
m_isHandlingError = false;
}
void BuildDirManager::emitReparseRequest() const
{
if (m_reparseParameters & REPARSE_URGENT)
emit requestReparse();
else
emit requestDelayedReparse();
}
void BuildDirManager::updateReaderType(const BuildDirParameters &p,
std::function<void()> todo)
{
@@ -208,7 +229,7 @@ void BuildDirManager::stopParsingAndClearState()
}
void BuildDirManager::setParametersAndRequestParse(const BuildDirParameters &parameters,
int reparseOptions)
const int reparseParameters)
{
if (!parameters.cmakeTool()) {
TaskHub::addTask(Task::Error,
@@ -222,9 +243,9 @@ void BuildDirManager::setParametersAndRequestParse(const BuildDirParameters &par
m_parameters = parameters;
m_parameters.workDirectory = workDirectory(parameters);
updateReparseParameters(reparseParameters);
updateReaderType(m_parameters,
[this, reparseOptions]() { emit requestReparse(reparseOptions); });
updateReaderType(m_parameters, [this]() { emitReparseRequest(); });
}
CMakeBuildConfiguration *BuildDirManager::buildConfiguration() const
@@ -248,7 +269,8 @@ void BuildDirManager::becameDirty()
if (!tool->isAutoRun())
return;
emit requestReparse(REPARSE_CHECK_CONFIGURATION | REPARSE_SCAN);
updateReparseParameters(REPARSE_CHECK_CONFIGURATION | REPARSE_SCAN);
emit requestReparse();
}
void BuildDirManager::resetData()
@@ -276,19 +298,30 @@ bool BuildDirManager::persistCMakeState()
return true;
}
void BuildDirManager::parse(int reparseParameters)
void BuildDirManager::requestFilesystemScan()
{
qCDebug(cmakeBuildDirManagerLog)
<< "Parse called with flags:" << flagsString(reparseParameters);
updateReparseParameters(REPARSE_SCAN);
}
bool BuildDirManager::isFilesystemScanRequested() const
{
return m_reparseParameters & REPARSE_SCAN;
}
void BuildDirManager::parse()
{
QTC_ASSERT(m_parameters.isValid(), return );
QTC_ASSERT(m_reader, return);
QTC_ASSERT((reparseParameters & REPARSE_IGNORE) == 0, return);
m_reader->stop();
TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
int reparseParameters = takeReparseParameters();
qCDebug(cmakeBuildDirManagerLog)
<< "Parse called with flags:" << flagsString(reparseParameters);
const QString cache = m_parameters.workDirectory.pathAppended("CMakeCache.txt").toString();
if (!QFileInfo::exists(cache)) {
reparseParameters |= REPARSE_FORCE_CONFIGURATION | REPARSE_FORCE_CMAKE_RUN;
@@ -323,8 +356,10 @@ QVector<FilePath> BuildDirManager::takeProjectFilesToWatch()
if (!toWatch.isEmpty()) {
connect(project(), &Project::projectFileIsDirty, this, [this]() {
if (m_parameters.cmakeTool() && m_parameters.cmakeTool()->isAutoRun())
requestReparse(REPARSE_DEFAULT);
if (m_parameters.cmakeTool() && m_parameters.cmakeTool()->isAutoRun()) {
updateReparseParameters(REPARSE_DEFAULT);
emit requestReparse();
}
});
} else {
disconnect(project(), nullptr, this, nullptr);
@@ -452,8 +487,6 @@ QString BuildDirManager::flagsString(int reparseFlags)
result += " CHECK_CONFIG";
if (reparseFlags & REPARSE_SCAN)
result += " SCAN";
if (reparseFlags & REPARSE_IGNORE)
result += " IGNORE";
}
return result.trimmed();
}

View File

@@ -60,6 +60,17 @@ class BuildDirManager : public QObject
Q_OBJECT
public:
enum ReparseParameters {
REPARSE_DEFAULT = 0, // Nothing special:-)
REPARSE_FORCE_CMAKE_RUN = (1 << 0), // Force cmake to run
REPARSE_FORCE_CONFIGURATION = (1 << 1), // Force configuration arguments to cmake
REPARSE_CHECK_CONFIGURATION = (1 << 2), // Check for on-disk config and QtC config diff
REPARSE_SCAN = (1 << 3), // Run filesystem scan
REPARSE_URGENT = (1 << 4), // Do not delay the parser run by 1s
};
static QString flagsString(int reparseFlags);
BuildDirManager(CMakeProject *project);
~BuildDirManager() final;
@@ -67,7 +78,8 @@ public:
void stopParsingAndClearState();
void setParametersAndRequestParse(const BuildDirParameters &parameters, int reparseOptions);
void setParametersAndRequestParse(const BuildDirParameters &parameters,
const int reparseOptions);
// nullptr if the BC is not active anymore!
CMakeBuildConfiguration *buildConfiguration() const;
CMakeProject *project() const {return m_project; }
@@ -78,7 +90,9 @@ public:
void resetData();
bool persistCMakeState();
void parse(int reparseParameters);
void requestFilesystemScan();
bool isFilesystemScanRequested() const;
void parse();
QVector<Utils::FilePath> takeProjectFilesToWatch();
std::unique_ptr<CMakeProjectNode> generateProjectTree(const QList<const ProjectExplorer::FileNode *> &allFiles,
@@ -91,32 +105,20 @@ public:
static CMakeConfig parseCMakeConfiguration(const Utils::FilePath &cacheFile,
QString *errorMessage);
enum ReparseParameters {
REPARSE_DEFAULT = BuildSystem::PARAM_DEFAULT, // use defaults
REPARSE_URGENT = BuildSystem::PARAM_URGENT, // Do not wait for more requests, start ASAP
REPARSE_IGNORE = BuildSystem::PARAM_IGNORE,
REPARSE_FORCE_CMAKE_RUN = (1
<< (BuildSystem::PARAM_CUSTOM_OFFSET + 0)), // Force cmake to run
REPARSE_FORCE_CONFIGURATION = (1 << (BuildSystem::PARAM_CUSTOM_OFFSET
+ 1)), // Force configuration arguments to cmake
REPARSE_CHECK_CONFIGURATION
= (1 << (BuildSystem::PARAM_CUSTOM_OFFSET
+ 2)), // Check and warn if on-disk config and QtC config differ
REPARSE_SCAN = (1 << (BuildSystem::PARAM_CUSTOM_OFFSET + 3)), // Run filesystem scan
};
static QString flagsString(int reparseFlags);
signals:
void requestReparse(int reparseParameters) const;
void requestReparse() const;
void requestDelayedReparse() const;
void parsingStarted() const;
void dataAvailable() const;
void errorOccured(const QString &err) const;
private:
void updateReparseParameters(const int parameters);
int takeReparseParameters();
void emitDataAvailable();
void emitErrorOccured(const QString &message) const;
void emitReparseRequest() const;
bool checkConfiguration();
Utils::FilePath workDirectory(const BuildDirParameters &parameters) const;
@@ -129,6 +131,7 @@ private:
void becameDirty();
BuildDirParameters m_parameters;
int m_reparseParameters;
CMakeProject *m_project = nullptr;
mutable std::unordered_map<Utils::FilePath, std::unique_ptr<Utils::TemporaryDirectory>> m_buildDirToTempDir;
mutable std::unique_ptr<BuildDirReader> m_reader;

View File

@@ -93,12 +93,13 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *parent, Core::Id id)
BuildSystem *bs = qobject_cast<CMakeBuildSystem *>(project()->buildSystem());
// BuildDirManager:
connect(&m_buildDirManager, &BuildDirManager::requestReparse, this, [this, bs](int options) {
if (isActive()) {
qCDebug(cmakeBuildConfigurationLog)
<< "Passing on reparse request with flags" << BuildDirManager::flagsString(options);
bs->requestParse(options);
}
connect(&m_buildDirManager, &BuildDirManager::requestReparse, this, [this, bs]() {
if (isActive())
bs->requestParse();
});
connect(&m_buildDirManager, &BuildDirManager::requestDelayedReparse, this, [this, bs]() {
if (isActive())
bs->requestDelayedParse();
});
connect(&m_buildDirManager,
&BuildDirManager::dataAvailable,

View File

@@ -30,38 +30,6 @@
#include "cmakeprojectconstants.h"
#include "cmakeprojectnodes.h"
#if 0
#include "cmakebuildstep.h"
#include "cmakekitinformation.h"
#include "cmakeprojectmanager.h"
#include "cmakeprojectnodes.h"
#include <cpptools/cpprawprojectpart.h>
#include <cpptools/cpptoolsconstants.h>
#include <cpptools/projectinfo.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/buildtargetinfo.h>
#include <projectexplorer/deploymentdata.h>
#include <projectexplorer/headerpath.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/toolchain.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitinformation.h>
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
#include <utils/qtcprocess.h>
#include <utils/stringutils.h>
#include <QDir>
#include <QElapsedTimer>
#include <QSet>
#endif
#include <coreplugin/progressmanager/progressmanager.h>
#include <cpptools/cppprojectupdater.h>
#include <cpptools/generatedcodemodelsupport.h>
@@ -79,85 +47,12 @@
using namespace ProjectExplorer;
using namespace Utils;
namespace {
CMakeProjectManager::Internal::CMakeBuildConfiguration *activeBc(Project *p)
{
if (!p)
return nullptr;
return qobject_cast<CMakeProjectManager::Internal::CMakeBuildConfiguration *>(
p->activeTarget() ? p->activeTarget()->activeBuildConfiguration() : nullptr);
}
} // namespace
namespace CMakeProjectManager {
using namespace Internal;
Q_LOGGING_CATEGORY(cmakeBuildSystemLog, "qtc.cmake.buildsystem", QtWarningMsg);
// --------------------------------------------------------------------
// BuildSystem:
// --------------------------------------------------------------------
BuildSystem::BuildSystem(Project *project)
: m_project(project)
{
QTC_CHECK(project);
// Timer:
m_delayedParsingTimer.setSingleShot(true);
connect(&m_delayedParsingTimer, &QTimer::timeout, this, &BuildSystem::triggerParsing);
}
BuildSystem::~BuildSystem() = default;
Project *BuildSystem::project() const
{
return m_project;
}
bool BuildSystem::isWaitingForParse() const
{
return m_delayedParsingTimer.isActive();
}
void BuildSystem::requestParse(int reparseParameters)
{
QTC_ASSERT(!(reparseParameters & PARAM_ERROR), return );
if (reparseParameters & PARAM_IGNORE)
return;
m_delayedParsingTimer.setInterval((reparseParameters & PARAM_URGENT) ? 0 : 1000);
m_delayedParsingTimer.start();
m_delayedParsingParameters = m_delayedParsingParameters | reparseParameters;
}
void BuildSystem::triggerParsing()
{
int parameters = m_delayedParsingParameters;
m_delayedParsingParameters = BuildSystem::PARAM_DEFAULT;
QTC_CHECK(!m_project->isParsing());
QTC_ASSERT((parameters & BuildSystem::PARAM_ERROR) == 0, return );
if (parameters & BuildSystem::PARAM_IGNORE)
return;
// Clear buildsystem specific parameters before passing them on!
parameters = parameters
& ~(BuildSystem::PARAM_ERROR | BuildSystem::PARAM_IGNORE
| BuildSystem::PARAM_URGENT);
{
ParsingContext ctx(m_project->guardParsingRun(), parameters, m_project, activeBc(m_project));
if (validateParsingContext(ctx))
parseProject(std::move(ctx));
}
}
// --------------------------------------------------------------------
// CMakeBuildSystem:
// --------------------------------------------------------------------
@@ -227,13 +122,12 @@ void CMakeBuildSystem::parseProject(ParsingContext &&ctx)
m_currentContext = std::move(ctx);
auto bc = qobject_cast<CMakeBuildConfiguration *>(m_currentContext.buildConfiguration);
int parameters = m_currentContext.parameters;
QTC_ASSERT(bc, return );
if (m_allFiles.isEmpty())
parameters |= BuildDirManager::REPARSE_SCAN;
bc->m_buildDirManager.requestFilesystemScan();
m_waitingForScan = parameters & BuildDirManager::REPARSE_SCAN;
m_waitingForScan = bc->m_buildDirManager.isFilesystemScanRequested();
m_waitingForParse = true;
m_combinedScanAndParseResult = true;
@@ -246,7 +140,7 @@ void CMakeBuildSystem::parseProject(ParsingContext &&ctx)
"CMake.Scan.Tree");
}
bc->m_buildDirManager.parse(parameters);
bc->m_buildDirManager.parse();
}
void CMakeBuildSystem::handleTreeScanningFinished()

View File

@@ -25,20 +25,12 @@
#pragma once
#include <projectexplorer/project.h>
#include <projectexplorer/treescanner.h>
#include <QTimer>
#include <projectexplorer/buildsystem.h>
namespace CppTools {
class CppProjectUpdater;
} // namespace CppTools
namespace ProjectExplorer {
class BuildConfiguration;
class ExtraCompiler;
} // namespace ProjectExplorer
namespace CMakeProjectManager {
class CMakeProject;
@@ -47,88 +39,11 @@ namespace Internal {
class CMakeBuildConfiguration;
} // namespace Internal
// --------------------------------------------------------------------
// BuildSystem:
// --------------------------------------------------------------------
class BuildSystem : public QObject
{
Q_OBJECT
public:
const static int PARAM_CUSTOM_OFFSET = 3;
enum Parameters : int {
PARAM_DEFAULT = 0, // use defaults
PARAM_IGNORE = (1 << (PARAM_CUSTOM_OFFSET - 3)), // Ignore this request without raising a fuss
PARAM_ERROR = (1 << (PARAM_CUSTOM_OFFSET - 2)), // Ignore this request and warn
PARAM_URGENT = (1 << (PARAM_CUSTOM_OFFSET - 1)), // Do not wait for more requests, start ASAP
};
explicit BuildSystem(ProjectExplorer::Project *project);
~BuildSystem() override;
BuildSystem(const BuildSystem &other) = delete;
ProjectExplorer::Project *project() const;
bool isWaitingForParse() const;
void requestParse(int reparseParameters); // request a (delayed!) parser run.
protected:
class ParsingContext
{
public:
ParsingContext() = default;
ParsingContext(const ParsingContext &other) = delete;
ParsingContext &operator=(const ParsingContext &other) = delete;
ParsingContext(ParsingContext &&other) = default;
ParsingContext &operator=(ParsingContext &&other) = default;
ProjectExplorer::Project::ParseGuard guard;
int parameters = PARAM_DEFAULT;
ProjectExplorer::Project *project = nullptr;
ProjectExplorer::BuildConfiguration *buildConfiguration = nullptr;
private:
ParsingContext(ProjectExplorer::Project::ParseGuard &&g,
int params,
ProjectExplorer::Project *p,
ProjectExplorer::BuildConfiguration *bc)
: guard(std::move(g))
, parameters(params)
, project(p)
, buildConfiguration(bc)
{}
friend class BuildSystem;
};
virtual bool validateParsingContext(const ParsingContext &ctx)
{
Q_UNUSED(ctx)
return true;
}
virtual void parseProject(ParsingContext &&ctx) = 0; // actual code to parse project
private:
void triggerParsing();
ProjectExplorer::Project *m_project;
QTimer m_delayedParsingTimer;
int m_delayedParsingParameters = PARAM_DEFAULT;
};
// --------------------------------------------------------------------
// CMakeBuildSystem:
// --------------------------------------------------------------------
class CMakeBuildSystem : public BuildSystem
class CMakeBuildSystem : public ProjectExplorer::BuildSystem
{
Q_OBJECT

View File

@@ -85,14 +85,14 @@ static CMakeBuildConfiguration *activeBc(const CMakeProject *p)
CMakeProject::CMakeProject(const FilePath &fileName)
: Project(Constants::CMAKEMIMETYPE, fileName)
{
m_buildsystem = std::make_unique<CMakeBuildSystem>(this);
setId(CMakeProjectManager::Constants::CMAKEPROJECT_ID);
setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
setDisplayName(projectDirectory().fileName());
setCanBuildProducts();
setKnowsAllBuildExecutables(false);
setHasMakeInstallEquivalent(true);
setBuildSystem(std::make_unique<CMakeBuildSystem>(this));
}
CMakeProject::~CMakeProject() = default;

View File

@@ -32,10 +32,8 @@
#include "cmakebuildtarget.h"
#include "cmakeprojectimporter.h"
#include <projectexplorer/extracompiler.h>
#include <projectexplorer/buildsystem.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectmacro.h>
#include <projectexplorer/treescanner.h>
#include <utils/fileutils.h>
@@ -50,8 +48,6 @@ namespace ProjectExplorer { class FileNode; }
namespace CMakeProjectManager {
class BuildSystem;
namespace Internal {
class CMakeBuildConfiguration;
class CMakeBuildSettingsWidget;
@@ -66,8 +62,6 @@ public:
explicit CMakeProject(const Utils::FilePath &filename);
~CMakeProject() final;
BuildSystem *buildSystem() const { return m_buildsystem.get(); }
ProjectExplorer::Tasks projectIssues(const ProjectExplorer::Kit *k) const final;
void runCMake();
@@ -94,11 +88,6 @@ private:
mutable std::unique_ptr<Internal::CMakeProjectImporter> m_projectImporter;
std::unique_ptr<CMakeBuildSystem> m_buildsystem;
// friend class Internal::CMakeBuildConfiguration;
// friend class Internal::CMakeBuildSettingsWidget;
friend class CMakeBuildSystem;
};

View File

@@ -32,12 +32,13 @@
#include "cmaketoolmanager.h"
#include "cmakeprojectnodes.h"
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>

View File

@@ -21,6 +21,7 @@ add_qtc_plugin(ProjectExplorer
buildstep.cpp buildstep.h
buildsteplist.cpp buildsteplist.h
buildstepspage.cpp buildstepspage.h
buildsystem.cpp buildsystem.h
buildtargetinfo.h
clangparser.cpp clangparser.h
codestylesettingspropertiespage.cpp codestylesettingspropertiespage.h codestylesettingspropertiespage.ui

View File

@@ -0,0 +1,102 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "buildsystem.h"
#include "buildconfiguration.h"
#include "target.h"
#include <utils/qtcassert.h>
using namespace Utils;
namespace ProjectExplorer {
// --------------------------------------------------------------------
// BuildSystem:
// --------------------------------------------------------------------
BuildSystem::BuildSystem(Project *project)
: m_project(project)
{
QTC_CHECK(project);
// Timer:
m_delayedParsingTimer.setSingleShot(true);
connect(&m_delayedParsingTimer, &QTimer::timeout, this, &BuildSystem::triggerParsing);
}
Project *BuildSystem::project() const
{
return m_project;
}
bool BuildSystem::isWaitingForParse() const
{
return m_delayedParsingTimer.isActive();
}
void BuildSystem::requestParse()
{
requestParse(0);
}
void BuildSystem::requestDelayedParse()
{
requestParse(1000);
}
void BuildSystem::requestParse(int delay)
{
m_delayedParsingTimer.setInterval(delay);
m_delayedParsingTimer.start();
}
void BuildSystem::triggerParsing()
{
QTC_CHECK(!project()->isParsing());
Project *p = project();
Target *t = p->activeTarget();
BuildConfiguration *bc = t ? t->activeBuildConfiguration() : nullptr;
MacroExpander *e = nullptr;
if (bc)
e = bc->macroExpander();
else if (t)
e = t->macroExpander();
else
e = p->macroExpander();
Utils::Environment env = p->activeParseEnvironment();
ParsingContext ctx(p->guardParsingRun(), p, bc, e, env);
if (validateParsingContext(ctx))
parseProject(std::move(ctx));
}
} // namespace ProjectExplorer

View File

@@ -0,0 +1,111 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "projectexplorer_export.h"
#include "project.h"
#include "treescanner.h"
#include <QTimer>
namespace ProjectExplorer {
class BuildConfiguration;
class ExtraCompiler;
// --------------------------------------------------------------------
// BuildSystem:
// --------------------------------------------------------------------
class PROJECTEXPLORER_EXPORT BuildSystem : public QObject
{
Q_OBJECT
public:
explicit BuildSystem(Project *project);
BuildSystem(const BuildSystem &other) = delete;
Project *project() const;
bool isWaitingForParse() const;
void requestParse();
void requestDelayedParse();
protected:
class ParsingContext
{
public:
ParsingContext() = default;
ParsingContext(const ParsingContext &other) = delete;
ParsingContext &operator=(const ParsingContext &other) = delete;
ParsingContext(ParsingContext &&other) = default;
ParsingContext &operator=(ParsingContext &&other) = default;
Project::ParseGuard guard;
Project *project = nullptr;
BuildConfiguration *buildConfiguration = nullptr;
Utils::MacroExpander *expander = nullptr;
Utils::Environment environment;
private:
ParsingContext(Project::ParseGuard &&g,
Project *p,
BuildConfiguration *bc,
Utils::MacroExpander *e,
Utils::Environment &env)
: guard(std::move(g))
, project(p)
, buildConfiguration(bc)
, expander(e)
, environment(env)
{}
friend class BuildSystem;
};
virtual bool validateParsingContext(const ParsingContext &ctx)
{
Q_UNUSED(ctx)
return true;
}
virtual void parseProject(ParsingContext &&ctx) = 0; // actual code to parse project
private:
void requestParse(int delay); // request a (delayed!) parser run.
void triggerParsing();
QTimer m_delayedParsingTimer;
Project *m_project;
};
} // namespace ProjectExplorer

View File

@@ -27,6 +27,7 @@
#include "buildconfiguration.h"
#include "buildinfo.h"
#include "buildsystem.h"
#include "deployconfiguration.h"
#include "editorconfiguration.h"
#include "kit.h"
@@ -182,6 +183,7 @@ public:
bool m_knowsAllBuildExecutables = true;
bool m_hasMakeInstallEquivalent = false;
bool m_needsBuildConfigurations = true;
std::unique_ptr<BuildSystem> m_buildSystem;
std::unique_ptr<Core::IDocument> m_document;
std::vector<std::unique_ptr<Core::IDocument>> m_extraProjectDocuments;
std::unique_ptr<ProjectNode> m_rootProjectNode;
@@ -253,6 +255,11 @@ bool Project::canBuildProducts() const
return d->m_canBuildProducts;
}
BuildSystem *Project::buildSystem() const
{
return d->m_buildSystem.get();
}
Utils::FilePath Project::projectFilePath() const
{
QTC_ASSERT(d->m_document, return Utils::FilePath());
@@ -879,6 +886,12 @@ Utils::Environment Project::activeParseEnvironment() const
return result;
}
void Project::setBuildSystem(std::unique_ptr<BuildSystem> &&bs)
{
QTC_ASSERT(!bs->parent(), bs->setParent(nullptr));
d->m_buildSystem = std::move(bs);
}
Core::Context Project::projectContext() const
{
return Core::Context(d->m_id);

View File

@@ -50,6 +50,7 @@ class MacroExpander;
namespace ProjectExplorer {
class BuildInfo;
class BuildSystem;
class ContainerNode;
class EditorConfiguration;
class FolderNode;
@@ -85,6 +86,8 @@ public:
QString mimeType() const;
bool canBuildProducts() const;
BuildSystem *buildSystem() const;
Utils::FilePath projectFilePath() const;
Utils::FilePath projectDirectory() const;
static Utils::FilePath projectDirectory(const Utils::FilePath &top);
@@ -234,6 +237,8 @@ public:
// as the main project file.
void setExtraProjectFiles(const QVector<Utils::FilePath> &projectDocumentPaths);
Utils::Environment activeParseEnvironment() const;
signals:
void projectFileIsDirty(const Utils::FilePath &path);
@@ -294,7 +299,7 @@ protected:
static ProjectExplorer::Task createProjectTask(ProjectExplorer::Task::TaskType type,
const QString &description);
Utils::Environment activeParseEnvironment() const;
void setBuildSystem(std::unique_ptr<BuildSystem> &&bs); // takes ownership!
private:
// Helper methods to manage parsing state and signalling

View File

@@ -13,6 +13,7 @@ HEADERS += projectexplorer.h \
addrunconfigdialog.h \
ansifilterparser.h \
buildinfo.h \
buildsystem.h \
clangparser.h \
configtaskhandler.h \
desktoprunconfiguration.h \
@@ -170,6 +171,7 @@ SOURCES += projectexplorer.cpp \
addrunconfigdialog.cpp \
ansifilterparser.cpp \
buildinfo.cpp \
buildsystem.cpp \
clangparser.cpp \
configtaskhandler.cpp \
desktoprunconfiguration.cpp \

View File

@@ -40,6 +40,7 @@ Project {
"buildstep.cpp", "buildstep.h",
"buildsteplist.cpp", "buildsteplist.h",
"buildstepspage.cpp", "buildstepspage.h",
"buildsystem.cpp", "buildsystem.h",
"buildtargetinfo.h",
"clangparser.cpp", "clangparser.h",
"codestylesettingspropertiespage.cpp", "codestylesettingspropertiespage.h", "codestylesettingspropertiespage.ui",