summaryrefslogtreecommitdiffstats
path: root/src/graph.cc
diff options
context:
space:
mode:
authorEvan Martin <martine@danga.com>2012-12-29 19:55:52 (GMT)
committerEvan Martin <martine@danga.com>2013-04-08 21:45:06 (GMT)
commit5504c0cb054ecfa1c8cd04fa141f5831560d13f4 (patch)
treefa543a6bba11b01fd43b0b05aebaebc59479a3ee /src/graph.cc
parent00ffada47e1f9649ba76f12ff514f9434a182ef8 (diff)
downloadNinja-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.cc135
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;
}