BuildManager: Employ task tree for running

Task-number: QTCREATORBUG-29168
Change-Id: Ibdc1882f3a019855bc06e7a7e49e2ae6e3bf17f1
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
Jarek Kobus
2023-07-17 08:07:30 +02:00
parent 86e11befca
commit a140a93067
3 changed files with 202 additions and 241 deletions

View File

@@ -260,31 +260,23 @@ public:
Internal::CompileOutputWindow *m_outputWindow = nullptr; Internal::CompileOutputWindow *m_outputWindow = nullptr;
Internal::TaskWindow *m_taskWindow = nullptr; Internal::TaskWindow *m_taskWindow = nullptr;
QMetaObject::Connection m_scheduledBuild; QList<BuildItem> m_pendingQueue;
QList<BuildItem> m_buildQueue; QList<BuildItem> m_buildQueue;
int m_progress = 0; int m_progress = 0;
int m_maxProgress = 0; int m_maxProgress = 0;
bool m_poppedUpTaskWindow = false; bool m_poppedUpTaskWindow = false;
bool m_running = false;
bool m_isDeploying = false; bool m_isDeploying = false;
// is set to true while canceling, so that nextBuildStep knows that the BuildStep finished because of canceling
bool m_skipDisabled = false;
bool m_canceling = false;
bool m_lastStepSucceeded = true;
bool m_allStepsSucceeded = true;
BuildStep *m_currentBuildStep = nullptr;
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;
QHash<Target *, int> m_activeBuildStepsPerTarget; QHash<Target *, int> m_activeBuildStepsPerTarget;
QHash<ProjectConfiguration *, int> m_activeBuildStepsPerProjectConfiguration; QHash<ProjectConfiguration *, int> m_activeBuildStepsPerProjectConfiguration;
Project *m_previousBuildStepProject = nullptr;
// Progress reporting to the progress manager // Progress reporting to the progress manager
QFutureInterface<void> *m_progressFutureInterface = nullptr; QFutureInterface<void> *m_progressFutureInterface = nullptr;
QFutureWatcher<void> m_progressWatcher; QFutureWatcher<void> m_progressWatcher;
QPointer<FutureProgress> m_futureProgress; QPointer<FutureProgress> m_futureProgress;
std::unique_ptr<TaskTree> m_taskTree;
QElapsedTimer m_elapsed; QElapsedTimer m_elapsed;
}; };
@@ -475,7 +467,7 @@ void BuildManager::aboutToRemoveProject(Project *p)
bool BuildManager::isBuilding() bool BuildManager::isBuilding()
{ {
// we are building even if we are not running yet // we are building even if we are not running yet
return !d->m_buildQueue.isEmpty() || d->m_running; return !d->m_pendingQueue.isEmpty() || !d->m_buildQueue.isEmpty();
} }
bool BuildManager::isDeploying() bool BuildManager::isDeploying()
@@ -506,20 +498,51 @@ QString BuildManager::displayNameForStepId(Id stepId)
return Tr::tr("Build"); return Tr::tr("Build");
} }
void BuildManager::cleanupBuild()
{
const QList<BuildItem> buildQueue = d->m_buildQueue;
d->m_buildQueue.clear();
for (const BuildItem &item : buildQueue) {
decrementActiveBuildSteps(item.buildStep);
disconnect(item.buildStep, nullptr, m_instance, nullptr);
}
if (d->m_progressFutureInterface) {
d->m_progressFutureInterface->reportFinished();
d->m_progressWatcher.setFuture(QFuture<void>());
delete d->m_progressFutureInterface;
d->m_progressFutureInterface = nullptr;
}
d->m_progress = 0;
d->m_maxProgress = 0;
d->m_futureProgress = nullptr;
}
void BuildManager::cancel() void BuildManager::cancel()
{ {
if (d->m_scheduledBuild) { if (!d->m_taskTree)
disconnect(d->m_scheduledBuild);
d->m_scheduledBuild = {};
clearBuildQueue();
return; return;
d->m_taskTree.reset();
const QList<BuildItem> pendingQueue = d->m_pendingQueue;
d->m_pendingQueue.clear();
for (const BuildItem &item : pendingQueue) {
decrementActiveBuildSteps(item.buildStep);
disconnect(item.buildStep, nullptr, m_instance, nullptr);
} }
if (d->m_running) {
if (d->m_canceling) d->m_poppedUpTaskWindow = false;
return; d->m_isDeploying = false;
d->m_canceling = true;
d->m_currentBuildStep->cancel(); if (d->m_progressFutureInterface) {
d->m_progressFutureInterface->setProgressValueAndText(100 * d->m_progress,
Tr::tr("Build/Deployment canceled"));
d->m_progressFutureInterface->reportCanceled();
} }
cleanupBuild();
addToOutputWindow(Tr::tr("Canceled build/deployment."), BuildStep::OutputFormat::ErrorMessage);
emit m_instance->buildQueueFinished(false);
} }
void BuildManager::updateTaskCount() void BuildManager::updateTaskCount()
@@ -541,39 +564,6 @@ void BuildManager::finish()
QApplication::alert(ICore::dialogParent(), 3000); QApplication::alert(ICore::dialogParent(), 3000);
} }
void BuildManager::emitCancelMessage()
{
addToOutputWindow(Tr::tr("Canceled build/deployment."), BuildStep::OutputFormat::ErrorMessage);
}
void BuildManager::clearBuildQueue()
{
for (const BuildItem &item : std::as_const(d->m_buildQueue)) {
decrementActiveBuildSteps(item.buildStep);
disconnectOutput(item.buildStep);
}
d->m_buildQueue.clear();
d->m_running = false;
d->m_poppedUpTaskWindow = false;
d->m_isDeploying = false;
d->m_previousBuildStepProject = nullptr;
d->m_currentBuildStep = nullptr;
if (d->m_progressFutureInterface) {
d->m_progressFutureInterface->reportCanceled();
d->m_progressFutureInterface->reportFinished();
d->m_progressWatcher.setFuture(QFuture<void>());
delete d->m_progressFutureInterface;
d->m_progressFutureInterface = nullptr;
}
d->m_futureProgress = nullptr;
d->m_maxProgress = 0;
emit m_instance->buildQueueFinished(false);
}
void BuildManager::toggleOutputWindow() void BuildManager::toggleOutputWindow()
{ {
d->m_outputWindow->toggle(IOutputPane::ModeSwitch | IOutputPane::WithFocus); d->m_outputWindow->toggle(IOutputPane::ModeSwitch | IOutputPane::WithFocus);
@@ -600,58 +590,137 @@ bool BuildManager::tasksAvailable()
void BuildManager::startBuildQueue() void BuildManager::startBuildQueue()
{ {
if (d->m_buildQueue.isEmpty()) { if (compileOutputSettings().popUp())
emit m_instance->buildQueueFinished(true); d->m_outputWindow->popup(IOutputPane::NoModeSwitch);
return;
}
const auto onAwaiterSetup = [](QSet<BuildSystem *> &buildSystems) {
// Delay if any of the involved build systems are currently parsing. // Delay if any of the involved build systems are currently parsing.
const auto buildSystems = transform<QSet<BuildSystem *>>(d->m_buildQueue, buildSystems = transform<QSet<BuildSystem *>>(
[](const BuildItem &item) { return item.buildStep->buildSystem(); }); d->m_buildQueue, [](const BuildItem &item) { return item.buildStep->buildSystem(); });
for (const BuildSystem * const bs : buildSystems) { };
if (!bs || !bs->isParsing())
continue; const GroupItem abortPolicy
d->m_scheduledBuild = QObject::connect(bs, &BuildSystem::parsingFinished, = ProjectExplorerPlugin::projectExplorerSettings().abortBuildAllOnError
BuildManager::instance(), ? stopOnError : continueOnError;
[](bool parsingSuccess) {
if (!d->m_scheduledBuild) QList<GroupItem> topLevel { abortPolicy, ParserAwaiterTask(onAwaiterSetup) };
return; Project *lastProject = nullptr;
QObject::disconnect(d->m_scheduledBuild); Target *lastTarget = nullptr;
d->m_scheduledBuild = {}; QList<GroupItem> targetTasks;
if (parsingSuccess) d->m_progress = 0;
startBuildQueue(); d->m_maxProgress = 0;
else
clearBuildQueue(); for (const BuildItem &item : std::as_const(d->m_buildQueue)) {
}, Qt::QueuedConnection); BuildStep *buildStep = item.buildStep;
return; Target *target = buildStep->target();
if (lastTarget != target) {
if (!targetTasks.isEmpty())
topLevel.append(Group(targetTasks));
targetTasks.clear();
lastTarget = target;
} }
if (!d->m_running) { Project *project = buildStep->project();
d->m_elapsed.start(); if (lastProject != project) {
targetTasks.append(Sync([projectName = buildStep->project()->displayName()] {
addToOutputWindow(Tr::tr("Running steps for project %1...")
.arg(projectName), BuildStep::OutputFormat::NormalMessage);
}));
lastProject = project;
}
if (!item.enabled) {
targetTasks.append(Sync([name = buildStep->displayName()] {
addToOutputWindow(Tr::tr("Skipping disabled step %1.")
.arg(name), BuildStep::OutputFormat::NormalMessage);
}));
continue;
}
++d->m_maxProgress;
const auto onRecipeSetup = [buildStep, name = item.name] {
d->m_outputWindow->reset();
buildStep->setupOutputFormatter(d->m_outputWindow->outputFormatter());
connect(buildStep, &BuildStep::progress, instance(), &BuildManager::progressChanged);
if (d->m_futureProgress)
d->m_futureProgress.data()->setTitle(name);
};
const auto onRecipeDone = [buildStep] {
disconnect(buildStep, &BuildStep::progress, instance(), nullptr);
d->m_outputWindow->flush();
++d->m_progress;
d->m_progressFutureInterface->setProgressValueAndText(
100 * d->m_progress, msgProgress(d->m_progress, d->m_maxProgress));
};
const auto onRecipeError = [buildStep, target, onRecipeDone] {
onRecipeDone();
const QString projectName = buildStep->project()->displayName();
const QString targetName = target->displayName();
addToOutputWindow(Tr::tr("Error while building/deploying project %1 (kit: %2)")
.arg(projectName, targetName), BuildStep::OutputFormat::Stderr);
const Tasks kitTasks = target->kit()->validate();
if (!kitTasks.isEmpty()) {
addToOutputWindow(Tr::tr("The kit %1 has configuration issues which might "
"be the root cause for this problem.")
.arg(targetName), BuildStep::OutputFormat::Stderr);
}
addToOutputWindow(Tr::tr("When executing step \"%1\"")
.arg(buildStep->displayName()), BuildStep::OutputFormat::Stderr);
};
const Group recipeGroup {
onGroupSetup(onRecipeSetup),
buildStep->runRecipe(),
onGroupDone(onRecipeDone),
onGroupError(onRecipeError),
};
targetTasks.append(recipeGroup);
}
if (!targetTasks.isEmpty())
topLevel.append(Group(targetTasks));
d->m_taskTree.reset(new TaskTree(Group{topLevel}));
const auto endHandler = [](bool success) {
d->m_taskTree.release()->deleteLater();
if (!success && d->m_progressFutureInterface)
d->m_progressFutureInterface->reportCanceled();
cleanupBuild();
if (d->m_pendingQueue.isEmpty()) {
d->m_poppedUpTaskWindow = false;
d->m_isDeploying = false;
}
emit m_instance->buildQueueFinished(success);
if (!d->m_pendingQueue.isEmpty()) {
d->m_buildQueue = d->m_pendingQueue;
d->m_pendingQueue.clear();
startBuildQueue();
}
};
connect(d->m_taskTree.get(), &TaskTree::done, instance(), [endHandler] { endHandler(true); });
connect(d->m_taskTree.get(), &TaskTree::errorOccurred, instance(),
[endHandler] { endHandler(false); });
// Progress Reporting // Progress Reporting
d->m_progressFutureInterface = new QFutureInterface<void>; d->m_progressFutureInterface = new QFutureInterface<void>;
d->m_progressWatcher.setFuture(d->m_progressFutureInterface->future()); d->m_progressWatcher.setFuture(d->m_progressFutureInterface->future());
ProgressManager::setApplicationLabel(QString()); ProgressManager::setApplicationLabel({});
d->m_futureProgress = ProgressManager::addTask(d->m_progressFutureInterface->future(), d->m_futureProgress = ProgressManager::addTask(d->m_progressFutureInterface->future(),
QString(), "ProjectExplorer.Task.Build", {}, "ProjectExplorer.Task.Build",
ProgressManager::KeepOnFinish | ProgressManager::ShowInApplicationIcon); ProgressManager::KeepOnFinish | ProgressManager::ShowInApplicationIcon);
connect(d->m_futureProgress.data(), &FutureProgress::clicked, connect(d->m_futureProgress.data(), &FutureProgress::clicked,
m_instance, &BuildManager::showBuildResults); m_instance, &BuildManager::showBuildResults);
d->m_futureProgress.data()->setWidget(new Internal::BuildProgress(d->m_taskWindow)); d->m_futureProgress.data()->setWidget(new BuildProgress(d->m_taskWindow));
d->m_futureProgress.data()->setStatusBarWidget(new Internal::BuildProgress(d->m_taskWindow, d->m_futureProgress.data()->setStatusBarWidget(new BuildProgress(d->m_taskWindow,
Qt::Horizontal)); Qt::Horizontal));
d->m_progress = 0;
d->m_progressFutureInterface->setProgressRange(0, d->m_maxProgress * 100); d->m_progressFutureInterface->setProgressRange(0, d->m_maxProgress * 100);
d->m_running = true;
d->m_allStepsSucceeded = true;
d->m_progressFutureInterface->reportStarted(); d->m_progressFutureInterface->reportStarted();
nextStep();
} else { d->m_elapsed.start();
// Already running d->m_taskTree->start();
d->m_progressFutureInterface->setProgressRange(0, d->m_maxProgress * 100);
d->m_progressFutureInterface->setProgressValueAndText(d->m_progress*100, msgProgress(d->m_progress, d->m_maxProgress));
}
} }
void BuildManager::showBuildResults() void BuildManager::showBuildResults()
@@ -684,127 +753,15 @@ void BuildManager::addToOutputWindow(const QString &string, BuildStep::OutputFor
d->m_outputWindow->appendText(stringToWrite, format); d->m_outputWindow->appendText(stringToWrite, format);
} }
void BuildManager::nextBuildQueue()
{
d->m_outputWindow->flush();
disconnectOutput(d->m_currentBuildStep);
decrementActiveBuildSteps(d->m_currentBuildStep);
if (d->m_canceling) {
d->m_canceling = false;
QTimer::singleShot(0, m_instance, &BuildManager::emitCancelMessage);
//TODO NBS fix in qtconcurrent
d->m_progressFutureInterface->setProgressValueAndText(d->m_progress*100,
Tr::tr("Build/Deployment canceled"));
clearBuildQueue();
return;
}
if (!d->m_skipDisabled)
++d->m_progress;
d->m_progressFutureInterface->setProgressValueAndText(d->m_progress*100, msgProgress(d->m_progress, d->m_maxProgress));
const bool success = d->m_skipDisabled || d->m_lastStepSucceeded;
if (success) {
nextStep();
} else {
// Build Failure
d->m_allStepsSucceeded = false;
Target *t = d->m_currentBuildStep->target();
const QString projectName = d->m_currentBuildStep->project()->displayName();
const QString targetName = t->displayName();
addToOutputWindow(Tr::tr("Error while building/deploying project %1 (kit: %2)").arg(projectName, targetName), BuildStep::OutputFormat::Stderr);
const Tasks kitTasks = t->kit()->validate();
if (!kitTasks.isEmpty()) {
addToOutputWindow(Tr::tr("The kit %1 has configuration issues which might be the root cause for this problem.")
.arg(targetName), BuildStep::OutputFormat::Stderr);
}
addToOutputWindow(Tr::tr("When executing step \"%1\"").arg(d->m_currentBuildStep->displayName()), BuildStep::OutputFormat::Stderr);
bool abort = ProjectExplorerPlugin::projectExplorerSettings().abortBuildAllOnError;
if (!abort) {
while (!d->m_buildQueue.isEmpty()
&& d->m_buildQueue.front().buildStep->target() == t) {
BuildStep * const nextStepForFailedTarget = d->m_buildQueue.takeFirst().buildStep;
disconnectOutput(nextStepForFailedTarget);
decrementActiveBuildSteps(nextStepForFailedTarget);
}
if (d->m_buildQueue.isEmpty())
abort = true;
}
if (abort) {
// NBS TODO fix in qtconcurrent
d->m_progressFutureInterface->setProgressValueAndText(d->m_progress * 100,
Tr::tr("Error while building/deploying project %1 (kit: %2)")
.arg(projectName, targetName));
clearBuildQueue();
} else {
nextStep();
}
}
}
void BuildManager::progressChanged(int percent, const QString &text) void BuildManager::progressChanged(int percent, const QString &text)
{ {
if (d->m_progressFutureInterface) if (d->m_progressFutureInterface)
d->m_progressFutureInterface->setProgressValueAndText(percent + 100 * d->m_progress, text); d->m_progressFutureInterface->setProgressValueAndText(percent + 100 * d->m_progress, text);
} }
void BuildManager::nextStep()
{
if (!d->m_buildQueue.empty()) {
const BuildItem item = d->m_buildQueue.takeFirst();
d->m_currentBuildStep = item.buildStep;
d->m_skipDisabled = !item.enabled;
if (d->m_futureProgress)
d->m_futureProgress.data()->setTitle(item.name);
if (d->m_currentBuildStep->project() != d->m_previousBuildStepProject) {
const QString projectName = d->m_currentBuildStep->project()->displayName();
addToOutputWindow(Tr::tr("Running steps for project %1...")
.arg(projectName), BuildStep::OutputFormat::NormalMessage);
d->m_previousBuildStepProject = d->m_currentBuildStep->project();
}
if (d->m_skipDisabled) {
addToOutputWindow(Tr::tr("Skipping disabled step %1.")
.arg(d->m_currentBuildStep->displayName()), BuildStep::OutputFormat::NormalMessage);
nextBuildQueue();
return;
}
static const auto finishedHandler = [](bool success) {
d->m_outputWindow->flush();
d->m_lastStepSucceeded = success;
disconnect(d->m_currentBuildStep, nullptr, instance(), nullptr);
BuildManager::nextBuildQueue();
};
connect(d->m_currentBuildStep, &BuildStep::finished, instance(), finishedHandler);
connect(d->m_currentBuildStep, &BuildStep::progress,
instance(), &BuildManager::progressChanged);
d->m_outputWindow->reset();
d->m_currentBuildStep->setupOutputFormatter(d->m_outputWindow->outputFormatter());
d->m_currentBuildStep->run();
} else {
d->m_running = false;
d->m_poppedUpTaskWindow = false;
d->m_isDeploying = false;
d->m_previousBuildStepProject = nullptr;
d->m_progressFutureInterface->reportFinished();
d->m_progressWatcher.setFuture(QFuture<void>());
d->m_currentBuildStep = nullptr;
delete d->m_progressFutureInterface;
d->m_progressFutureInterface = nullptr;
d->m_maxProgress = 0;
emit m_instance->buildQueueFinished(d->m_allStepsSucceeded);
}
}
bool BuildManager::buildQueueAppend(const QList<BuildItem> &items, const QStringList &preambleMessage) bool BuildManager::buildQueueAppend(const QList<BuildItem> &items, const QStringList &preambleMessage)
{ {
if (!d->m_running) { if (!d->m_taskTree) {
d->m_outputWindow->clearContents(); d->m_outputWindow->clearContents();
if (ProjectExplorerPlugin::projectExplorerSettings().clearIssuesOnRebuild) { if (ProjectExplorerPlugin::projectExplorerSettings().clearIssuesOnRebuild) {
TaskHub::clearTasks(Constants::TASK_CATEGORY_COMPILE); TaskHub::clearTasks(Constants::TASK_CATEGORY_COMPILE);
@@ -819,33 +776,45 @@ bool BuildManager::buildQueueAppend(const QList<BuildItem> &items, const QString
QList<BuildStep *> connectedSteps; QList<BuildStep *> connectedSteps;
int enabledCount = 0; int enabledCount = 0;
for (const BuildItem &item : items) { for (const BuildItem &item : items) {
connect(item.buildStep, &BuildStep::addTask, m_instance, &BuildManager::addToTaskWindow); BuildStep *buildStep = item.buildStep;
connect(item.buildStep, &BuildStep::addOutput, m_instance, &BuildManager::addToOutputWindow); connect(buildStep, &BuildStep::addTask, m_instance, &BuildManager::addToTaskWindow);
connectedSteps.append(item.buildStep); connect(buildStep, &BuildStep::addOutput, m_instance, &BuildManager::addToOutputWindow);
connectedSteps.append(buildStep);
if (!item.enabled) if (!item.enabled)
continue; continue;
++enabledCount; ++enabledCount;
if (item.buildStep->init()) if (!isBuilding(buildStep) && buildStep->init())
continue; continue;
// init() failed, print something for the user... // init() failed, print something for the user...
const QString projectName = item.buildStep->project()->displayName(); const QString projectName = buildStep->project()->displayName();
const QString targetName = item.buildStep->target()->displayName(); const QString targetName = buildStep->target()->displayName();
addToOutputWindow(Tr::tr("Error while building/deploying project %1 (kit: %2)") addToOutputWindow(Tr::tr("Error while building/deploying project %1 (kit: %2)")
.arg(projectName, targetName), BuildStep::OutputFormat::Stderr); .arg(projectName, targetName), BuildStep::OutputFormat::Stderr);
addToOutputWindow(Tr::tr("When executing step \"%1\"") addToOutputWindow(Tr::tr("When executing step \"%1\"")
.arg(item.buildStep->displayName()), BuildStep::OutputFormat::Stderr); .arg(buildStep->displayName()), BuildStep::OutputFormat::Stderr);
for (BuildStep *buildStep : std::as_const(connectedSteps)) for (BuildStep *buildStep : std::as_const(connectedSteps))
disconnectOutput(buildStep); connect(buildStep, nullptr, m_instance, nullptr);
d->m_outputWindow->popup(IOutputPane::NoModeSwitch); d->m_outputWindow->popup(IOutputPane::NoModeSwitch);
return false; return false;
} }
d->m_buildQueue << items; if (d->m_taskTree)
d->m_maxProgress += enabledCount; d->m_pendingQueue << items;
for (const BuildItem &item : items) else
incrementActiveBuildSteps(item.buildStep); d->m_buildQueue = items;
if (d->m_buildQueue.isEmpty() && d->m_pendingQueue.isEmpty()) {
if (compileOutputSettings().popUp()) if (compileOutputSettings().popUp())
d->m_outputWindow->popup(IOutputPane::NoModeSwitch); d->m_outputWindow->popup(IOutputPane::NoModeSwitch);
emit m_instance->buildQueueFinished(true);
return true;
}
for (const BuildItem &item : items)
incrementActiveBuildSteps(item.buildStep);
if (!d->m_taskTree)
startBuildQueue(); startBuildQueue();
return true; return true;
} }
@@ -857,6 +826,7 @@ bool BuildManager::buildList(BuildStepList *bsl)
bool BuildManager::buildLists(const QList<BuildStepList *> &bsls, const QStringList &preambleMessage) bool BuildManager::buildLists(const QList<BuildStepList *> &bsls, const QStringList &preambleMessage)
{ {
const bool wasDeploying = d->m_isDeploying;
QList<BuildItem> buildItems; QList<BuildItem> buildItems;
for (BuildStepList *list : bsls) { for (BuildStepList *list : bsls) {
const QString name = displayNameForStepId(list->id()); const QString name = displayNameForStepId(list->id());
@@ -869,7 +839,7 @@ bool BuildManager::buildLists(const QList<BuildStepList *> &bsls, const QStringL
if (buildQueueAppend(buildItems, preambleMessage)) if (buildQueueAppend(buildItems, preambleMessage))
return true; return true;
d->m_isDeploying = false; d->m_isDeploying = wasDeploying;
return false; return false;
} }
@@ -905,8 +875,8 @@ bool BuildManager::isBuilding(const ProjectConfiguration *p)
bool BuildManager::isBuilding(BuildStep *step) bool BuildManager::isBuilding(BuildStep *step)
{ {
return (d->m_currentBuildStep == step) || Utils::anyOf( const auto checker = [step](const BuildItem &item) { return item.buildStep == step; };
d->m_buildQueue, [step](const BuildItem &item) { return item.buildStep == step; }); return Utils::anyOf(d->m_buildQueue, checker) || Utils::anyOf(d->m_pendingQueue, checker);
} }
template <class T> bool increment(QHash<T *, int> &hash, T *key) template <class T> bool increment(QHash<T *, int> &hash, T *key)
@@ -956,10 +926,4 @@ void BuildManager::decrementActiveBuildSteps(BuildStep *bs)
emit m_instance->buildStateChanged(bs->project()); emit m_instance->buildStateChanged(bs->project());
} }
void BuildManager::disconnectOutput(BuildStep *bs)
{
disconnect(bs, &BuildStep::addTask, m_instance, nullptr);
disconnect(bs, &BuildStep::addOutput, m_instance, nullptr);
}
} // namespace ProjectExplorer } // namespace ProjectExplorer

View File

@@ -78,25 +78,21 @@ signals:
void buildQueueFinished(bool success); void buildQueueFinished(bool success);
private: private:
static void cleanupBuild();
static void addToTaskWindow(const ProjectExplorer::Task &task, int linkedOutputLines, int skipLines); static void addToTaskWindow(const ProjectExplorer::Task &task, int linkedOutputLines, int skipLines);
static void addToOutputWindow(const QString &string, BuildStep::OutputFormat format, static void addToOutputWindow(const QString &string, BuildStep::OutputFormat format,
BuildStep::OutputNewlineSetting newlineSettings = BuildStep::DoAppendNewline); BuildStep::OutputNewlineSetting newlineSettings = BuildStep::DoAppendNewline);
static void nextBuildQueue();
static void progressChanged(int percent, const QString &text); static void progressChanged(int percent, const QString &text);
static void emitCancelMessage();
static void showBuildResults(); static void showBuildResults();
static void updateTaskCount(); static void updateTaskCount();
static void finish(); static void finish();
static void startBuildQueue(); static void startBuildQueue();
static void nextStep();
static void clearBuildQueue();
static bool buildQueueAppend(const QList<BuildItem> &items, static bool buildQueueAppend(const QList<BuildItem> &items,
const QStringList &preambleMessage = {}); const QStringList &preambleMessage = {});
static void incrementActiveBuildSteps(BuildStep *bs); static void incrementActiveBuildSteps(BuildStep *bs);
static void decrementActiveBuildSteps(BuildStep *bs); static void decrementActiveBuildSteps(BuildStep *bs);
static void disconnectOutput(BuildStep *bs);
}; };
} // namespace ProjectExplorer } // namespace ProjectExplorer

View File

@@ -132,6 +132,7 @@ protected:
private: private:
using ProjectConfiguration::parent; using ProjectConfiguration::parent;
friend class BuildManager;
virtual Tasking::GroupItem runRecipe() = 0; virtual Tasking::GroupItem runRecipe() = 0;
BuildStepList * const m_stepList; BuildStepList * const m_stepList;