Ninja
manifest_parser.cc
Go to the documentation of this file.
1 // Copyright 2011 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "manifest_parser.h"
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <vector>
20 
21 #include "graph.h"
22 #include "state.h"
23 #include "util.h"
24 #include "version.h"
25 
26 using namespace std;
27 
29  ManifestParserOptions options)
30  : Parser(state, file_reader),
31  options_(options), quiet_(false) {
32  env_ = &state->bindings_;
33 }
34 
35 bool ManifestParser::Parse(const string& filename, const string& input,
36  string* err) {
37  lexer_.Start(filename, input);
38 
39  for (;;) {
40  Lexer::Token token = lexer_.ReadToken();
41  switch (token) {
42  case Lexer::POOL:
43  if (!ParsePool(err))
44  return false;
45  break;
46  case Lexer::BUILD:
47  if (!ParseEdge(err))
48  return false;
49  break;
50  case Lexer::RULE:
51  if (!ParseRule(err))
52  return false;
53  break;
54  case Lexer::DEFAULT:
55  if (!ParseDefault(err))
56  return false;
57  break;
58  case Lexer::IDENT: {
60  string name;
61  EvalString let_value;
62  if (!ParseLet(&name, &let_value, err))
63  return false;
64  string value = let_value.Evaluate(env_);
65  // Check ninja_required_version immediately so we can exit
66  // before encountering any syntactic surprises.
67  if (name == "ninja_required_version")
68  CheckNinjaVersion(value);
69  env_->AddBinding(name, value);
70  break;
71  }
72  case Lexer::INCLUDE:
73  if (!ParseFileInclude(false, err))
74  return false;
75  break;
76  case Lexer::SUBNINJA:
77  if (!ParseFileInclude(true, err))
78  return false;
79  break;
80  case Lexer::ERROR: {
81  return lexer_.Error(lexer_.DescribeLastError(), err);
82  }
83  case Lexer::TEOF:
84  return true;
85  case Lexer::NEWLINE:
86  break;
87  default:
88  return lexer_.Error(string("unexpected ") + Lexer::TokenName(token),
89  err);
90  }
91  }
92  return false; // not reached
93 }
94 
95 
96 bool ManifestParser::ParsePool(string* err) {
97  string name;
98  if (!lexer_.ReadIdent(&name))
99  return lexer_.Error("expected pool name", err);
100 
101  if (!ExpectToken(Lexer::NEWLINE, err))
102  return false;
103 
104  if (state_->LookupPool(name) != NULL)
105  return lexer_.Error("duplicate pool '" + name + "'", err);
106 
107  int depth = -1;
108 
109  while (lexer_.PeekToken(Lexer::INDENT)) {
110  string key;
111  EvalString value;
112  if (!ParseLet(&key, &value, err))
113  return false;
114 
115  if (key == "depth") {
116  string depth_string = value.Evaluate(env_);
117  depth = atol(depth_string.c_str());
118  if (depth < 0)
119  return lexer_.Error("invalid pool depth", err);
120  } else {
121  return lexer_.Error("unexpected variable '" + key + "'", err);
122  }
123  }
124 
125  if (depth < 0)
126  return lexer_.Error("expected 'depth =' line", err);
127 
128  state_->AddPool(new Pool(name, depth));
129  return true;
130 }
131 
132 
133 bool ManifestParser::ParseRule(string* err) {
134  string name;
135  if (!lexer_.ReadIdent(&name))
136  return lexer_.Error("expected rule name", err);
137 
138  if (!ExpectToken(Lexer::NEWLINE, err))
139  return false;
140 
141  if (env_->LookupRuleCurrentScope(name) != NULL)
142  return lexer_.Error("duplicate rule '" + name + "'", err);
143 
144  Rule* rule = new Rule(name); // XXX scoped_ptr
145 
146  while (lexer_.PeekToken(Lexer::INDENT)) {
147  string key;
148  EvalString value;
149  if (!ParseLet(&key, &value, err))
150  return false;
151 
152  if (Rule::IsReservedBinding(key)) {
153  rule->AddBinding(key, value);
154  } else {
155  // Die on other keyvals for now; revisit if we want to add a
156  // scope here.
157  return lexer_.Error("unexpected variable '" + key + "'", err);
158  }
159  }
160 
161  if (rule->bindings_["rspfile"].empty() !=
162  rule->bindings_["rspfile_content"].empty()) {
163  return lexer_.Error("rspfile and rspfile_content need to be "
164  "both specified", err);
165  }
166 
167  if (rule->bindings_["command"].empty())
168  return lexer_.Error("expected 'command =' line", err);
169 
170  env_->AddRule(rule);
171  return true;
172 }
173 
174 bool ManifestParser::ParseLet(string* key, EvalString* value, string* err) {
175  if (!lexer_.ReadIdent(key))
176  return lexer_.Error("expected variable name", err);
177  if (!ExpectToken(Lexer::EQUALS, err))
178  return false;
179  if (!lexer_.ReadVarValue(value, err))
180  return false;
181  return true;
182 }
183 
184 bool ManifestParser::ParseDefault(string* err) {
185  EvalString eval;
186  if (!lexer_.ReadPath(&eval, err))
187  return false;
188  if (eval.empty())
189  return lexer_.Error("expected target name", err);
190 
191  do {
192  string path = eval.Evaluate(env_);
193  string path_err;
194  uint64_t slash_bits; // Unused because this only does lookup.
195  if (!CanonicalizePath(&path, &slash_bits, &path_err))
196  return lexer_.Error(path_err, err);
197  if (!state_->AddDefault(path, &path_err))
198  return lexer_.Error(path_err, err);
199 
200  eval.Clear();
201  if (!lexer_.ReadPath(&eval, err))
202  return false;
203  } while (!eval.empty());
204 
205  if (!ExpectToken(Lexer::NEWLINE, err))
206  return false;
207 
208  return true;
209 }
210 
211 bool ManifestParser::ParseEdge(string* err) {
212  vector<EvalString> ins, outs;
213 
214  {
215  EvalString out;
216  if (!lexer_.ReadPath(&out, err))
217  return false;
218  while (!out.empty()) {
219  outs.push_back(out);
220 
221  out.Clear();
222  if (!lexer_.ReadPath(&out, err))
223  return false;
224  }
225  }
226 
227  // Add all implicit outs, counting how many as we go.
228  int implicit_outs = 0;
230  for (;;) {
231  EvalString out;
232  if (!lexer_.ReadPath(&out, err))
233  return false;
234  if (out.empty())
235  break;
236  outs.push_back(out);
237  ++implicit_outs;
238  }
239  }
240 
241  if (outs.empty())
242  return lexer_.Error("expected path", err);
243 
244  if (!ExpectToken(Lexer::COLON, err))
245  return false;
246 
247  string rule_name;
248  if (!lexer_.ReadIdent(&rule_name))
249  return lexer_.Error("expected build command name", err);
250 
251  const Rule* rule = env_->LookupRule(rule_name);
252  if (!rule)
253  return lexer_.Error("unknown build rule '" + rule_name + "'", err);
254 
255  for (;;) {
256  // XXX should we require one path here?
257  EvalString in;
258  if (!lexer_.ReadPath(&in, err))
259  return false;
260  if (in.empty())
261  break;
262  ins.push_back(in);
263  }
264 
265  // Add all implicit deps, counting how many as we go.
266  int implicit = 0;
268  for (;;) {
269  EvalString in;
270  if (!lexer_.ReadPath(&in, err))
271  return false;
272  if (in.empty())
273  break;
274  ins.push_back(in);
275  ++implicit;
276  }
277  }
278 
279  // Add all order-only deps, counting how many as we go.
280  int order_only = 0;
282  for (;;) {
283  EvalString in;
284  if (!lexer_.ReadPath(&in, err))
285  return false;
286  if (in.empty())
287  break;
288  ins.push_back(in);
289  ++order_only;
290  }
291  }
292 
293  if (!ExpectToken(Lexer::NEWLINE, err))
294  return false;
295 
296  // Bindings on edges are rare, so allocate per-edge envs only when needed.
297  bool has_indent_token = lexer_.PeekToken(Lexer::INDENT);
298  BindingEnv* env = has_indent_token ? new BindingEnv(env_) : env_;
299  while (has_indent_token) {
300  string key;
301  EvalString val;
302  if (!ParseLet(&key, &val, err))
303  return false;
304 
305  env->AddBinding(key, val.Evaluate(env_));
306  has_indent_token = lexer_.PeekToken(Lexer::INDENT);
307  }
308 
309  Edge* edge = state_->AddEdge(rule);
310  edge->env_ = env;
311 
312  string pool_name = edge->GetBinding("pool");
313  if (!pool_name.empty()) {
314  Pool* pool = state_->LookupPool(pool_name);
315  if (pool == NULL)
316  return lexer_.Error("unknown pool name '" + pool_name + "'", err);
317  edge->pool_ = pool;
318  }
319 
320  edge->outputs_.reserve(outs.size());
321  for (size_t i = 0, e = outs.size(); i != e; ++i) {
322  string path = outs[i].Evaluate(env);
323  string path_err;
324  uint64_t slash_bits;
325  if (!CanonicalizePath(&path, &slash_bits, &path_err))
326  return lexer_.Error(path_err, err);
327  if (!state_->AddOut(edge, path, slash_bits)) {
329  lexer_.Error("multiple rules generate " + path + " [-w dupbuild=err]",
330  err);
331  return false;
332  } else {
333  if (!quiet_) {
334  Warning("multiple rules generate %s. "
335  "builds involving this target will not be correct; "
336  "continuing anyway [-w dupbuild=warn]",
337  path.c_str());
338  }
339  if (e - i <= static_cast<size_t>(implicit_outs))
340  --implicit_outs;
341  }
342  }
343  }
344  if (edge->outputs_.empty()) {
345  // All outputs of the edge are already created by other edges. Don't add
346  // this edge. Do this check before input nodes are connected to the edge.
347  state_->edges_.pop_back();
348  delete edge;
349  return true;
350  }
351  edge->implicit_outs_ = implicit_outs;
352 
353  edge->inputs_.reserve(ins.size());
354  for (vector<EvalString>::iterator i = ins.begin(); i != ins.end(); ++i) {
355  string path = i->Evaluate(env);
356  string path_err;
357  uint64_t slash_bits;
358  if (!CanonicalizePath(&path, &slash_bits, &path_err))
359  return lexer_.Error(path_err, err);
360  state_->AddIn(edge, path, slash_bits);
361  }
362  edge->implicit_deps_ = implicit;
363  edge->order_only_deps_ = order_only;
364 
366  edge->maybe_phonycycle_diagnostic()) {
367  // CMake 2.8.12.x and 3.0.x incorrectly write phony build statements
368  // that reference themselves. Ninja used to tolerate these in the
369  // build graph but that has since been fixed. Filter them out to
370  // support users of those old CMake versions.
371  Node* out = edge->outputs_[0];
372  vector<Node*>::iterator new_end =
373  remove(edge->inputs_.begin(), edge->inputs_.end(), out);
374  if (new_end != edge->inputs_.end()) {
375  edge->inputs_.erase(new_end, edge->inputs_.end());
376  if (!quiet_) {
377  Warning("phony target '%s' names itself as an input; "
378  "ignoring [-w phonycycle=warn]",
379  out->path().c_str());
380  }
381  }
382  }
383 
384  // Lookup, validate, and save any dyndep binding. It will be used later
385  // to load generated dependency information dynamically, but it must
386  // be one of our manifest-specified inputs.
387  string dyndep = edge->GetUnescapedDyndep();
388  if (!dyndep.empty()) {
389  uint64_t slash_bits;
390  if (!CanonicalizePath(&dyndep, &slash_bits, err))
391  return false;
392  edge->dyndep_ = state_->GetNode(dyndep, slash_bits);
393  edge->dyndep_->set_dyndep_pending(true);
394  vector<Node*>::iterator dgi =
395  std::find(edge->inputs_.begin(), edge->inputs_.end(), edge->dyndep_);
396  if (dgi == edge->inputs_.end()) {
397  return lexer_.Error("dyndep '" + dyndep + "' is not an input", err);
398  }
399  }
400 
401  return true;
402 }
403 
404 bool ManifestParser::ParseFileInclude(bool new_scope, string* err) {
405  EvalString eval;
406  if (!lexer_.ReadPath(&eval, err))
407  return false;
408  string path = eval.Evaluate(env_);
409 
411  if (new_scope) {
412  subparser.env_ = new BindingEnv(env_);
413  } else {
414  subparser.env_ = env_;
415  }
416 
417  if (!subparser.Load(path, err, &lexer_))
418  return false;
419 
420  if (!ExpectToken(Lexer::NEWLINE, err))
421  return false;
422 
423  return true;
424 }
bool ParseEdge(std::string *err)
bool AddDefault(StringPiece path, std::string *error)
Definition: state.cc:153
std::string Evaluate(Env *env) const
Definition: eval_env.cc:101
const Rule * LookupRuleCurrentScope(const std::string &rule_name)
Definition: eval_env.cc:39
int order_only_deps_
Definition: graph.h:197
int implicit_deps_
Definition: graph.h:196
State * state_
Definition: parser.h:38
BindingEnv * env_
void Clear()
Definition: eval_env.h:42
bool CanonicalizePath(string *path, uint64_t *slash_bits, string *err)
Definition: util.cc:95
Node * GetNode(StringPiece path, uint64_t slash_bits)
Definition: state.cc:104
PhonyCycleAction phony_cycle_action_
void UnreadToken()
Rewind to the last read Token.
Definition: lexer.cc:115
ManifestParser(State *state, FileReader *file_reader, ManifestParserOptions options=ManifestParserOptions())
Information about a node in the dependency graph: the file, whether it&#39;s dirty, mtime, etc.
Definition: graph.h:37
bool Parse(const std::string &filename, const std::string &input, std::string *err)
Parse a file, given its contents as a string.
bool ParsePool(std::string *err)
Parse various statement types.
void AddIn(Edge *edge, StringPiece path, uint64_t slash_bits)
Definition: state.cc:138
Base class for parsers.
Definition: parser.h:26
std::vector< Node * > outputs_
Definition: graph.h:175
bool Load(const std::string &filename, std::string *err, Lexer *parent=NULL)
Load and parse a file.
Definition: parser.cc:22
bool PeekToken(Token token)
If the next token is token, read it and return true.
Definition: lexer.cc:458
An edge in the dependency graph; links between Nodes using Rules.
Definition: graph.h:139
bool ReadVarValue(EvalString *value, std::string *err)
Read the value side of a var = value line (complete with $escapes).
Definition: lexer.h:85
bool empty() const
Definition: eval_env.h:43
const std::string & path() const
Definition: graph.h:76
void CheckNinjaVersion(const string &version)
Definition: version.cc:36
Token ReadToken()
Read a Token from the Token enum.
Definition: lexer.cc:119
Edge * AddEdge(const Rule *rule)
Definition: state.cc:95
bool ParseLet(std::string *key, EvalString *val, std::string *err)
Parses .ninja files.
bool ReadPath(EvalString *path, std::string *err)
Read a path (complete with $escapes).
Definition: lexer.h:79
An Env which contains a mapping of variables to values as well as a pointer to a parent scope...
Definition: eval_env.h:81
static bool IsReservedBinding(const std::string &var)
Definition: eval_env.cc:67
bool ParseRule(std::string *err)
void AddRule(const Rule *rule)
Definition: eval_env.cc:34
bool AddOut(Edge *edge, StringPiece path, uint64_t slash_bits)
Definition: state.cc:144
void set_dyndep_pending(bool pending)
Definition: graph.h:92
bool Error(const std::string &message, std::string *err)
Construct an error message with context.
Definition: lexer.cc:25
BindingEnv * env_
Definition: graph.h:177
void AddBinding(const std::string &key, const EvalString &val)
Definition: eval_env.cc:55
An invokable build command and associated metadata (description, etc.).
Definition: eval_env.h:59
bool ParseFileInclude(bool new_scope, std::string *err)
Parse either a &#39;subninja&#39; or &#39;include&#39; line.
std::string DescribeLastError()
If the last token read was an ERROR token, provide more info or the empty string. ...
Definition: lexer.cc:105
int implicit_outs_
Definition: graph.h:211
A pool for delayed edges.
Definition: state.h:39
bool ParseDefault(std::string *err)
void AddPool(Pool *pool)
Definition: state.cc:83
Token
Definition: lexer.h:32
BindingEnv bindings_
Definition: state.h:126
FileReader * file_reader_
Definition: parser.h:39
Pool * LookupPool(const std::string &pool_name)
Definition: state.cc:88
const Rule * LookupRule(const std::string &rule_name)
Definition: eval_env.cc:46
std::vector< Node * > inputs_
Definition: graph.h:174
Pool * pool_
Definition: graph.h:173
std::string GetBinding(const std::string &key) const
Returns the shell-escaped value of |key|.
Definition: graph.cc:411
Lexer lexer_
Definition: parser.h:40
bool maybe_phonycycle_diagnostic() const
Definition: graph.cc:464
void AddBinding(const std::string &key, const std::string &val)
Definition: eval_env.cc:30
static const char * TokenName(Token t)
Return a human-readable form of a token, used in error messages.
Definition: lexer.cc:75
ManifestParserOptions options_
Global state (file status) for a single run.
Definition: state.h:84
bool ReadIdent(std::string *out)
Read a simple identifier (a rule or variable name).
Definition: lexer.cc:549
unsigned long long uint64_t
Definition: win32port.h:29
std::vector< Edge * > edges_
All the edges of the graph.
Definition: state.h:124
Bindings bindings_
Definition: eval_env.h:76
A tokenized string that contains variable references.
Definition: eval_env.h:34
void Warning(const char *msg,...)
Log a warning message.
Definition: util.cc:77
DupeEdgeAction dupe_edge_action_
std::string GetUnescapedDyndep() const
Like GetBinding("dyndep"), but without shell escaping.
Definition: graph.cc:425
Node * dyndep_
Definition: graph.h:176
void Start(StringPiece filename, StringPiece input)
Start parsing some input.
Definition: lexer.cc:68
bool ExpectToken(Lexer::Token expected, std::string *err)
If the next token is not expected, produce an error string saying "expected foo, got bar"...
Definition: parser.cc:44
Interface for reading files from disk.