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
29using namespace std;
30
33 : Parser(state, file_reader),
34 options_(options), quiet_(false) {
35 env_ = &state->bindings_;
36}
37
38bool 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: {
62 lexer_.UnreadToken();
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
99bool 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
136bool 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
177bool 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
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
212bool 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;
232 if (lexer_.PeekToken(Lexer::PIPE)) {
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;
270 if (lexer_.PeekToken(Lexer::PIPE)) {
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;
284 if (lexer_.PeekToken(Lexer::PIPE2)) {
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.
297 if (lexer_.PeekToken(Lexer::PIPEAT)) {
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
380 if (options_.phony_cycle_action_ == kPhonyCycleActionWarn &&
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
419bool 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
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
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
const std::string & path() const
Definition graph.h:82
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
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
Parser(State *state, FileReader *file_reader)
Definition parser.h:27
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
BindingEnv bindings_
Definition state.h:140
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