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

@@ -327,17 +327,18 @@ QString AndroidAvdManager::findAvd(const QString &avdName) const
return QString(); return QString();
} }
QString AndroidAvdManager::waitForAvd(const QString &avdName, const QFutureInterface<bool> &fi) const QString AndroidAvdManager::waitForAvd(const QString &avdName,
const std::function<bool()> &cancelChecker) const
{ {
// we cannot use adb -e wait-for-device, since that doesn't work if a emulator is already running // we cannot use adb -e wait-for-device, since that doesn't work if a emulator is already running
// 60 rounds of 2s sleeping, two minutes for the avd to start // 60 rounds of 2s sleeping, two minutes for the avd to start
QString serialNumber; QString serialNumber;
for (int i = 0; i < 60; ++i) { for (int i = 0; i < 60; ++i) {
if (fi.isCanceled()) if (cancelChecker())
return QString(); return QString();
serialNumber = findAvd(avdName); serialNumber = findAvd(avdName);
if (!serialNumber.isEmpty()) if (!serialNumber.isEmpty())
return waitForBooted(serialNumber, fi) ? serialNumber : QString(); return waitForBooted(serialNumber, cancelChecker) ? serialNumber : QString();
QThread::sleep(2); QThread::sleep(2);
} }
return QString(); return QString();
@@ -358,11 +359,12 @@ bool AndroidAvdManager::isAvdBooted(const QString &device) const
return value == "stopped"; return value == "stopped";
} }
bool AndroidAvdManager::waitForBooted(const QString &serialNumber, const QFutureInterface<bool> &fi) const bool AndroidAvdManager::waitForBooted(const QString &serialNumber,
const std::function<bool()> &cancelChecker) const
{ {
// found a serial number, now wait until it's done booting... // found a serial number, now wait until it's done booting...
for (int i = 0; i < 60; ++i) { for (int i = 0; i < 60; ++i) {
if (fi.isCanceled()) if (cancelChecker())
return false; return false;
if (isAvdBooted(serialNumber)) { if (isAvdBooted(serialNumber)) {
return true; return true;

View File

@@ -26,6 +26,7 @@
#include "androidconfigurations.h" #include "androidconfigurations.h"
#include <functional>
#include <memory> #include <memory>
namespace Android { namespace Android {
@@ -51,11 +52,12 @@ public:
bool startAvdAsync(const QString &avdName) const; bool startAvdAsync(const QString &avdName) const;
QString findAvd(const QString &avdName) const; QString findAvd(const QString &avdName) const;
QString waitForAvd(const QString &avdName, QString waitForAvd(const QString &avdName,
const QFutureInterface<bool> &fi = QFutureInterface<bool>()) const; const std::function<bool()> &cancelChecker = {}) const;
bool isAvdBooted(const QString &device) const; bool isAvdBooted(const QString &device) const;
private: private:
bool waitForBooted(const QString &serialNumber, const QFutureInterface<bool> &fi) const; bool waitForBooted(const QString &serialNumber,
const std::function<bool()> &cancelChecker) const;
private: private:
const AndroidConfig &m_config; const AndroidConfig &m_config;

View File

@@ -340,14 +340,14 @@ bool AndroidBuildApkStep::verifyCertificatePassword()
return success; return success;
} }
void AndroidBuildApkStep::run(QFutureInterface<bool> &fi) void AndroidBuildApkStep::doRun()
{ {
if (m_skipBuilding) { if (m_skipBuilding) {
emit addOutput(tr("No application .pro file found, not building an APK."), BuildStep::OutputFormat::ErrorMessage); emit addOutput(tr("No application .pro file found, not building an APK."), BuildStep::OutputFormat::ErrorMessage);
reportRunResult(fi, true); emit finished(true);
return; return;
} }
AbstractProcessStep::run(fi); AbstractProcessStep::doRun();
} }
void AndroidBuildApkStep::processStarted() void AndroidBuildApkStep::processStarted()

View File

@@ -86,7 +86,7 @@ private:
bool verifyKeystorePassword(); bool verifyKeystorePassword();
bool verifyCertificatePassword(); bool verifyCertificatePassword();
void run(QFutureInterface<bool> &fi) override; void doRun() override;
bool m_signPackage = false; bool m_signPackage = false;
bool m_verbose = false; bool m_verbose = false;

View File

@@ -298,7 +298,7 @@ bool AndroidDeployQtStep::init()
return true; return true;
} }
AndroidDeployQtStep::DeployErrorCode AndroidDeployQtStep::runDeploy(QFutureInterface<bool> &fi) AndroidDeployQtStep::DeployErrorCode AndroidDeployQtStep::runDeploy()
{ {
QString args; QString args;
if (m_useAndroiddeployqt) { if (m_useAndroiddeployqt) {
@@ -386,7 +386,7 @@ AndroidDeployQtStep::DeployErrorCode AndroidDeployQtStep::runDeploy(QFutureInter
if (m_process->state() == QProcess::NotRunning) if (m_process->state() == QProcess::NotRunning)
break; break;
if (fi.isCanceled()) { if (isCanceled()) {
m_process->kill(); m_process->kill();
m_process->waitForFinished(); m_process->waitForFinished();
} }
@@ -472,25 +472,23 @@ void AndroidDeployQtStep::slotSetSerialNumber(const QString &serialNumber)
AndroidManager::setDeviceSerialNumber(target(), serialNumber); AndroidManager::setDeviceSerialNumber(target(), serialNumber);
} }
void AndroidDeployQtStep::run(QFutureInterface<bool> &fi) bool AndroidDeployQtStep::runImpl()
{ {
if (!m_avdName.isEmpty()) { if (!m_avdName.isEmpty()) {
QString serialNumber = AndroidAvdManager().waitForAvd(m_avdName, fi); QString serialNumber = AndroidAvdManager().waitForAvd(m_avdName, cancelChecker());
qCDebug(deployStepLog) << "Deploying to AVD:" << m_avdName << serialNumber; qCDebug(deployStepLog) << "Deploying to AVD:" << m_avdName << serialNumber;
if (serialNumber.isEmpty()) { if (serialNumber.isEmpty())
reportRunResult(fi, false); return false;
return;
}
m_serialNumber = serialNumber; m_serialNumber = serialNumber;
emit setSerialNumber(serialNumber); emit setSerialNumber(serialNumber);
} }
DeployErrorCode returnValue = runDeploy(fi); DeployErrorCode returnValue = runDeploy();
if (returnValue > DeployErrorCode::NoError && returnValue < DeployErrorCode::Failure) { if (returnValue > DeployErrorCode::NoError && returnValue < DeployErrorCode::Failure) {
emit askForUninstall(returnValue); emit askForUninstall(returnValue);
if (m_askForUninstall) { if (m_askForUninstall) {
m_uninstallPreviousPackageRun = true; m_uninstallPreviousPackageRun = true;
returnValue = runDeploy(fi); returnValue = runDeploy();
} }
} }
@@ -509,7 +507,7 @@ void AndroidDeployQtStep::run(QFutureInterface<bool> &fi)
} }
} }
reportRunResult(fi, returnValue == NoError); return returnValue == NoError;
} }
void AndroidDeployQtStep::gatherFilesToPull() void AndroidDeployQtStep::gatherFilesToPull()
@@ -550,6 +548,11 @@ void AndroidDeployQtStep::gatherFilesToPull()
qCDebug(deployStepLog) << itr.key() << "to" << itr.value(); qCDebug(deployStepLog) << itr.key() << "to" << itr.value();
} }
void AndroidDeployQtStep::doRun()
{
runInThread([this] { return runImpl(); });
}
void AndroidDeployQtStep::runCommand(const QString &program, const QStringList &arguments) void AndroidDeployQtStep::runCommand(const QString &program, const QStringList &arguments)
{ {
Utils::SynchronousProcess buildProc; Utils::SynchronousProcess buildProc;

View File

@@ -84,12 +84,14 @@ private:
void runCommand(const QString &program, const QStringList &arguments); void runCommand(const QString &program, const QStringList &arguments);
bool init() override; bool init() override;
void run(QFutureInterface<bool> &fi) override; void doRun() override;
void gatherFilesToPull(); void gatherFilesToPull();
DeployErrorCode runDeploy(QFutureInterface<bool> &fi); DeployErrorCode runDeploy();
void slotAskForUninstall(DeployErrorCode errorCode); void slotAskForUninstall(DeployErrorCode errorCode);
void slotSetSerialNumber(const QString &serialNumber); void slotSetSerialNumber(const QString &serialNumber);
bool runImpl();
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override; ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
void processReadyReadStdOutput(DeployErrorCode &errorCode); void processReadyReadStdOutput(DeployErrorCode &errorCode);

View File

@@ -95,7 +95,7 @@ bool AndroidPackageInstallationStep::init()
return AbstractProcessStep::init(); return AbstractProcessStep::init();
} }
void AndroidPackageInstallationStep::run(QFutureInterface<bool> &fi) void AndroidPackageInstallationStep::doRun()
{ {
QString error; QString error;
foreach (const QString &dir, m_androidDirsToClean) { foreach (const QString &dir, m_androidDirsToClean) {
@@ -104,12 +104,12 @@ void AndroidPackageInstallationStep::run(QFutureInterface<bool> &fi)
emit addOutput(tr("Removing directory %1").arg(dir), OutputFormat::NormalMessage); emit addOutput(tr("Removing directory %1").arg(dir), OutputFormat::NormalMessage);
if (!FileUtils::removeRecursively(androidDir, &error)) { if (!FileUtils::removeRecursively(androidDir, &error)) {
emit addOutput(error, OutputFormat::Stderr); emit addOutput(error, OutputFormat::Stderr);
reportRunResult(fi, false); emit finished(false);
return; return;
} }
} }
} }
AbstractProcessStep::run(fi); AbstractProcessStep::doRun();
} }
BuildStepConfigWidget *AndroidPackageInstallationStep::createConfigWidget() BuildStepConfigWidget *AndroidPackageInstallationStep::createConfigWidget()

View File

@@ -40,13 +40,13 @@ class ANDROID_EXPORT AndroidPackageInstallationStep : public ProjectExplorer::Ab
public: public:
explicit AndroidPackageInstallationStep(ProjectExplorer::BuildStepList *bsl); explicit AndroidPackageInstallationStep(ProjectExplorer::BuildStepList *bsl);
bool init() override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override; ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
void run(QFutureInterface<bool> &fi) override;
private: private:
bool init() override;
void doRun() override;
QStringList m_androidDirsToClean; QStringList m_androidDirsToClean;
}; };

View File

@@ -86,7 +86,7 @@ bool AutogenStep::init()
return AbstractProcessStep::init(); return AbstractProcessStep::init();
} }
void AutogenStep::run(QFutureInterface<bool> &fi) void AutogenStep::doRun()
{ {
BuildConfiguration *bc = buildConfiguration(); BuildConfiguration *bc = buildConfiguration();
@@ -104,12 +104,12 @@ void AutogenStep::run(QFutureInterface<bool> &fi)
if (!m_runAutogen) { if (!m_runAutogen) {
emit addOutput(tr("Configuration unchanged, skipping autogen step."), BuildStep::OutputFormat::NormalMessage); emit addOutput(tr("Configuration unchanged, skipping autogen step."), BuildStep::OutputFormat::NormalMessage);
reportRunResult(fi, true); emit finished(true);
return; return;
} }
m_runAutogen = false; m_runAutogen = false;
AbstractProcessStep::run(fi); AbstractProcessStep::doRun();
} }
BuildStepConfigWidget *AutogenStep::createConfigWidget() BuildStepConfigWidget *AutogenStep::createConfigWidget()

View File

@@ -66,11 +66,12 @@ class AutogenStep : public ProjectExplorer::AbstractProcessStep
public: public:
explicit AutogenStep(ProjectExplorer::BuildStepList *bsl); explicit AutogenStep(ProjectExplorer::BuildStepList *bsl);
bool init() override;
void run(QFutureInterface<bool> &fi) override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override; ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
private: private:
bool init() override;
void doRun() override;
ProjectExplorer::BaseStringAspect *m_additionalArgumentsAspect = nullptr; ProjectExplorer::BaseStringAspect *m_additionalArgumentsAspect = nullptr;
bool m_runAutogen = false; bool m_runAutogen = false;
}; };

View File

@@ -84,7 +84,7 @@ bool AutoreconfStep::init()
return AbstractProcessStep::init(); return AbstractProcessStep::init();
} }
void AutoreconfStep::run(QFutureInterface<bool> &fi) void AutoreconfStep::doRun()
{ {
BuildConfiguration *bc = buildConfiguration(); BuildConfiguration *bc = buildConfiguration();
@@ -96,12 +96,12 @@ void AutoreconfStep::run(QFutureInterface<bool> &fi)
if (!m_runAutoreconf) { if (!m_runAutoreconf) {
emit addOutput(tr("Configuration unchanged, skipping autoreconf step."), BuildStep::OutputFormat::NormalMessage); emit addOutput(tr("Configuration unchanged, skipping autoreconf step."), BuildStep::OutputFormat::NormalMessage);
reportRunResult(fi, true); emit finished(true);
return; return;
} }
m_runAutoreconf = false; m_runAutoreconf = false;
AbstractProcessStep::run(fi); AbstractProcessStep::doRun();
} }
BuildStepConfigWidget *AutoreconfStep::createConfigWidget() BuildStepConfigWidget *AutoreconfStep::createConfigWidget()

View File

@@ -67,7 +67,7 @@ public:
explicit AutoreconfStep(ProjectExplorer::BuildStepList *bsl); explicit AutoreconfStep(ProjectExplorer::BuildStepList *bsl);
bool init() override; bool init() override;
void run(QFutureInterface<bool> &fi) override; void doRun() override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override; ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
private: private:

View File

@@ -105,7 +105,7 @@ bool ConfigureStep::init()
return AbstractProcessStep::init(); return AbstractProcessStep::init();
} }
void ConfigureStep::run(QFutureInterface<bool>& fi) void ConfigureStep::doRun()
{ {
BuildConfiguration *bc = buildConfiguration(); BuildConfiguration *bc = buildConfiguration();
@@ -121,12 +121,12 @@ void ConfigureStep::run(QFutureInterface<bool>& fi)
if (!m_runConfigure) { if (!m_runConfigure) {
emit addOutput(tr("Configuration unchanged, skipping configure step."), BuildStep::OutputFormat::NormalMessage); emit addOutput(tr("Configuration unchanged, skipping configure step."), BuildStep::OutputFormat::NormalMessage);
reportRunResult(fi, true); emit finished(true);
return; return;
} }
m_runConfigure = false; m_runConfigure = false;
AbstractProcessStep::run(fi); AbstractProcessStep::doRun();
} }
BuildStepConfigWidget *ConfigureStep::createConfigWidget() BuildStepConfigWidget *ConfigureStep::createConfigWidget()

View File

@@ -67,14 +67,15 @@ class ConfigureStep : public ProjectExplorer::AbstractProcessStep
public: public:
explicit ConfigureStep(ProjectExplorer::BuildStepList *bsl); explicit ConfigureStep(ProjectExplorer::BuildStepList *bsl);
bool init() override;
void run(QFutureInterface<bool> &fi) override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override; ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
void setAdditionalArguments(const QString &list); void setAdditionalArguments(const QString &list);
void notifyBuildDirectoryChanged(); void notifyBuildDirectoryChanged();
private: private:
bool init() override;
void doRun() override;
void updateDetails(); void updateDetails();
ProjectExplorer::BaseStringAspect *m_additionalArgumentsAspect = nullptr; ProjectExplorer::BaseStringAspect *m_additionalArgumentsAspect = nullptr;

View File

@@ -66,12 +66,11 @@ BareMetalGdbCommandsDeployStep::BareMetalGdbCommandsDeployStep(BuildStepList *bs
: BuildStep(bsl, stepId()) : BuildStep(bsl, stepId())
{ {
setDefaultDisplayName(displayName()); setDefaultDisplayName(displayName());
setRunInGuiThread(true);
} }
void BareMetalGdbCommandsDeployStep::run(QFutureInterface<bool> &fi) void BareMetalGdbCommandsDeployStep::doRun()
{ {
reportRunResult(fi, true); emit finished(true);
} }
bool BareMetalGdbCommandsDeployStep::fromMap(const QVariantMap &map) bool BareMetalGdbCommandsDeployStep::fromMap(const QVariantMap &map)

View File

@@ -40,9 +40,6 @@ class BareMetalGdbCommandsDeployStep : public ProjectExplorer::BuildStep
public: public:
explicit BareMetalGdbCommandsDeployStep(ProjectExplorer::BuildStepList *bsl); explicit BareMetalGdbCommandsDeployStep(ProjectExplorer::BuildStepList *bsl);
bool init() override;
void run(QFutureInterface<bool> &fi) override;
bool fromMap(const QVariantMap &map) override; bool fromMap(const QVariantMap &map) override;
QVariantMap toMap() const override; QVariantMap toMap() const override;
@@ -55,6 +52,9 @@ public:
QString gdbCommands() const; QString gdbCommands() const;
private: private:
bool init() override;
void doRun() override;
QString m_gdbCommands; QString m_gdbCommands;
}; };

View File

@@ -233,46 +233,47 @@ bool CMakeBuildStep::init()
return AbstractProcessStep::init(); return AbstractProcessStep::init();
} }
void CMakeBuildStep::run(QFutureInterface<bool> &fi) void CMakeBuildStep::doRun()
{ {
// Make sure CMake state was written to disk before trying to build: // Make sure CMake state was written to disk before trying to build:
CMakeBuildConfiguration *bc = cmakeBuildConfiguration(); CMakeBuildConfiguration *bc = cmakeBuildConfiguration();
QTC_ASSERT(bc, return); QTC_ASSERT(bc, return);
bool mustDelay = false; m_waiting = false;
auto p = static_cast<CMakeProject *>(bc->project()); auto p = static_cast<CMakeProject *>(bc->project());
if (p->persistCMakeState()) { if (p->persistCMakeState()) {
emit addOutput(tr("Persisting CMake state..."), BuildStep::OutputFormat::NormalMessage); emit addOutput(tr("Persisting CMake state..."), BuildStep::OutputFormat::NormalMessage);
mustDelay = true; m_waiting = true;
} else if (p->mustUpdateCMakeStateBeforeBuild()) { } else if (p->mustUpdateCMakeStateBeforeBuild()) {
emit addOutput(tr("Running CMake in preparation to build..."), BuildStep::OutputFormat::NormalMessage); emit addOutput(tr("Running CMake in preparation to build..."), BuildStep::OutputFormat::NormalMessage);
mustDelay = true; m_waiting = true;
} else {
mustDelay = false;
} }
if (mustDelay) { if (m_waiting) {
m_runTrigger = connect(project(), &Project::parsingFinished, m_runTrigger = connect(project(), &Project::parsingFinished,
this, [this, &fi](bool success) { handleProjectWasParsed(fi, success); }); this, [this](bool success) { handleProjectWasParsed(success); });
} else { } else {
runImpl(fi); runImpl();
} }
} }
void CMakeBuildStep::runImpl(QFutureInterface<bool> &fi) void CMakeBuildStep::runImpl()
{ {
// Do the actual build: // Do the actual build:
AbstractProcessStep::run(fi); AbstractProcessStep::doRun();
} }
void CMakeBuildStep::handleProjectWasParsed(QFutureInterface<bool> &fi, bool success) void CMakeBuildStep::handleProjectWasParsed(bool success)
{ {
m_waiting = false;
disconnect(m_runTrigger); disconnect(m_runTrigger);
if (success) { if (isCanceled()) {
runImpl(fi); emit finished(false);
} else if (success) {
runImpl();
} else { } else {
AbstractProcessStep::stdError(tr("Project did not parse successfully, cannot build.")); AbstractProcessStep::stdError(tr("Project did not parse successfully, cannot build."));
reportRunResult(fi, false); emit finished(false);
} }
} }
@@ -288,7 +289,7 @@ void CMakeBuildStep::stdOutput(const QString &line)
bool ok = false; bool ok = false;
int percent = m_percentProgress.cap(1).toInt(&ok); int percent = m_percentProgress.cap(1).toInt(&ok);
if (ok) if (ok)
futureInterface()->setProgressValue(percent); emit progress(percent, QString());
return; return;
} else if (m_ninjaProgress.indexIn(line) != -1) { } else if (m_ninjaProgress.indexIn(line) != -1) {
AbstractProcessStep::stdOutput(line); AbstractProcessStep::stdOutput(line);
@@ -299,7 +300,7 @@ void CMakeBuildStep::stdOutput(const QString &line)
int all = m_ninjaProgress.cap(2).toInt(&ok); int all = m_ninjaProgress.cap(2).toInt(&ok);
if (ok && all != 0) { if (ok && all != 0) {
const int percent = static_cast<int>(100.0 * done/all); const int percent = static_cast<int>(100.0 * done/all);
futureInterface()->setProgressValue(percent); emit progress(percent, QString());
} }
} }
return; return;
@@ -551,12 +552,11 @@ CMakeBuildStepFactory::CMakeBuildStepFactory()
void CMakeBuildStep::processStarted() void CMakeBuildStep::processStarted()
{ {
m_useNinja = false; m_useNinja = false;
futureInterface()->setProgressRange(0, 100);
AbstractProcessStep::processStarted(); AbstractProcessStep::processStarted();
} }
void CMakeBuildStep::processFinished(int exitCode, QProcess::ExitStatus status) void CMakeBuildStep::processFinished(int exitCode, QProcess::ExitStatus status)
{ {
AbstractProcessStep::processFinished(exitCode, status); AbstractProcessStep::processFinished(exitCode, status);
futureInterface()->setProgressValue(100); emit progress(100, QString());
} }

View File

@@ -56,11 +56,6 @@ public:
CMakeBuildConfiguration *cmakeBuildConfiguration() const; CMakeBuildConfiguration *cmakeBuildConfiguration() const;
bool init() override;
void run(QFutureInterface<bool> &fi) override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
QString buildTarget() const; QString buildTarget() const;
bool buildsBuildTarget(const QString &target) const; bool buildsBuildTarget(const QString &target) const;
void setBuildTarget(const QString &target); void setBuildTarget(const QString &target);
@@ -98,8 +93,12 @@ protected:
private: private:
void ctor(ProjectExplorer::BuildStepList *bsl); void ctor(ProjectExplorer::BuildStepList *bsl);
void runImpl(QFutureInterface<bool> &fi); bool init() override;
void handleProjectWasParsed(QFutureInterface<bool> &fi, bool success); void doRun() override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
void runImpl();
void handleProjectWasParsed(bool success);
void handleBuildTargetChanges(bool success); void handleBuildTargetChanges(bool success);
CMakeRunConfiguration *targetsActiveRunConfiguration() const; CMakeRunConfiguration *targetsActiveRunConfiguration() const;
@@ -112,6 +111,7 @@ private:
QString m_buildTarget; QString m_buildTarget;
QString m_toolArguments; QString m_toolArguments;
bool m_useNinja = false; bool m_useNinja = false;
bool m_waiting = false;
}; };
class CMakeBuildStepConfigWidget : public ProjectExplorer::BuildStepConfigWidget class CMakeBuildStepConfigWidget : public ProjectExplorer::BuildStepConfigWidget

View File

@@ -169,9 +169,9 @@ QString IosBuildStep::buildCommand() const
return QString("xcodebuild"); // add path? return QString("xcodebuild"); // add path?
} }
void IosBuildStep::run(QFutureInterface<bool> &fi) void IosBuildStep::doRun()
{ {
AbstractProcessStep::run(fi); AbstractProcessStep::doRun();
} }
BuildStepConfigWidget *IosBuildStep::createConfigWidget() BuildStepConfigWidget *IosBuildStep::createConfigWidget()

View File

@@ -48,9 +48,6 @@ class IosBuildStep : public ProjectExplorer::AbstractProcessStep
public: public:
explicit IosBuildStep(ProjectExplorer::BuildStepList *parent); explicit IosBuildStep(ProjectExplorer::BuildStepList *parent);
bool init() override;
void run(QFutureInterface<bool> &fi) override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override; ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
void setBaseArguments(const QStringList &args); void setBaseArguments(const QStringList &args);
void setExtraArguments(const QStringList &extraArgs); void setExtraArguments(const QStringList &extraArgs);
@@ -60,6 +57,8 @@ public:
QString buildCommand() const; QString buildCommand() const;
private: private:
bool init() override;
void doRun() override;
bool fromMap(const QVariantMap &map) override; bool fromMap(const QVariantMap &map) override;
QVariantMap toMap() const override; QVariantMap toMap() const override;

View File

@@ -58,7 +58,6 @@ IosDeployStep::IosDeployStep(BuildStepList *parent)
: BuildStep(parent, stepId()) : BuildStep(parent, stepId())
{ {
setImmutable(true); setImmutable(true);
setRunInGuiThread(true);
updateDisplayNames(); updateDisplayNames();
connect(DeviceManager::instance(), &DeviceManager::updated, connect(DeviceManager::instance(), &DeviceManager::updated,
this, &IosDeployStep::updateDisplayNames); this, &IosDeployStep::updateDisplayNames);
@@ -101,22 +100,19 @@ bool IosDeployStep::init()
return true; return true;
} }
void IosDeployStep::run(QFutureInterface<bool> &fi) void IosDeployStep::doRun()
{ {
m_futureInterface = fi;
QTC_CHECK(m_transferStatus == NoTransfer); QTC_CHECK(m_transferStatus == NoTransfer);
if (device().isNull()) { if (device().isNull()) {
TaskHub::addTask(Task::Error, tr("Deployment failed. No iOS device found."), TaskHub::addTask(Task::Error, tr("Deployment failed. No iOS device found."),
ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT); ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT);
reportRunResult(m_futureInterface, !iossimulator().isNull()); emit finished(!iossimulator().isNull());
cleanup(); cleanup();
return; return;
} }
m_toolHandler = new IosToolHandler(m_deviceType, this); m_toolHandler = new IosToolHandler(m_deviceType, this);
m_transferStatus = TransferInProgress; m_transferStatus = TransferInProgress;
m_futureInterface.setProgressRange(0, 200); emit progress(0, tr("Transferring application"));
m_futureInterface.setProgressValueAndText(0, QLatin1String("Transferring application"));
m_futureInterface.reportStarted();
connect(m_toolHandler, &IosToolHandler::isTransferringApp, connect(m_toolHandler, &IosToolHandler::isTransferringApp,
this, &IosDeployStep::handleIsTransferringApp); this, &IosDeployStep::handleIsTransferringApp);
connect(m_toolHandler, &IosToolHandler::didTransferApp, connect(m_toolHandler, &IosToolHandler::didTransferApp,
@@ -129,7 +125,7 @@ void IosDeployStep::run(QFutureInterface<bool> &fi)
m_toolHandler->requestTransferApp(appBundle(), m_deviceType.identifier); m_toolHandler->requestTransferApp(appBundle(), m_deviceType.identifier);
} }
void IosDeployStep::cancel() void IosDeployStep::doCancel()
{ {
if (m_toolHandler) if (m_toolHandler)
m_toolHandler->stop(); m_toolHandler->stop();
@@ -150,8 +146,7 @@ void IosDeployStep::handleIsTransferringApp(IosToolHandler *handler, const QStri
{ {
Q_UNUSED(handler); Q_UNUSED(bundlePath); Q_UNUSED(deviceId); Q_UNUSED(handler); Q_UNUSED(bundlePath); Q_UNUSED(deviceId);
QTC_CHECK(m_transferStatus == TransferInProgress); QTC_CHECK(m_transferStatus == TransferInProgress);
m_futureInterface.setProgressRange(0, maxProgress); emit this->progress(progress * 100 / maxProgress, info);
m_futureInterface.setProgressValueAndText(progress, info);
} }
void IosDeployStep::handleDidTransferApp(IosToolHandler *handler, const QString &bundlePath, void IosDeployStep::handleDidTransferApp(IosToolHandler *handler, const QString &bundlePath,
@@ -168,7 +163,7 @@ void IosDeployStep::handleDidTransferApp(IosToolHandler *handler, const QString
tr("Deployment failed. The settings in the Devices window of Xcode might be incorrect."), tr("Deployment failed. The settings in the Devices window of Xcode might be incorrect."),
ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT); ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT);
} }
reportRunResult(m_futureInterface, status == IosToolHandler::Success); emit finished(status == IosToolHandler::Success);
} }
void IosDeployStep::handleFinished(IosToolHandler *handler) void IosDeployStep::handleFinished(IosToolHandler *handler)
@@ -178,7 +173,7 @@ void IosDeployStep::handleFinished(IosToolHandler *handler)
m_transferStatus = TransferFailed; m_transferStatus = TransferFailed;
TaskHub::addTask(Task::Error, tr("Deployment failed."), TaskHub::addTask(Task::Error, tr("Deployment failed."),
ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT); ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT);
reportRunResult(m_futureInterface, false); emit finished(false);
break; break;
case NoTransfer: case NoTransfer:
case TransferOk: case TransferOk:

View File

@@ -32,7 +32,6 @@
#include <projectexplorer/buildstep.h> #include <projectexplorer/buildstep.h>
#include <projectexplorer/devicesupport/idevice.h> #include <projectexplorer/devicesupport/idevice.h>
#include <QFutureInterface>
#include <QProcess> #include <QProcess>
namespace Ios { namespace Ios {
@@ -54,14 +53,13 @@ public:
explicit IosDeployStep(ProjectExplorer::BuildStepList *bc); explicit IosDeployStep(ProjectExplorer::BuildStepList *bc);
static Core::Id stepId(); static Core::Id stepId();
void cleanup();
private:
void doRun() override;
void doCancel() override;
bool fromMap(const QVariantMap &map) override; bool fromMap(const QVariantMap &map) override;
QVariantMap toMap() const override; QVariantMap toMap() const override;
void run(QFutureInterface<bool> &fi) override;
void cleanup();
void cancel() override;
private:
void handleIsTransferringApp(Ios::IosToolHandler *handler, const QString &bundlePath, void handleIsTransferringApp(Ios::IosToolHandler *handler, const QString &bundlePath,
const QString &deviceId, int progress, int maxProgress, const QString &deviceId, int progress, int maxProgress,
const QString &info); const QString &info);
@@ -85,7 +83,6 @@ private:
TransferStatus m_transferStatus = NoTransfer; TransferStatus m_transferStatus = NoTransfer;
IosToolHandler *m_toolHandler = nullptr; IosToolHandler *m_toolHandler = nullptr;
QFutureInterface<bool> m_futureInterface;
ProjectExplorer::IDevice::ConstPtr m_device; ProjectExplorer::IDevice::ConstPtr m_device;
QString m_bundlePath; QString m_bundlePath;
IosDeviceType m_deviceType; IosDeviceType m_deviceType;

View File

@@ -187,9 +187,9 @@ bool IosDsymBuildStep::isDefault() const
return arguments() == defaultArguments() && command() == defaultCommand(); return arguments() == defaultArguments() && command() == defaultCommand();
} }
void IosDsymBuildStep::run(QFutureInterface<bool> &fi) void IosDsymBuildStep::doRun()
{ {
AbstractProcessStep::run(fi); AbstractProcessStep::doRun();
} }
BuildStepConfigWidget *IosDsymBuildStep::createConfigWidget() BuildStepConfigWidget *IosDsymBuildStep::createConfigWidget()

View File

@@ -42,9 +42,6 @@ class IosDsymBuildStep : public ProjectExplorer::AbstractProcessStep
public: public:
IosDsymBuildStep(ProjectExplorer::BuildStepList *parent); IosDsymBuildStep(ProjectExplorer::BuildStepList *parent);
bool init() override;
void run(QFutureInterface<bool> &fi) override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override; ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
void setArguments(const QStringList &args); void setArguments(const QStringList &args);
QStringList arguments() const; QStringList arguments() const;
@@ -54,10 +51,12 @@ public:
void setCommand(const QString &command); void setCommand(const QString &command);
bool isDefault() const; bool isDefault() const;
QVariantMap toMap() const override;
private: private:
bool init() override;
void doRun() override;
QVariantMap toMap() const override;
bool fromMap(const QVariantMap &map) override; bool fromMap(const QVariantMap &map) override;
QStringList defaultCleanCmdList() const; QStringList defaultCleanCmdList() const;
QStringList defaultCmdList() const; QStringList defaultCmdList() const;

View File

@@ -61,28 +61,33 @@ bool NimCompilerCleanStep::init()
return result; return result;
} }
void NimCompilerCleanStep::run(QFutureInterface<bool> &fi) void NimCompilerCleanStep::doRun()
{ {
if (!m_buildDir.exists()) { if (!m_buildDir.exists()) {
emit addOutput(tr("Build directory \"%1\" does not exist.").arg(m_buildDir.toUserOutput()), BuildStep::OutputFormat::ErrorMessage); emit addOutput(tr("Build directory \"%1\" does not exist.").arg(m_buildDir.toUserOutput()), BuildStep::OutputFormat::ErrorMessage);
reportRunResult(fi, false); emit finished(false);
return; return;
} }
if (!removeCacheDirectory()) { if (!removeCacheDirectory()) {
emit addOutput(tr("Failed to delete the cache directory."), BuildStep::OutputFormat::ErrorMessage); emit addOutput(tr("Failed to delete the cache directory."), BuildStep::OutputFormat::ErrorMessage);
reportRunResult(fi, false); emit finished(false);
return; return;
} }
if (!removeOutFilePath()) { if (!removeOutFilePath()) {
emit addOutput(tr("Failed to delete the out file."), BuildStep::OutputFormat::ErrorMessage); emit addOutput(tr("Failed to delete the out file."), BuildStep::OutputFormat::ErrorMessage);
reportRunResult(fi, false); emit finished(false);
return; return;
} }
emit addOutput(tr("Clean step completed successfully."), BuildStep::OutputFormat::NormalMessage); emit addOutput(tr("Clean step completed successfully."), BuildStep::OutputFormat::NormalMessage);
reportRunResult(fi, true); emit finished(true);
}
void NimCompilerCleanStep::doCancel()
{
// Can be left empty. The run() function hardly does anything.
} }
bool NimCompilerCleanStep::removeCacheDirectory() bool NimCompilerCleanStep::removeCacheDirectory()

View File

@@ -39,10 +39,12 @@ public:
NimCompilerCleanStep(ProjectExplorer::BuildStepList *parentList); NimCompilerCleanStep(ProjectExplorer::BuildStepList *parentList);
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override; ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
bool init() override;
void run(QFutureInterface<bool> &fi) override;
private: private:
bool init() override;
void doRun() override;
void doCancel() override;
bool removeCacheDirectory(); bool removeCacheDirectory();
bool removeOutFilePath(); bool removeOutFilePath();

View File

@@ -104,7 +104,6 @@ public:
Private(AbstractProcessStep *q) : q(q) {} Private(AbstractProcessStep *q) : q(q) {}
AbstractProcessStep *q; AbstractProcessStep *q;
QFutureInterface<bool> *m_futureInterface = nullptr;
std::unique_ptr<Utils::QtcProcess> m_process; std::unique_ptr<Utils::QtcProcess> m_process;
std::unique_ptr<IOutputParser> m_outputParserChain; std::unique_ptr<IOutputParser> m_outputParserChain;
ProcessParameters m_param; ProcessParameters m_param;
@@ -125,7 +124,6 @@ AbstractProcessStep::AbstractProcessStep(BuildStepList *bsl, Core::Id id) :
BuildStep(bsl, id), BuildStep(bsl, id),
d(new Private(this)) d(new Private(this))
{ {
setRunInGuiThread(true);
} }
AbstractProcessStep::~AbstractProcessStep() AbstractProcessStep::~AbstractProcessStep()
@@ -209,7 +207,7 @@ bool AbstractProcessStep::init()
YourBuildStep::run(). YourBuildStep::run().
*/ */
void AbstractProcessStep::run(QFutureInterface<bool> &fi) void AbstractProcessStep::doRun()
{ {
QDir wd(d->m_param.effectiveWorkingDirectory()); QDir wd(d->m_param.effectiveWorkingDirectory());
if (!wd.exists()) { if (!wd.exists()) {
@@ -217,7 +215,7 @@ void AbstractProcessStep::run(QFutureInterface<bool> &fi)
emit addOutput(tr("Could not create directory \"%1\"") emit addOutput(tr("Could not create directory \"%1\"")
.arg(QDir::toNativeSeparators(wd.absolutePath())), .arg(QDir::toNativeSeparators(wd.absolutePath())),
BuildStep::OutputFormat::ErrorMessage); BuildStep::OutputFormat::ErrorMessage);
reportRunResult(fi, false); finish(false);
return; return;
} }
} }
@@ -225,12 +223,10 @@ void AbstractProcessStep::run(QFutureInterface<bool> &fi)
QString effectiveCommand = d->m_param.effectiveCommand(); QString effectiveCommand = d->m_param.effectiveCommand();
if (!QFileInfo::exists(effectiveCommand)) { if (!QFileInfo::exists(effectiveCommand)) {
processStartupFailed(); processStartupFailed();
reportRunResult(fi, false); finish(false);
return; return;
} }
d->m_futureInterface = &fi;
d->m_process.reset(new Utils::QtcProcess()); d->m_process.reset(new Utils::QtcProcess());
d->m_process->setUseCtrlCStub(Utils::HostOsInfo::isWindowsHost()); d->m_process->setUseCtrlCStub(Utils::HostOsInfo::isWindowsHost());
d->m_process->setWorkingDirectory(wd.absolutePath()); d->m_process->setWorkingDirectory(wd.absolutePath());
@@ -249,13 +245,13 @@ void AbstractProcessStep::run(QFutureInterface<bool> &fi)
processStartupFailed(); processStartupFailed();
d->m_process.reset(); d->m_process.reset();
d->m_outputParserChain.reset(); d->m_outputParserChain.reset();
reportRunResult(fi, false); finish(false);
return; return;
} }
processStarted(); processStarted();
} }
void AbstractProcessStep::cancel() void AbstractProcessStep::doCancel()
{ {
Core::Reaper::reap(d->m_process.release()); Core::Reaper::reap(d->m_process.release());
} }
@@ -275,7 +271,7 @@ void AbstractProcessStep::cleanUp(QProcess *process)
d->m_process.reset(); d->m_process.reset();
// Report result // Report result
reportRunResult(*d->m_futureInterface, returnValue); finish(returnValue);
} }
/*! /*!
@@ -420,9 +416,9 @@ void AbstractProcessStep::stdError(const QString &line)
emit addOutput(line, BuildStep::OutputFormat::Stderr, BuildStep::DontAppendNewline); emit addOutput(line, BuildStep::OutputFormat::Stderr, BuildStep::DontAppendNewline);
} }
QFutureInterface<bool> *AbstractProcessStep::futureInterface() const void AbstractProcessStep::finish(bool success)
{ {
return d->m_futureInterface; emit finished(success);
} }
void AbstractProcessStep::taskAdded(const Task &task, int linkedOutputLines, int skipLines) void AbstractProcessStep::taskAdded(const Task &task, int linkedOutputLines, int skipLines)

View File

@@ -41,10 +41,6 @@ class PROJECTEXPLORER_EXPORT AbstractProcessStep : public BuildStep
Q_OBJECT Q_OBJECT
public: public:
bool init() override;
void run(QFutureInterface<bool> &) override;
void cancel() override;
ProcessParameters *processParameters(); ProcessParameters *processParameters();
bool ignoreReturnValue(); bool ignoreReturnValue();
@@ -59,6 +55,8 @@ public:
protected: protected:
AbstractProcessStep(BuildStepList *bsl, Core::Id id); AbstractProcessStep(BuildStepList *bsl, Core::Id id);
~AbstractProcessStep() override; ~AbstractProcessStep() override;
bool init() override;
void doRun() override;
virtual void processStarted(); virtual void processStarted();
virtual void processFinished(int exitCode, QProcess::ExitStatus status); virtual void processFinished(int exitCode, QProcess::ExitStatus status);
@@ -67,9 +65,11 @@ protected:
virtual void stdOutput(const QString &line); virtual void stdOutput(const QString &line);
virtual void stdError(const QString &line); virtual void stdError(const QString &line);
QFutureInterface<bool> *futureInterface() const; void doCancel() override;
private: private:
virtual void finish(bool success);
void processReadyReadStdOutput(); void processReadyReadStdOutput();
void processReadyReadStdError(); void processReadyReadStdError();
void slotProcessFinished(int, QProcess::ExitStatus); void slotProcessFinished(int, QProcess::ExitStatus);

View File

@@ -79,9 +79,8 @@ public:
// is set to true while canceling, so that nextBuildStep knows that the BuildStep finished because of canceling // is set to true while canceling, so that nextBuildStep knows that the BuildStep finished because of canceling
bool m_skipDisabled = false; bool m_skipDisabled = false;
bool m_canceling = false; bool m_canceling = false;
QFutureWatcher<bool> m_watcher; bool m_lastStepSucceeded = true;
QFutureInterface<bool> m_futureInterfaceForAysnc; BuildStep *m_currentBuildStep = nullptr;
BuildStep *m_currentBuildStep;
QString m_currentConfiguration; QString m_currentConfiguration;
// used to decide if we are building a project to decide when to emit buildStateChanged(Project *) // used to decide if we are building a project to decide when to emit buildStateChanged(Project *)
QHash<Project *, int> m_activeBuildSteps; QHash<Project *, int> m_activeBuildSteps;
@@ -107,16 +106,6 @@ BuildManager::BuildManager(QObject *parent, QAction *cancelBuildAction)
m_instance = this; m_instance = this;
d = new BuildManagerPrivate; d = new BuildManagerPrivate;
connect(&d->m_watcher, &QFutureWatcherBase::finished,
this, &BuildManager::nextBuildQueue, Qt::QueuedConnection);
connect(&d->m_watcher, &QFutureWatcherBase::progressValueChanged,
this, &BuildManager::progressChanged);
connect(&d->m_watcher, &QFutureWatcherBase::progressTextChanged,
this, &BuildManager::progressTextChanged);
connect(&d->m_watcher, &QFutureWatcherBase::progressRangeChanged,
this, &BuildManager::progressChanged);
connect(SessionManager::instance(), &SessionManager::aboutToRemoveProject, connect(SessionManager::instance(), &SessionManager::aboutToRemoveProject,
this, &BuildManager::aboutToRemoveProject); this, &BuildManager::aboutToRemoveProject);
@@ -203,14 +192,9 @@ void BuildManager::cancel()
if (d->m_canceling) if (d->m_canceling)
return; return;
d->m_canceling = true; d->m_canceling = true;
d->m_watcher.cancel(); d->m_currentBuildStep->cancel();
if (d->m_currentBuildStep->runInGuiThread()) { while (d->m_canceling)
d->m_currentBuildStep->cancel(); QApplication::processEvents(QEventLoop::ExcludeUserInputEvents); // TODO: Is this really necessary?
while (d->m_canceling)
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
} else {
d->m_watcher.waitForFinished();
}
} }
} }
@@ -352,8 +336,6 @@ void BuildManager::addToOutputWindow(const QString &string, BuildStep::OutputFor
void BuildManager::nextBuildQueue() void BuildManager::nextBuildQueue()
{ {
d->m_futureInterfaceForAysnc = QFutureInterface<bool>();
d->m_outputWindow->flush(); d->m_outputWindow->flush();
if (d->m_canceling) { if (d->m_canceling) {
d->m_canceling = false; d->m_canceling = false;
@@ -375,7 +357,7 @@ void BuildManager::nextBuildQueue()
d->m_progressFutureInterface->setProgressValueAndText(d->m_progress*100, msgProgress(d->m_progress, d->m_maxProgress)); d->m_progressFutureInterface->setProgressValueAndText(d->m_progress*100, msgProgress(d->m_progress, d->m_maxProgress));
decrementActiveBuildSteps(d->m_currentBuildStep); decrementActiveBuildSteps(d->m_currentBuildStep);
const bool success = d->m_skipDisabled || d->m_watcher.result(); const bool success = d->m_skipDisabled || d->m_lastStepSucceeded;
if (success) { if (success) {
nextStep(); nextStep();
} else { } else {
@@ -397,28 +379,10 @@ void BuildManager::nextBuildQueue()
} }
} }
void BuildManager::progressChanged() void BuildManager::progressChanged(int percent, const QString &text)
{ {
if (!d->m_progressFutureInterface) if (d->m_progressFutureInterface)
return; d->m_progressFutureInterface->setProgressValueAndText(percent, text);
int range = d->m_watcher.progressMaximum() - d->m_watcher.progressMinimum();
if (range != 0) {
int percent = (d->m_watcher.progressValue() - d->m_watcher.progressMinimum()) * 100 / range;
d->m_progressFutureInterface->setProgressValueAndText(d->m_progress * 100 + percent, msgProgress(d->m_progress, d->m_maxProgress)
+ QLatin1Char('\n') + d->m_watcher.progressText());
}
}
void BuildManager::progressTextChanged()
{
if (!d->m_progressFutureInterface)
return;
int range = d->m_watcher.progressMaximum() - d->m_watcher.progressMinimum();
int percent = 0;
if (range != 0)
percent = (d->m_watcher.progressValue() - d->m_watcher.progressMinimum()) * 100 / range;
d->m_progressFutureInterface->setProgressValueAndText(d->m_progress*100 + percent, msgProgress(d->m_progress, d->m_maxProgress) +
QLatin1Char('\n') + d->m_watcher.progressText());
} }
void BuildManager::nextStep() void BuildManager::nextStep()
@@ -445,12 +409,16 @@ void BuildManager::nextStep()
return; return;
} }
if (d->m_currentBuildStep->runInGuiThread()) { static const auto finishedHandler = [](bool success) {
d->m_watcher.setFuture(d->m_futureInterfaceForAysnc.future()); d->m_lastStepSucceeded = success;
d->m_currentBuildStep->run(d->m_futureInterfaceForAysnc); disconnect(d->m_currentBuildStep, nullptr, instance(), nullptr);
} else { BuildManager::nextBuildQueue();
d->m_watcher.setFuture(Utils::runAsync(&BuildStep::run, d->m_currentBuildStep)); };
} connect(d->m_currentBuildStep, &BuildStep::finished, instance(), finishedHandler,
Qt::QueuedConnection);
connect(d->m_currentBuildStep, &BuildStep::progress,
instance(), &BuildManager::progressChanged);
d->m_currentBuildStep->run();
} else { } else {
d->m_running = false; d->m_running = false;
d->m_previousBuildStepProject = nullptr; d->m_previousBuildStepProject = nullptr;

View File

@@ -85,8 +85,7 @@ private:
BuildStep::OutputNewlineSetting newlineSettings = BuildStep::DoAppendNewline); BuildStep::OutputNewlineSetting newlineSettings = BuildStep::DoAppendNewline);
static void nextBuildQueue(); static void nextBuildQueue();
static void progressChanged(); static void progressChanged(int percent, const QString &text);
static void progressTextChanged();
static void emitCancelMessage(); static void emitCancelMessage();
static void showBuildResults(); static void showBuildResults();
static void updateTaskCount(); static void updateTaskCount();

View File

@@ -34,8 +34,11 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/runextensions.h>
#include <QFormLayout> #include <QFormLayout>
#include <QFutureWatcher>
#include <QPointer>
/*! /*!
\class ProjectExplorer::BuildStep \class ProjectExplorer::BuildStep
@@ -127,6 +130,18 @@ BuildStep::BuildStep(BuildStepList *bsl, Core::Id id) :
expander->registerSubProvider([this] { return projectConfiguration()->macroExpander(); }); expander->registerSubProvider([this] { return projectConfiguration()->macroExpander(); });
} }
void BuildStep::run()
{
m_cancelFlag = false;
doRun();
}
void BuildStep::cancel()
{
m_cancelFlag = true;
doCancel();
}
BuildStepConfigWidget *BuildStep::createConfigWidget() BuildStepConfigWidget *BuildStep::createConfigWidget()
{ {
auto widget = new BuildStepConfigWidget(this); auto widget = new BuildStepConfigWidget(this);
@@ -218,25 +233,32 @@ void BuildStep::setWidgetExpandedByDefault(bool widgetExpandedByDefault)
immutable steps are run. The default implementation returns \c false. immutable steps are run. The default implementation returns \c false.
*/ */
bool BuildStep::runInGuiThread() const void BuildStep::runInThread(const std::function<bool()> &syncImpl)
{ {
return m_runInGuiThread; m_runInGuiThread = false;
m_cancelFlag = false;
auto * const watcher = new QFutureWatcher<bool>(this);
connect(watcher, &QFutureWatcher<bool>::finished, this, [this, watcher] {
emit finished(watcher->result());
watcher->deleteLater();
});
watcher->setFuture(Utils::runAsync(syncImpl));
} }
void BuildStep::setRunInGuiThread(bool runInGuiThread) std::function<bool ()> BuildStep::cancelChecker() const
{ {
m_runInGuiThread = runInGuiThread; return [step = QPointer<const BuildStep>(this)] { return step && step->isCanceled(); };
} }
/*! bool BuildStep::isCanceled() const
This function needs to be reimplemented only for build steps that return
\c false from runInGuiThread().
\sa runInGuiThread()
*/
void BuildStep::cancel()
{ {
// Do nothing return m_cancelFlag;
}
void BuildStep::doCancel()
{
QTC_ASSERT(!m_runInGuiThread, qWarning() << "Build step" << displayName()
<< "neeeds to implement the doCancel() function");
} }
void BuildStep::setEnabled(bool b) void BuildStep::setEnabled(bool b)

View File

@@ -33,6 +33,9 @@
#include <QFutureInterface> #include <QFutureInterface>
#include <QWidget> #include <QWidget>
#include <functional>
#include <memory>
namespace ProjectExplorer { namespace ProjectExplorer {
class BuildConfiguration; class BuildConfiguration;
@@ -54,11 +57,10 @@ protected:
public: public:
virtual bool init() = 0; virtual bool init() = 0;
virtual void run(QFutureInterface<bool> &fi) = 0; void run();
void cancel();
virtual BuildStepConfigWidget *createConfigWidget(); virtual BuildStepConfigWidget *createConfigWidget();
virtual void cancel();
bool fromMap(const QVariantMap &map) override; bool fromMap(const QVariantMap &map) override;
QVariantMap toMap() const override; QVariantMap toMap() const override;
@@ -88,9 +90,6 @@ public:
bool isImmutable() const { return m_immutable; } bool isImmutable() const { return m_immutable; }
void setImmutable(bool immutable) { m_immutable = immutable; } void setImmutable(bool immutable) { m_immutable = immutable; }
bool runInGuiThread() const;
void setRunInGuiThread(bool runInGuiThread);
signals: signals:
/// Adds a \p task to the Issues pane. /// Adds a \p task to the Issues pane.
/// Do note that for linking compile output with tasks, you should first emit the task /// Do note that for linking compile output with tasks, you should first emit the task
@@ -104,11 +103,24 @@ signals:
void enabledChanged(); void enabledChanged();
void progress(int percentage, const QString &message);
void finished(bool result);
protected:
void runInThread(const std::function<bool()> &syncImpl);
std::function<bool()> cancelChecker() const;
bool isCanceled() const;
private: private:
virtual void doRun() = 0;
virtual void doCancel();
std::atomic_bool m_cancelFlag;
bool m_enabled = true; bool m_enabled = true;
bool m_immutable = false; bool m_immutable = false;
bool m_widgetExpandedByDefault = true; bool m_widgetExpandedByDefault = true;
bool m_runInGuiThread = false; bool m_runInGuiThread = true;
}; };
class PROJECTEXPLORER_EXPORT BuildStepInfo class PROJECTEXPLORER_EXPORT BuildStepInfo

View File

@@ -77,9 +77,9 @@ bool DeviceCheckBuildStep::init()
return true; return true;
} }
void DeviceCheckBuildStep::run(QFutureInterface<bool> &fi) void DeviceCheckBuildStep::doRun()
{ {
reportRunResult(fi, true); emit finished(true);
} }
Core::Id DeviceCheckBuildStep::stepId() Core::Id DeviceCheckBuildStep::stepId()

View File

@@ -39,7 +39,7 @@ public:
explicit DeviceCheckBuildStep(BuildStepList *bsl); explicit DeviceCheckBuildStep(BuildStepList *bsl);
bool init() override; bool init() override;
void run(QFutureInterface<bool> &fi) override; void doRun() override;
static Core::Id stepId(); static Core::Id stepId();
static QString displayName(); static QString displayName();

View File

@@ -71,9 +71,9 @@ bool ProcessStep::init()
return AbstractProcessStep::init(); return AbstractProcessStep::init();
} }
void ProcessStep::run(QFutureInterface<bool> & fi) void ProcessStep::doRun()
{ {
AbstractProcessStep::run(fi); AbstractProcessStep::doRun();
} }
BuildStepConfigWidget *ProcessStep::createConfigWidget() BuildStepConfigWidget *ProcessStep::createConfigWidget()

View File

@@ -45,9 +45,6 @@ class ProcessStep : public AbstractProcessStep
public: public:
explicit ProcessStep(BuildStepList *bsl); explicit ProcessStep(BuildStepList *bsl);
bool init() override;
void run(QFutureInterface<bool> &) override;
BuildStepConfigWidget *createConfigWidget() override; BuildStepConfigWidget *createConfigWidget() override;
QString command() const; QString command() const;
@@ -58,9 +55,10 @@ public:
void setArguments(const QString &arguments); void setArguments(const QString &arguments);
void setWorkingDirectory(const QString &workingDirectory); void setWorkingDirectory(const QString &workingDirectory);
QVariantMap toMap() const override;
private: private:
bool init() override;
void doRun() override;
QVariantMap toMap() const override;
bool fromMap(const QVariantMap &map) override; bool fromMap(const QVariantMap &map) override;
QString m_command; QString m_command;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -45,16 +45,6 @@ public:
explicit QbsInstallStep(ProjectExplorer::BuildStepList *bsl); explicit QbsInstallStep(ProjectExplorer::BuildStepList *bsl);
~QbsInstallStep() override; ~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; qbs::InstallOptions installOptions() const;
QString installRoot() const; QString installRoot() const;
bool removeFirst() const; bool removeFirst() const;
@@ -65,6 +55,13 @@ signals:
void changed(); void changed();
private: 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; const QbsBuildConfiguration *buildConfig() const;
void installDone(bool success); void installDone(bool success);
void handleTaskStarted(const QString &desciption, int max); void handleTaskStarted(const QString &desciption, int max);
@@ -80,9 +77,9 @@ private:
qbs::InstallOptions m_qbsInstallOptions; qbs::InstallOptions m_qbsInstallOptions;
QFutureInterface<bool> *m_fi = nullptr;
qbs::InstallJob *m_job = nullptr; qbs::InstallJob *m_job = nullptr;
int m_progressBase; QString m_description;
int m_maxProgress;
bool m_showCompilerOutput = true; bool m_showCompilerOutput = true;
ProjectExplorer::IOutputParser *m_parser = nullptr; ProjectExplorer::IOutputParser *m_parser = nullptr;

View File

@@ -172,10 +172,10 @@ bool QmakeMakeStep::init()
return AbstractProcessStep::init(); return AbstractProcessStep::init();
} }
void QmakeMakeStep::run(QFutureInterface<bool> & fi) void QmakeMakeStep::doRun()
{ {
if (m_scriptTarget) { if (m_scriptTarget) {
reportRunResult(fi, true); emit finished(true);
return; return;
} }
@@ -183,11 +183,11 @@ void QmakeMakeStep::run(QFutureInterface<bool> & fi)
if (!ignoreReturnValue()) if (!ignoreReturnValue())
emit addOutput(tr("Cannot find Makefile. Check your build settings."), BuildStep::OutputFormat::NormalMessage); emit addOutput(tr("Cannot find Makefile. Check your build settings."), BuildStep::OutputFormat::NormalMessage);
const bool success = ignoreReturnValue(); const bool success = ignoreReturnValue();
reportRunResult(fi, success); emit finished(success);
return; return;
} }
AbstractProcessStep::run(fi); AbstractProcessStep::doRun();
} }
/// ///

View File

@@ -55,7 +55,7 @@ public:
QmakeBuildConfiguration *qmakeBuildConfiguration() const; QmakeBuildConfiguration *qmakeBuildConfiguration() const;
bool init() override; bool init() override;
void run(QFutureInterface<bool> &) override; void doRun() override;
private: private:
bool m_scriptTarget = false; bool m_scriptTarget = false;

View File

@@ -77,13 +77,6 @@ QMakeStep::QMakeStep(BuildStepList *bsl) : AbstractProcessStep(bsl, QMAKE_BS_ID)
{ {
//: QMakeStep default display name //: QMakeStep default display name
setDefaultDisplayName(tr("qmake")); setDefaultDisplayName(tr("qmake"));
connect(&m_inputWatcher, &QFutureWatcher<bool>::canceled,
this, [this]() {
if (m_commandFuture)
m_commandFuture->cancel();
});
connect(&m_commandWatcher, &QFutureWatcher<bool>::finished, this, &QMakeStep::runNextCommand);
} }
QmakeBuildConfiguration *QMakeStep::qmakeBuildConfiguration() const QmakeBuildConfiguration *QMakeStep::qmakeBuildConfiguration() const
@@ -172,9 +165,6 @@ QMakeStepConfig QMakeStep::deducedArguments() const
bool QMakeStep::init() bool QMakeStep::init()
{ {
if (m_commandFuture)
return false;
QmakeBuildConfiguration *qmakeBc = qmakeBuildConfiguration(); QmakeBuildConfiguration *qmakeBc = qmakeBuildConfiguration();
const BaseQtVersion *qtVersion = QtKitInformation::qtVersion(target()->kit()); const BaseQtVersion *qtVersion = QtKitInformation::qtVersion(target()->kit());
@@ -262,21 +252,16 @@ bool QMakeStep::init()
return AbstractProcessStep::init(); return AbstractProcessStep::init();
} }
void QMakeStep::run(QFutureInterface<bool> &fi) void QMakeStep::doRun()
{ {
m_inputFuture = fi;
m_inputWatcher.setFuture(m_inputFuture.future());
fi.setProgressRange(0, static_cast<int>(State::POST_PROCESS));
fi.setProgressValue(0);
if (m_scriptTemplate) { if (m_scriptTemplate) {
reportRunResult(fi, true); emit finished(true);
return; return;
} }
if (!m_needToRunQMake) { if (!m_needToRunQMake) {
emit addOutput(tr("Configuration unchanged, skipping qmake step."), BuildStep::OutputFormat::NormalMessage); emit addOutput(tr("Configuration unchanged, skipping qmake step."), BuildStep::OutputFormat::NormalMessage);
reportRunResult(fi, true); emit finished(true);
return; return;
} }
@@ -312,6 +297,17 @@ bool QMakeStep::processSucceeded(int exitCode, QProcess::ExitStatus status)
return result; return result;
} }
void QMakeStep::doCancel()
{
AbstractProcessStep::doCancel();
}
void QMakeStep::finish(bool success)
{
m_wasSuccess = success;
runNextCommand();
}
void QMakeStep::startOneCommand(const QString &command, const QString &args) void QMakeStep::startOneCommand(const QString &command, const QString &args)
{ {
ProcessParameters *pp = processParameters(); ProcessParameters *pp = processParameters();
@@ -319,31 +315,19 @@ void QMakeStep::startOneCommand(const QString &command, const QString &args)
pp->setArguments(args); pp->setArguments(args);
pp->resolveAll(); pp->resolveAll();
QTC_ASSERT(!m_commandFuture || m_commandFuture->future().isFinished(), return); AbstractProcessStep::doRun();
m_commandFuture.reset(new QFutureInterface<bool>);
m_commandWatcher.setFuture(m_commandFuture->future());
AbstractProcessStep::run(*m_commandFuture);
} }
void QMakeStep::runNextCommand() void QMakeStep::runNextCommand()
{ {
bool wasSuccess = true; if (isCanceled())
if (m_commandFuture) { m_wasSuccess = false;
if (m_commandFuture->isCanceled())
wasSuccess = false;
else if (m_commandFuture->isFinished())
wasSuccess = m_commandFuture->future().result();
else
wasSuccess = false; // should not happen
}
m_commandFuture.reset(); if (!m_wasSuccess)
if (!wasSuccess)
m_nextState = State::POST_PROCESS; m_nextState = State::POST_PROCESS;
m_inputFuture.setProgressValue(static_cast<int>(m_nextState)); emit progress(static_cast<int>(m_nextState) * 100 / static_cast<int>(State::POST_PROCESS),
QString());
switch (m_nextState) { switch (m_nextState) {
case State::IDLE: case State::IDLE:
@@ -364,8 +348,7 @@ void QMakeStep::runNextCommand()
return; return;
case State::POST_PROCESS: case State::POST_PROCESS:
m_nextState = State::IDLE; m_nextState = State::IDLE;
reportRunResult(m_inputFuture, wasSuccess); emit finished(m_wasSuccess);
m_inputFuture = QFutureInterface<bool>();
return; return;
} }
} }

View File

@@ -29,7 +29,6 @@
#include <projectexplorer/abstractprocessstep.h> #include <projectexplorer/abstractprocessstep.h>
#include <QStringList> #include <QStringList>
#include <QFutureWatcher>
#include <memory> #include <memory>
@@ -116,7 +115,7 @@ public:
QmakeBuildConfiguration *qmakeBuildConfiguration() const; QmakeBuildConfiguration *qmakeBuildConfiguration() const;
bool init() override; bool init() override;
void run(QFutureInterface<bool> &) override; void doRun() override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override; ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
void setForced(bool b); void setForced(bool b);
@@ -165,6 +164,9 @@ protected:
bool processSucceeded(int exitCode, QProcess::ExitStatus status) override; bool processSucceeded(int exitCode, QProcess::ExitStatus status) override;
private: private:
void doCancel() override;
void finish(bool success) override;
void startOneCommand(const QString &command, const QString &args); void startOneCommand(const QString &command, const QString &args);
void runNextCommand(); void runNextCommand();
@@ -176,13 +178,9 @@ private:
// Extra arguments for qmake. // Extra arguments for qmake.
QStringList m_extraArgs; QStringList m_extraArgs;
QFutureInterface<bool> m_inputFuture;
QFutureWatcher<bool> m_inputWatcher;
std::unique_ptr<QFutureInterface<bool>> m_commandFuture;
QFutureWatcher<bool> m_commandWatcher;
// last values // last values
enum class State { IDLE = 0, RUN_QMAKE, RUN_MAKE_QMAKE_ALL, POST_PROCESS }; enum class State { IDLE = 0, RUN_QMAKE, RUN_MAKE_QMAKE_ALL, POST_PROCESS };
bool m_wasSuccess = true;
State m_nextState = State::IDLE; State m_nextState = State::IDLE;
bool m_forced = false; bool m_forced = false;
bool m_needToRunQMake = false; // set in init(), read in run() bool m_needToRunQMake = false; // set in init(), read in run()

View File

@@ -40,7 +40,6 @@ class AbstractRemoteLinuxDeployStepPrivate
{ {
public: public:
bool hasError; bool hasError;
QFutureInterface<bool> future;
}; };
} // namespace Internal } // namespace Internal
@@ -48,7 +47,6 @@ public:
AbstractRemoteLinuxDeployStep::AbstractRemoteLinuxDeployStep(BuildStepList *bsl, Core::Id id) AbstractRemoteLinuxDeployStep::AbstractRemoteLinuxDeployStep(BuildStepList *bsl, Core::Id id)
: BuildStep(bsl, id), d(new Internal::AbstractRemoteLinuxDeployStepPrivate) : BuildStep(bsl, id), d(new Internal::AbstractRemoteLinuxDeployStepPrivate)
{ {
setRunInGuiThread(true);
} }
AbstractRemoteLinuxDeployStep::~AbstractRemoteLinuxDeployStep() AbstractRemoteLinuxDeployStep::~AbstractRemoteLinuxDeployStep()
@@ -79,7 +77,7 @@ bool AbstractRemoteLinuxDeployStep::init()
return canDeploy; return canDeploy;
} }
void AbstractRemoteLinuxDeployStep::run(QFutureInterface<bool> &fi) void AbstractRemoteLinuxDeployStep::doRun()
{ {
connect(deployService(), &AbstractRemoteLinuxDeployService::errorMessage, connect(deployService(), &AbstractRemoteLinuxDeployService::errorMessage,
this, &AbstractRemoteLinuxDeployStep::handleErrorMessage); this, &AbstractRemoteLinuxDeployStep::handleErrorMessage);
@@ -95,11 +93,10 @@ void AbstractRemoteLinuxDeployStep::run(QFutureInterface<bool> &fi)
this, &AbstractRemoteLinuxDeployStep::handleFinished); this, &AbstractRemoteLinuxDeployStep::handleFinished);
d->hasError = false; d->hasError = false;
d->future = fi;
deployService()->start(); deployService()->start();
} }
void AbstractRemoteLinuxDeployStep::cancel() void AbstractRemoteLinuxDeployStep::doCancel()
{ {
if (d->hasError) if (d->hasError)
return; return;
@@ -139,7 +136,7 @@ void AbstractRemoteLinuxDeployStep::handleFinished()
else else
emit addOutput(tr("Deploy step finished."), OutputFormat::NormalMessage); emit addOutput(tr("Deploy step finished."), OutputFormat::NormalMessage);
disconnect(deployService(), nullptr, this, nullptr); disconnect(deployService(), nullptr, this, nullptr);
reportRunResult(d->future, !d->hasError); emit finished(!d->hasError);
} }
void AbstractRemoteLinuxDeployStep::handleStdOutData(const QString &data) void AbstractRemoteLinuxDeployStep::handleStdOutData(const QString &data)

View File

@@ -42,15 +42,15 @@ class REMOTELINUX_EXPORT AbstractRemoteLinuxDeployStep : public ProjectExplorer:
public: public:
~AbstractRemoteLinuxDeployStep() override; ~AbstractRemoteLinuxDeployStep() override;
bool fromMap(const QVariantMap &map) override;
QVariantMap toMap() const override;
bool init() override;
void run(QFutureInterface<bool> &fi) override;
void cancel() override;
virtual AbstractRemoteLinuxDeployService *deployService() const = 0; virtual AbstractRemoteLinuxDeployService *deployService() const = 0;
protected: protected:
bool fromMap(const QVariantMap &map) override;
QVariantMap toMap() const override;
bool init() override;
void doRun() override;
void doCancel() override;
explicit AbstractRemoteLinuxDeployStep(ProjectExplorer::BuildStepList *bsl, Core::Id id); explicit AbstractRemoteLinuxDeployStep(ProjectExplorer::BuildStepList *bsl, Core::Id id);
virtual bool initInternal(QString *error = nullptr) = 0; virtual bool initInternal(QString *error = nullptr) = 0;

View File

@@ -94,32 +94,9 @@ bool TarPackageCreationStep::init()
return true; return true;
} }
void TarPackageCreationStep::run(QFutureInterface<bool> &fi) void TarPackageCreationStep::doRun()
{ {
setPackagingStarted(); runInThread([this] { return runImpl(); });
const QList<DeployableFile> &files = target()->deploymentData().allFiles();
if (m_incrementalDeploymentAspect->value()) {
m_files.clear();
for (const DeployableFile &file : files)
addNeededDeploymentFiles(file, target()->kit());
} else {
m_files = files;
}
const bool success = doPackage(fi);
setPackagingFinished(success);
if (success)
emit addOutput(tr("Packaging finished successfully."), OutputFormat::NormalMessage);
else
emit addOutput(tr("Packaging failed."), OutputFormat::ErrorMessage);
connect(BuildManager::instance(), &BuildManager::buildQueueFinished,
this, &TarPackageCreationStep::deployFinished);
reportRunResult(fi, success);
} }
void TarPackageCreationStep::addNeededDeploymentFiles( void TarPackageCreationStep::addNeededDeploymentFiles(
@@ -151,7 +128,7 @@ void TarPackageCreationStep::addNeededDeploymentFiles(
} }
} }
bool TarPackageCreationStep::doPackage(QFutureInterface<bool> &fi) bool TarPackageCreationStep::doPackage()
{ {
emit addOutput(tr("Creating tarball..."), OutputFormat::NormalMessage); emit addOutput(tr("Creating tarball..."), OutputFormat::NormalMessage);
if (!m_packagingNeeded) { if (!m_packagingNeeded) {
@@ -176,7 +153,7 @@ bool TarPackageCreationStep::doPackage(QFutureInterface<bool> &fi)
} }
QFileInfo fileInfo = d.localFilePath().toFileInfo(); QFileInfo fileInfo = d.localFilePath().toFileInfo();
if (!appendFile(tarFile, fileInfo, d.remoteDirectory() + QLatin1Char('/') if (!appendFile(tarFile, fileInfo, d.remoteDirectory() + QLatin1Char('/')
+ fileInfo.fileName(), fi)) { + fileInfo.fileName())) {
return false; return false;
} }
} }
@@ -192,7 +169,7 @@ bool TarPackageCreationStep::doPackage(QFutureInterface<bool> &fi)
} }
bool TarPackageCreationStep::appendFile(QFile &tarFile, const QFileInfo &fileInfo, bool TarPackageCreationStep::appendFile(QFile &tarFile, const QFileInfo &fileInfo,
const QString &remoteFilePath, const QFutureInterface<bool> &fi) const QString &remoteFilePath)
{ {
if (!writeHeader(tarFile, fileInfo, remoteFilePath)) if (!writeHeader(tarFile, fileInfo, remoteFilePath))
return false; return false;
@@ -202,7 +179,7 @@ bool TarPackageCreationStep::appendFile(QFile &tarFile, const QFileInfo &fileInf
dir.entryList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) { dir.entryList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
const QString thisLocalFilePath = dir.path() + QLatin1Char('/') + fileName; const QString thisLocalFilePath = dir.path() + QLatin1Char('/') + fileName;
const QString thisRemoteFilePath = remoteFilePath + QLatin1Char('/') + fileName; const QString thisRemoteFilePath = remoteFilePath + QLatin1Char('/') + fileName;
if (!appendFile(tarFile, QFileInfo(thisLocalFilePath), thisRemoteFilePath, fi)) if (!appendFile(tarFile, QFileInfo(thisLocalFilePath), thisRemoteFilePath))
return false; return false;
} }
return true; return true;
@@ -231,7 +208,7 @@ bool TarPackageCreationStep::appendFile(QFile &tarFile, const QFileInfo &fileInf
while (!file.atEnd() && file.error() == QFile::NoError && tarFile.error() == QFile::NoError) { while (!file.atEnd() && file.error() == QFile::NoError && tarFile.error() == QFile::NoError) {
const QByteArray data = file.read(chunkSize); const QByteArray data = file.read(chunkSize);
tarFile.write(data); tarFile.write(data);
if (fi.isCanceled()) if (isCanceled())
return false; return false;
} }
if (file.error() != QFile::NoError) { if (file.error() != QFile::NoError) {
@@ -339,6 +316,34 @@ QString TarPackageCreationStep::packageFileName() const
return project()->displayName() + QLatin1String(".tar"); return project()->displayName() + QLatin1String(".tar");
} }
bool TarPackageCreationStep::runImpl()
{
setPackagingStarted();
const QList<DeployableFile> &files = target()->deploymentData().allFiles();
if (m_incrementalDeploymentAspect->value()) {
m_files.clear();
for (const DeployableFile &file : files)
addNeededDeploymentFiles(file, target()->kit());
} else {
m_files = files;
}
const bool success = doPackage();
setPackagingFinished(success);
if (success)
emit addOutput(tr("Packaging finished successfully."), OutputFormat::NormalMessage);
else
emit addOutput(tr("Packaging failed."), OutputFormat::ErrorMessage);
connect(BuildManager::instance(), &BuildManager::buildQueueFinished,
this, &TarPackageCreationStep::deployFinished);
return success;
}
BuildStepConfigWidget *TarPackageCreationStep::createConfigWidget() BuildStepConfigWidget *TarPackageCreationStep::createConfigWidget()
{ {
auto widget = BuildStep::createConfigWidget(); auto widget = BuildStep::createConfigWidget();

View File

@@ -48,9 +48,6 @@ public:
static Core::Id stepId(); static Core::Id stepId();
static QString displayName(); static QString displayName();
bool init() override;
void run(QFutureInterface<bool> &fi) override;
void setIgnoreMissingFiles(bool ignoreMissingFiles); void setIgnoreMissingFiles(bool ignoreMissingFiles);
bool ignoreMissingFiles() const; bool ignoreMissingFiles() const;
@@ -58,6 +55,9 @@ public:
bool isIncrementalDeployment() const; bool isIncrementalDeployment() const;
private: private:
bool init() override;
void doRun() override;
void deployFinished(bool success); void deployFinished(bool success);
void addNeededDeploymentFiles(const ProjectExplorer::DeployableFile &deployable, void addNeededDeploymentFiles(const ProjectExplorer::DeployableFile &deployable,
@@ -69,9 +69,10 @@ private:
QString packageFileName() const override; QString packageFileName() const override;
bool doPackage(QFutureInterface<bool> &fi); bool runImpl();
bool doPackage();
bool appendFile(QFile &tarFile, const QFileInfo &fileInfo, bool appendFile(QFile &tarFile, const QFileInfo &fileInfo,
const QString &remoteFilePath, const QFutureInterface<bool> &fi); const QString &remoteFilePath);
bool writeHeader(QFile &tarFile, const QFileInfo &fileInfo, bool writeHeader(QFile &tarFile, const QFileInfo &fileInfo,
const QString &remoteFilePath); const QString &remoteFilePath);

View File

@@ -114,7 +114,7 @@ bool WinRtPackageDeploymentStep::init()
return AbstractProcessStep::init(); return AbstractProcessStep::init();
} }
void WinRtPackageDeploymentStep::run(QFutureInterface<bool> &fi) void WinRtPackageDeploymentStep::doRun()
{ {
const QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target()->kit()); const QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target()->kit());
if (!qt) if (!qt)
@@ -143,7 +143,7 @@ void WinRtPackageDeploymentStep::run(QFutureInterface<bool> &fi)
} }
} }
AbstractProcessStep::run(fi); AbstractProcessStep::doRun();
} }
bool WinRtPackageDeploymentStep::processSucceeded(int exitCode, QProcess::ExitStatus status) bool WinRtPackageDeploymentStep::processSucceeded(int exitCode, QProcess::ExitStatus status)

View File

@@ -38,18 +38,18 @@ class WinRtPackageDeploymentStep : public ProjectExplorer::AbstractProcessStep
public: public:
explicit WinRtPackageDeploymentStep(ProjectExplorer::BuildStepList *bsl); explicit WinRtPackageDeploymentStep(ProjectExplorer::BuildStepList *bsl);
bool init() override;
void run(QFutureInterface<bool> &fi) override;
bool processSucceeded(int exitCode, QProcess::ExitStatus status) override;
void stdOutput(const QString &line) override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
QString defaultWinDeployQtArguments() const; QString defaultWinDeployQtArguments() const;
void raiseError(const QString &errorMessage); void raiseError(const QString &errorMessage);
void raiseWarning(const QString &warningMessage); void raiseWarning(const QString &warningMessage);
private: private:
bool init() override;
void doRun() override;
bool processSucceeded(int exitCode, QProcess::ExitStatus status) override;
void stdOutput(const QString &line) override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
bool parseIconsAndExecutableFromManifest(QString manifestFileName, QStringList *items, QString *executable); bool parseIconsAndExecutableFromManifest(QString manifestFileName, QStringList *items, QString *executable);
ProjectExplorer::BaseStringAspect *m_argsAspect = nullptr; ProjectExplorer::BaseStringAspect *m_argsAspect = nullptr;