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

View File

@@ -60,6 +60,17 @@ class BuildDirManager : public QObject
Q_OBJECT Q_OBJECT
public: 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(CMakeProject *project);
~BuildDirManager() final; ~BuildDirManager() final;
@@ -67,7 +78,8 @@ public:
void stopParsingAndClearState(); 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! // nullptr if the BC is not active anymore!
CMakeBuildConfiguration *buildConfiguration() const; CMakeBuildConfiguration *buildConfiguration() const;
CMakeProject *project() const {return m_project; } CMakeProject *project() const {return m_project; }
@@ -78,7 +90,9 @@ public:
void resetData(); void resetData();
bool persistCMakeState(); bool persistCMakeState();
void parse(int reparseParameters); void requestFilesystemScan();
bool isFilesystemScanRequested() const;
void parse();
QVector<Utils::FilePath> takeProjectFilesToWatch(); QVector<Utils::FilePath> takeProjectFilesToWatch();
std::unique_ptr<CMakeProjectNode> generateProjectTree(const QList<const ProjectExplorer::FileNode *> &allFiles, std::unique_ptr<CMakeProjectNode> generateProjectTree(const QList<const ProjectExplorer::FileNode *> &allFiles,
@@ -91,32 +105,20 @@ public:
static CMakeConfig parseCMakeConfiguration(const Utils::FilePath &cacheFile, static CMakeConfig parseCMakeConfiguration(const Utils::FilePath &cacheFile,
QString *errorMessage); 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: signals:
void requestReparse(int reparseParameters) const; void requestReparse() const;
void requestDelayedReparse() const;
void parsingStarted() const; void parsingStarted() const;
void dataAvailable() const; void dataAvailable() const;
void errorOccured(const QString &err) const; void errorOccured(const QString &err) const;
private: private:
void updateReparseParameters(const int parameters);
int takeReparseParameters();
void emitDataAvailable(); void emitDataAvailable();
void emitErrorOccured(const QString &message) const; void emitErrorOccured(const QString &message) const;
void emitReparseRequest() const;
bool checkConfiguration(); bool checkConfiguration();
Utils::FilePath workDirectory(const BuildDirParameters &parameters) const; Utils::FilePath workDirectory(const BuildDirParameters &parameters) const;
@@ -129,6 +131,7 @@ private:
void becameDirty(); void becameDirty();
BuildDirParameters m_parameters; BuildDirParameters m_parameters;
int m_reparseParameters;
CMakeProject *m_project = nullptr; CMakeProject *m_project = nullptr;
mutable std::unordered_map<Utils::FilePath, std::unique_ptr<Utils::TemporaryDirectory>> m_buildDirToTempDir; mutable std::unordered_map<Utils::FilePath, std::unique_ptr<Utils::TemporaryDirectory>> m_buildDirToTempDir;
mutable std::unique_ptr<BuildDirReader> m_reader; 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()); BuildSystem *bs = qobject_cast<CMakeBuildSystem *>(project()->buildSystem());
// BuildDirManager: // BuildDirManager:
connect(&m_buildDirManager, &BuildDirManager::requestReparse, this, [this, bs](int options) { connect(&m_buildDirManager, &BuildDirManager::requestReparse, this, [this, bs]() {
if (isActive()) { if (isActive())
qCDebug(cmakeBuildConfigurationLog) bs->requestParse();
<< "Passing on reparse request with flags" << BuildDirManager::flagsString(options); });
bs->requestParse(options); connect(&m_buildDirManager, &BuildDirManager::requestDelayedReparse, this, [this, bs]() {
} if (isActive())
bs->requestDelayedParse();
}); });
connect(&m_buildDirManager, connect(&m_buildDirManager,
&BuildDirManager::dataAvailable, &BuildDirManager::dataAvailable,

View File

@@ -30,38 +30,6 @@
#include "cmakeprojectconstants.h" #include "cmakeprojectconstants.h"
#include "cmakeprojectnodes.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 <coreplugin/progressmanager/progressmanager.h>
#include <cpptools/cppprojectupdater.h> #include <cpptools/cppprojectupdater.h>
#include <cpptools/generatedcodemodelsupport.h> #include <cpptools/generatedcodemodelsupport.h>
@@ -79,85 +47,12 @@
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace Utils; 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 { namespace CMakeProjectManager {
using namespace Internal; using namespace Internal;
Q_LOGGING_CATEGORY(cmakeBuildSystemLog, "qtc.cmake.buildsystem", QtWarningMsg); 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: // CMakeBuildSystem:
// -------------------------------------------------------------------- // --------------------------------------------------------------------
@@ -227,13 +122,12 @@ void CMakeBuildSystem::parseProject(ParsingContext &&ctx)
m_currentContext = std::move(ctx); m_currentContext = std::move(ctx);
auto bc = qobject_cast<CMakeBuildConfiguration *>(m_currentContext.buildConfiguration); auto bc = qobject_cast<CMakeBuildConfiguration *>(m_currentContext.buildConfiguration);
QTC_ASSERT(bc, return );
int parameters = m_currentContext.parameters;
if (m_allFiles.isEmpty()) 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_waitingForParse = true;
m_combinedScanAndParseResult = true; m_combinedScanAndParseResult = true;
@@ -246,7 +140,7 @@ void CMakeBuildSystem::parseProject(ParsingContext &&ctx)
"CMake.Scan.Tree"); "CMake.Scan.Tree");
} }
bc->m_buildDirManager.parse(parameters); bc->m_buildDirManager.parse();
} }
void CMakeBuildSystem::handleTreeScanningFinished() void CMakeBuildSystem::handleTreeScanningFinished()

View File

@@ -25,20 +25,12 @@
#pragma once #pragma once
#include <projectexplorer/project.h> #include <projectexplorer/buildsystem.h>
#include <projectexplorer/treescanner.h>
#include <QTimer>
namespace CppTools { namespace CppTools {
class CppProjectUpdater; class CppProjectUpdater;
} // namespace CppTools } // namespace CppTools
namespace ProjectExplorer {
class BuildConfiguration;
class ExtraCompiler;
} // namespace ProjectExplorer
namespace CMakeProjectManager { namespace CMakeProjectManager {
class CMakeProject; class CMakeProject;
@@ -47,88 +39,11 @@ namespace Internal {
class CMakeBuildConfiguration; class CMakeBuildConfiguration;
} // namespace Internal } // 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: // CMakeBuildSystem:
// -------------------------------------------------------------------- // --------------------------------------------------------------------
class CMakeBuildSystem : public BuildSystem class CMakeBuildSystem : public ProjectExplorer::BuildSystem
{ {
Q_OBJECT Q_OBJECT

View File

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

View File

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

View File

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

View File

@@ -21,6 +21,7 @@ add_qtc_plugin(ProjectExplorer
buildstep.cpp buildstep.h buildstep.cpp buildstep.h
buildsteplist.cpp buildsteplist.h buildsteplist.cpp buildsteplist.h
buildstepspage.cpp buildstepspage.h buildstepspage.cpp buildstepspage.h
buildsystem.cpp buildsystem.h
buildtargetinfo.h buildtargetinfo.h
clangparser.cpp clangparser.h clangparser.cpp clangparser.h
codestylesettingspropertiespage.cpp codestylesettingspropertiespage.h codestylesettingspropertiespage.ui 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 "buildconfiguration.h"
#include "buildinfo.h" #include "buildinfo.h"
#include "buildsystem.h"
#include "deployconfiguration.h" #include "deployconfiguration.h"
#include "editorconfiguration.h" #include "editorconfiguration.h"
#include "kit.h" #include "kit.h"
@@ -182,6 +183,7 @@ public:
bool m_knowsAllBuildExecutables = true; bool m_knowsAllBuildExecutables = true;
bool m_hasMakeInstallEquivalent = false; bool m_hasMakeInstallEquivalent = false;
bool m_needsBuildConfigurations = true; bool m_needsBuildConfigurations = true;
std::unique_ptr<BuildSystem> m_buildSystem;
std::unique_ptr<Core::IDocument> m_document; std::unique_ptr<Core::IDocument> m_document;
std::vector<std::unique_ptr<Core::IDocument>> m_extraProjectDocuments; std::vector<std::unique_ptr<Core::IDocument>> m_extraProjectDocuments;
std::unique_ptr<ProjectNode> m_rootProjectNode; std::unique_ptr<ProjectNode> m_rootProjectNode;
@@ -253,6 +255,11 @@ bool Project::canBuildProducts() const
return d->m_canBuildProducts; return d->m_canBuildProducts;
} }
BuildSystem *Project::buildSystem() const
{
return d->m_buildSystem.get();
}
Utils::FilePath Project::projectFilePath() const Utils::FilePath Project::projectFilePath() const
{ {
QTC_ASSERT(d->m_document, return Utils::FilePath()); QTC_ASSERT(d->m_document, return Utils::FilePath());
@@ -879,6 +886,12 @@ Utils::Environment Project::activeParseEnvironment() const
return result; 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 Core::Context Project::projectContext() const
{ {
return Core::Context(d->m_id); return Core::Context(d->m_id);

View File

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

View File

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

View File

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