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