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