split out graph into its own header
authorEvan Martin <martine@danga.com>
Sat, 8 Jan 2011 17:44:15 +0000 (09:44 -0800)
committerEvan Martin <martine@danga.com>
Sat, 8 Jan 2011 17:44:15 +0000 (09:44 -0800)
13 files changed:
build.ninja
src/build.cc
src/build_log.cc
src/graph.cc [new file with mode: 0644]
src/graph.h [new file with mode: 0644]
src/graphviz.h
src/ninja.cc
src/ninja.h
src/ninja_jumble.cc
src/ninja_test.cc
src/parsers.cc
src/parsers_test.cc
src/test.h

index c650cd2..9f5173a 100644 (file)
@@ -30,13 +30,14 @@ rule link
 # and build that "ninja.o" by compiling "ninja.cc".
 build $builddir/build.o: cxx src/build.cc
 build $builddir/build_log.o: cxx src/build_log.cc
+build $builddir/graph.o: cxx src/graph.cc
 build $builddir/parsers.o: cxx src/parsers.cc
 build $builddir/subprocess.o: cxx src/subprocess.cc
 build $builddir/util.o: cxx src/util.cc
 build $builddir/ninja_jumble.o: cxx src/ninja_jumble.cc
 build $builddir/ninja.a: ar $builddir/build.o $builddir/build_log.o \
-    $builddir/parsers.o $builddir/subprocess.o $builddir/util.o \
-    $builddir/ninja_jumble.o
+    $builddir/graph.o $builddir/parsers.o $builddir/subprocess.o \
+    $builddir/util.o $builddir/ninja_jumble.o
 
 build $builddir/ninja.o: cxx src/ninja.cc
 build ninja: link $builddir/ninja.o $builddir/ninja.a
index 8ffbc7c..0aa1d10 100644 (file)
@@ -3,6 +3,7 @@
 #include <stdio.h>
 
 #include "build_log.h"
+#include "graph.h"
 #include "ninja.h"
 #include "subprocess.h"
 
index 666b80b..53fca4e 100644 (file)
@@ -4,6 +4,7 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "graph.h"
 #include "ninja.h"
 
 // Implementation details:
diff --git a/src/graph.cc b/src/graph.cc
new file mode 100644 (file)
index 0000000..22283a5
--- /dev/null
@@ -0,0 +1,201 @@
+#include "graph.h"
+
+#include <stdio.h>
+
+#include "build_log.h"
+#include "ninja.h"
+#include "parsers.h"
+
+void FileStat::Touch(int mtime) {
+  mtime_ = mtime;
+  if (node_)
+    node_->MarkDirty();
+}
+
+bool FileStat::Stat(DiskInterface* disk_interface) {
+  mtime_ = disk_interface->Stat(path_);
+  return mtime_ > 0;
+}
+
+void Node::MarkDirty() {
+  if (dirty_)
+    return;  // We already know.
+
+  dirty_ = true;
+  MarkDependentsDirty();
+}
+
+void Node::MarkDependentsDirty() {
+  for (vector<Edge*>::iterator i = out_edges_.begin(); i != out_edges_.end(); ++i)
+    (*i)->MarkDirty(this);
+}
+
+bool Edge::RecomputeDirty(State* state, DiskInterface* disk_interface,
+                          string* err) {
+  bool dirty = false;
+
+  if (!rule_->depfile_.empty()) {
+    if (!LoadDepFile(state, disk_interface, err))
+      return false;
+  }
+
+  time_t most_recent_input = 1;
+  for (vector<Node*>::iterator i = inputs_.begin(); i != inputs_.end(); ++i) {
+    if ((*i)->file_->StatIfNecessary(disk_interface)) {
+      if (Edge* edge = (*i)->in_edge_) {
+        if (!edge->RecomputeDirty(state, disk_interface, err))
+          return false;
+      } else {
+        // This input has no in-edge; it is dirty if it is missing.
+        // But it's ok for implicit deps to be missing.
+        if (!is_implicit(i - inputs_.begin()))
+          (*i)->dirty_ = !(*i)->file_->exists();
+      }
+    }
+
+    if (is_order_only(i - inputs_.begin())) {
+      // Order-only deps only make us dirty if they're missing.
+      if (!(*i)->file_->exists())
+        dirty = true;
+      continue;
+    }
+
+    // If a regular input is dirty (or missing), we're dirty.
+    // Otherwise consider mtime.
+    if ((*i)->dirty_) {
+      dirty = true;
+    } else {
+      if ((*i)->file_->mtime_ > most_recent_input)
+        most_recent_input = (*i)->file_->mtime_;
+    }
+  }
+
+  string command = EvaluateCommand();
+
+  assert(!outputs_.empty());
+  for (vector<Node*>::iterator i = outputs_.begin(); i != outputs_.end(); ++i) {
+    // We may have other outputs, that our input-recursive traversal hasn't hit
+    // yet (or never will).  Stat them if we haven't already.
+    (*i)->file_->StatIfNecessary(disk_interface);
+
+    // Output is dirty if we're dirty, we're missing the output,
+    // or if it's older than the most recent input mtime.
+    if (dirty || !(*i)->file_->exists() ||
+        (*i)->file_->mtime_ < most_recent_input) {
+      (*i)->dirty_ = true;
+    } else {
+      // May also be dirty due to the command changing since the last build.
+      BuildLog::LogEntry* entry;
+      if (state->build_log_ &&
+          (entry = state->build_log_->LookupByOutput((*i)->file_->path_))) {
+        if (command != entry->command)
+          (*i)->dirty_ = true;
+      }
+    }
+  }
+  return true;
+}
+
+void Edge::MarkDirty(Node* node) {
+  if (rule_ == &State::kPhonyRule)
+    return;
+
+  vector<Node*>::iterator i = find(inputs_.begin(), inputs_.end(), node);
+  if (i == inputs_.end())
+    return;
+  if (i - inputs_.begin() >= ((int)inputs_.size()) - order_only_deps_)
+    return;  // Order-only deps don't cause us to become dirty.
+  for (i = outputs_.begin(); i != outputs_.end(); ++i)
+    (*i)->MarkDirty();
+}
+
+struct EdgeEnv : public Env {
+  EdgeEnv(Edge* edge) : edge_(edge) {}
+  virtual string LookupVariable(const string& var) {
+    string result;
+    if (var == "in") {
+      int explicit_deps = edge_->inputs_.size() - edge_->implicit_deps_ -
+          edge_->order_only_deps_;
+      for (vector<Node*>::iterator i = edge_->inputs_.begin();
+           i != edge_->inputs_.end() && explicit_deps; ++i, --explicit_deps) {
+        if (!result.empty())
+          result.push_back(' ');
+        result.append((*i)->file_->path_);
+      }
+    } else if (var == "out") {
+      result = edge_->outputs_[0]->file_->path_;
+    } else if (edge_->env_) {
+      return edge_->env_->LookupVariable(var);
+    }
+    return result;
+  }
+  Edge* edge_;
+};
+
+string Edge::EvaluateCommand() {
+  EdgeEnv env(this);
+  return rule_->command_.Evaluate(&env);
+}
+
+string Edge::GetDescription() {
+  EdgeEnv env(this);
+  return rule_->description_.Evaluate(&env);
+}
+
+bool Edge::LoadDepFile(State* state, DiskInterface* disk_interface, string* err) {
+  EdgeEnv env(this);
+  string path = rule_->depfile_.Evaluate(&env);
+
+  string content = disk_interface->ReadFile(path, err);
+  if (!err->empty())
+    return false;
+  if (content.empty())
+    return true;
+
+  MakefileParser makefile;
+  if (!makefile.Parse(content, err))
+    return false;
+
+  // Check that this depfile matches our output.
+  if (outputs_.size() != 1) {
+    *err = "expected only one output";
+    return false;
+  }
+  if (outputs_[0]->file_->path_ != makefile.out_) {
+    *err = "expected makefile to mention '" + outputs_[0]->file_->path_ + "', "
+           "got '" + makefile.out_ + "'";
+    return false;
+  }
+
+  // Add all its in-edges.
+  for (vector<string>::iterator i = makefile.ins_.begin();
+       i != makefile.ins_.end(); ++i) {
+    Node* node = state->GetNode(*i);
+    for (vector<Node*>::iterator j = inputs_.begin(); j != inputs_.end(); ++j) {
+      if (*j == node) {
+        node = NULL;
+        break;
+      }
+    }
+    if (node) {
+      inputs_.insert(inputs_.end() - order_only_deps_, node);
+      node->out_edges_.push_back(this);
+      ++implicit_deps_;
+    }
+  }
+
+  return true;
+}
+
+void Edge::Dump() {
+  printf("[ ");
+  for (vector<Node*>::iterator i = inputs_.begin(); i != inputs_.end(); ++i) {
+    printf("%s ", (*i)->file_->path_.c_str());
+  }
+  printf("--%s-> ", rule_->name_.c_str());
+  for (vector<Node*>::iterator i = outputs_.begin(); i != outputs_.end(); ++i) {
+    printf("%s ", (*i)->file_->path_.c_str());
+  }
+  printf("]\n");
+}
+
diff --git a/src/graph.h b/src/graph.h
new file mode 100644 (file)
index 0000000..3f46db4
--- /dev/null
@@ -0,0 +1,109 @@
+#ifndef NINJA_GRAPH_H_
+#define NINJA_GRAPH_H_
+
+#include <string>
+#include <vector>
+using namespace std;
+
+#include "eval_env.h"
+
+struct DiskInterface;
+
+struct Node;
+struct FileStat {
+  FileStat(const string& path) : path_(path), mtime_(-1), node_(NULL) {}
+  void Touch(int mtime);
+  // Return true if the file exists (mtime_ got a value).
+  bool Stat(DiskInterface* disk_interface);
+
+  // Return true if we needed to stat.
+  bool StatIfNecessary(DiskInterface* disk_interface) {
+    if (status_known())
+      return false;
+    Stat(disk_interface);
+    return true;
+  }
+
+  bool exists() const {
+    return mtime_ != 0;
+  }
+
+  bool status_known() const {
+    return mtime_ != -1;
+  }
+
+  string path_;
+  // Possible values of mtime_:
+  //   -1: file hasn't been examined
+  //   0:  we looked, and file doesn't exist
+  //   >0: actual file's mtime
+  time_t mtime_;
+  Node* node_;
+};
+
+struct Edge;
+struct Node {
+  Node(FileStat* file) : file_(file), dirty_(false), in_edge_(NULL) {}
+
+  bool dirty() const { return dirty_; }
+  void MarkDirty();
+  void MarkDependentsDirty();
+
+  FileStat* file_;
+  bool dirty_;
+  Edge* in_edge_;
+  vector<Edge*> out_edges_;
+};
+
+struct Rule {
+  Rule(const string& name) : name_(name) { }
+
+  bool ParseCommand(const string& command, string* err) {
+    return command_.Parse(command, err);
+  }
+  string name_;
+  EvalString command_;
+  EvalString description_;
+  EvalString depfile_;
+};
+
+struct State;
+struct Edge {
+  Edge() : rule_(NULL), env_(NULL), implicit_deps_(0), order_only_deps_(0) {}
+
+  void MarkDirty(Node* node);
+  bool RecomputeDirty(State* state, DiskInterface* disk_interface, string* err);
+  string EvaluateCommand();  // XXX move to env, take env ptr
+  string GetDescription();
+  bool LoadDepFile(State* state, DiskInterface* disk_interface, string* err);
+
+  void Dump();
+
+  const Rule* rule_;
+  vector<Node*> inputs_;
+  vector<Node*> outputs_;
+  Env* env_;
+
+  // XXX There are three types of inputs.
+  // 1) explicit deps, which show up as $in on the command line;
+  // 2) implicit deps, which the target depends on implicitly (e.g. C headers),
+  //                   and changes in them cause the target to rebuild;
+  // 3) order-only deps, which are needed before the target builds but which
+  //                     don't cause the target to rebuild.
+  // Currently we stuff all of these into inputs_ and keep counts of #2 and #3
+  // when we need to compute subsets.  This is suboptimal; should think of a
+  // better representation.  (Could make each pointer into a pair of a pointer
+  // and a type of input, or if memory matters could use the low bits of the
+  // pointer...)
+  int implicit_deps_;
+  int order_only_deps_;
+  bool is_implicit(int index) {
+    return index >= ((int)inputs_.size()) - order_only_deps_ - implicit_deps_ &&
+        !is_order_only(index);
+  }
+  bool is_order_only(int index) {
+    return index >= ((int)inputs_.size()) - order_only_deps_;
+  }
+};
+
+#endif  // NINJA_GRAPH_H_
index d688a15..eb9ee25 100644 (file)
@@ -1,5 +1,7 @@
 #include <set>
 
+// XXX deinline all this code so we don't need this include
+#include "graph.h"
 struct Node;
 
 struct GraphViz {
index d568267..5602806 100644 (file)
@@ -6,9 +6,10 @@
 
 #include "build.h"
 #include "build_log.h"
-#include "graphviz.h"
 #include "parsers.h"
 
+#include "graphviz.h"
+
 option options[] = {
   { "help", no_argument, NULL, 'h' },
   { }
index 3ece1ab..26432c3 100644 (file)
@@ -14,6 +14,11 @@ using namespace std;
 #include "eval_env.h"
 #include "hash_map.h"
 
+struct Edge;
+struct FileStat;
+struct Node;
+struct Rule;
+
 int ReadFile(const string& path, string* contents, string* err);
 
 struct DiskInterface {
@@ -34,106 +39,6 @@ struct RealDiskInterface : public DiskInterface {
   virtual string ReadFile(const string& path, string* err);
 };
 
-struct Node;
-struct FileStat {
-  FileStat(const string& path) : path_(path), mtime_(-1), node_(NULL) {}
-  void Touch(int mtime);
-  // Return true if the file exists (mtime_ got a value).
-  bool Stat(DiskInterface* disk_interface);
-
-  // Return true if we needed to stat.
-  bool StatIfNecessary(DiskInterface* disk_interface) {
-    if (status_known())
-      return false;
-    Stat(disk_interface);
-    return true;
-  }
-
-  bool exists() const {
-    assert(status_known());
-    return mtime_ != 0;
-  }
-
-  bool status_known() const {
-    return mtime_ != -1;
-  }
-
-  string path_;
-  // Possible values of mtime_:
-  //   -1: file hasn't been examined
-  //   0:  we looked, and file doesn't exist
-  //   >0: actual file's mtime
-  time_t mtime_;
-  Node* node_;
-};
-
-struct Edge;
-struct Node {
-  Node(FileStat* file) : file_(file), dirty_(false), in_edge_(NULL) {}
-
-  bool dirty() const { return dirty_; }
-  void MarkDirty();
-  void MarkDependentsDirty();
-
-  FileStat* file_;
-  bool dirty_;
-  Edge* in_edge_;
-  vector<Edge*> out_edges_;
-};
-
-struct Rule {
-  Rule(const string& name) : name_(name) { }
-
-  bool ParseCommand(const string& command, string* err) {
-    return command_.Parse(command, err);
-  }
-  string name_;
-  EvalString command_;
-  EvalString description_;
-  EvalString depfile_;
-};
-
-struct State;
-struct Edge {
-  Edge() : rule_(NULL), env_(NULL), implicit_deps_(0), order_only_deps_(0) {}
-
-  void MarkDirty(Node* node);
-  bool RecomputeDirty(State* state, DiskInterface* disk_interface, string* err);
-  string EvaluateCommand();  // XXX move to env, take env ptr
-  string GetDescription();
-  bool LoadDepFile(State* state, DiskInterface* disk_interface, string* err);
-
-  void Dump();
-
-  enum InOut { IN, OUT };
-
-  const Rule* rule_;
-  vector<Node*> inputs_;
-  vector<Node*> outputs_;
-  Env* env_;
-
-  // XXX There are three types of inputs.
-  // 1) explicit deps, which show up as $in on the command line;
-  // 2) implicit deps, which the target depends on implicitly (e.g. C headers),
-  //                   and changes in them cause the target to rebuild;
-  // 3) order-only deps, which are needed before the target builds but which
-  //                     don't cause the target to rebuild.
-  // Currently we stuff all of these into inputs_ and keep counts of #2 and #3
-  // when we need to compute subsets.  This is suboptimal; should think of a
-  // better representation.  (Could make each pointer into a pair of a pointer
-  // and a type of input, or if memory matters could use the low bits of the
-  // pointer...)
-  int implicit_deps_;
-  int order_only_deps_;
-  bool is_implicit(int index) {
-    return index >= ((int)inputs_.size()) - order_only_deps_ - implicit_deps_ &&
-        !is_order_only(index);
-  }
-  bool is_order_only(int index) {
-    return index >= ((int)inputs_.size()) - order_only_deps_;
-  }
-};
-
 struct StatCache {
   typedef hash_map<string, FileStat*> Paths;
   Paths paths_;
@@ -141,6 +46,7 @@ struct StatCache {
   void Dump();
   void Reload();
 };
+
 struct State {
   State();
 
@@ -151,7 +57,8 @@ struct State {
   Edge* AddEdge(const Rule* rule);
   Node* GetNode(const string& path);
   Node* LookupNode(const string& path);
-  void AddInOut(Edge* edge, Edge::InOut inout, const string& path);
+  void AddIn(Edge* edge, const string& path);
+  void AddOut(Edge* edge, const string& path);
 
   StatCache stat_cache_;
   map<string, const Rule*> rules_;
index 18faac8..d351a6c 100644 (file)
@@ -3,13 +3,14 @@
 
 #include "ninja.h"
 
-#include "build_log.h"
-
 #include <errno.h>
 #include <sys/stat.h>
 #include <stdio.h>
 #include <string.h>
 
+#include "build_log.h"
+#include "graph.h"
+
 int ReadFile(const string& path, string* contents, string* err) {
   FILE* f = fopen(path.c_str(), "r");
   if (!f) {
@@ -90,141 +91,6 @@ bool RealDiskInterface::MakeDir(const string& path) {
   }
   return true;
 }
-void FileStat::Touch(int mtime) {
-  mtime_ = mtime;
-  if (node_)
-    node_->MarkDirty();
-}
-
-bool FileStat::Stat(DiskInterface* disk_interface) {
-  mtime_ = disk_interface->Stat(path_);
-  return mtime_ > 0;
-}
-
-void Node::MarkDirty() {
-  if (dirty_)
-    return;  // We already know.
-
-  dirty_ = true;
-  MarkDependentsDirty();
-}
-
-void Node::MarkDependentsDirty() {
-  for (vector<Edge*>::iterator i = out_edges_.begin(); i != out_edges_.end(); ++i)
-    (*i)->MarkDirty(this);
-}
-
-bool Edge::RecomputeDirty(State* state, DiskInterface* disk_interface,
-                          string* err) {
-  bool dirty = false;
-
-  if (!rule_->depfile_.empty()) {
-    if (!LoadDepFile(state, disk_interface, err))
-      return false;
-  }
-
-  time_t most_recent_input = 1;
-  for (vector<Node*>::iterator i = inputs_.begin(); i != inputs_.end(); ++i) {
-    if ((*i)->file_->StatIfNecessary(disk_interface)) {
-      if (Edge* edge = (*i)->in_edge_) {
-        if (!edge->RecomputeDirty(state, disk_interface, err))
-          return false;
-      } else {
-        // This input has no in-edge; it is dirty if it is missing.
-        // But it's ok for implicit deps to be missing.
-        if (!is_implicit(i - inputs_.begin()))
-          (*i)->dirty_ = !(*i)->file_->exists();
-      }
-    }
-
-    if (is_order_only(i - inputs_.begin())) {
-      // Order-only deps only make us dirty if they're missing.
-      if (!(*i)->file_->exists())
-        dirty = true;
-      continue;
-    }
-
-    // If a regular input is dirty (or missing), we're dirty.
-    // Otherwise consider mtime.
-    if ((*i)->dirty_) {
-      dirty = true;
-    } else {
-      if ((*i)->file_->mtime_ > most_recent_input)
-        most_recent_input = (*i)->file_->mtime_;
-    }
-  }
-
-  string command = EvaluateCommand();
-
-  assert(!outputs_.empty());
-  for (vector<Node*>::iterator i = outputs_.begin(); i != outputs_.end(); ++i) {
-    // We may have other outputs, that our input-recursive traversal hasn't hit
-    // yet (or never will).  Stat them if we haven't already.
-    (*i)->file_->StatIfNecessary(disk_interface);
-
-    // Output is dirty if we're dirty, we're missing the output,
-    // or if it's older than the most recent input mtime.
-    if (dirty || !(*i)->file_->exists() ||
-        (*i)->file_->mtime_ < most_recent_input) {
-      (*i)->dirty_ = true;
-    } else {
-      // May also be dirty due to the command changing since the last build.
-      BuildLog::LogEntry* entry;
-      if (state->build_log_ &&
-          (entry = state->build_log_->LookupByOutput((*i)->file_->path_))) {
-        if (command != entry->command)
-          (*i)->dirty_ = true;
-      }
-    }
-  }
-  return true;
-}
-
-void Edge::MarkDirty(Node* node) {
-  if (rule_ == &State::kPhonyRule)
-    return;
-
-  vector<Node*>::iterator i = find(inputs_.begin(), inputs_.end(), node);
-  if (i == inputs_.end())
-    return;
-  if (i - inputs_.begin() >= ((int)inputs_.size()) - order_only_deps_)
-    return;  // Order-only deps don't cause us to become dirty.
-  for (i = outputs_.begin(); i != outputs_.end(); ++i)
-    (*i)->MarkDirty();
-}
-
-struct EdgeEnv : public Env {
-  EdgeEnv(Edge* edge) : edge_(edge) {}
-  virtual string LookupVariable(const string& var) {
-    string result;
-    if (var == "in") {
-      int explicit_deps = edge_->inputs_.size() - edge_->implicit_deps_ -
-          edge_->order_only_deps_;
-      for (vector<Node*>::iterator i = edge_->inputs_.begin();
-           i != edge_->inputs_.end() && explicit_deps; ++i, --explicit_deps) {
-        if (!result.empty())
-          result.push_back(' ');
-        result.append((*i)->file_->path_);
-      }
-    } else if (var == "out") {
-      result = edge_->outputs_[0]->file_->path_;
-    } else if (edge_->env_) {
-      return edge_->env_->LookupVariable(var);
-    }
-    return result;
-  }
-  Edge* edge_;
-};
-
-string Edge::EvaluateCommand() {
-  EdgeEnv env(this);
-  return rule_->command_.Evaluate(&env);
-}
-
-string Edge::GetDescription() {
-  EdgeEnv env(this);
-  return rule_->description_.Evaluate(&env);
-}
 
 FileStat* StatCache::GetFile(const string& path) {
   Paths::iterator i = paths_.find(path);
@@ -248,65 +114,6 @@ void StatCache::Dump() {
   }
 }
 
-#include "parsers.h"
-
-bool Edge::LoadDepFile(State* state, DiskInterface* disk_interface, string* err) {
-  EdgeEnv env(this);
-  string path = rule_->depfile_.Evaluate(&env);
-
-  string content = disk_interface->ReadFile(path, err);
-  if (!err->empty())
-    return false;
-  if (content.empty())
-    return true;
-
-  MakefileParser makefile;
-  if (!makefile.Parse(content, err))
-    return false;
-
-  // Check that this depfile matches our output.
-  if (outputs_.size() != 1) {
-    *err = "expected only one output";
-    return false;
-  }
-  if (outputs_[0]->file_->path_ != makefile.out_) {
-    *err = "expected makefile to mention '" + outputs_[0]->file_->path_ + "', "
-           "got '" + makefile.out_ + "'";
-    return false;
-  }
-
-  // Add all its in-edges.
-  for (vector<string>::iterator i = makefile.ins_.begin();
-       i != makefile.ins_.end(); ++i) {
-    Node* node = state->GetNode(*i);
-    for (vector<Node*>::iterator j = inputs_.begin(); j != inputs_.end(); ++j) {
-      if (*j == node) {
-        node = NULL;
-        break;
-      }
-    }
-    if (node) {
-      inputs_.insert(inputs_.end() - order_only_deps_, node);
-      node->out_edges_.push_back(this);
-      ++implicit_deps_;
-    }
-  }
-
-  return true;
-}
-
-void Edge::Dump() {
-  printf("[ ");
-  for (vector<Node*>::iterator i = inputs_.begin(); i != inputs_.end(); ++i) {
-    printf("%s ", (*i)->file_->path_.c_str());
-  }
-  printf("--%s-> ", rule_->name_.c_str());
-  for (vector<Node*>::iterator i = outputs_.begin(); i != outputs_.end(); ++i) {
-    printf("%s ", (*i)->file_->path_.c_str());
-  }
-  printf("]\n");
-}
-
 const Rule State::kPhonyRule("phony");
 
 State::State() : build_log_(NULL) {
@@ -348,19 +155,20 @@ Node* State::GetNode(const string& path) {
   return file->node_;
 }
 
-void State::AddInOut(Edge* edge, Edge::InOut inout, const string& path) {
+void State::AddIn(Edge* edge, const string& path) {
   Node* node = GetNode(path);
-  if (inout == Edge::IN) {
-    edge->inputs_.push_back(node);
-    node->out_edges_.push_back(edge);
-  } else {
-    edge->outputs_.push_back(node);
-    if (node->in_edge_) {
-      fprintf(stderr, "WARNING: multiple rules generate %s. "
-              "build will not be correct; continuing anyway\n", path.c_str());
-    }
-    node->in_edge_ = edge;
+  edge->inputs_.push_back(node);
+  node->out_edges_.push_back(edge);
+}
+
+void State::AddOut(Edge* edge, const string& path) {
+  Node* node = GetNode(path);
+  edge->outputs_.push_back(node);
+  if (node->in_edge_) {
+    fprintf(stderr, "WARNING: multiple rules generate %s. "
+            "build will not be correct; continuing anyway\n", path.c_str());
   }
+  node->in_edge_ = edge;
 }
 
 bool EvalString::Parse(const string& input, string* err) {
index 12ba93c..0c992e9 100644 (file)
@@ -31,9 +31,9 @@ TEST(State, Basic) {
   ASSERT_EQ("", err);
   state.AddRule(rule);
   Edge* edge = state.AddEdge(rule);
-  state.AddInOut(edge, Edge::IN, "in1");
-  state.AddInOut(edge, Edge::IN, "in2");
-  state.AddInOut(edge, Edge::OUT, "out");
+  state.AddIn(edge, "in1");
+  state.AddIn(edge, "in2");
+  state.AddOut(edge, "out");
 
   EXPECT_EQ("cat in1 in2 > out", edge->EvaluateCommand());
 
index 7eee93c..f57c3b9 100644 (file)
@@ -5,6 +5,7 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "graph.h"
 #include "ninja.h"
 
 string Token::AsString() const {
@@ -460,9 +461,9 @@ bool ManifestParser::ParseEdge(string* err) {
   Edge* edge = state_->AddEdge(rule);
   edge->env_ = env;
   for (vector<string>::iterator i = ins.begin(); i != ins.end(); ++i)
-    state_->AddInOut(edge, Edge::IN, *i);
+    state_->AddIn(edge, *i);
   for (vector<string>::iterator i = outs.begin(); i != outs.end(); ++i)
-    state_->AddInOut(edge, Edge::OUT, *i);
+    state_->AddOut(edge, *i);
   edge->order_only_deps_ = order_only;
 
   return true;
index 6fb418d..28ba619 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <gtest/gtest.h>
 
+#include "graph.h"
 #include "ninja.h"
 
 struct ParserTest : public testing::Test,
index 4d45a2e..405f039 100644 (file)
@@ -1,7 +1,8 @@
-#include "ninja.h"
-
 #include <gtest/gtest.h>
 
+#include "graph.h"
+#include "ninja.h"
+
 struct StateTestWithBuiltinRules : public testing::Test {
   StateTestWithBuiltinRules();
   Node* GetNode(const string& path);