diff options
author | Evan Martin <martine@danga.com> | 2012-12-29 19:55:52 (GMT) |
---|---|---|
committer | Evan Martin <martine@danga.com> | 2013-04-08 21:45:06 (GMT) |
commit | 5504c0cb054ecfa1c8cd04fa141f5831560d13f4 (patch) | |
tree | fa543a6bba11b01fd43b0b05aebaebc59479a3ee /src/graph.cc | |
parent | 00ffada47e1f9649ba76f12ff514f9434a182ef8 (diff) | |
download | Ninja-5504c0cb054ecfa1c8cd04fa141f5831560d13f4.zip Ninja-5504c0cb054ecfa1c8cd04fa141f5831560d13f4.tar.gz Ninja-5504c0cb054ecfa1c8cd04fa141f5831560d13f4.tar.bz2 |
use DepsLog in loading dependencies
WIP
Diffstat (limited to 'src/graph.cc')
-rw-r--r-- | src/graph.cc | 135 |
1 files changed, 79 insertions, 56 deletions
diff --git a/src/graph.cc b/src/graph.cc index cbd93b6..43f4304 100644 --- a/src/graph.cc +++ b/src/graph.cc @@ -19,6 +19,7 @@ #include "build_log.h" #include "depfile_parser.h" +#include "deps_log.h" #include "disk_interface.h" #include "explain.h" #include "manifest_parser.h" @@ -282,6 +283,48 @@ bool Edge::GetBindingBool(const string& key) { return !GetBinding(key).empty(); } +void Edge::Dump(const char* prefix) const { + printf("%s[ ", prefix); + for (vector<Node*>::const_iterator i = inputs_.begin(); + i != inputs_.end() && *i != NULL; ++i) { + printf("%s ", (*i)->path().c_str()); + } + printf("--%s-> ", rule_->name().c_str()); + for (vector<Node*>::const_iterator i = outputs_.begin(); + i != outputs_.end() && *i != NULL; ++i) { + printf("%s ", (*i)->path().c_str()); + } + if (pool_) { + if (!pool_->name().empty()) { + printf("(in pool '%s')", pool_->name().c_str()); + } + } else { + printf("(null pool?)"); + } + printf("] 0x%p\n", this); +} + +bool Edge::is_phony() const { + return rule_ == &State::kPhonyRule; +} + +void Node::Dump(const char* prefix) const { + printf("%s <%s 0x%p> mtime: %d%s, (:%s), ", + prefix, path().c_str(), this, + mtime(), mtime() ? "" : " (:missing)", + dirty() ? " dirty" : " clean"); + if (in_edge()) { + in_edge()->Dump("in-edge: "); + } else { + printf("no in-edge\n"); + } + printf(" out edges:\n"); + for (vector<Edge*>::const_iterator e = out_edges().begin(); + e != out_edges().end() && *e != NULL; ++e) { + (*e)->Dump(" +- "); + } +} + bool ImplicitDepLoader::LoadDepFile(Edge* edge, const string& path, string* err) { METRIC_RECORD("depfile load"); @@ -311,11 +354,8 @@ bool ImplicitDepLoader::LoadDepFile(Edge* edge, const string& path, } // Preallocate space in edge->inputs_ to be filled in below. - edge->inputs_.insert(edge->inputs_.end() - edge->order_only_deps_, - depfile.ins_.size(), 0); - edge->implicit_deps_ += depfile.ins_.size(); vector<Node*>::iterator implicit_dep = - edge->inputs_.end() - edge->order_only_deps_ - depfile.ins_.size(); + PreallocateSpace(edge, depfile.ins_.size()); // Add all its in-edges. for (vector<StringPiece>::iterator i = depfile.ins_.begin(); @@ -326,66 +366,49 @@ bool ImplicitDepLoader::LoadDepFile(Edge* edge, const string& path, Node* node = state_->GetNode(*i); *implicit_dep = node; node->AddOutEdge(edge); - - // If we don't have a edge that generates this input already, - // create one; this makes us not abort if the input is missing, - // but instead will rebuild in that circumstance. - if (!node->in_edge()) { - Edge* phony_edge = state_->AddEdge(&State::kPhonyRule); - node->set_in_edge(phony_edge); - phony_edge->outputs_.push_back(node); - - // RecomputeDirty might not be called for phony_edge if a previous call - // to RecomputeDirty had caused the file to be stat'ed. Because previous - // invocations of RecomputeDirty would have seen this node without an - // input edge (and therefore ready), we have to set outputs_ready_ to true - // to avoid a potential stuck build. If we do call RecomputeDirty for - // this node, it will simply set outputs_ready_ to the correct value. - phony_edge->outputs_ready_ = true; - } + CreatePhonyInEdge(node); } return true; } -void Edge::Dump(const char* prefix) const { - printf("%s[ ", prefix); - for (vector<Node*>::const_iterator i = inputs_.begin(); - i != inputs_.end() && *i != NULL; ++i) { - printf("%s ", (*i)->path().c_str()); - } - printf("--%s-> ", rule_->name().c_str()); - for (vector<Node*>::const_iterator i = outputs_.begin(); - i != outputs_.end() && *i != NULL; ++i) { - printf("%s ", (*i)->path().c_str()); - } - if (pool_) { - if (!pool_->name().empty()) { - printf("(in pool '%s')", pool_->name().c_str()); - } - } else { - printf("(null pool?)"); +bool ImplicitDepLoader::LoadDepsFromLog(Edge* edge, string* err) { + DepsLog::Deps* deps = deps_log_->GetDeps(edge->outputs_[0]); + if (!deps) + return false; + + // XXX mtime + + vector<Node*>::iterator implicit_dep = + PreallocateSpace(edge, deps->node_count); + for (int i = 0; i < deps->node_count; ++i, ++implicit_dep) { + *implicit_dep = deps->nodes[i]; + CreatePhonyInEdge(*implicit_dep); } - printf("] 0x%p\n", this); + return true; } -bool Edge::is_phony() const { - return rule_ == &State::kPhonyRule; +vector<Node*>::iterator ImplicitDepLoader::PreallocateSpace(Edge* edge, + int count) { + edge->inputs_.insert(edge->inputs_.end() - edge->order_only_deps_, + (size_t)count, 0); + edge->implicit_deps_ += count; + return edge->inputs_.end() - edge->order_only_deps_ - count; } -void Node::Dump(const char* prefix) const { - printf("%s <%s 0x%p> mtime: %d%s, (:%s), ", - prefix, path().c_str(), this, - mtime(), mtime() ? "" : " (:missing)", - dirty() ? " dirty" : " clean"); - if (in_edge()) { - in_edge()->Dump("in-edge: "); - } else { - printf("no in-edge\n"); - } - printf(" out edges:\n"); - for (vector<Edge*>::const_iterator e = out_edges().begin(); - e != out_edges().end() && *e != NULL; ++e) { - (*e)->Dump(" +- "); - } +void ImplicitDepLoader::CreatePhonyInEdge(Node* node) { + if (node->in_edge()) + return; + + Edge* phony_edge = state_->AddEdge(&State::kPhonyRule); + node->set_in_edge(phony_edge); + phony_edge->outputs_.push_back(node); + + // RecomputeDirty might not be called for phony_edge if a previous call + // to RecomputeDirty had caused the file to be stat'ed. Because previous + // invocations of RecomputeDirty would have seen this node without an + // input edge (and therefore ready), we have to set outputs_ready_ to true + // to avoid a potential stuck build. If we do call RecomputeDirty for + // this node, it will simply set outputs_ready_ to the correct value. + phony_edge->outputs_ready_ = true; } |