ProjectExplorer: Rework the build step run interface

Originally, the build manager used to run all build steps in a dedicated
thread. Communication between the step and the manager happened via a
QFutureInterface that was passed into the step's run() function.
Later, new steps were added that operated asynchronously, so the build
manager had to differentiate between the different kinds of steps for
starting and stopping.
These days, almost all build and deploy steps work asynchronously, which
made the QFuture-based interface look increasingly odd.
With this patch, all build steps are expected to work asynchronously, so
the build manager no longer needs to differentiate. Steps are started
and requested to stop via the run() and cancel() functions,
respectively, and emit the finished() signal when they are done. Build
step implementors no longer have to deal with a QFutureInterface. For
steps whose implementation is inherently synchronous, the BuildStep base
class offers a runInThread() function.

Change-Id: If905c68b234c5a669f6e19f43142eaa57d594803
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Christian Kandeler
2019-01-25 14:26:34 +01:00
parent 536618b012
commit 966f4ea6a9
52 changed files with 355 additions and 399 deletions

View File

@@ -127,14 +127,13 @@ QbsBuildStep::QbsBuildStep(ProjectExplorer::BuildStepList *bsl) :
{
setDisplayName(tr("Qbs Build"));
setQbsConfiguration(QVariantMap());
setRunInGuiThread(true);
// setQbsConfiguration(other->qbsConfiguration(PreserveVariables));
}
QbsBuildStep::~QbsBuildStep()
{
cancel();
doCancel();
if (m_job) {
m_job->deleteLater();
m_job = nullptr;
@@ -171,10 +170,8 @@ bool QbsBuildStep::init()
return true;
}
void QbsBuildStep::run(QFutureInterface<bool> &fi)
void QbsBuildStep::doRun()
{
m_fi = &fi;
// We need a pre-build parsing step in order not to lose project file changes done
// right before building (but before the delay has elapsed).
parseProject();
@@ -185,7 +182,7 @@ ProjectExplorer::BuildStepConfigWidget *QbsBuildStep::createConfigWidget()
return new QbsBuildStepConfigWidget(this);
}
void QbsBuildStep::cancel()
void QbsBuildStep::doCancel()
{
if (m_parsingProject)
qbsProject()->cancelParsing();
@@ -354,17 +351,14 @@ void QbsBuildStep::reparsingDone(bool success)
void QbsBuildStep::handleTaskStarted(const QString &desciption, int max)
{
Q_UNUSED(desciption);
QTC_ASSERT(m_fi, return);
m_progressBase = m_fi->progressValue();
m_fi->setProgressRange(0, m_progressBase + max);
m_currentTask = desciption;
m_maxProgress = max;
}
void QbsBuildStep::handleProgress(int value)
{
QTC_ASSERT(m_fi, return);
m_fi->setProgressValue(m_progressBase + value);
if (m_maxProgress > 0)
emit progress(value * 100 / m_maxProgress, m_currentTask);
}
void QbsBuildStep::handleCommandDescriptionReport(const QString &highlight, const QString &message)
@@ -489,11 +483,11 @@ void QbsBuildStep::build()
m_job = qbsProject()->build(options, m_products, error);
if (!m_job) {
emit addOutput(error, OutputFormat::ErrorMessage);
reportRunResult(*m_fi, false);
emit finished(false);
return;
}
m_progressBase = 0;
m_maxProgress = 0;
connect(m_job, &qbs::AbstractJob::finished, this, &QbsBuildStep::buildingDone);
connect(m_job, &qbs::AbstractJob::taskStarted,
@@ -509,9 +503,7 @@ void QbsBuildStep::build()
void QbsBuildStep::finish()
{
QTC_ASSERT(m_fi, return);
reportRunResult(*m_fi, m_lastWasSuccess);
m_fi = nullptr; // do not delete, it is not ours
emit finished(m_lastWasSuccess);
if (m_job) {
m_job->deleteLater();
m_job = nullptr;

View File

@@ -58,13 +58,6 @@ public:
explicit QbsBuildStep(ProjectExplorer::BuildStepList *bsl);
~QbsBuildStep() override;
bool init() override;
void run(QFutureInterface<bool> &fi) override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
void cancel() override;
QVariantMap qbsConfiguration(VariableHandling variableHandling) const;
void setQbsConfiguration(const QVariantMap &config);
@@ -91,6 +84,10 @@ signals:
void qbsBuildOptionsChanged();
private:
bool init() override;
void doRun() override;
void doCancel() override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
bool fromMap(const QVariantMap &map) override;
QVariantMap toMap() const override;
@@ -129,9 +126,9 @@ private:
QStringList m_activeFileTags;
QStringList m_products;
QFutureInterface<bool> *m_fi;
qbs::BuildJob *m_job = nullptr;
int m_progressBase;
QString m_currentTask;
int m_maxProgress;
bool m_lastWasSuccess;
ProjectExplorer::IOutputParser *m_parser = nullptr;
bool m_parsingProject = false;

View File

@@ -49,7 +49,6 @@ QbsCleanStep::QbsCleanStep(ProjectExplorer::BuildStepList *bsl) :
ProjectExplorer::BuildStep(bsl, Constants::QBS_CLEANSTEP_ID)
{
setDisplayName(tr("Qbs Clean"));
setRunInGuiThread(true);
m_dryRunAspect = addAspect<BaseBoolAspect>();
m_dryRunAspect->setSettingsKey("Qbs.DryRun");
@@ -75,7 +74,7 @@ QbsCleanStep::QbsCleanStep(ProjectExplorer::BuildStepList *bsl) :
QbsCleanStep::~QbsCleanStep()
{
cancel();
doCancel();
if (m_job) {
m_job->deleteLater();
m_job = nullptr;
@@ -96,10 +95,8 @@ bool QbsCleanStep::init()
return true;
}
void QbsCleanStep::run(QFutureInterface<bool> &fi)
void QbsCleanStep::doRun()
{
m_fi = &fi;
auto pro = static_cast<QbsProject *>(project());
qbs::CleanOptions options;
options.setDryRun(m_dryRunAspect->value());
@@ -109,11 +106,11 @@ void QbsCleanStep::run(QFutureInterface<bool> &fi)
m_job = pro->clean(options, m_products, error);
if (!m_job) {
emit addOutput(error, OutputFormat::ErrorMessage);
reportRunResult(*m_fi, false);
emit finished(false);
return;
}
m_progressBase = 0;
m_maxProgress = 0;
connect(m_job, &qbs::AbstractJob::finished, this, &QbsCleanStep::cleaningDone);
connect(m_job, &qbs::AbstractJob::taskStarted,
@@ -131,7 +128,7 @@ ProjectExplorer::BuildStepConfigWidget *QbsCleanStep::createConfigWidget()
return w;
}
void QbsCleanStep::cancel()
void QbsCleanStep::doCancel()
{
if (m_job)
m_job->cancel();
@@ -145,9 +142,7 @@ void QbsCleanStep::cleaningDone(bool success)
item.codeLocation().filePath(), item.codeLocation().line());
}
QTC_ASSERT(m_fi, return);
reportRunResult(*m_fi, success);
m_fi = nullptr; // do not delete, it is not ours
emit finished(success);
m_job->deleteLater();
m_job = nullptr;
}
@@ -155,15 +150,13 @@ void QbsCleanStep::cleaningDone(bool success)
void QbsCleanStep::handleTaskStarted(const QString &desciption, int max)
{
Q_UNUSED(desciption);
QTC_ASSERT(m_fi, return);
m_progressBase = m_fi->progressValue();
m_fi->setProgressRange(0, m_progressBase + max);
m_maxProgress = max;
}
void QbsCleanStep::handleProgress(int value)
{
QTC_ASSERT(m_fi, return);
m_fi->setProgressValue(m_progressBase + value);
if (m_maxProgress > 0)
emit progress(value * 100 / m_maxProgress, m_description);
}
void QbsCleanStep::updateState()

View File

@@ -44,13 +44,6 @@ public:
explicit QbsCleanStep(ProjectExplorer::BuildStepList *bsl);
~QbsCleanStep() override;
bool init() override;
void run(QFutureInterface<bool> &fi) override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
void cancel() override;
bool dryRun() const { return m_dryRunAspect->value(); }
bool keepGoing() const { return m_keepGoingAspect->value(); }
@@ -58,6 +51,11 @@ signals:
void stateChanged();
private:
bool init() override;
void doRun() override;
void doCancel() override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
void cleaningDone(bool success);
void handleTaskStarted(const QString &desciption, int max);
void handleProgress(int value);
@@ -72,9 +70,9 @@ private:
QStringList m_products;
QFutureInterface<bool> *m_fi = nullptr;
qbs::CleanJob *m_job = nullptr;
int m_progressBase;
QString m_description;
int m_maxProgress;
bool m_showCompilerOutput = true;
ProjectExplorer::IOutputParser *m_parser = nullptr;
};

View File

@@ -61,7 +61,6 @@ QbsInstallStep::QbsInstallStep(ProjectExplorer::BuildStepList *bsl) :
ProjectExplorer::BuildStep(bsl, Constants::QBS_INSTALLSTEP_ID)
{
setDisplayName(tr("Qbs Install"));
setRunInGuiThread(true);
const QbsBuildConfiguration * const bc = buildConfig();
connect(bc, &QbsBuildConfiguration::qbsConfigurationChanged,
@@ -74,7 +73,7 @@ QbsInstallStep::QbsInstallStep(ProjectExplorer::BuildStepList *bsl) :
QbsInstallStep::~QbsInstallStep()
{
cancel();
doCancel();
if (m_job)
m_job->deleteLater();
m_job = nullptr;
@@ -86,19 +85,17 @@ bool QbsInstallStep::init()
return true;
}
void QbsInstallStep::run(QFutureInterface<bool> &fi)
void QbsInstallStep::doRun()
{
m_fi = &fi;
auto pro = static_cast<QbsProject *>(project());
m_job = pro->install(m_qbsInstallOptions);
if (!m_job) {
reportRunResult(*m_fi, false);
emit finished(false);
return;
}
m_progressBase = 0;
m_maxProgress = 0;
connect(m_job, &qbs::AbstractJob::finished, this, &QbsInstallStep::installDone);
connect(m_job, &qbs::AbstractJob::taskStarted,
@@ -112,7 +109,7 @@ ProjectExplorer::BuildStepConfigWidget *QbsInstallStep::createConfigWidget()
return new QbsInstallStepConfigWidget(this);
}
void QbsInstallStep::cancel()
void QbsInstallStep::doCancel()
{
if (m_job)
m_job->cancel();
@@ -180,25 +177,21 @@ void QbsInstallStep::installDone(bool success)
item.codeLocation().filePath(), item.codeLocation().line());
}
QTC_ASSERT(m_fi, return);
reportRunResult(*m_fi, success);
m_fi = nullptr; // do not delete, it is not ours
emit finished(success);
m_job->deleteLater();
m_job = nullptr;
}
void QbsInstallStep::handleTaskStarted(const QString &desciption, int max)
{
Q_UNUSED(desciption);
QTC_ASSERT(m_fi, return);
m_progressBase = m_fi->progressValue();
m_fi->setProgressRange(0, m_progressBase + max);
m_description = desciption;
m_maxProgress = max;
}
void QbsInstallStep::handleProgress(int value)
{
QTC_ASSERT(m_fi, return);
m_fi->setProgressValue(m_progressBase + value);
if (m_maxProgress > 0)
emit progress(value * 100 / m_maxProgress, m_description);
}
void QbsInstallStep::createTaskAndOutput(ProjectExplorer::Task::TaskType type,

View File

@@ -45,16 +45,6 @@ public:
explicit QbsInstallStep(ProjectExplorer::BuildStepList *bsl);
~QbsInstallStep() override;
bool init() override;
void run(QFutureInterface<bool> &fi) override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
void cancel() override;
bool fromMap(const QVariantMap &map) override;
QVariantMap toMap() const override;
qbs::InstallOptions installOptions() const;
QString installRoot() const;
bool removeFirst() const;
@@ -65,6 +55,13 @@ signals:
void changed();
private:
bool init() override;
void doRun() override;
void doCancel() override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
bool fromMap(const QVariantMap &map) override;
QVariantMap toMap() const override;
const QbsBuildConfiguration *buildConfig() const;
void installDone(bool success);
void handleTaskStarted(const QString &desciption, int max);
@@ -80,9 +77,9 @@ private:
qbs::InstallOptions m_qbsInstallOptions;
QFutureInterface<bool> *m_fi = nullptr;
qbs::InstallJob *m_job = nullptr;
int m_progressBase;
QString m_description;
int m_maxProgress;
bool m_showCompilerOutput = true;
ProjectExplorer::IOutputParser *m_parser = nullptr;