41 map<string, EvalString>::const_iterator i =
bindings_.find(key);
49 return var ==
"command" ||
51 var ==
"description" ||
57 var ==
"rspfile_content";
73 Node* most_recent_input = NULL;
74 for (vector<Node*>::iterator i = edge->
inputs_.begin();
75 i != edge->
inputs_.end(); ++i) {
77 if (
Edge* in_edge = (*i)->in_edge()) {
83 EXPLAIN(
"%s has no in-edge and is missing", (*i)->path().c_str());
84 (*i)->set_dirty(!(*i)->exists());
89 if (
Edge* in_edge = (*i)->in_edge()) {
90 if (!in_edge->outputs_ready_)
98 EXPLAIN(
"%s is dirty", (*i)->path().c_str());
101 if (!most_recent_input || (*i)->
mtime() > most_recent_input->
mtime()) {
102 most_recent_input = *i;
113 for (vector<Node*>::iterator i = edge->
outputs_.begin();
126 for (vector<Node*>::iterator i = edge->
outputs_.begin();
145 Node* most_recent_input,
147 const string& command,
159 EXPLAIN(
"output %s doesn't exist", output->
path().c_str());
164 if (most_recent_input && output->
mtime() < most_recent_input->
mtime()) {
171 bool used_restat =
false;
178 if (output_mtime < most_recent_input->mtime()) {
179 EXPLAIN(
"%soutput %s older than most recent input %s "
181 used_restat ?
"restat of " :
"", output->
path().c_str(),
182 most_recent_input->
path().c_str(),
183 output_mtime, most_recent_input->
mtime());
189 if (deps_mtime && output->
mtime() > deps_mtime) {
190 EXPLAIN(
"stored deps info out of date for for %s (%d vs %d)",
191 output->
path().c_str(), deps_mtime, output->
mtime());
199 if (entry || (entry =
build_log()->LookupByOutput(output->
path()))) {
201 EXPLAIN(
"command line changed for %s", output->
path().c_str());
206 EXPLAIN(
"command line not found in log for %s", output->
path().c_str());
215 for (vector<Node*>::const_iterator i =
inputs_.begin();
217 if ((*i)->in_edge() && !(*i)->in_edge()->outputs_ready())
231 vector<Node*>::iterator end,
238 if (var ==
"in" || var ==
"in_newline") {
243 var ==
"in" ?
' ' :
'\n');
244 }
else if (var ==
"out") {
256 vector<Node*>::iterator end,
259 for (vector<Node*>::iterator i = begin; i != end; ++i) {
261 result.push_back(sep);
262 const string& path = (*i)->path();
263 if (path.find(
" ") != string::npos) {
277 string rspfile_content =
GetBinding(
"rspfile_content");
278 if (!rspfile_content.empty())
279 command +=
";rspfile=" + rspfile_content;
294 printf(
"%s[ ", prefix);
295 for (vector<Node*>::const_iterator i =
inputs_.begin();
296 i !=
inputs_.end() && *i != NULL; ++i) {
297 printf(
"%s ", (*i)->path().c_str());
299 printf(
"--%s-> ",
rule_->
name().c_str());
300 for (vector<Node*>::const_iterator i =
outputs_.begin();
301 i !=
outputs_.end() && *i != NULL; ++i) {
302 printf(
"%s ", (*i)->path().c_str());
306 printf(
"(in pool '%s')",
pool_->
name().c_str());
309 printf(
"(null pool?)");
311 printf(
"] 0x%p\n",
this);
319 printf(
"%s <%s 0x%p> mtime: %d%s, (:%s), ",
320 prefix,
path().c_str(),
this,
322 dirty() ?
" dirty" :
" clean");
326 printf(
"no in-edge\n");
328 printf(
" out edges:\n");
329 for (vector<Edge*>::const_iterator e =
out_edges().begin();
330 e !=
out_edges().end() && *e != NULL; ++e) {
337 if (!deps_type.empty()) {
348 if (!depfile.empty()) {
352 EXPLAIN(
"depfile '%s' is missing", depfile.c_str());
367 *err =
"loading '" + path +
"': " + *err;
376 if (!depfile.
Parse(&content, &depfile_err)) {
377 *err = path +
": " + depfile_err;
384 if (opath != depfile.
out_) {
385 *err =
"expected depfile '" + path +
"' to mention '" +
391 vector<Node*>::iterator implicit_dep =
395 for (vector<StringPiece>::iterator i = depfile.
ins_.begin();
396 i != depfile.
ins_.end(); ++i, ++implicit_dep) {
401 *implicit_dep = node;
415 *deps_mtime = deps->
mtime;
417 vector<Node*>::iterator implicit_dep =
419 for (
int i = 0; i < deps->
node_count; ++i, ++implicit_dep) {
420 *implicit_dep = deps->
nodes[i];
441 phony_edge->
outputs_.push_back(node);
An Env for an Edge, providing $in and $out.
void Dump(const char *prefix="") const
virtual string ReadFile(const string &path, string *err)=0
Read a file to a string. Fill in |err| on error.
static bool IsReservedBinding(const string &var)
Parser for the dependency information emitted by gcc's -M flags.
Node * GetNode(StringPiece path)
bool RecomputeOutputDirty(Edge *edge, Node *most_recent_input, TimeStamp deps_mtime, const string &command, Node *output)
Recompute whether a given single output should be marked dirty.
bool RecomputeDirty(Edge *edge, string *err)
Examine inputs, outputs, and command lines to judge whether an edge needs to be re-run, and update outputs_ready_ and each outputs' |dirty_| state accordingly.
StringPiece represents a slice of a string whose memory is managed externally.
Information about a node in the dependency graph: the file, whether it's dirty, mtime, etc.
bool Parse(string *content, string *err)
Parse an input file.
vector< Node * >::iterator PreallocateSpace(Edge *edge, int count)
Preallocate count spaces in the input array on edge, returning an iterator pointing at the first new ...
string MakePathList(vector< Node * >::iterator begin, vector< Node * >::iterator end, char sep)
Given a span of Nodes, construct a list of paths suitable for a command line.
virtual string LookupVariable(const string &var)
ImplicitDepLoader dep_loader_
Interface for accessing the disk.
bool GetBindingBool(const string &key)
string AsString() const
Convert the slice into a full-fledged std::string, copying the data into a new string.
void Dump(const char *prefix="") const
void AddOutEdge(Edge *edge)
An edge in the dependency graph; links between Nodes using Rules.
string EvaluateCommand(bool incl_rsp_file=false)
Expand all variables in a command and return it as a string.
bool is_order_only(size_t index)
bool CanonicalizePath(string *path, string *err)
Canonicalize a path like "foo/../bar.h" into just "bar.h".
const EvalString * GetBinding(const string &key) const
bool Stat(DiskInterface *disk_interface)
Return true if the file exists (mtime_ got a value).
Edge * AddEdge(const Rule *rule)
BuildLog * build_log() const
bool LoadDepFile(Edge *edge, const string &path, string *err)
Load implicit dependencies for edge from a depfile attribute.
DiskInterface * disk_interface_
Deps * GetDeps(Node *node)
string LookupWithFallback(const string &var, const EvalString *eval, Env *env)
This is tricky.
void CreatePhonyInEdge(Node *node)
If we don't have a edge that generates this input already, create one; this makes us not abort if the...
vector< StringPiece > ins_
TimeStamp mtime_
Possible values of mtime_: -1: file hasn't been examined 0: we looked, and file doesn't exist >0: act...
#define METRIC_RECORD(name)
The primary interface to metrics.
const string & name() const
const string & path() const
void AddBinding(const string &key, const EvalString &val)
bool LoadDepsFromLog(Edge *edge, TimeStamp *mtime, string *err)
Load implicit dependencies for edge from the DepsLog.
string GetBinding(const string &key)
static uint64_t HashCommand(StringPiece command)
LogEntry * LookupByOutput(const string &path)
Lookup a previously-run command by its output path.
map< string, EvalString > bindings_
void set_in_edge(Edge *edge)
const string & name() const
bool AllInputsReady() const
Return true if all inputs' in-edges are ready.
bool LoadDeps(Edge *edge, TimeStamp *mtime, string *err)
Load implicit dependencies for edge.
DiskInterface * disk_interface_
A tokenized string that contains variable references.
An interface for a scope for variable (e.g. "$foo") lookups.
const vector< Edge * > & out_edges() const
virtual TimeStamp Stat(const string &path)=0
stat() a file, returning the mtime, or 0 if missing and -1 on other errors.
static const Rule kPhonyRule
vector< Node * > outputs_