builddir
authorEvan Martin <martine@danga.com>
Sun, 24 Oct 2010 02:28:42 +0000 (19:28 -0700)
committerEvan Martin <martine@danga.com>
Sun, 24 Oct 2010 02:28:42 +0000 (19:28 -0700)
manifest_parser.h
ninja_test.cc

index 6b65437..4fb872d 100644 (file)
@@ -84,7 +84,7 @@ static bool IsIdentChar(char c) {
     ('a' <= c && c <= 'z') ||
     ('+' <= c && c <= '9') ||  // +,-./ and numbers
     ('A' <= c && c <= 'Z') ||
-    (c == '_');
+    (c == '_') || (c == '@');
 }
 
 bool Parser::Token(const string& expected, string* err) {
@@ -161,8 +161,11 @@ struct ManifestParser {
   bool ParseLet(string* err);
   bool ParseEdge(string* err);
 
+  string ExpandFile(const string& file);
+
   State* state_;
   Parser parser_;
+  string builddir_;
 };
 
 bool ManifestParser::Load(const string& filename, string* err) {
@@ -246,6 +249,11 @@ bool ManifestParser::ParseLet(string* err) {
     return false;
 
   state_->AddBinding(name, value);
+  if (name == "builddir") {
+    builddir_ = value;
+    if (!builddir_.empty() && builddir_[builddir_.size() - 1] != '/')
+      builddir_.push_back('/');
+  }
 
   return true;
 }
@@ -262,7 +270,7 @@ bool ManifestParser::ParseEdge(string* err) {
       return parser_.Error("expected output file list", err);
     if (out == ":")
       break;
-    outs.push_back(out);
+    outs.push_back(ExpandFile(out));
   }
 
   string rule_name;
@@ -277,7 +285,7 @@ bool ManifestParser::ParseEdge(string* err) {
     string in;
     if (!parser_.ReadToken(&in))
       break;
-    ins.push_back(in);
+    ins.push_back(ExpandFile(in));
   }
 
   if (!parser_.Newline(err))
@@ -292,3 +300,9 @@ bool ManifestParser::ParseEdge(string* err) {
   return true;
 }
 
+string ManifestParser::ExpandFile(const string& file) {
+  if (!file.empty() && file[0] == '@')
+    return builddir_ + file.substr(1);
+  return file;
+}
+
index a00cfd9..949be66 100644 (file)
@@ -105,6 +105,19 @@ TEST(Parser, Errors) {
   }
 }
 
+TEST(Parser, BuildDir) {
+  State state;
+  ASSERT_NO_FATAL_FAILURE(AssertParse(&state,
+"builddir = out\n"
+"rule cat\n"
+"command cat @in > $out\n"
+"build @bin: cat @a.o\n"
+"build @a.o: cat a.cc\n"));
+  state.stat_cache()->Dump();
+  ASSERT_TRUE(state.LookupNode("out/a.o"));
+}
+
+
 TEST(State, Basic) {
   State state;
   Rule* rule = state.AddRule("cat", "cat @in > $out");