30 : state_(state), file_reader_(file_reader),
31 options_(options), quiet_(false) {
40 *err =
"loading '" + filename +
"': " + read_err;
42 parent->
Error(
string(*err), err);
51 contents.resize(contents.size() + 1);
53 return Parse(filename, contents, err);
83 if (!
ParseLet(&name, &let_value, err))
88 if (name ==
"ninja_required_version")
126 return lexer_.
Error(
"duplicate pool '" + name +
"'", err);
136 if (key ==
"depth") {
138 depth = atol(depth_string.c_str());
142 return lexer_.
Error(
"unexpected variable '" + key +
"'", err);
147 return lexer_.
Error(
"expected 'depth =' line", err);
163 return lexer_.
Error(
"duplicate rule '" + name +
"'", err);
178 return lexer_.
Error(
"unexpected variable '" + key +
"'", err);
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);
189 return lexer_.
Error(
"expected 'command =' line", err);
197 return lexer_.
Error(
"expected variable name", err);
224 }
while (!eval.
empty());
233 vector<EvalString> ins, outs;
239 while (!out.
empty()) {
249 int implicit_outs = 0;
270 return lexer_.
Error(
"expected build command name", err);
274 return lexer_.
Error(
"unknown build rule '" + rule_name +
"'", err);
320 while (has_indent_token) {
334 if (!pool_name.empty()) {
337 return lexer_.
Error(
"unknown pool name '" + pool_name +
"'", err);
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);
350 lexer_.
Error(
"multiple rules generate " + path +
" [-w dupbuild=err]",
355 Warning(
"multiple rules generate %s. " 356 "builds involving this target will not be correct; " 357 "continuing anyway [-w dupbuild=warn]",
360 if (e - i <= static_cast<size_t>(implicit_outs))
374 edge->
inputs_.reserve(ins.size());
375 for (vector<EvalString>::iterator i = ins.begin(); i != ins.end(); ++i) {
376 string path = i->Evaluate(env);
393 vector<Node*>::iterator new_end =
395 if (new_end != edge->
inputs_.end()) {
398 Warning(
"phony target '%s' names itself as an input; " 399 "ignoring [-w phonycycle=warn]",
400 out->
path().c_str());
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",
440 if (token != expected) {
static bool IsReservedBinding(const string &var)
string Evaluate(Env *env) const
bool Load(const string &filename, string *err, Lexer *parent=NULL)
Load and parse a file.
vector< Edge * > edges_
All the edges of the graph.
const Rule * LookupRule(const string &rule_name)
bool ParsePool(string *err)
Parse various statement types.
const string & path() const
bool CanonicalizePath(string *path, uint64_t *slash_bits, string *err)
Canonicalize a path like "foo/../bar.h" into just "bar.h".
PhonyCycleAction phony_cycle_action_
Pool * LookupPool(const string &pool_name)
void UnreadToken()
Rewind to the last read Token.
ManifestParser(State *state, FileReader *file_reader, ManifestParserOptions options=ManifestParserOptions())
Information about a node in the dependency graph: the file, whether it's dirty, mtime, etc.
const Rule * LookupRuleCurrentScope(const string &rule_name)
static const char * TokenErrorHint(Token expected)
Return a human-readable token hint, used in error messages.
void AddIn(Edge *edge, StringPiece path, uint64_t slash_bits)
bool PeekToken(Token token)
If the next token is token, read it and return true.
An edge in the dependency graph; links between Nodes using Rules.
bool Error(const string &message, string *err)
Construct an error message with context.
void CheckNinjaVersion(const string &version)
Check whether version is compatible with the current Ninja version, aborting if not.
Token ReadToken()
Read a Token from the Token enum.
bool ReadPath(EvalString *path, string *err)
Read a path (complete with $escapes).
Edge * AddEdge(const Rule *rule)
An Env which contains a mapping of variables to values as well as a pointer to a parent scope...
void AddRule(const Rule *rule)
bool AddOut(Edge *edge, StringPiece path, uint64_t slash_bits)
bool ParseEdge(string *err)
An invokable build command and associated metadata (description, etc.).
string DescribeLastError()
If the last token read was an ERROR token, provide more info or the empty string. ...
A pool for delayed edges.
bool ParseLet(string *key, EvalString *val, string *err)
#define METRIC_RECORD(name)
The primary interface to metrics.
bool ReadIdent(string *out)
Read a simple identifier (a rule or variable name).
virtual Status ReadFile(const string &path, string *contents, string *err)=0
Read and store in given string.
void AddBinding(const string &key, const EvalString &val)
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).
bool AddDefault(StringPiece path, string *error)
string GetBinding(const string &key)
Returns the shell-escaped value of |key|.
bool ParseRule(string *err)
void AddBinding(const string &key, const string &val)
bool maybe_phonycycle_diagnostic() const
static const char * TokenName(Token t)
Return a human-readable form of a token, used in error messages.
ManifestParserOptions options_
Global state (file status) for a single run.
FileReader * file_reader_
bool ParseFileInclude(bool new_scope, string *err)
Parse either a 'subninja' or 'include' line.
unsigned long long uint64_t
A tokenized string that contains variable references.
void Warning(const char *msg,...)
Log a warning message.
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.
vector< Node * > outputs_
Interface for reading files from disk.