diff options
author | Joerg Bornemann <joerg.bornemann@qt.io> | 2016-11-11 09:39:32 +0100 |
---|---|---|
committer | Joerg Bornemann <joerg.bornemann@qt.io> | 2016-11-14 10:27:36 +0000 |
commit | 3992c478749a2256f13016a74200fc9d73158507 (patch) | |
tree | c6eac3ee66f9496ae79f726f23d61104081c209e /src | |
parent | bb07c8d8b6b5b554f649b703a3428eb062902803 (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.cpp | 21 | ||||
-rw-r--r-- | src/jomlib/dependencygraph.h | 5 | ||||
-rw-r--r-- | src/jomlib/targetexecutor.cpp | 30 |
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; |