summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@qt.io>2016-11-11 09:39:32 +0100
committerJoerg Bornemann <joerg.bornemann@qt.io>2016-11-14 10:27:36 +0000
commit3992c478749a2256f13016a74200fc9d73158507 (patch)
treec6eac3ee66f9496ae79f726f23d61104081c209e /src
parentbb07c8d8b6b5b554f649b703a3428eb062902803 (diff)
Fix "build unrelated targets on error" mode
With the /k option given, jom tried to build all targets, even targets that depended on failed targets. Thus it behaved the same as /i (ignore exit codes), which is wrong. Task-number: QTCREATORBUG-17131 Change-Id: I1dcbabbf423042de44222a600f7a1b8be1203f45 Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/jomlib/dependencygraph.cpp21
-rw-r--r--src/jomlib/dependencygraph.h5
-rw-r--r--src/jomlib/targetexecutor.cpp30
3 files changed, 46 insertions, 10 deletions
diff --git a/src/jomlib/dependencygraph.cpp b/src/jomlib/dependencygraph.cpp
index 382a13b..bf8cfbc 100644
--- a/src/jomlib/dependencygraph.cpp
+++ b/src/jomlib/dependencygraph.cpp
@@ -82,6 +82,24 @@ void DependencyGraph::build(DescriptionBlock* target)
//qDebug() << "\nFINISHED";
}
+void DependencyGraph::markParentsRecursivlyUnbuildable(DescriptionBlock *target)
+{
+ markParentsRecursivlyUnbuildable(m_nodeContainer.value(target));
+}
+
+bool DependencyGraph::isUnbuildable(DescriptionBlock *target) const
+{
+ return m_nodeContainer.value(target)->state == Node::Unbuildable;
+}
+
+void DependencyGraph::markParentsRecursivlyUnbuildable(Node *node)
+{
+ foreach (Node *parent, node->parents) {
+ parent->state = Node::Unbuildable;
+ markParentsRecursivlyUnbuildable(parent);
+ }
+}
+
bool DependencyGraph::isTargetUpToDate(DescriptionBlock* target)
{
FastFileInfo fi(target->targetName());
@@ -313,7 +331,8 @@ DescriptionBlock *DependencyGraph::findAvailableTarget(bool ignoreTimeStamps)
// return the first leaf that is not currently executed
foreach (Node *leaf, m_leaves) {
if (leaf->state != Node::ExecutingState) {
- leaf->state = Node::ExecutingState;
+ if (leaf->state != Node::Unbuildable)
+ leaf->state = Node::ExecutingState;
displayNodeBuildInfo(leaf, ignoreTimeStamps ? isTargetUpToDate(leaf->target) : false);
return leaf->target;
}
diff --git a/src/jomlib/dependencygraph.h b/src/jomlib/dependencygraph.h
index 89bc782..2ed92fc 100644
--- a/src/jomlib/dependencygraph.h
+++ b/src/jomlib/dependencygraph.h
@@ -40,6 +40,8 @@ public:
~DependencyGraph();
void build(DescriptionBlock* target);
+ void markParentsRecursivlyUnbuildable(DescriptionBlock *target);
+ bool isUnbuildable(DescriptionBlock *target) const;
bool isEmpty() const;
void removeLeaf(DescriptionBlock* target);
DescriptionBlock *findAvailableTarget(bool ignoreTimeStamps);
@@ -52,7 +54,7 @@ private:
struct Node
{
- enum State {UnknownState, ExecutingState};
+ enum State {UnknownState, ExecutingState, Unbuildable};
State state;
DescriptionBlock* target;
@@ -68,6 +70,7 @@ private:
void internalDump(Node* node, QString& indent);
void internalDotDump(Node* node, const QString& parent);
void displayNodeBuildInfo(Node* node, bool isUpToDate);
+ static void markParentsRecursivlyUnbuildable(Node *node);
private:
Node* m_root;
diff --git a/src/jomlib/targetexecutor.cpp b/src/jomlib/targetexecutor.cpp
index 0f20d62..9345939 100644
--- a/src/jomlib/targetexecutor.cpp
+++ b/src/jomlib/targetexecutor.cpp
@@ -203,18 +203,35 @@ void TargetExecutor::findNextTarget()
{
forever {
m_nextTarget = m_depgraph->findAvailableTarget(m_makefile->options()->buildAllTargets);
- if (m_nextTarget && m_nextTarget->m_commands.isEmpty()) {
- // Short cut for targets without commands.
- m_depgraph->removeLeaf(m_nextTarget);
- } else {
- return;
+ if (m_nextTarget) {
+ if (m_nextTarget->m_commands.isEmpty()) {
+ // Short cut for targets without commands.
+ m_depgraph->removeLeaf(m_nextTarget);
+ continue;
+ } else if (m_makefile->options()->buildUnrelatedTargetsOnError
+ && m_depgraph->isUnbuildable(m_nextTarget)) {
+ fprintf(stderr, "jom: Target '%s' cannot be built due to failed dependencies.\n",
+ qPrintable(m_nextTarget->targetName()));
+ m_depgraph->removeLeaf(m_nextTarget);
+ continue;
+ }
}
+ return;
}
}
void TargetExecutor::onChildFinished(CommandExecutor* executor, bool commandFailed)
{
Q_CHECK_PTR(executor->target());
+ if (commandFailed) {
+ m_allCommandsSuccessfullyExecuted = false;
+ if (m_makefile->options()->buildUnrelatedTargetsOnError) {
+ // Recursively mark all parents of this node as unbuildable due to unsatisfied
+ // dependencies. This must happen before removing the node from the build graph.
+ m_depgraph->markParentsRecursivlyUnbuildable(executor->target());
+ fputs("jom: Option /K specified. Continuing.\n", stderr);
+ }
+ }
FastFileInfo::clearCacheForFile(executor->target()->targetName());
m_depgraph->removeLeaf(executor->target());
if (m_jobAcquisitionCount > 0) {
@@ -235,9 +252,6 @@ void TargetExecutor::onChildFinished(CommandExecutor* executor, bool commandFail
m_availableProcesses.first()->setBufferedOutput(false);
}
- if (commandFailed)
- m_allCommandsSuccessfullyExecuted = false;
-
bool abortMakeProcess = commandFailed && !m_makefile->options()->buildUnrelatedTargetsOnError;
if (abortMakeProcess) {
m_bAborted = true;