summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile7
-rw-r--r--ninja.cc5
-rw-r--r--ninja.h80
-rw-r--r--ninja_test.cc20
5 files changed, 114 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6484956
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+ninja
+ninja_test
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..18f8918
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,7 @@
+CXXFLAGS := -Wall -g
+
+all: ninja ninja_test
+ninja: ninja.cc | Makefile
+
+ninja_test: LDFLAGS = -lgtest -lgtest_main
+ninja_test: ninja_test.cc | Makefile
diff --git a/ninja.cc b/ninja.cc
new file mode 100644
index 0000000..3e305c8
--- /dev/null
+++ b/ninja.cc
@@ -0,0 +1,5 @@
+#include "ninja.h"
+
+int main(int argc, char** argv) {
+ return 0;
+}
diff --git a/ninja.h b/ninja.h
new file mode 100644
index 0000000..e6eb3e1
--- /dev/null
+++ b/ninja.h
@@ -0,0 +1,80 @@
+#include <map>
+#include <string>
+#include <vector>
+
+using namespace std;
+
+struct Node;
+struct FileStat {
+ FileStat(const string& path) : path_(path), node_(NULL) {}
+ string path_;
+ Node* node_;
+};
+
+struct Edge;
+struct Node {
+ Node(FileStat* file) : file_(file), dirty_(false) {}
+ FileStat* file_;
+ bool dirty_;
+ vector<Edge*> edges_;
+};
+
+struct Rule {
+ Rule(const string& name, const string& command) :
+ name_(name), command_(command) {}
+ string name_;
+ string command_;
+};
+
+struct Edge {
+ Rule* rule_;
+ enum InOut { IN, OUT };
+ vector<Node*> inputs_;
+ vector<Node*> outputs_;
+};
+
+struct StatCache {
+ map<string, FileStat*> paths_;
+};
+struct State {
+ StatCache stat_cache_;
+ map<string, Rule*> rules_;
+ vector<Edge*> edges_;
+
+ Rule* AddRule(const string& name, const string& command);
+ Edge* AddEdge(Rule* rule);
+ Edge* AddEdge(const string& rule_name);
+ Node* GetNode(const string& path);
+ void AddInOut(Edge* edge, Edge::InOut inout, const string& path);
+};
+
+Rule* State::AddRule(const string& name, const string& command) {
+ Rule* rule = new Rule(name, command);
+ rules_[name] = rule;
+ return rule;
+}
+
+Edge* State::AddEdge(const string& rule_name) {
+ return AddEdge(rules_[rule_name]);
+}
+
+Edge* State::AddEdge(Rule* rule) {
+ Edge* edge = new Edge();
+ edge->rule_ = rule;
+ edges_.push_back(edge);
+ return edge;
+}
+
+Node* State::GetNode(const string& path) {
+ FileStat* file = new FileStat(path);
+ stat_cache_.paths_[path] = file;
+ return new Node(file);
+}
+
+void State::AddInOut(Edge* edge, Edge::InOut inout, const string& path) {
+ Node* node = GetNode(path);
+ if (inout == Edge::IN)
+ edge->inputs_.push_back(node);
+ else
+ edge->outputs_.push_back(node);
+}
diff --git a/ninja_test.cc b/ninja_test.cc
new file mode 100644
index 0000000..145c53c
--- /dev/null
+++ b/ninja_test.cc
@@ -0,0 +1,20 @@
+#include "ninja.h"
+
+#include <gtest/gtest.h>
+
+struct NinjaTest : public testing::Test {
+ NinjaTest() {
+ rule_cat_ = state_.AddRule("cat", "cat @in > $out");
+ }
+
+ Rule* rule_cat_;
+ State state_;
+};
+
+TEST_F(NinjaTest, Basic) {
+ Edge* edge = state_.AddEdge(rule_cat_);
+ state_.AddInOut(edge, Edge::IN, "in1");
+ state_.AddInOut(edge, Edge::IN, "in2");
+ state_.AddInOut(edge, Edge::OUT, "out");
+}
+