summaryrefslogtreecommitdiff
path: root/ninja/src/manifest_parser.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ninja/src/manifest_parser.cc')
-rw-r--r--ninja/src/manifest_parser.cc49
1 files changed, 36 insertions, 13 deletions
diff --git a/ninja/src/manifest_parser.cc b/ninja/src/manifest_parser.cc
index 388b5bc679e..e8c0436041e 100644
--- a/ninja/src/manifest_parser.cc
+++ b/ninja/src/manifest_parser.cc
@@ -24,8 +24,10 @@
#include "util.h"
#include "version.h"
-ManifestParser::ManifestParser(State* state, FileReader* file_reader)
- : state_(state), file_reader_(file_reader) {
+ManifestParser::ManifestParser(State* state, FileReader* file_reader,
+ bool dupe_edge_should_err)
+ : state_(state), file_reader_(file_reader),
+ dupe_edge_should_err_(dupe_edge_should_err), quiet_(false) {
env_ = &state->bindings_;
}
@@ -156,7 +158,7 @@ bool ManifestParser::ParseRule(string* err) {
if (!ExpectToken(Lexer::NEWLINE, err))
return false;
- if (state_->LookupRule(name) != NULL)
+ if (env_->LookupRuleCurrentScope(name) != NULL)
return lexer_.Error("duplicate rule '" + name + "'", err);
Rule* rule = new Rule(name); // XXX scoped_ptr
@@ -185,7 +187,7 @@ bool ManifestParser::ParseRule(string* err) {
if (rule->bindings_["command"].empty())
return lexer_.Error("expected 'command =' line", err);
- state_->AddRule(rule);
+ env_->AddRule(rule);
return true;
}
@@ -252,7 +254,7 @@ bool ManifestParser::ParseEdge(string* err) {
if (!lexer_.ReadIdent(&rule_name))
return lexer_.Error("expected build command name", err);
- const Rule* rule = state_->LookupRule(rule_name);
+ const Rule* rule = env_->LookupRule(rule_name);
if (!rule)
return lexer_.Error("unknown build rule '" + rule_name + "'", err);
@@ -298,16 +300,16 @@ bool ManifestParser::ParseEdge(string* err) {
return false;
// Bindings on edges are rare, so allocate per-edge envs only when needed.
- bool hasIdent = lexer_.PeekToken(Lexer::INDENT);
- BindingEnv* env = hasIdent ? new BindingEnv(env_) : env_;
- while (hasIdent) {
+ bool has_indent_token = lexer_.PeekToken(Lexer::INDENT);
+ BindingEnv* env = has_indent_token ? new BindingEnv(env_) : env_;
+ while (has_indent_token) {
string key;
EvalString val;
if (!ParseLet(&key, &val, err))
return false;
env->AddBinding(key, val.Evaluate(env_));
- hasIdent = lexer_.PeekToken(Lexer::INDENT);
+ has_indent_token = lexer_.PeekToken(Lexer::INDENT);
}
Edge* edge = state_->AddEdge(rule);
@@ -321,21 +323,42 @@ bool ManifestParser::ParseEdge(string* err) {
edge->pool_ = pool;
}
- for (vector<EvalString>::iterator i = ins.begin(); i != ins.end(); ++i) {
+ edge->outputs_.reserve(outs.size());
+ for (vector<EvalString>::iterator i = outs.begin(); i != outs.end(); ++i) {
string path = i->Evaluate(env);
string path_err;
unsigned int slash_bits;
if (!CanonicalizePath(&path, &slash_bits, &path_err))
return lexer_.Error(path_err, err);
- state_->AddIn(edge, path, slash_bits);
+ if (!state_->AddOut(edge, path, slash_bits)) {
+ if (dupe_edge_should_err_) {
+ lexer_.Error("multiple rules generate " + path + " [-w dupbuild=err]",
+ err);
+ return false;
+ } else if (!quiet_) {
+ Warning("multiple rules generate %s. "
+ "builds involving this target will not be correct; "
+ "continuing anyway [-w dupbuild=warn]",
+ path.c_str());
+ }
+ }
}
- for (vector<EvalString>::iterator i = outs.begin(); i != outs.end(); ++i) {
+ if (edge->outputs_.empty()) {
+ // All outputs of the edge are already created by other edges. Don't add
+ // this edge. Do this check before input nodes are connected to the edge.
+ state_->edges_.pop_back();
+ delete edge;
+ return true;
+ }
+
+ edge->inputs_.reserve(ins.size());
+ for (vector<EvalString>::iterator i = ins.begin(); i != ins.end(); ++i) {
string path = i->Evaluate(env);
string path_err;
unsigned int slash_bits;
if (!CanonicalizePath(&path, &slash_bits, &path_err))
return lexer_.Error(path_err, err);
- state_->AddOut(edge, path, slash_bits);
+ state_->AddIn(edge, path, slash_bits);
}
edge->implicit_deps_ = implicit;
edge->order_only_deps_ = order_only;