diff options
author | Evan Martin <martine@danga.com> | 2010-12-19 22:53:38 (GMT) |
---|---|---|
committer | Evan Martin <martine@danga.com> | 2010-12-19 22:54:15 (GMT) |
commit | ac4cc82452ec145e2f567b8edab6c14d642d41c8 (patch) | |
tree | 65667e1d2d13ea2ef2e1db9043084e2fd0149237 /src | |
parent | cd5dd9e74df2accca52c85cbb1c0e7075660919e (diff) | |
download | Ninja-ac4cc82452ec145e2f567b8edab6c14d642d41c8.zip Ninja-ac4cc82452ec145e2f567b8edab6c14d642d41c8.tar.gz Ninja-ac4cc82452ec145e2f567b8edab6c14d642d41c8.tar.bz2 |
expand variables in build paths
Diffstat (limited to 'src')
-rw-r--r-- | src/parsers.cc | 22 | ||||
-rw-r--r-- | src/parsers_test.cc | 21 |
2 files changed, 39 insertions, 4 deletions
diff --git a/src/parsers.cc b/src/parsers.cc index 4d6c058..c66b91b 100644 --- a/src/parsers.cc +++ b/src/parsers.cc @@ -82,7 +82,7 @@ static bool IsIdentChar(char c) { ('a' <= c && c <= 'z') || ('+' <= c && c <= '9') || // +,-./ and numbers ('A' <= c && c <= 'Z') || - (c == '_') || (c == '@'); + (c == '_') || (c == '@') || (c == '$'); } bool Tokenizer::ExpectToken(Token::Type expected, string* err) { @@ -379,7 +379,7 @@ bool ManifestParser::ParseEdge(string* err) { string out; if (!tokenizer_.ReadIdent(&out)) return tokenizer_.Error("expected output file list", err); - outs.push_back(ExpandFile(out)); + outs.push_back(out); } // XXX check outs not empty @@ -402,7 +402,7 @@ bool ManifestParser::ParseEdge(string* err) { string in; if (!tokenizer_.ReadIdent(&in)) break; - ins.push_back(ExpandFile(in)); + ins.push_back(in); } // Add all order-only deps, counting how many as we go. @@ -413,7 +413,7 @@ bool ManifestParser::ParseEdge(string* err) { string in; if (!tokenizer_.ReadIdent(&in)) break; - ins.push_back(ExpandFile(in)); + ins.push_back(in); ++order_only; } } @@ -440,6 +440,20 @@ bool ManifestParser::ParseEdge(string* err) { tokenizer_.ConsumeToken(); } + // Evaluate all variables in paths. + // XXX: fast path skip the eval parse if there's no $ in the path? + vector<string>* paths[2] = { &ins, &outs }; + for (int p = 0; p < 2; ++p) { + for (vector<string>::iterator i = paths[p]->begin(); + i != paths[p]->end(); ++i) { + EvalString eval; + string eval_err; + if (!eval.Parse(*i, &eval_err)) + return tokenizer_.Error(eval_err, err); + *i = ExpandFile(eval.Evaluate(env)); + } + } + Edge* edge = state_->AddEdge(rule); edge->env_ = env; for (vector<string>::iterator i = ins.begin(); i != ins.end(); ++i) diff --git a/src/parsers_test.cc b/src/parsers_test.cc index 6bd8e4b..f38e6dc 100644 --- a/src/parsers_test.cc +++ b/src/parsers_test.cc @@ -125,6 +125,17 @@ TEST_F(ParserTest, CanonicalizeFile) { EXPECT_FALSE(state.LookupNode("in//2")); } +TEST_F(ParserTest, PathVariables) { + ASSERT_NO_FATAL_FAILURE(AssertParse( +"rule cat\n" +" command = cat $in > $out\n" +"dir = out\n" +"build $dir/exe: cat src\n")); + + EXPECT_FALSE(state.LookupNode("$dir/exe")); + EXPECT_TRUE(state.LookupNode("out/exe")); +} + TEST_F(ParserTest, Errors) { { ManifestParser parser(NULL, NULL); @@ -218,6 +229,16 @@ TEST_F(ParserTest, Errors) { &err)); EXPECT_EQ("line 4, col 0: unexpected variable 'othervar'", err); } + + { + State state; + ManifestParser parser(&state, NULL); + string err; + EXPECT_FALSE(parser.Parse("rule cc\n command = foo\n" + "build $: cc bar.cc\n", + &err)); + EXPECT_EQ("line 4, col 1: expected variable after $", err); + } } TEST_F(ParserTest, BuildDir) { |