summaryrefslogtreecommitdiff
path: root/src/graph.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/graph.cc')
-rw-r--r--src/graph.cc66
1 files changed, 59 insertions, 7 deletions
diff --git a/src/graph.cc b/src/graph.cc
index c875d3b..8d58587 100644
--- a/src/graph.cc
+++ b/src/graph.cc
@@ -15,6 +15,7 @@
#include "graph.h"
#include <algorithm>
+#include <deque>
#include <assert.h>
#include <stdio.h>
@@ -46,13 +47,42 @@ void Node::UpdatePhonyMtime(TimeStamp mtime) {
}
}
-bool DependencyScan::RecomputeDirty(Node* node, string* err) {
- vector<Node*> stack;
- return RecomputeDirty(node, &stack, err);
+bool DependencyScan::RecomputeDirty(Node* initial_node,
+ std::vector<Node*>* validation_nodes,
+ string* err) {
+ std::vector<Node*> stack;
+ std::vector<Node*> new_validation_nodes;
+
+ std::deque<Node*> nodes(1, initial_node);
+
+ // RecomputeNodeDirty might return new validation nodes that need to be
+ // checked for dirty state, keep a queue of nodes to visit.
+ while (!nodes.empty()) {
+ Node* node = nodes.front();
+ nodes.pop_front();
+
+ stack.clear();
+ new_validation_nodes.clear();
+
+ if (!RecomputeNodeDirty(node, &stack, &new_validation_nodes, err))
+ return false;
+ nodes.insert(nodes.end(), new_validation_nodes.begin(),
+ new_validation_nodes.end());
+ if (!new_validation_nodes.empty()) {
+ assert(validation_nodes &&
+ "validations require RecomputeDirty to be called with validation_nodes");
+ validation_nodes->insert(validation_nodes->end(),
+ new_validation_nodes.begin(),
+ new_validation_nodes.end());
+ }
+ }
+
+ return true;
}
-bool DependencyScan::RecomputeDirty(Node* node, vector<Node*>* stack,
- string* err) {
+bool DependencyScan::RecomputeNodeDirty(Node* node, std::vector<Node*>* stack,
+ std::vector<Node*>* validation_nodes,
+ string* err) {
Edge* edge = node->in_edge();
if (!edge) {
// If we already visited this leaf node then we are done.
@@ -96,7 +126,7 @@ bool DependencyScan::RecomputeDirty(Node* node, vector<Node*>* stack,
// Later during the build the dyndep file will become ready and be
// loaded to update this edge before it can possibly be scheduled.
if (edge->dyndep_ && edge->dyndep_->dyndep_pending()) {
- if (!RecomputeDirty(edge->dyndep_, stack, err))
+ if (!RecomputeNodeDirty(edge->dyndep_, stack, validation_nodes, err))
return false;
if (!edge->dyndep_->in_edge() ||
@@ -127,12 +157,20 @@ bool DependencyScan::RecomputeDirty(Node* node, vector<Node*>* stack,
}
}
+ // Store any validation nodes from the edge for adding to the initial
+ // nodes. Don't recurse into them, that would trigger the dependency
+ // cycle detector if the validation node depends on this node.
+ // RecomputeDirty will add the validation nodes to the initial nodes
+ // and recurse into them.
+ validation_nodes->insert(validation_nodes->end(),
+ edge->validations_.begin(), edge->validations_.end());
+
// Visit all inputs; we're dirty if any of the inputs are dirty.
Node* most_recent_input = NULL;
for (vector<Node*>::iterator i = edge->inputs_.begin();
i != edge->inputs_.end(); ++i) {
// Visit this input.
- if (!RecomputeDirty(*i, stack, err))
+ if (!RecomputeNodeDirty(*i, stack, validation_nodes, err))
return false;
// If an input is not ready, neither are our outputs.
@@ -463,6 +501,13 @@ void Edge::Dump(const char* prefix) const {
i != outputs_.end() && *i != NULL; ++i) {
printf("%s ", (*i)->path().c_str());
}
+ if (!validations_.empty()) {
+ printf(" validations ");
+ for (std::vector<Node*>::const_iterator i = validations_.begin();
+ i != validations_.end() && *i != NULL; ++i) {
+ printf("%s ", (*i)->path().c_str());
+ }
+ }
if (pool_) {
if (!pool_->name().empty()) {
printf("(in pool '%s')", pool_->name().c_str());
@@ -519,6 +564,13 @@ void Node::Dump(const char* prefix) const {
e != out_edges().end() && *e != NULL; ++e) {
(*e)->Dump(" +- ");
}
+ if (!validation_out_edges().empty()) {
+ printf(" validation out edges:\n");
+ for (std::vector<Edge*>::const_iterator e = validation_out_edges().begin();
+ e != validation_out_edges().end() && *e != NULL; ++e) {
+ (*e)->Dump(" +- ");
+ }
+ }
}
bool ImplicitDepLoader::LoadDeps(Edge* edge, string* err) {