diff options
Diffstat (limited to 'ninja/src/manifest_parser.cc')
-rw-r--r-- | ninja/src/manifest_parser.cc | 49 |
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; |