aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/projectexplorer
diff options
context:
space:
mode:
authorhjk <hjk@qt.io>2019-10-25 09:55:32 +0200
committerhjk <hjk@qt.io>2019-11-19 11:05:52 +0000
commit27586827238ca9079860e77a7b23ae20d163143e (patch)
tree2197dc7f97a4a70524381071888336558dc0b4a3 /src/plugins/projectexplorer
parent9073c46c9c431ec0e83987a5781163ca7b1f7ea7 (diff)
ProjectExplorer: Move BuildSystem owership to BuildConfiguration
... or Target. This patch moves build system from conceptually "one per project" to "one per target (i.e. per project-and-kit)" or "per BuildConfigurations" for targets where the builds differ significantly. Building requires usually items from the kit (Qt version, compiler, ...) so a target-agnostic build is practically almost always wrong. Moving the build system to the target also has the potential to solve issues caused by switching targets while parsing, that used Project::activeTarget() regularly, with potentially different results before and after the switch. This patch might create performance/size regressions when several targets are set up per project as the build system implementation's internal data are duplicated in this case. The idea is to fix that by sharing per-project pieces again in the project implementation once these problems occur. Change-Id: I87f640ce418b93175b5029124eaa55f3b8721dca Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Diffstat (limited to 'src/plugins/projectexplorer')
-rw-r--r--src/plugins/projectexplorer/buildconfiguration.cpp32
-rw-r--r--src/plugins/projectexplorer/buildconfiguration.h5
-rw-r--r--src/plugins/projectexplorer/buildsettingspropertiespage.cpp20
-rw-r--r--src/plugins/projectexplorer/buildstep.cpp7
-rw-r--r--src/plugins/projectexplorer/buildstep.h3
-rw-r--r--src/plugins/projectexplorer/buildstepspage.cpp4
-rw-r--r--src/plugins/projectexplorer/buildstepspage.h2
-rw-r--r--src/plugins/projectexplorer/buildsystem.cpp217
-rw-r--r--src/plugins/projectexplorer/buildsystem.h118
-rw-r--r--src/plugins/projectexplorer/customexecutablerunconfiguration.cpp5
-rw-r--r--src/plugins/projectexplorer/customexecutablerunconfiguration.h1
-rw-r--r--src/plugins/projectexplorer/deploymentdataview.cpp5
-rw-r--r--src/plugins/projectexplorer/desktoprunconfiguration.cpp29
-rw-r--r--src/plugins/projectexplorer/desktoprunconfiguration.h4
-rw-r--r--src/plugins/projectexplorer/makestep.cpp2
-rw-r--r--src/plugins/projectexplorer/project.cpp144
-rw-r--r--src/plugins/projectexplorer/project.h97
-rw-r--r--src/plugins/projectexplorer/projectexplorer.cpp4
-rw-r--r--src/plugins/projectexplorer/projectmodels.cpp16
-rw-r--r--src/plugins/projectexplorer/projectnodes.cpp5
-rw-r--r--src/plugins/projectexplorer/projecttree.cpp13
-rw-r--r--src/plugins/projectexplorer/projecttree.h4
-rw-r--r--src/plugins/projectexplorer/runconfiguration.cpp38
-rw-r--r--src/plugins/projectexplorer/runconfiguration.h7
-rw-r--r--src/plugins/projectexplorer/runcontrol.cpp2
-rw-r--r--src/plugins/projectexplorer/session.cpp11
-rw-r--r--src/plugins/projectexplorer/session.h6
-rw-r--r--src/plugins/projectexplorer/target.cpp105
-rw-r--r--src/plugins/projectexplorer/target.h20
29 files changed, 500 insertions, 426 deletions
diff --git a/src/plugins/projectexplorer/buildconfiguration.cpp b/src/plugins/projectexplorer/buildconfiguration.cpp
index d1e6225b98..b312e0fb7e 100644
--- a/src/plugins/projectexplorer/buildconfiguration.cpp
+++ b/src/plugins/projectexplorer/buildconfiguration.cpp
@@ -28,6 +28,8 @@
#include "buildenvironmentwidget.h"
#include "buildinfo.h"
#include "buildsteplist.h"
+#include "buildstepspage.h"
+#include "buildsystem.h"
#include "namedwidget.h"
#include "kit.h"
#include "kitinformation.h"
@@ -89,6 +91,7 @@ BuildConfiguration::BuildConfiguration(Target *target, Core::Id id)
: ProjectConfiguration(target, id), d(new Internal::BuildConfigurationPrivate)
{
QTC_CHECK(target && target == this->target());
+
Utils::MacroExpander *expander = macroExpander();
expander->setDisplayName(tr("Build Settings"));
expander->setAccumulating(true);
@@ -128,8 +131,8 @@ BuildConfiguration::BuildConfiguration(Target *target, Core::Id id)
this->target()->buildEnvironmentChanged(this);
});
- connect(project(), &Project::parsingStarted, this, &BuildConfiguration::enabledChanged);
- connect(project(), &Project::parsingFinished, this, &BuildConfiguration::enabledChanged);
+ connect(target, &Target::parsingStarted, this, &BuildConfiguration::enabledChanged);
+ connect(target, &Target::parsingFinished, this, &BuildConfiguration::enabledChanged);
connect(this, &BuildConfiguration::enabledChanged, this, [this] {
if (isActive() && project() == SessionManager::startupProject()) {
@@ -164,6 +167,19 @@ void BuildConfiguration::setBuildDirectory(const Utils::FilePath &dir)
emitBuildDirectoryChanged();
}
+void BuildConfiguration::addConfigWidgets(const std::function<void(NamedWidget *)> &adder)
+{
+ if (NamedWidget *generalConfigWidget = createConfigWidget())
+ adder(generalConfigWidget);
+
+ adder(new Internal::BuildStepListWidget(stepList(Constants::BUILDSTEPS_BUILD)));
+ adder(new Internal::BuildStepListWidget(stepList(Constants::BUILDSTEPS_CLEAN)));
+
+ QList<NamedWidget *> subConfigWidgets = createSubConfigWidgets();
+ foreach (NamedWidget *subConfigWidget, subConfigWidgets)
+ adder(subConfigWidget);
+}
+
NamedWidget *BuildConfiguration::createConfigWidget()
{
NamedWidget *named = new NamedWidget(d->m_configWidgetDisplayName);
@@ -203,6 +219,12 @@ QList<NamedWidget *> BuildConfiguration::createSubConfigWidgets()
return {new BuildEnvironmentWidget(this)};
}
+BuildSystem *BuildConfiguration::buildSystem() const
+{
+ QTC_CHECK(target()->fallbackBuildSystem());
+ return target()->fallbackBuildSystem();
+}
+
QList<Core::Id> BuildConfiguration::knownStepLists() const
{
return Utils::transform(d->m_stepLists, &BuildStepList::id);
@@ -368,14 +390,14 @@ void BuildConfiguration::setUserEnvironmentChanges(const Utils::EnvironmentItems
bool BuildConfiguration::isEnabled() const
{
- return !project()->isParsing() && project()->hasParsingData();
+ return !buildSystem()->isParsing() && buildSystem()->hasParsingData();
}
QString BuildConfiguration::disabledReason() const
{
- if (project()->isParsing())
+ if (buildSystem()->isParsing())
return (tr("The project is currently being parsed."));
- if (!project()->hasParsingData())
+ if (!buildSystem()->hasParsingData())
return (tr("The project was not parsed successfully."));
return QString();
}
diff --git a/src/plugins/projectexplorer/buildconfiguration.h b/src/plugins/projectexplorer/buildconfiguration.h
index 6160e3b6a4..2a57fb5858 100644
--- a/src/plugins/projectexplorer/buildconfiguration.h
+++ b/src/plugins/projectexplorer/buildconfiguration.h
@@ -38,6 +38,7 @@ namespace Internal { class BuildConfigurationPrivate; }
class BaseStringAspect;
class BuildInfo;
+class BuildSystem;
class BuildStepList;
class Kit;
class NamedWidget;
@@ -59,6 +60,8 @@ public:
Utils::FilePath rawBuildDirectory() const;
void setBuildDirectory(const Utils::FilePath &dir);
+ virtual BuildSystem *buildSystem() const;
+
virtual NamedWidget *createConfigWidget();
virtual QList<NamedWidget *> createSubConfigWidgets();
@@ -110,6 +113,8 @@ public:
void setConfigWidgetHasFrame(bool configWidgetHasFrame);
void setBuildDirectorySettingsKey(const QString &key);
+ void addConfigWidgets(const std::function<void (NamedWidget *)> &adder);
+
signals:
void environmentChanged();
void buildDirectoryChanged();
diff --git a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
index 468d4751ac..f5d33a7b4e 100644
--- a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
@@ -139,6 +139,7 @@ BuildSettingsWidget::BuildSettingsWidget(Target *target) :
void BuildSettingsWidget::addSubWidget(NamedWidget *widget)
{
+ widget->setParent(this);
widget->setContentsMargins(0, 10, 0, 0);
auto label = new QLabel(this);
@@ -192,23 +193,8 @@ void BuildSettingsWidget::updateBuildSettings()
m_renameButton->setEnabled(!bcs.isEmpty());
m_cloneButton->setEnabled(!bcs.isEmpty());
- if (!m_buildConfiguration)
- return;
-
- // Add pages
- NamedWidget *generalConfigWidget = m_buildConfiguration->createConfigWidget();
- if (generalConfigWidget)
- addSubWidget(generalConfigWidget);
-
- BuildStepList *buildSteps = m_buildConfiguration->stepList(Constants::BUILDSTEPS_BUILD);
- addSubWidget(new BuildStepListWidget(buildSteps, this));
-
- BuildStepList *cleanSteps = m_buildConfiguration->stepList(Constants::BUILDSTEPS_CLEAN);
- addSubWidget(new BuildStepListWidget(cleanSteps, this));
-
- QList<NamedWidget *> subConfigWidgets = m_buildConfiguration->createSubConfigWidgets();
- foreach (NamedWidget *subConfigWidget, subConfigWidgets)
- addSubWidget(subConfigWidget);
+ if (m_buildConfiguration)
+ m_buildConfiguration->addConfigWidgets([this](NamedWidget *w) { addSubWidget(w); });
}
void BuildSettingsWidget::currentIndexChanged(int index)
diff --git a/src/plugins/projectexplorer/buildstep.cpp b/src/plugins/projectexplorer/buildstep.cpp
index fb8c1f3848..ba0bfa221a 100644
--- a/src/plugins/projectexplorer/buildstep.cpp
+++ b/src/plugins/projectexplorer/buildstep.cpp
@@ -204,6 +204,13 @@ ProjectConfiguration *BuildStep::projectConfiguration() const
return static_cast<ProjectConfiguration *>(parent()->parent());
}
+BuildSystem *BuildStep::buildSystem() const
+{
+ if (auto bc = buildConfiguration())
+ return bc->buildSystem();
+ return target()->buildSystem();
+}
+
void BuildStep::reportRunResult(QFutureInterface<bool> &fi, bool success)
{
fi.reportResult(success);
diff --git a/src/plugins/projectexplorer/buildstep.h b/src/plugins/projectexplorer/buildstep.h
index f9fb6fbec6..0c9a85e9b3 100644
--- a/src/plugins/projectexplorer/buildstep.h
+++ b/src/plugins/projectexplorer/buildstep.h
@@ -44,6 +44,7 @@ class BuildConfiguration;
class BuildStepConfigWidget;
class BuildStepFactory;
class BuildStepList;
+class BuildSystem;
class DeployConfiguration;
class Target;
class Task;
@@ -75,6 +76,8 @@ public:
DeployConfiguration *deployConfiguration() const;
ProjectConfiguration *projectConfiguration() const;
+ BuildSystem *buildSystem() const;
+
enum class OutputFormat {
Stdout, Stderr, // These are for forwarded output from external tools
NormalMessage, ErrorMessage // These are for messages from Creator itself
diff --git a/src/plugins/projectexplorer/buildstepspage.cpp b/src/plugins/projectexplorer/buildstepspage.cpp
index 76fadceb68..ea795fec1a 100644
--- a/src/plugins/projectexplorer/buildstepspage.cpp
+++ b/src/plugins/projectexplorer/buildstepspage.cpp
@@ -191,9 +191,9 @@ BuildStepsWidgetData::~BuildStepsWidgetData()
// We do not own the step
}
-BuildStepListWidget::BuildStepListWidget(BuildStepList *bsl, QWidget *parent)
+BuildStepListWidget::BuildStepListWidget(BuildStepList *bsl)
//: %1 is the name returned by BuildStepList::displayName
- : NamedWidget(tr("%1 Steps").arg(bsl->displayName()), parent), m_buildStepList(bsl)
+ : NamedWidget(tr("%1 Steps").arg(bsl->displayName())), m_buildStepList(bsl)
{
setupUi();
diff --git a/src/plugins/projectexplorer/buildstepspage.h b/src/plugins/projectexplorer/buildstepspage.h
index 7eade2d663..9fef567a1f 100644
--- a/src/plugins/projectexplorer/buildstepspage.h
+++ b/src/plugins/projectexplorer/buildstepspage.h
@@ -97,7 +97,7 @@ class BuildStepListWidget : public NamedWidget
Q_OBJECT
public:
- BuildStepListWidget(BuildStepList *bsl, QWidget *parent = nullptr);
+ explicit BuildStepListWidget(BuildStepList *bsl);
~BuildStepListWidget() override;
private:
diff --git a/src/plugins/projectexplorer/buildsystem.cpp b/src/plugins/projectexplorer/buildsystem.cpp
index 496f9cc9f4..e6e6ad9677 100644
--- a/src/plugins/projectexplorer/buildsystem.cpp
+++ b/src/plugins/projectexplorer/buildsystem.cpp
@@ -26,10 +26,14 @@
#include "buildsystem.h"
#include "buildconfiguration.h"
+#include "runconfiguration.h"
+#include "runcontrol.h"
#include "target.h"
#include <utils/qtcassert.h>
+#include <QTimer>
+
using namespace Utils;
namespace ProjectExplorer {
@@ -38,77 +42,129 @@ namespace ProjectExplorer {
// BuildSystem:
// --------------------------------------------------------------------
-BuildSystem::BuildSystem(Project *project)
- : m_project(project)
+class BuildSystemPrivate
+{
+public:
+ Target *m_target = nullptr;
+ BuildConfiguration *m_buildConfiguration = nullptr;
+
+ QTimer m_delayedParsingTimer;
+
+ bool m_isParsing = false;
+ bool m_hasParsingData = false;
+
+ DeploymentData m_deploymentData;
+ QList<BuildTargetInfo> m_appTargets;
+};
+
+BuildSystem::BuildSystem(BuildConfiguration *bc)
+ : BuildSystem(bc->target())
+{
+ d->m_buildConfiguration = bc;
+}
+
+BuildSystem::BuildSystem(Target *target)
+ : d(new BuildSystemPrivate)
{
- QTC_CHECK(project);
+ QTC_CHECK(target);
+ d->m_target = target;
// Timer:
- m_delayedParsingTimer.setSingleShot(true);
+ d->m_delayedParsingTimer.setSingleShot(true);
- connect(&m_delayedParsingTimer, &QTimer::timeout, this, &BuildSystem::triggerParsing);
+ connect(&d->m_delayedParsingTimer, &QTimer::timeout, this, &BuildSystem::triggerParsing);
+}
+
+BuildSystem::~BuildSystem()
+{
+ delete d;
}
Project *BuildSystem::project() const
{
- return m_project;
+ return d->m_target->project();
+}
+
+Target *BuildSystem::target() const
+{
+ return d->m_target;
+}
+
+void BuildSystem::emitParsingStarted()
+{
+ QTC_ASSERT(!d->m_isParsing, return);
+
+ d->m_isParsing = true;
+ d->m_hasParsingData = false;
+ emit d->m_target->parsingStarted();
+}
+
+void BuildSystem::emitParsingFinished(bool success)
+{
+ // Intentionally no return, as we currently get start - start - end - end
+ // sequences when switching qmake targets quickly.
+ QTC_CHECK(d->m_isParsing);
+
+ d->m_isParsing = false;
+ d->m_hasParsingData = success;
+ emit d->m_target->parsingFinished(success);
}
FilePath BuildSystem::projectFilePath() const
{
- return m_project->projectFilePath();
+ return d->m_target->project()->projectFilePath();
}
FilePath BuildSystem::projectDirectory() const
{
- return m_project->projectDirectory();
+ return d->m_target->project()->projectDirectory();
}
bool BuildSystem::isWaitingForParse() const
{
- return m_delayedParsingTimer.isActive();
+ return d->m_delayedParsingTimer.isActive();
}
void BuildSystem::requestParse()
{
- requestParse(0);
+ requestParseHelper(0);
}
void BuildSystem::requestDelayedParse()
{
- requestParse(1000);
+ requestParseHelper(1000);
}
-void BuildSystem::requestParse(int delay)
+bool BuildSystem::isParsing() const
{
- m_delayedParsingTimer.setInterval(delay);
- m_delayedParsingTimer.start();
+ return d->m_isParsing;
}
-void BuildSystem::triggerParsing()
+bool BuildSystem::hasParsingData() const
{
- QTC_ASSERT(!project()->isParsing(), return );
-
- Project *p = project();
- Target *t = p->activeTarget();
- BuildConfiguration *bc = t ? t->activeBuildConfiguration() : nullptr;
+ return d->m_hasParsingData;
+}
- MacroExpander *e = nullptr;
+Environment BuildSystem::activeParseEnvironment() const
+{
+ const BuildConfiguration *const bc = d->m_target->activeBuildConfiguration();
if (bc)
- e = bc->macroExpander();
- else if (t)
- e = t->macroExpander();
- else
- e = p->macroExpander();
+ return bc->environment();
- Utils::Environment env = p->activeParseEnvironment();
+ const RunConfiguration *const rc = d->m_target->activeRunConfiguration();
+ if (rc)
+ return rc->runnable().environment;
- ParsingContext ctx(p->guardParsingRun(), p, bc, e, env);
+ Environment result = Utils::Environment::systemEnvironment();
+ d->m_target->kit()->addToEnvironment(result);
- QTC_ASSERT(ctx.guard.guardsProject(), return );
+ return result;
+}
- if (validateParsingContext(ctx))
- parseProject(std::move(ctx));
+void BuildSystem::requestParseHelper(int delay)
+{
+ d->m_delayedParsingTimer.setInterval(delay);
+ d->m_delayedParsingTimer.start();
}
bool BuildSystem::addFiles(Node *, const QStringList &filePaths, QStringList *notAdded)
@@ -157,4 +213,103 @@ bool BuildSystem::supportsAction(Node *, ProjectAction, const Node *) const
return false;
}
+QStringList BuildSystem::filesGeneratedFrom(const QString &sourceFile) const
+{
+ Q_UNUSED(sourceFile)
+ return {};
+}
+
+QVariant BuildSystem::additionalData(Core::Id id) const
+{
+ Q_UNUSED(id)
+ return {};
+}
+
+// ParseGuard
+
+BuildSystem::ParseGuard::ParseGuard(BuildSystem::ParseGuard &&other)
+ : m_buildSystem{std::move(other.m_buildSystem)}
+ , m_success{std::move(other.m_success)}
+{
+ // No need to release this as this is invalid anyway:-)
+ other.m_buildSystem = nullptr;
+}
+
+BuildSystem::ParseGuard::ParseGuard(BuildSystem *p)
+ : m_buildSystem(p)
+{
+ if (m_buildSystem && !m_buildSystem->isParsing())
+ m_buildSystem->emitParsingStarted();
+ else
+ m_buildSystem = nullptr;
+}
+
+void BuildSystem::ParseGuard::release()
+{
+ if (m_buildSystem)
+ m_buildSystem->emitParsingFinished(m_success);
+ m_buildSystem = nullptr;
+}
+
+BuildSystem::ParseGuard &BuildSystem::ParseGuard::operator=(BuildSystem::ParseGuard &&other)
+{
+ release();
+
+ m_buildSystem = std::move(other.m_buildSystem);
+ m_success = std::move(other.m_success);
+
+ other.m_buildSystem = nullptr;
+ return *this;
+}
+
+void BuildSystem::setDeploymentData(const DeploymentData &deploymentData)
+{
+ if (d->m_deploymentData != deploymentData) {
+ d->m_deploymentData = deploymentData;
+ emit deploymentDataChanged();
+ emit applicationTargetsChanged();
+ emit target()->deploymentDataChanged();
+ emit target()->applicationTargetsChanged();
+ }
+}
+
+DeploymentData BuildSystem::deploymentData() const
+{
+ return d->m_deploymentData;
+}
+
+void BuildSystem::setApplicationTargets(const QList<BuildTargetInfo> &appTargets)
+{
+ if (Utils::toSet(appTargets) != Utils::toSet(d->m_appTargets)) {
+ d->m_appTargets = appTargets;
+ emit applicationTargetsChanged();
+ emit target()->applicationTargetsChanged();
+ }
+}
+
+const QList<BuildTargetInfo> BuildSystem::applicationTargets() const
+{
+ return d->m_appTargets;
+}
+
+BuildTargetInfo BuildSystem::buildTarget(const QString &buildKey) const
+{
+ return Utils::findOrDefault(d->m_appTargets, [&buildKey](const BuildTargetInfo &ti) {
+ return ti.buildKey == buildKey;
+ });
+}
+
+QString BuildSystem::disabledReason(const QString &buildKey) const
+{
+ if (hasParsingData()) {
+ QString msg = isParsing() ? tr("The project is currently being parsed.")
+ : tr("The project could not be fully parsed.");
+ const FilePath projectFilePath = buildTarget(buildKey).projectFilePath;
+ if (!projectFilePath.isEmpty() && !projectFilePath.exists())
+ msg += '\n' + tr("The project file \"%1\" does not exist.").arg(projectFilePath.toString());
+ return msg;
+ }
+ return {};
+}
+
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/buildsystem.h b/src/plugins/projectexplorer/buildsystem.h
index 9bd5de6639..b73b459b7b 100644
--- a/src/plugins/projectexplorer/buildsystem.h
+++ b/src/plugins/projectexplorer/buildsystem.h
@@ -27,15 +27,15 @@
#include "projectexplorer_export.h"
+#include "buildtargetinfo.h"
#include "project.h"
#include "treescanner.h"
-#include <QTimer>
+#include <QObject>
namespace ProjectExplorer {
class BuildConfiguration;
-class ExtraCompiler;
class Node;
// --------------------------------------------------------------------
@@ -47,11 +47,13 @@ class PROJECTEXPLORER_EXPORT BuildSystem : public QObject
Q_OBJECT
public:
- explicit BuildSystem(Project *project);
-
- BuildSystem(const BuildSystem &other) = delete;
+ explicit BuildSystem(Target *target);
+ explicit BuildSystem(BuildConfiguration *bc);
+ ~BuildSystem() override;
Project *project() const;
+ Target *target() const;
+
Utils::FilePath projectFilePath() const;
Utils::FilePath projectDirectory() const;
@@ -60,6 +62,11 @@ public:
void requestParse();
void requestDelayedParse();
+ bool isParsing() const;
+ bool hasParsingData() const;
+
+ Utils::Environment activeParseEnvironment() const;
+
virtual bool addFiles(Node *context, const QStringList &filePaths, QStringList *notAdded = nullptr);
virtual RemovedFilesFromProject removeFiles(Node *context, const QStringList &filePaths,
QStringList *notRemoved = nullptr);
@@ -69,69 +76,64 @@ public:
virtual bool addDependencies(Node *context, const QStringList &dependencies);
virtual bool supportsAction(Node *context, ProjectAction action, const Node *node) const;
-protected:
- class ParsingContext
+ virtual QStringList filesGeneratedFrom(const QString &sourceFile) const;
+ virtual QVariant additionalData(Core::Id id) const;
+
+ void setDeploymentData(const DeploymentData &deploymentData);
+ DeploymentData deploymentData() const;
+
+ void setApplicationTargets(const QList<BuildTargetInfo> &appTargets);
+ const QList<BuildTargetInfo> applicationTargets() const;
+ BuildTargetInfo buildTarget(const QString &buildKey) const;
+
+ class ParseGuard
{
+ friend class BuildSystem;
+ explicit ParseGuard(BuildSystem *p);
+
+ void release();
+
public:
- ParsingContext() = default;
-
- ParsingContext(const ParsingContext &other) = delete;
- ParsingContext &operator=(const ParsingContext &other) = delete;
- ParsingContext(ParsingContext &&other)
- : guard{std::move(other.guard)}
- , project{std::move(other.project)}
- , buildConfiguration{std::move(other.buildConfiguration)}
- , expander{std::move(other.expander)}
- , environment{std::move(other.environment)}
- {}
- ParsingContext &operator=(ParsingContext &&other)
- {
- guard = std::move(other.guard);
- project = std::move(other.project);
- buildConfiguration = std::move(other.buildConfiguration);
- expander = std::move(other.expander);
- environment = std::move(other.environment);
- return *this;
- }
-
- Project::ParseGuard guard;
-
- Project *project = nullptr;
- BuildConfiguration *buildConfiguration = nullptr;
- Utils::MacroExpander *expander = nullptr;
- Utils::Environment environment;
+ ParseGuard() = default;
+ ~ParseGuard() { release(); }
- 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)
- {}
+ void markAsSuccess() const { m_success = true; }
+ bool isSuccess() const { return m_success; }
+ bool guardsProject() const { return m_buildSystem; }
- friend class BuildSystem;
+ ParseGuard(const ParseGuard &other) = delete;
+ ParseGuard &operator=(const ParseGuard &other) = delete;
+ ParseGuard(ParseGuard &&other);
+ ParseGuard &operator=(ParseGuard &&other);
+
+ private:
+ BuildSystem *m_buildSystem = nullptr;
+ mutable bool m_success = false;
};
- virtual bool validateParsingContext(const ParsingContext &ctx)
- {
- Q_UNUSED(ctx)
- return true;
- }
+public:
+ // FIXME: Make this private and the BuildSystem a friend
+ ParseGuard guardParsingRun() { return ParseGuard(this); }
- virtual void parseProject(ParsingContext &&) {} // actual code to parse project
+ QString disabledReason(const QString &buildKey) const;
-private:
- void requestParse(int delay); // request a (delayed!) parser run.
- void triggerParsing();
+ virtual void triggerParsing() = 0;
+
+signals:
+ void deploymentDataChanged();
+ void applicationTargetsChanged();
- QTimer m_delayedParsingTimer;
+protected:
+ // Helper methods to manage parsing state and signalling
+ // Call in GUI thread before the actual parsing starts
+ void emitParsingStarted();
+ // Call in GUI thread right after the actual parsing is done
+ void emitParsingFinished(bool success);
+
+private:
+ void requestParseHelper(int delay); // request a (delayed!) parser run.
- Project *m_project;
+ class BuildSystemPrivate *d = nullptr;
};
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp
index ef198bea92..62ba2eace5 100644
--- a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp
+++ b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp
@@ -246,6 +246,11 @@ bool CustomExecutableRunConfiguration::isConfigured() const
return !rawExecutable().isEmpty();
}
+bool CustomExecutableRunConfiguration::isEnabled() const
+{
+ return true;
+}
+
Runnable CustomExecutableRunConfiguration::runnable() const
{
FilePath workingDirectory =
diff --git a/src/plugins/projectexplorer/customexecutablerunconfiguration.h b/src/plugins/projectexplorer/customexecutablerunconfiguration.h
index 6abd0f3185..bcd7b3b9ba 100644
--- a/src/plugins/projectexplorer/customexecutablerunconfiguration.h
+++ b/src/plugins/projectexplorer/customexecutablerunconfiguration.h
@@ -45,6 +45,7 @@ public:
/** Returns whether this runconfiguration ever was configured with an executable
*/
bool isConfigured() const override;
+ bool isEnabled() const override;
ConfigurationState ensureConfigured(QString *errorMessage) override;
QString defaultDisplayName() const;
diff --git a/src/plugins/projectexplorer/deploymentdataview.cpp b/src/plugins/projectexplorer/deploymentdataview.cpp
index f620cf4a5b..8796c897db 100644
--- a/src/plugins/projectexplorer/deploymentdataview.cpp
+++ b/src/plugins/projectexplorer/deploymentdataview.cpp
@@ -25,9 +25,11 @@
#include "deploymentdataview.h"
+#include "buildsystem.h"
#include "deploymentdata.h"
#include "target.h"
+#include <utils/qtcassert.h>
#include <utils/treemodel.h>
#include <QAbstractTableModel>
@@ -78,7 +80,8 @@ DeploymentDataView::DeploymentDataView(Target *target)
auto updatModel = [this, target, model, view] {
model->clear();
- for (const DeployableFile &file : target->deploymentData().allFiles())
+ QTC_ASSERT(target->buildSystem(), return);
+ for (const DeployableFile &file : target->buildSystem()->deploymentData().allFiles())
model->rootItem()->appendChild(new DeploymentDataItem(file));
QHeaderView *header = view->header();
diff --git a/src/plugins/projectexplorer/desktoprunconfiguration.cpp b/src/plugins/projectexplorer/desktoprunconfiguration.cpp
index a3f1f735ac..616bf19f70 100644
--- a/src/plugins/projectexplorer/desktoprunconfiguration.cpp
+++ b/src/plugins/projectexplorer/desktoprunconfiguration.cpp
@@ -78,7 +78,7 @@ DesktopRunConfiguration::DesktopRunConfiguration(Target *target, Core::Id id, Ki
if (kind == Qbs) {
- connect(project(), &Project::parsingFinished,
+ connect(target, &Target::parsingFinished,
envAspect, &EnvironmentAspect::environmentChanged);
connect(target, &Target::deploymentDataChanged,
@@ -95,12 +95,15 @@ DesktopRunConfiguration::DesktopRunConfiguration(Target *target, Core::Id id, Ki
}
- connect(target->project(), &Project::parsingFinished,
+ connect(target, &Target::parsingFinished,
this, &DesktopRunConfiguration::updateTargetInformation);
}
void DesktopRunConfiguration::updateTargetInformation()
{
+ if (!activeBuildSystem())
+ return;
+
BuildTargetInfo bti = buildTargetInfo();
auto terminalAspect = aspect<TerminalAspect>();
@@ -184,28 +187,6 @@ Utils::FilePath DesktopRunConfiguration::executableToRun(const BuildTargetInfo &
return appInLocalInstallDir.exists() ? appInLocalInstallDir : appInBuildDir;
}
-bool DesktopRunConfiguration::isBuildTargetValid() const
-{
- return Utils::anyOf(target()->applicationTargets(), [this](const BuildTargetInfo &bti) {
- return bti.buildKey == buildKey();
- });
-}
-
-void DesktopRunConfiguration::updateEnabledState()
-{
- if (m_kind == CMake && !isBuildTargetValid())
- setEnabled(false);
- else
- RunConfiguration::updateEnabledState();
-}
-
-QString DesktopRunConfiguration::disabledReason() const
-{
- if (m_kind == CMake && !isBuildTargetValid())
- return tr("The project no longer builds the target associated with this run configuration.");
- return RunConfiguration::disabledReason();
-}
-
// Factory
class DesktopQmakeRunConfiguration : public DesktopRunConfiguration
diff --git a/src/plugins/projectexplorer/desktoprunconfiguration.h b/src/plugins/projectexplorer/desktoprunconfiguration.h
index 4063337ef1..065014edf7 100644
--- a/src/plugins/projectexplorer/desktoprunconfiguration.h
+++ b/src/plugins/projectexplorer/desktoprunconfiguration.h
@@ -43,14 +43,10 @@ protected:
private:
void doAdditionalSetup(const RunConfigurationCreationInfo &info) final;
bool fromMap(const QVariantMap &map) final;
- void updateEnabledState() final;
void updateTargetInformation();
Utils::FilePath executableToRun(const BuildTargetInfo &targetInfo) const;
- QString disabledReason() const override;
-
- bool isBuildTargetValid() const;
const Kind m_kind;
};
diff --git a/src/plugins/projectexplorer/makestep.cpp b/src/plugins/projectexplorer/makestep.cpp
index 64834f190b..8358ea4df3 100644
--- a/src/plugins/projectexplorer/makestep.cpp
+++ b/src/plugins/projectexplorer/makestep.cpp
@@ -443,7 +443,7 @@ MakeStepConfigWidget::MakeStepConfigWidget(MakeStep *makeStep)
this, &MakeStepConfigWidget::updateDetails);
connect(m_makeStep->buildConfiguration(), &BuildConfiguration::buildDirectoryChanged,
this, &MakeStepConfigWidget::updateDetails);
- connect(m_makeStep->project(), &Project::parsingFinished,
+ connect(m_makeStep->target(), &Target::parsingFinished,
this, &MakeStepConfigWidget::updateDetails);
Core::VariableChooser::addSupportForChildWidgets(this, m_makeStep->macroExpander());
diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp
index 2e75cd3caf..4f084bc7fa 100644
--- a/src/plugins/projectexplorer/project.cpp
+++ b/src/plugins/projectexplorer/project.cpp
@@ -176,14 +176,15 @@ public:
~ProjectPrivate();
Core::Id m_id;
- bool m_isParsing = false;
- bool m_hasParsingData = false;
bool m_needsInitialExpansion = false;
bool m_canBuildProducts = false;
bool m_knowsAllBuildExecutables = true;
bool m_hasMakeInstallEquivalent = false;
bool m_needsBuildConfigurations = true;
- std::unique_ptr<BuildSystem> m_buildSystem;
+ bool m_needsDeployConfigurations = true;
+
+ std::function<BuildSystem *(Target *)> m_buildSystemCreator;
+
std::unique_ptr<Core::IDocument> m_document;
std::vector<std::unique_ptr<Core::IDocument>> m_extraProjectDocuments;
std::unique_ptr<ProjectNode> m_rootProjectNode;
@@ -255,9 +256,9 @@ bool Project::canBuildProducts() const
return d->m_canBuildProducts;
}
-BuildSystem *Project::buildSystem() const
+BuildSystem *Project::createBuildSystem(Target *target) const
{
- return d->m_buildSystem.get();
+ return d->m_buildSystemCreator ? d->m_buildSystemCreator(target) : nullptr;
}
Utils::FilePath Project::projectFilePath() const
@@ -341,8 +342,6 @@ void Project::setActiveTarget(Target *target)
(target && Utils::contains(d->m_targets, target))) {
d->m_activeTarget = target;
emit activeTargetChanged(d->m_activeTarget);
- emit activeBuildConfigurationChanged(
- d->m_activeTarget ? d->m_activeTarget->activeBuildConfiguration() : nullptr);
}
}
@@ -506,33 +505,14 @@ bool Project::copySteps(Target *sourceTarget, Target *newTarget)
bool Project::setupTarget(Target *t)
{
- if (needsBuildConfigurations())
+ if (d->m_needsBuildConfigurations)
t->updateDefaultBuildConfigurations();
- t->updateDefaultDeployConfigurations();
+ if (d->m_needsDeployConfigurations)
+ t->updateDefaultDeployConfigurations();
t->updateDefaultRunConfigurations();
return true;
}
-void Project::emitParsingStarted()
-{
- QTC_ASSERT(!d->m_isParsing, return);
-
- d->m_isParsing = true;
- d->m_hasParsingData = false;
- emit parsingStarted();
-}
-
-void Project::emitParsingFinished(bool success)
-{
- // Intentionally no return, as we currently get start - start - end - end
- // sequences when switching qmake targets quickly.
- QTC_CHECK(d->m_isParsing);
-
- d->m_isParsing = false;
- d->m_hasParsingData = success;
- emit parsingFinished(success);
-}
-
void Project::setDisplayName(const QString &name)
{
if (name == d->m_displayName)
@@ -596,9 +576,6 @@ void Project::saveSettings()
Project::RestoreResult Project::restoreSettings(QString *errorMessage)
{
- BuildConfiguration *oldBc = activeTarget() ? activeTarget()->activeBuildConfiguration()
- : nullptr;
-
if (!d->m_accessor)
d->m_accessor = std::make_unique<Internal::UserFileAccessor>(this);
QVariantMap map(d->m_accessor->restoreSettings(Core::ICore::mainWindow()));
@@ -606,10 +583,6 @@ Project::RestoreResult Project::restoreSettings(QString *errorMessage)
if (result == RestoreResult::Ok)
emit settingsLoaded();
- BuildConfiguration *bc = activeTarget() ? activeTarget()->activeBuildConfiguration() : nullptr;
- if (bc != oldBc)
- emit activeBuildConfigurationChanged(bc);
-
return result;
}
@@ -798,12 +771,6 @@ EditorConfiguration *Project::editorConfiguration() const
return &d->m_editorConfiguration;
}
-QStringList Project::filesGeneratedFrom(const QString &file) const
-{
- Q_UNUSED(file)
- return QStringList();
-}
-
bool Project::isKnownFile(const Utils::FilePath &filename) const
{
if (d->m_sortedNodeList.empty())
@@ -852,10 +819,6 @@ void Project::setHasMakeInstallEquivalent(bool enabled)
d->m_hasMakeInstallEquivalent = enabled;
}
-void Project::projectLoaded()
-{
-}
-
void Project::setKnowsAllBuildExecutables(bool value)
{
d->m_knowsAllBuildExecutables = value;
@@ -866,31 +829,19 @@ void Project::setNeedsBuildConfigurations(bool value)
d->m_needsBuildConfigurations = value;
}
-Task Project::createProjectTask(Task::TaskType type, const QString &description)
+void Project::setNeedsDeployConfigurations(bool value)
{
- return Task(type, description, Utils::FilePath(), -1, Core::Id());
+ d->m_needsDeployConfigurations = value;
}
-Utils::Environment Project::activeParseEnvironment() const
+Task Project::createProjectTask(Task::TaskType type, const QString &description)
{
- const Target *const t = activeTarget();
- const BuildConfiguration *const bc = t ? t->activeBuildConfiguration() : nullptr;
- if (bc)
- return bc->environment();
-
- const RunConfiguration *const rc = t ? t->activeRunConfiguration() : nullptr;
- if (rc)
- return rc->runnable().environment;
-
- Utils::Environment result = Utils::Environment::systemEnvironment();
- if (t)
- t->kit()->addToEnvironment(result);
- return result;
+ return Task(type, description, Utils::FilePath(), -1, Core::Id());
}
-void Project::setBuildSystemCreator(const std::function<BuildSystem *(Project *)> &creator)
+void Project::setBuildSystemCreator(const std::function<BuildSystem *(Target *)> &creator)
{
- d->m_buildSystem.reset(creator(this));
+ d->m_buildSystemCreator = creator;
}
Core::Context Project::projectContext() const
@@ -988,23 +939,6 @@ Utils::MacroExpander *Project::macroExpander() const
return &d->m_macroExpander;
}
-QVariant Project::additionalData(Core::Id id, const Target *target) const
-{
- Q_UNUSED(id)
- Q_UNUSED(target)
- return QVariant();
-}
-
-bool Project::isParsing() const
-{
- return d->m_isParsing;
-}
-
-bool Project::hasParsingData() const
-{
- return d->m_hasParsingData;
-}
-
ProjectNode *Project::findNodeForBuildKey(const QString &buildKey) const
{
if (!d->m_rootProjectNode)
@@ -1072,6 +1006,14 @@ const QString TEST_PROJECT_MIMETYPE = "application/vnd.test.qmakeprofile";
const QString TEST_PROJECT_DISPLAYNAME = "testProjectFoo";
const char TEST_PROJECT_ID[] = "Test.Project.Id";
+class TestBuildSystem : public BuildSystem
+{
+public:
+ using BuildSystem::BuildSystem;
+
+ void triggerParsing() {}
+};
+
class TestProject : public Project
{
public:
@@ -1079,9 +1021,17 @@ public:
{
setId(TEST_PROJECT_ID);
setDisplayName(TEST_PROJECT_DISPLAYNAME);
+ setBuildSystemCreator([](Target *t) { return new TestBuildSystem(t); });
+ setNeedsBuildConfigurations(false);
+ setNeedsDeployConfigurations(false);
+
+ target = addTargetForKit(&testKit);
}
bool needsConfiguration() const final { return false; }
+
+ Kit testKit;
+ Target *target = nullptr;
};
void ProjectExplorerPlugin::testProject_setup()
@@ -1108,8 +1058,8 @@ void ProjectExplorerPlugin::testProject_setup()
QCOMPARE(project.id(), Core::Id(TEST_PROJECT_ID));
- QVERIFY(!project.isParsing());
- QVERIFY(!project.hasParsingData());
+ QVERIFY(!project.target->buildSystem()->isParsing());
+ QVERIFY(!project.target->buildSystem()->hasParsingData());
}
void ProjectExplorerPlugin::testProject_changeDisplayName()
@@ -1132,16 +1082,16 @@ void ProjectExplorerPlugin::testProject_parsingSuccess()
{
TestProject project;
- QSignalSpy startSpy(&project, &Project::parsingStarted);
- QSignalSpy stopSpy(&project, &Project::parsingFinished);
+ QSignalSpy startSpy(project.target, &Target::parsingStarted);
+ QSignalSpy stopSpy(project.target, &Target::parsingFinished);
{
- Project::ParseGuard guard = project.guardParsingRun();
+ BuildSystem::ParseGuard guard = project.target->buildSystem()->guardParsingRun();
QCOMPARE(startSpy.count(), 1);
QCOMPARE(stopSpy.count(), 0);
- QVERIFY(project.isParsing());
- QVERIFY(!project.hasParsingData());
+ QVERIFY(project.target->buildSystem()->isParsing());
+ QVERIFY(!project.target->buildSystem()->hasParsingData());
guard.markAsSuccess();
}
@@ -1150,32 +1100,32 @@ void ProjectExplorerPlugin::testProject_parsingSuccess()
QCOMPARE(stopSpy.count(), 1);
QCOMPARE(stopSpy.at(0), {QVariant(true)});
- QVERIFY(!project.isParsing());
- QVERIFY(project.hasParsingData());
+ QVERIFY(!project.target->buildSystem()->isParsing());
+ QVERIFY(project.target->buildSystem()->hasParsingData());
}
void ProjectExplorerPlugin::testProject_parsingFail()
{
TestProject project;
- QSignalSpy startSpy(&project, &Project::parsingStarted);
- QSignalSpy stopSpy(&project, &Project::parsingFinished);
+ QSignalSpy startSpy(project.target, &Target::parsingStarted);
+ QSignalSpy stopSpy(project.target, &Target::parsingFinished);
{
- Project::ParseGuard guard = project.guardParsingRun();
+ BuildSystem::ParseGuard guard = project.target->buildSystem()->guardParsingRun();
QCOMPARE(startSpy.count(), 1);
QCOMPARE(stopSpy.count(), 0);
- QVERIFY(project.isParsing());
- QVERIFY(!project.hasParsingData());
+ QVERIFY(project.target->buildSystem()->isParsing());
+ QVERIFY(!project.target->buildSystem()->hasParsingData());
}
QCOMPARE(startSpy.count(), 1);
QCOMPARE(stopSpy.count(), 1);
QCOMPARE(stopSpy.at(0), {QVariant(false)});
- QVERIFY(!project.isParsing());
- QVERIFY(!project.hasParsingData());
+ QVERIFY(!project.target->buildSystem()->isParsing());
+ QVERIFY(!project.target->buildSystem()->hasParsingData());
}
std::unique_ptr<ProjectNode> createFileTree(Project *project)
diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h
index 326763bf8c..243d9a079f 100644
--- a/src/plugins/projectexplorer/project.h
+++ b/src/plugins/projectexplorer/project.h
@@ -50,6 +50,7 @@ namespace ProjectExplorer {
class BuildInfo;
class BuildSystem;
+class BuildConfiguration;
class ContainerNode;
class EditorConfiguration;
class FolderNode;
@@ -64,7 +65,6 @@ class Target;
class PROJECTEXPLORER_EXPORT Project : public QObject
{
friend class SessionManager; // for setActiveTarget
- friend class ProjectExplorerPlugin; // for projectLoaded
Q_OBJECT
public:
@@ -84,7 +84,7 @@ public:
QString mimeType() const;
bool canBuildProducts() const;
- BuildSystem *buildSystem() const;
+ BuildSystem *createBuildSystem(Target *target) const;
Utils::FilePath projectFilePath() const;
Utils::FilePath projectDirectory() const;
@@ -124,7 +124,6 @@ public:
static const NodeMatcher GeneratedFiles;
Utils::FilePathList files(const NodeMatcher &matcher) const;
- virtual QStringList filesGeneratedFrom(const QString &sourceFile) const;
bool isKnownFile(const Utils::FilePath &filename) const;
virtual QVariantMap toMap() const;
@@ -155,81 +154,20 @@ public:
void setup(const QList<BuildInfo> &infoList);
Utils::MacroExpander *macroExpander() const;
- virtual QVariant additionalData(Core::Id id, const Target *target) const;
-
- bool isParsing() const;
- bool hasParsingData() const;
-
ProjectNode *findNodeForBuildKey(const QString &buildKey) const;
bool needsInitialExpansion() const;
void setNeedsInitialExpansion(bool needsInitialExpansion);
- class ParseGuard
- {
- public:
- ParseGuard()
- : ParseGuard(nullptr)
- {}
-
- ~ParseGuard() { release(); }
-
- void markAsSuccess() const { m_success = true; }
- bool isSuccess() const { return m_success; }
- bool guardsProject() const { return m_project; }
-
- ParseGuard(const ParseGuard &other) = delete;
- ParseGuard &operator=(const ParseGuard &other) = delete;
- ParseGuard(ParseGuard &&other)
- : m_project{std::move(other.m_project)}
- , m_success{std::move(other.m_success)}
- {
- // No need to release this as this is invalid anyway:-)
- other.m_project = nullptr;
- }
- ParseGuard &operator=(ParseGuard &&other)
- {
- release();
-
- m_project = std::move(other.m_project);
- m_success = std::move(other.m_success);
-
- other.m_project = nullptr;
- return *this;
- }
-
- private:
- ParseGuard(Project *p)
- : m_project(p)
- {
- if (m_project && !m_project->isParsing())
- m_project->emitParsingStarted();
- else
- m_project = nullptr;
- }
-
- void release()
- {
- if (m_project)
- m_project->emitParsingFinished(m_success);
- m_project = nullptr;
- }
-
- Project *m_project = nullptr;
- mutable bool m_success = false;
-
- friend class Project;
- };
-
- // FIXME: Make this private and the BuildSystem a friend
- ParseGuard guardParsingRun() { return ParseGuard(this); }
void setRootProjectNode(std::unique_ptr<ProjectNode> &&root);
// Set project files that will be watched and trigger the same callback
// as the main project file.
void setExtraProjectFiles(const QVector<Utils::FilePath> &projectDocumentPaths);
- Utils::Environment activeParseEnvironment() const;
+ void setDisplayName(const QString &name);
+ void setProjectLanguage(Core::Id id, bool enabled);
+ void addProjectLanguage(Core::Id id);
signals:
void projectFileIsDirty(const Utils::FilePath &path);
@@ -243,11 +181,6 @@ signals:
void removedProjectConfiguration(ProjectExplorer::ProjectConfiguration *pc);
void addedProjectConfiguration(ProjectExplorer::ProjectConfiguration *pc);
- // *ANY* active build configuration changed somewhere in the tree. This might not be
- // the one that would get started right now, since some part of the tree in between might
- // not be active.
- void activeBuildConfigurationChanged(ProjectExplorer::ProjectConfiguration *bc);
-
void aboutToRemoveTarget(ProjectExplorer::Target *target);
void removedTarget(ProjectExplorer::Target *target);
void addedTarget(ProjectExplorer::Target *target);
@@ -257,8 +190,8 @@ signals:
void projectLanguagesUpdated();
- void parsingStarted();
- void parsingFinished(bool success);
+ void anyParsingStarted(Target *target);
+ void anyParsingFinished(Target *target, bool success);
void rootProjectDirectoryChanged();
@@ -267,7 +200,6 @@ protected:
void createTargetFromMap(const QVariantMap &map, int index);
virtual bool setupTarget(Target *t);
- void setDisplayName(const QString &name);
// Used to pre-check kits in the TargetSetupPage. RequiredKitPredicate
// is used to select kits available in the TargetSetupPage
void setPreferredKitPredicate(const Kit::Predicate &predicate);
@@ -278,35 +210,26 @@ protected:
void setId(Core::Id id);
void setProjectLanguages(Core::Context language);
- void addProjectLanguage(Core::Id id);
void removeProjectLanguage(Core::Id id);
- void setProjectLanguage(Core::Id id, bool enabled);
void setHasMakeInstallEquivalent(bool enabled);
- virtual void projectLoaded(); // Called when the project is fully loaded.
void setKnowsAllBuildExecutables(bool value);
void setNeedsBuildConfigurations(bool value);
+ void setNeedsDeployConfigurations(bool value);
static ProjectExplorer::Task createProjectTask(ProjectExplorer::Task::TaskType type,
const QString &description);
- void setBuildSystemCreator(const std::function<BuildSystem *(Project *)> &creator);
+ void setBuildSystemCreator(const std::function<BuildSystem *(Target *)> &creator);
private:
- // Helper methods to manage parsing state and signalling
- // Call in GUI thread before the actual parsing starts
- void emitParsingStarted();
- // Call in GUI thread right after the actual parsing is done
- void emitParsingFinished(bool success);
-
void addTarget(std::unique_ptr<Target> &&target);
void handleSubTreeChanged(FolderNode *node);
void setActiveTarget(Target *target);
- ProjectPrivate *d;
-
friend class ContainerNode;
+ ProjectPrivate *d;
};
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index 4d7aee5fc8..93f003b7b2 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -2046,7 +2046,6 @@ ProjectExplorerPlugin::OpenProjectResult ProjectExplorerPlugin::openProject(cons
return result;
dd->addToRecentProjects(fileName, project->displayName());
SessionManager::setStartupProject(project);
- project->projectLoaded();
return result;
}
@@ -2113,9 +2112,6 @@ ProjectExplorerPlugin::OpenProjectResult ProjectExplorerPlugin::openProjects(con
appendError(errorString,
tr("Failed opening project \"%1\": Project is not a file.").arg(fileName));
} else if (Project *pro = ProjectManager::openProject(mt, filePath)) {
- QObject::connect(pro, &Project::parsingFinished, [pro]() {
- emit SessionManager::instance()->projectFinishedParsing(pro);
- });
QString restoreError;
Project::RestoreResult restoreResult = pro->restoreSettings(&restoreError);
if (restoreResult == Project::RestoreResult::Ok) {
diff --git a/src/plugins/projectexplorer/projectmodels.cpp b/src/plugins/projectexplorer/projectmodels.cpp
index 76fe5ed9dc..007fe38e21 100644
--- a/src/plugins/projectexplorer/projectmodels.cpp
+++ b/src/plugins/projectexplorer/projectmodels.cpp
@@ -25,6 +25,7 @@
#include "projectmodels.h"
+#include "buildsystem.h"
#include "project.h"
#include "projectnodes.h"
#include "projectexplorer.h"
@@ -119,6 +120,8 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
const FolderNode * const folderNode = node->asFolderNode();
const ContainerNode * const containerNode = node->asContainerNode();
const Project * const project = containerNode ? containerNode->project() : nullptr;
+ const Target * const target = project ? project->activeTarget() : nullptr;
+ const BuildSystem * const bs = target ? target->buildSystem() : nullptr;
switch (role) {
case Qt::DisplayRole:
@@ -128,7 +131,7 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
case Qt::ToolTipRole: {
QString tooltip = node->tooltip();
if (project) {
- if (project->activeTarget()) {
+ if (target) {
QString projectIssues = toHtml(project->projectIssues(project->activeTarget()->kit()));
if (!projectIssues.isEmpty())
tooltip += "<p>" + projectIssues;
@@ -148,10 +151,9 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
static QIcon emptyIcon = Utils::Icons::EMPTY16.icon();
if (project->needsConfiguration())
return warnIcon;
- if (project->isParsing())
+ if (bs && bs->isParsing())
return emptyIcon;
- if (!project->activeTarget()
- || !project->projectIssues(project->activeTarget()->kit()).isEmpty())
+ if (!target || !project->projectIssues(target->kit()).isEmpty())
return warnIcon;
return containerNode->rootProjectNode() ? containerNode->rootProjectNode()->icon()
: folderNode->icon();
@@ -167,7 +169,7 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
case Project::FilePathRole:
return node->filePath().toString();
case Project::isParsingRole:
- return project ? project->isParsing() && !project->needsConfiguration() : false;
+ return project && bs ? bs->isParsing() && !project->needsConfiguration() : false;
}
return QVariant();
@@ -359,12 +361,12 @@ void FlatModel::handleProjectAdded(Project *project)
{
QTC_ASSERT(project, return);
- connect(project, &Project::parsingStarted,
+ connect(project, &Project::anyParsingStarted,
this, [this, project]() {
if (nodeForProject(project))
parsingStateChanged(project);
});
- connect(project, &Project::parsingFinished,
+ connect(project, &Project::anyParsingFinished,
this, [this, project]() {
if (nodeForProject(project))
parsingStateChanged(project);
diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp
index dd3783ebe0..09fb24520d 100644
--- a/src/plugins/projectexplorer/projectnodes.cpp
+++ b/src/plugins/projectexplorer/projectnodes.cpp
@@ -25,10 +25,12 @@
#include "projectnodes.h"
+#include "buildconfiguration.h"
#include "buildsystem.h"
#include "project.h"
#include "projectexplorerconstants.h"
#include "projecttree.h"
+#include "target.h"
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
@@ -988,7 +990,8 @@ void ProjectNode::setFallbackData(Core::Id key, const QVariant &value)
BuildSystem *ProjectNode::buildSystem() const
{
Project *p = getProject();
- return p ? p->buildSystem() : nullptr;
+ Target *t = p ? p->activeTarget() : nullptr;
+ return t ? t->buildSystem() : nullptr;
}
bool FolderNode::isEmpty() const
diff --git a/src/plugins/projectexplorer/projecttree.cpp b/src/plugins/projectexplorer/projecttree.cpp
index 8fda8340d7..b42da7ad66 100644
--- a/src/plugins/projectexplorer/projecttree.cpp
+++ b/src/plugins/projectexplorer/projecttree.cpp
@@ -30,6 +30,7 @@
#include "projectnodes.h"
#include "projecttreewidget.h"
#include "session.h"
+#include "target.h"
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
@@ -104,6 +105,18 @@ Project *ProjectTree::currentProject()
return s_instance->m_currentProject;
}
+Target *ProjectTree::currentTarget()
+{
+ Project *p = currentProject();
+ return p ? p->activeTarget() : nullptr;
+}
+
+BuildSystem *ProjectTree::currentBuildSystem()
+{
+ Target *t = currentTarget();
+ return t ? t->buildSystem() : nullptr;
+}
+
Node *ProjectTree::currentNode()
{
s_instance->update();
diff --git a/src/plugins/projectexplorer/projecttree.h b/src/plugins/projectexplorer/projecttree.h
index 4adcaa7571..bf1335e5be 100644
--- a/src/plugins/projectexplorer/projecttree.h
+++ b/src/plugins/projectexplorer/projecttree.h
@@ -34,12 +34,14 @@
namespace Utils { class FilePath; }
namespace ProjectExplorer {
+class BuildSystem;
class FileNode;
class FolderNode;
class Node;
class Project;
class ProjectNode;
class SessionNode;
+class Target;
namespace Internal { class ProjectTreeWidget; }
@@ -53,6 +55,8 @@ public:
static ProjectTree *instance();
static Project *currentProject();
+ static Target *currentTarget();
+ static BuildSystem *currentBuildSystem();
static Node *currentNode();
static Utils::FilePath currentFilePath();
diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp
index 4629e0bc22..7c40d8bc41 100644
--- a/src/plugins/projectexplorer/runconfiguration.cpp
+++ b/src/plugins/projectexplorer/runconfiguration.cpp
@@ -27,6 +27,7 @@
#include "abi.h"
#include "buildconfiguration.h"
+#include "buildsystem.h"
#include "environmentaspect.h"
#include "kitinformation.h"
#include "kitinformation.h"
@@ -168,8 +169,7 @@ RunConfiguration::RunConfiguration(Target *target, Core::Id id)
: ProjectConfiguration(target, id)
{
QTC_CHECK(target && target == this->target());
- connect(target->project(), &Project::parsingFinished,
- this, [this]() { updateEnabledState(); });
+ connect(target, &Target::parsingFinished, this, [this] { updateEnabledState(); });
connect(target, &Target::addedRunConfiguration,
this, [this](const RunConfiguration *rc) {
@@ -224,25 +224,16 @@ bool RunConfiguration::isActive() const
return target()->isActive() && target()->activeRunConfiguration() == this;
}
-void RunConfiguration::setEnabled(bool enabled)
+QString RunConfiguration::disabledReason() const
{
- if (enabled == m_isEnabled)
- return;
- m_isEnabled = enabled;
- emit enabledChanged();
+ BuildSystem *bs = activeBuildSystem();
+ return bs ? bs->disabledReason(m_buildKey) : tr("No build system active");
}
-QString RunConfiguration::disabledReason() const
+bool RunConfiguration::isEnabled() const
{
- if (!project()->hasParsingData()) {
- QString msg = project()->isParsing() ? tr("The project is currently being parsed.")
- : tr("The project could not be fully parsed.");
- const FilePath projectFilePath = buildTargetInfo().projectFilePath;
- if (!projectFilePath.isEmpty() && !projectFilePath.exists())
- msg += '\n' + tr("The project file \"%1\" does not exist.").arg(projectFilePath.toString());
- return msg;
- }
- return QString();
+ BuildSystem *bs = activeBuildSystem();
+ return bs && bs->hasParsingData();
}
QWidget *RunConfiguration::createConfigurationWidget()
@@ -266,7 +257,7 @@ QWidget *RunConfiguration::createConfigurationWidget()
void RunConfiguration::updateEnabledState()
{
- setEnabled(project()->hasParsingData());
+ emit enabledChanged();
}
void RunConfiguration::addAspectFactory(const AspectFactory &aspectFactory)
@@ -312,11 +303,14 @@ RunConfiguration::ConfigurationState RunConfiguration::ensureConfigured(QString
BuildConfiguration *RunConfiguration::activeBuildConfiguration() const
{
- if (!target())
- return nullptr;
return target()->activeBuildConfiguration();
}
+BuildSystem *RunConfiguration::activeBuildSystem() const
+{
+ return target()->buildSystem();
+}
+
QVariantMap RunConfiguration::toMap() const
{
QVariantMap map = ProjectConfiguration::toMap();
@@ -344,7 +338,9 @@ CommandLine RunConfiguration::commandLine() const
BuildTargetInfo RunConfiguration::buildTargetInfo() const
{
- return target()->buildTarget(m_buildKey);
+ BuildSystem *bs = target()->buildSystem();
+ QTC_ASSERT(bs, return {});
+ return bs->buildTarget(m_buildKey);
}
bool RunConfiguration::fromMap(const QVariantMap &map)
diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h
index 78175e6156..ae6ad9e2d6 100644
--- a/src/plugins/projectexplorer/runconfiguration.h
+++ b/src/plugins/projectexplorer/runconfiguration.h
@@ -43,6 +43,7 @@ namespace Utils { class OutputFormatter; }
namespace ProjectExplorer {
class BuildConfiguration;
+class BuildSystem;
class GlobalOrProjectAspect;
class Runnable;
class RunConfigurationFactory;
@@ -126,10 +127,8 @@ public:
bool isActive() const override;
- bool isEnabled() const { return m_isEnabled; }
- void setEnabled(bool enabled);
-
virtual QString disabledReason() const;
+ virtual bool isEnabled() const;
virtual QWidget *createConfigurationWidget();
@@ -182,6 +181,7 @@ protected:
/// convenience function to get current build configuration.
BuildConfiguration *activeBuildConfiguration() const;
+ BuildSystem *activeBuildSystem() const;
virtual void updateEnabledState();
virtual void doAdditionalSetup(const RunConfigurationCreationInfo &) {}
@@ -193,7 +193,6 @@ private:
friend class RunConfigurationFactory;
QString m_buildKey;
- bool m_isEnabled = false;
CommandLineGetter m_commandLineGetter;
};
diff --git a/src/plugins/projectexplorer/runcontrol.cpp b/src/plugins/projectexplorer/runcontrol.cpp
index b4a50d0099..ec775c72df 100644
--- a/src/plugins/projectexplorer/runcontrol.cpp
+++ b/src/plugins/projectexplorer/runcontrol.cpp
@@ -376,7 +376,7 @@ void RunControl::setTarget(Target *target)
QTC_CHECK(!d->target);
d->target = target;
- if (!d->buildKey.isEmpty())
+ if (!d->buildKey.isEmpty() && target->buildSystem())
d->buildTargetInfo = target->buildTarget(d->buildKey);
if (auto bc = target->activeBuildConfiguration()) {
diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp
index f224bce49e..858ceb815c 100644
--- a/src/plugins/projectexplorer/session.cpp
+++ b/src/plugins/projectexplorer/session.cpp
@@ -381,6 +381,17 @@ Project *SessionManager::startupProject()
return d->m_startupProject;
}
+Target *SessionManager::startupTarget()
+{
+ return d->m_startupProject ? d->m_startupProject->activeTarget() : nullptr;
+}
+
+BuildSystem *SessionManager::startupBuildSystem()
+{
+ Target *t = startupTarget();
+ return t ? t->buildSystem() : nullptr;
+}
+
void SessionManager::addProject(Project *pro)
{
QTC_ASSERT(pro, return);
diff --git a/src/plugins/projectexplorer/session.h b/src/plugins/projectexplorer/session.h
index 782079f9d7..dfc403bc42 100644
--- a/src/plugins/projectexplorer/session.h
+++ b/src/plugins/projectexplorer/session.h
@@ -42,7 +42,9 @@ namespace ProjectExplorer {
class Project;
class Target;
class BuildConfiguration;
+class BuildSystem;
class DeployConfiguration;
+
enum class SetActive { Cascade, NoCascade };
class PROJECTEXPLORER_EXPORT SessionManager : public QObject
@@ -96,6 +98,8 @@ public:
static Utils::FilePath sessionNameToFileName(const QString &session);
static Project *startupProject();
+ static Target *startupTarget();
+ static BuildSystem *startupBuildSystem();
static const QList<Project *> projects();
static bool hasProjects();
@@ -119,6 +123,8 @@ public:
static bool loadingSession();
signals:
+ void targetAdded(ProjectExplorer::Target *target);
+ void targetRemoved(ProjectExplorer::Target *target);
void projectAdded(ProjectExplorer::Project *project);
void aboutToRemoveProject(ProjectExplorer::Project *project);
void projectDisplayNameChanged(ProjectExplorer::Project *project);
diff --git a/src/plugins/projectexplorer/target.cpp b/src/plugins/projectexplorer/target.cpp
index f8a0da25e7..dd9d98fd82 100644
--- a/src/plugins/projectexplorer/target.cpp
+++ b/src/plugins/projectexplorer/target.cpp
@@ -29,6 +29,7 @@
#include "buildconfiguration.h"
#include "buildinfo.h"
#include "buildmanager.h"
+#include "buildsystem.h"
#include "buildtargetinfo.h"
#include "deployconfiguration.h"
#include "deploymentdata.h"
@@ -98,20 +99,24 @@ public:
m_runConfigurationModel(t)
{ }
+ ~TargetPrivate()
+ {
+ delete m_buildSystem;
+ }
+
QIcon m_overlayIcon;
QList<BuildConfiguration *> m_buildConfigurations;
- BuildConfiguration *m_activeBuildConfiguration = nullptr;
+ QPointer<BuildConfiguration> m_activeBuildConfiguration;
QList<DeployConfiguration *> m_deployConfigurations;
DeployConfiguration *m_activeDeployConfiguration = nullptr;
QList<RunConfiguration *> m_runConfigurations;
RunConfiguration* m_activeRunConfiguration = nullptr;
- DeploymentData m_deploymentData;
- QList<BuildTargetInfo> m_appTargets;
QVariantMap m_pluginSettings;
Kit *const m_kit;
MacroExpander m_macroExpander;
+ BuildSystem *m_buildSystem = nullptr;
ProjectConfigurationModel m_buildConfigurationModel;
ProjectConfigurationModel m_deployConfigurationModel;
@@ -123,13 +128,24 @@ Target::Target(Project *project, Kit *k, _constructor_tag) :
QObject(project),
d(std::make_unique<TargetPrivate>(this, k))
{
+ // Note: nullptr is a valid state for the per-buildConfig systems.
+ d->m_buildSystem = project->createBuildSystem(this);
+
QTC_CHECK(d->m_kit);
connect(DeviceManager::instance(), &DeviceManager::updated, this, &Target::updateDeviceState);
- connect(project, &Project::parsingFinished, this, [this](bool success) {
- if (success && this->project() == SessionManager::startupProject()
- && this == this->project()->activeTarget()) {
+
+ connect(this, &Target::parsingStarted, this, [this, project] {
+ project->anyParsingStarted(this);
+ });
+
+ connect(this, &Target::parsingFinished, this, [this, project](bool success) {
+ if (success && project == SessionManager::startupProject()
+ && this == project->activeTarget()) {
updateDefaultRunConfigurations();
}
+ // For testing.
+ emit SessionManager::instance()->projectFinishedParsing(project);
+ project->anyParsingFinished(this, success);
}, Qt::QueuedConnection); // Must wait for run configs to change their enabled state.
KitManager *km = KitManager::instance();
@@ -193,6 +209,37 @@ Kit *Target::kit() const
return d->m_kit;
}
+BuildSystem *Target::buildSystem() const
+{
+ if (d->m_activeBuildConfiguration)
+ return d->m_activeBuildConfiguration->buildSystem();
+
+ return d->m_buildSystem;
+}
+
+BuildSystem *Target::fallbackBuildSystem() const
+{
+ return d->m_buildSystem;
+}
+
+DeploymentData Target::deploymentData() const
+{
+ QTC_ASSERT(buildSystem(), return {});
+ return buildSystem()->deploymentData();
+}
+
+const QList<BuildTargetInfo> Target::applicationTargets() const
+{
+ QTC_ASSERT(buildSystem(), return {});
+ return buildSystem()->applicationTargets();
+}
+
+BuildTargetInfo Target::buildTarget(const QString &buildKey) const
+{
+ QTC_ASSERT(buildSystem(), return {});
+ return buildSystem()->buildTarget(buildKey);
+}
+
Core::Id Target::id() const
{
return d->m_kit->id();
@@ -277,7 +324,6 @@ void Target::setActiveBuildConfiguration(BuildConfiguration *bc)
(bc && d->m_buildConfigurations.contains(bc) &&
bc != d->m_activeBuildConfiguration)) {
d->m_activeBuildConfiguration = bc;
- project()->activeBuildConfigurationChanged(d->m_activeBuildConfiguration);
emit activeBuildConfigurationChanged(d->m_activeBuildConfiguration);
}
}
@@ -353,49 +399,6 @@ void Target::setActiveDeployConfiguration(DeployConfiguration *dc)
updateDeviceState();
}
-void Target::setDeploymentData(const DeploymentData &deploymentData)
-{
- if (d->m_deploymentData != deploymentData) {
- d->m_deploymentData = deploymentData;
- emit deploymentDataChanged();
- emit applicationTargetsChanged();
- }
-}
-
-DeploymentData Target::deploymentData() const
-{
- return d->m_deploymentData;
-}
-
-void Target::setApplicationTargets(const QList<BuildTargetInfo> &appTargets)
-{
- if (Utils::toSet(appTargets) != Utils::toSet(d->m_appTargets)) {
- d->m_appTargets = appTargets;
- emit applicationTargetsChanged();
- }
-}
-
-const QList<BuildTargetInfo> Target::applicationTargets() const
-{
- return d->m_appTargets;
-}
-
-BuildTargetInfo Target::buildTarget(const QString &buildKey) const
-{
- return Utils::findOrDefault(d->m_appTargets, [&buildKey](const BuildTargetInfo &ti) {
- return ti.buildKey == buildKey;
- });
-}
-
-QList<ProjectConfiguration *> Target::projectConfigurations() const
-{
- QList<ProjectConfiguration *> result;
- result.append(Utils::static_container_cast<ProjectConfiguration *>(buildConfigurations()));
- result.append(Utils::static_container_cast<ProjectConfiguration *>(deployConfigurations()));
- result.append(Utils::static_container_cast<ProjectConfiguration *>(runConfigurations()));
- return result;
-}
-
QList<RunConfiguration *> Target::runConfigurations() const
{
return d->m_runConfigurations;
@@ -716,7 +719,7 @@ void Target::setNamedSettings(const QString &name, const QVariant &value)
QVariant Target::additionalData(Core::Id id) const
{
- return project()->additionalData(id, this);
+ return buildSystem()->additionalData(id);
}
MakeInstallCommand Target::makeInstallCommand(const QString &installRoot) const
diff --git a/src/plugins/projectexplorer/target.h b/src/plugins/projectexplorer/target.h
index 612adcef75..247b0e0425 100644
--- a/src/plugins/projectexplorer/target.h
+++ b/src/plugins/projectexplorer/target.h
@@ -35,6 +35,7 @@ QT_FORWARD_DECLARE_CLASS(QIcon)
namespace ProjectExplorer {
class BuildConfiguration;
class BuildTargetInfo;
+class BuildSystem;
class DeployConfiguration;
class DeploymentData;
class Kit;
@@ -60,6 +61,7 @@ public:
Project *project() const;
Kit *kit() const;
+ BuildSystem *buildSystem() const;
Core::Id id() const;
QString displayName() const;
@@ -79,15 +81,6 @@ public:
QList<DeployConfiguration *> deployConfigurations() const;
DeployConfiguration *activeDeployConfiguration() const;
- void setDeploymentData(const DeploymentData &deploymentData);
- DeploymentData deploymentData() const;
-
- void setApplicationTargets(const QList<BuildTargetInfo> &appTargets);
- const QList<BuildTargetInfo> applicationTargets() const;
- BuildTargetInfo buildTarget(const QString &buildKey) const;
-
- QList<ProjectConfiguration *> projectConfigurations() const;
-
// Running
QList<RunConfiguration *> runConfigurations() const;
void addRunConfiguration(RunConfiguration *rc);
@@ -119,12 +112,20 @@ public:
ProjectConfigurationModel *deployConfigurationModel() const;
ProjectConfigurationModel *runConfigurationModel() const;
+ BuildSystem *fallbackBuildSystem() const;
+
+ DeploymentData deploymentData() const;
+ const QList<BuildTargetInfo> applicationTargets() const;
+ BuildTargetInfo buildTarget(const QString &buildKey) const;
+
signals:
void targetEnabled(bool);
void iconChanged();
void overlayIconChanged();
void kitChanged();
+ void parsingStarted();
+ void parsingFinished(bool);
// TODO clean up signal names
// might be better to also have aboutToRemove signals
@@ -143,6 +144,7 @@ signals:
void deploymentDataChanged();
void applicationTargetsChanged();
+ void targetPropertiesChanged();
private:
bool fromMap(const QVariantMap &map);