Ninja
graph.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 "graph.h"
16 
17 #include <algorithm>
18 #include <deque>
19 #include <assert.h>
20 #include <stdio.h>
21 
22 #include "build_log.h"
23 #include "debug_flags.h"
24 #include "depfile_parser.h"
25 #include "deps_log.h"
26 #include "disk_interface.h"
27 #include "manifest_parser.h"
28 #include "metrics.h"
29 #include "state.h"
30 #include "util.h"
31 
32 using namespace std;
33 
34 bool Node::Stat(DiskInterface* disk_interface, string* err) {
35  METRIC_RECORD("node stat");
36  mtime_ = disk_interface->Stat(path_, err);
37  if (mtime_ == -1) {
38  return false;
39  }
40  exists_ = (mtime_ != 0) ? ExistenceStatusExists : ExistenceStatusMissing;
41  return true;
42 }
43 
45  if (!exists()) {
46  mtime_ = std::max(mtime_, mtime);
47  }
48 }
49 
51  std::vector<Node*>* validation_nodes,
52  string* err) {
53  std::vector<Node*> stack;
54  std::vector<Node*> new_validation_nodes;
55 
56  std::deque<Node*> nodes(1, initial_node);
57 
58  // RecomputeNodeDirty might return new validation nodes that need to be
59  // checked for dirty state, keep a queue of nodes to visit.
60  while (!nodes.empty()) {
61  Node* node = nodes.front();
62  nodes.pop_front();
63 
64  stack.clear();
65  new_validation_nodes.clear();
66 
67  if (!RecomputeNodeDirty(node, &stack, &new_validation_nodes, err))
68  return false;
69  nodes.insert(nodes.end(), new_validation_nodes.begin(),
70  new_validation_nodes.end());
71  if (!new_validation_nodes.empty()) {
72  assert(validation_nodes &&
73  "validations require RecomputeDirty to be called with validation_nodes");
74  validation_nodes->insert(validation_nodes->end(),
75  new_validation_nodes.begin(),
76  new_validation_nodes.end());
77  }
78  }
79 
80  return true;
81 }
82 
83 bool DependencyScan::RecomputeNodeDirty(Node* node, std::vector<Node*>* stack,
84  std::vector<Node*>* validation_nodes,
85  string* err) {
86  Edge* edge = node->in_edge();
87  if (!edge) {
88  // If we already visited this leaf node then we are done.
89  if (node->status_known())
90  return true;
91  // This node has no in-edge; it is dirty if it is missing.
92  if (!node->StatIfNecessary(disk_interface_, err))
93  return false;
94  if (!node->exists())
95  EXPLAIN("%s has no in-edge and is missing", node->path().c_str());
96  node->set_dirty(!node->exists());
97  return true;
98  }
99 
100  // If we already finished this edge then we are done.
101  if (edge->mark_ == Edge::VisitDone)
102  return true;
103 
104  // If we encountered this edge earlier in the call stack we have a cycle.
105  if (!VerifyDAG(node, stack, err))
106  return false;
107 
108  // Mark the edge temporarily while in the call stack.
109  edge->mark_ = Edge::VisitInStack;
110  stack->push_back(node);
111 
112  bool dirty = false;
113  edge->outputs_ready_ = true;
114  edge->deps_missing_ = false;
115 
116  if (!edge->deps_loaded_) {
117  // This is our first encounter with this edge.
118  // If there is a pending dyndep file, visit it now:
119  // * If the dyndep file is ready then load it now to get any
120  // additional inputs and outputs for this and other edges.
121  // Once the dyndep file is loaded it will no longer be pending
122  // if any other edges encounter it, but they will already have
123  // been updated.
124  // * If the dyndep file is not ready then since is known to be an
125  // input to this edge, the edge will not be considered ready below.
126  // Later during the build the dyndep file will become ready and be
127  // loaded to update this edge before it can possibly be scheduled.
128  if (edge->dyndep_ && edge->dyndep_->dyndep_pending()) {
129  if (!RecomputeNodeDirty(edge->dyndep_, stack, validation_nodes, err))
130  return false;
131 
132  if (!edge->dyndep_->in_edge() ||
133  edge->dyndep_->in_edge()->outputs_ready()) {
134  // The dyndep file is ready, so load it now.
135  if (!LoadDyndeps(edge->dyndep_, err))
136  return false;
137  }
138  }
139  }
140 
141  // Load output mtimes so we can compare them to the most recent input below.
142  for (vector<Node*>::iterator o = edge->outputs_.begin();
143  o != edge->outputs_.end(); ++o) {
144  if (!(*o)->StatIfNecessary(disk_interface_, err))
145  return false;
146  }
147 
148  if (!edge->deps_loaded_) {
149  // This is our first encounter with this edge. Load discovered deps.
150  edge->deps_loaded_ = true;
151  if (!dep_loader_.LoadDeps(edge, err)) {
152  if (!err->empty())
153  return false;
154  // Failed to load dependency info: rebuild to regenerate it.
155  // LoadDeps() did EXPLAIN() already, no need to do it here.
156  dirty = edge->deps_missing_ = true;
157  }
158  }
159 
160  // Store any validation nodes from the edge for adding to the initial
161  // nodes. Don't recurse into them, that would trigger the dependency
162  // cycle detector if the validation node depends on this node.
163  // RecomputeDirty will add the validation nodes to the initial nodes
164  // and recurse into them.
165  validation_nodes->insert(validation_nodes->end(),
166  edge->validations_.begin(), edge->validations_.end());
167 
168  // Visit all inputs; we're dirty if any of the inputs are dirty.
169  Node* most_recent_input = NULL;
170  for (vector<Node*>::iterator i = edge->inputs_.begin();
171  i != edge->inputs_.end(); ++i) {
172  // Visit this input.
173  if (!RecomputeNodeDirty(*i, stack, validation_nodes, err))
174  return false;
175 
176  // If an input is not ready, neither are our outputs.
177  if (Edge* in_edge = (*i)->in_edge()) {
178  if (!in_edge->outputs_ready_)
179  edge->outputs_ready_ = false;
180  }
181 
182  if (!edge->is_order_only(i - edge->inputs_.begin())) {
183  // If a regular input is dirty (or missing), we're dirty.
184  // Otherwise consider mtime.
185  if ((*i)->dirty()) {
186  EXPLAIN("%s is dirty", (*i)->path().c_str());
187  dirty = true;
188  } else {
189  if (!most_recent_input || (*i)->mtime() > most_recent_input->mtime()) {
190  most_recent_input = *i;
191  }
192  }
193  }
194  }
195 
196  // We may also be dirty due to output state: missing outputs, out of
197  // date outputs, etc. Visit all outputs and determine whether they're dirty.
198  if (!dirty)
199  if (!RecomputeOutputsDirty(edge, most_recent_input, &dirty, err))
200  return false;
201 
202  // Finally, visit each output and update their dirty state if necessary.
203  for (vector<Node*>::iterator o = edge->outputs_.begin();
204  o != edge->outputs_.end(); ++o) {
205  if (dirty)
206  (*o)->MarkDirty();
207  }
208 
209  // If an edge is dirty, its outputs are normally not ready. (It's
210  // possible to be clean but still not be ready in the presence of
211  // order-only inputs.)
212  // But phony edges with no inputs have nothing to do, so are always
213  // ready.
214  if (dirty && !(edge->is_phony() && edge->inputs_.empty()))
215  edge->outputs_ready_ = false;
216 
217  // Mark the edge as finished during this walk now that it will no longer
218  // be in the call stack.
219  edge->mark_ = Edge::VisitDone;
220  assert(stack->back() == node);
221  stack->pop_back();
222 
223  return true;
224 }
225 
226 bool DependencyScan::VerifyDAG(Node* node, vector<Node*>* stack, string* err) {
227  Edge* edge = node->in_edge();
228  assert(edge != NULL);
229 
230  // If we have no temporary mark on the edge then we do not yet have a cycle.
231  if (edge->mark_ != Edge::VisitInStack)
232  return true;
233 
234  // We have this edge earlier in the call stack. Find it.
235  vector<Node*>::iterator start = stack->begin();
236  while (start != stack->end() && (*start)->in_edge() != edge)
237  ++start;
238  assert(start != stack->end());
239 
240  // Make the cycle clear by reporting its start as the node at its end
241  // instead of some other output of the starting edge. For example,
242  // running 'ninja b' on
243  // build a b: cat c
244  // build c: cat a
245  // should report a -> c -> a instead of b -> c -> a.
246  *start = node;
247 
248  // Construct the error message rejecting the cycle.
249  *err = "dependency cycle: ";
250  for (vector<Node*>::const_iterator i = start; i != stack->end(); ++i) {
251  err->append((*i)->path());
252  err->append(" -> ");
253  }
254  err->append((*start)->path());
255 
256  if ((start + 1) == stack->end() && edge->maybe_phonycycle_diagnostic()) {
257  // The manifest parser would have filtered out the self-referencing
258  // input if it were not configured to allow the error.
259  err->append(" [-w phonycycle=err]");
260  }
261 
262  return false;
263 }
264 
265 bool DependencyScan::RecomputeOutputsDirty(Edge* edge, Node* most_recent_input,
266  bool* outputs_dirty, string* err) {
267  string command = edge->EvaluateCommand(/*incl_rsp_file=*/true);
268  for (vector<Node*>::iterator o = edge->outputs_.begin();
269  o != edge->outputs_.end(); ++o) {
270  if (RecomputeOutputDirty(edge, most_recent_input, command, *o)) {
271  *outputs_dirty = true;
272  return true;
273  }
274  }
275  return true;
276 }
277 
279  const Node* most_recent_input,
280  const string& command,
281  Node* output) {
282  if (edge->is_phony()) {
283  // Phony edges don't write any output. Outputs are only dirty if
284  // there are no inputs and we're missing the output.
285  if (edge->inputs_.empty() && !output->exists()) {
286  EXPLAIN("output %s of phony edge with no inputs doesn't exist",
287  output->path().c_str());
288  return true;
289  }
290 
291  // Update the mtime with the newest input. Dependents can thus call mtime()
292  // on the fake node and get the latest mtime of the dependencies
293  if (most_recent_input) {
294  output->UpdatePhonyMtime(most_recent_input->mtime());
295  }
296 
297  // Phony edges are clean, nothing to do
298  return false;
299  }
300 
301  BuildLog::LogEntry* entry = 0;
302 
303  // Dirty if we're missing the output.
304  if (!output->exists()) {
305  EXPLAIN("output %s doesn't exist", output->path().c_str());
306  return true;
307  }
308 
309  // Dirty if the output is older than the input.
310  if (most_recent_input && output->mtime() < most_recent_input->mtime()) {
311  TimeStamp output_mtime = output->mtime();
312 
313  // If this is a restat rule, we may have cleaned the output with a restat
314  // rule in a previous run and stored the most recent input mtime in the
315  // build log. Use that mtime instead, so that the file will only be
316  // considered dirty if an input was modified since the previous run.
317  bool used_restat = false;
318  if (edge->GetBindingBool("restat") && build_log() &&
319  (entry = build_log()->LookupByOutput(output->path()))) {
320  output_mtime = entry->mtime;
321  used_restat = true;
322  }
323 
324  if (output_mtime < most_recent_input->mtime()) {
325  EXPLAIN("%soutput %s older than most recent input %s "
326  "(%" PRId64 " vs %" PRId64 ")",
327  used_restat ? "restat of " : "", output->path().c_str(),
328  most_recent_input->path().c_str(),
329  output_mtime, most_recent_input->mtime());
330  return true;
331  }
332  }
333 
334  if (build_log()) {
335  bool generator = edge->GetBindingBool("generator");
336  if (entry || (entry = build_log()->LookupByOutput(output->path()))) {
337  if (!generator &&
338  BuildLog::LogEntry::HashCommand(command) != entry->command_hash) {
339  // May also be dirty due to the command changing since the last build.
340  // But if this is a generator rule, the command changing does not make us
341  // dirty.
342  EXPLAIN("command line changed for %s", output->path().c_str());
343  return true;
344  }
345  if (most_recent_input && entry->mtime < most_recent_input->mtime()) {
346  // May also be dirty due to the mtime in the log being older than the
347  // mtime of the most recent input. This can occur even when the mtime
348  // on disk is newer if a previous run wrote to the output file but
349  // exited with an error or was interrupted.
350  EXPLAIN("recorded mtime of %s older than most recent input %s (%" PRId64 " vs %" PRId64 ")",
351  output->path().c_str(), most_recent_input->path().c_str(),
352  entry->mtime, most_recent_input->mtime());
353  return true;
354  }
355  }
356  if (!entry && !generator) {
357  EXPLAIN("command line not found in log for %s", output->path().c_str());
358  return true;
359  }
360  }
361 
362  return false;
363 }
364 
365 bool DependencyScan::LoadDyndeps(Node* node, string* err) const {
366  return dyndep_loader_.LoadDyndeps(node, err);
367 }
368 
370  string* err) const {
371  return dyndep_loader_.LoadDyndeps(node, ddf, err);
372 }
373 
374 bool Edge::AllInputsReady() const {
375  for (vector<Node*>::const_iterator i = inputs_.begin();
376  i != inputs_.end(); ++i) {
377  if ((*i)->in_edge() && !(*i)->in_edge()->outputs_ready())
378  return false;
379  }
380  return true;
381 }
382 
383 /// An Env for an Edge, providing $in and $out.
384 struct EdgeEnv : public Env {
385  enum EscapeKind { kShellEscape, kDoNotEscape };
386 
387  EdgeEnv(const Edge* const edge, const EscapeKind escape)
388  : edge_(edge), escape_in_out_(escape), recursive_(false) {}
389  virtual string LookupVariable(const string& var);
390 
391  /// Given a span of Nodes, construct a list of paths suitable for a command
392  /// line.
393  std::string MakePathList(const Node* const* span, size_t size, char sep) const;
394 
395  private:
396  vector<string> lookups_;
397  const Edge* const edge_;
400 };
401 
402 string EdgeEnv::LookupVariable(const string& var) {
403  if (var == "in" || var == "in_newline") {
404  int explicit_deps_count = edge_->inputs_.size() - edge_->implicit_deps_ -
405  edge_->order_only_deps_;
406 #if __cplusplus >= 201103L
407  return MakePathList(edge_->inputs_.data(), explicit_deps_count,
408 #else
409  return MakePathList(&edge_->inputs_[0], explicit_deps_count,
410 #endif
411  var == "in" ? ' ' : '\n');
412  } else if (var == "out") {
413  int explicit_outs_count = edge_->outputs_.size() - edge_->implicit_outs_;
414  return MakePathList(&edge_->outputs_[0], explicit_outs_count, ' ');
415  }
416 
417  if (recursive_) {
418  vector<string>::const_iterator it;
419  if ((it = find(lookups_.begin(), lookups_.end(), var)) != lookups_.end()) {
420  string cycle;
421  for (; it != lookups_.end(); ++it)
422  cycle.append(*it + " -> ");
423  cycle.append(var);
424  Fatal(("cycle in rule variables: " + cycle).c_str());
425  }
426  }
427 
428  // See notes on BindingEnv::LookupWithFallback.
429  const EvalString* eval = edge_->rule_->GetBinding(var);
430  if (recursive_ && eval)
431  lookups_.push_back(var);
432 
433  // In practice, variables defined on rules never use another rule variable.
434  // For performance, only start checking for cycles after the first lookup.
435  recursive_ = true;
436  return edge_->env_->LookupWithFallback(var, eval, this);
437 }
438 
439 std::string EdgeEnv::MakePathList(const Node* const* const span,
440  const size_t size, const char sep) const {
441  string result;
442  for (const Node* const* i = span; i != span + size; ++i) {
443  if (!result.empty())
444  result.push_back(sep);
445  const string& path = (*i)->PathDecanonicalized();
446  if (escape_in_out_ == kShellEscape) {
447 #ifdef _WIN32
448  GetWin32EscapedString(path, &result);
449 #else
450  GetShellEscapedString(path, &result);
451 #endif
452  } else {
453  result.append(path);
454  }
455  }
456  return result;
457 }
458 
459 void Edge::CollectInputs(bool shell_escape,
460  std::vector<std::string>* out) const {
461  for (std::vector<Node*>::const_iterator it = inputs_.begin();
462  it != inputs_.end(); ++it) {
463  std::string path = (*it)->PathDecanonicalized();
464  if (shell_escape) {
465  std::string unescaped;
466  unescaped.swap(path);
467 #ifdef _WIN32
468  GetWin32EscapedString(unescaped, &path);
469 #else
470  GetShellEscapedString(unescaped, &path);
471 #endif
472  }
473 #if __cplusplus >= 201103L
474  out->push_back(std::move(path));
475 #else
476  out->push_back(path);
477 #endif
478  }
479 }
480 
481 std::string Edge::EvaluateCommand(const bool incl_rsp_file) const {
482  string command = GetBinding("command");
483  if (incl_rsp_file) {
484  string rspfile_content = GetBinding("rspfile_content");
485  if (!rspfile_content.empty())
486  command += ";rspfile=" + rspfile_content;
487  }
488  return command;
489 }
490 
491 std::string Edge::GetBinding(const std::string& key) const {
492  EdgeEnv env(this, EdgeEnv::kShellEscape);
493  return env.LookupVariable(key);
494 }
495 
496 bool Edge::GetBindingBool(const string& key) const {
497  return !GetBinding(key).empty();
498 }
499 
501  EdgeEnv env(this, EdgeEnv::kDoNotEscape);
502  return env.LookupVariable("depfile");
503 }
504 
505 string Edge::GetUnescapedDyndep() const {
506  EdgeEnv env(this, EdgeEnv::kDoNotEscape);
507  return env.LookupVariable("dyndep");
508 }
509 
510 std::string Edge::GetUnescapedRspfile() const {
511  EdgeEnv env(this, EdgeEnv::kDoNotEscape);
512  return env.LookupVariable("rspfile");
513 }
514 
515 void Edge::Dump(const char* prefix) const {
516  printf("%s[ ", prefix);
517  for (vector<Node*>::const_iterator i = inputs_.begin();
518  i != inputs_.end() && *i != NULL; ++i) {
519  printf("%s ", (*i)->path().c_str());
520  }
521  printf("--%s-> ", rule_->name().c_str());
522  for (vector<Node*>::const_iterator i = outputs_.begin();
523  i != outputs_.end() && *i != NULL; ++i) {
524  printf("%s ", (*i)->path().c_str());
525  }
526  if (!validations_.empty()) {
527  printf(" validations ");
528  for (std::vector<Node*>::const_iterator i = validations_.begin();
529  i != validations_.end() && *i != NULL; ++i) {
530  printf("%s ", (*i)->path().c_str());
531  }
532  }
533  if (pool_) {
534  if (!pool_->name().empty()) {
535  printf("(in pool '%s')", pool_->name().c_str());
536  }
537  } else {
538  printf("(null pool?)");
539  }
540  printf("] 0x%p\n", this);
541 }
542 
543 bool Edge::is_phony() const {
544  return rule_ == &State::kPhonyRule;
545 }
546 
547 bool Edge::use_console() const {
548  return pool() == &State::kConsolePool;
549 }
550 
552  // CMake 2.8.12.x and 3.0.x produced self-referencing phony rules
553  // of the form "build a: phony ... a ...". Restrict our
554  // "phonycycle" diagnostic option to the form it used.
555  return is_phony() && outputs_.size() == 1 && implicit_outs_ == 0 &&
556  implicit_deps_ == 0;
557 }
558 
559 // static
560 string Node::PathDecanonicalized(const string& path, uint64_t slash_bits) {
561  string result = path;
562 #ifdef _WIN32
563  uint64_t mask = 1;
564  for (char* c = &result[0]; (c = strchr(c, '/')) != NULL;) {
565  if (slash_bits & mask)
566  *c = '\\';
567  c++;
568  mask <<= 1;
569  }
570 #endif
571  return result;
572 }
573 
574 void Node::Dump(const char* prefix) const {
575  printf("%s <%s 0x%p> mtime: %" PRId64 "%s, (:%s), ",
576  prefix, path().c_str(), this,
577  mtime(), exists() ? "" : " (:missing)",
578  dirty() ? " dirty" : " clean");
579  if (in_edge()) {
580  in_edge()->Dump("in-edge: ");
581  } else {
582  printf("no in-edge\n");
583  }
584  printf(" out edges:\n");
585  for (vector<Edge*>::const_iterator e = out_edges().begin();
586  e != out_edges().end() && *e != NULL; ++e) {
587  (*e)->Dump(" +- ");
588  }
589  if (!validation_out_edges().empty()) {
590  printf(" validation out edges:\n");
591  for (std::vector<Edge*>::const_iterator e = validation_out_edges().begin();
592  e != validation_out_edges().end() && *e != NULL; ++e) {
593  (*e)->Dump(" +- ");
594  }
595  }
596 }
597 
598 bool ImplicitDepLoader::LoadDeps(Edge* edge, string* err) {
599  string deps_type = edge->GetBinding("deps");
600  if (!deps_type.empty())
601  return LoadDepsFromLog(edge, err);
602 
603  string depfile = edge->GetUnescapedDepfile();
604  if (!depfile.empty())
605  return LoadDepFile(edge, depfile, err);
606 
607  // No deps to load.
608  return true;
609 }
610 
611 struct matches {
612  explicit matches(std::vector<StringPiece>::iterator i) : i_(i) {}
613 
614  bool operator()(const Node* node) const {
615  StringPiece opath = StringPiece(node->path());
616  return *i_ == opath;
617  }
618 
619  std::vector<StringPiece>::iterator i_;
620 };
621 
622 bool ImplicitDepLoader::LoadDepFile(Edge* edge, const string& path,
623  string* err) {
624  METRIC_RECORD("depfile load");
625  // Read depfile content. Treat a missing depfile as empty.
626  string content;
627  switch (disk_interface_->ReadFile(path, &content, err)) {
628  case DiskInterface::Okay:
629  break;
631  err->clear();
632  break;
634  *err = "loading '" + path + "': " + *err;
635  return false;
636  }
637  // On a missing depfile: return false and empty *err.
638  if (content.empty()) {
639  EXPLAIN("depfile '%s' is missing", path.c_str());
640  return false;
641  }
642 
643  DepfileParser depfile(depfile_parser_options_
644  ? *depfile_parser_options_
646  string depfile_err;
647  if (!depfile.Parse(&content, &depfile_err)) {
648  *err = path + ": " + depfile_err;
649  return false;
650  }
651 
652  if (depfile.outs_.empty()) {
653  *err = path + ": no outputs declared";
654  return false;
655  }
656 
657  uint64_t unused;
658  std::vector<StringPiece>::iterator primary_out = depfile.outs_.begin();
659  CanonicalizePath(const_cast<char*>(primary_out->str_), &primary_out->len_,
660  &unused);
661 
662  // Check that this depfile matches the edge's output, if not return false to
663  // mark the edge as dirty.
664  Node* first_output = edge->outputs_[0];
665  StringPiece opath = StringPiece(first_output->path());
666  if (opath != *primary_out) {
667  EXPLAIN("expected depfile '%s' to mention '%s', got '%s'", path.c_str(),
668  first_output->path().c_str(), primary_out->AsString().c_str());
669  return false;
670  }
671 
672  // Ensure that all mentioned outputs are outputs of the edge.
673  for (std::vector<StringPiece>::iterator o = depfile.outs_.begin();
674  o != depfile.outs_.end(); ++o) {
675  matches m(o);
676  if (std::find_if(edge->outputs_.begin(), edge->outputs_.end(), m) == edge->outputs_.end()) {
677  *err = path + ": depfile mentions '" + o->AsString() + "' as an output, but no such output was declared";
678  return false;
679  }
680  }
681 
682  return ProcessDepfileDeps(edge, &depfile.ins_, err);
683 }
684 
686  Edge* edge, std::vector<StringPiece>* depfile_ins, std::string* err) {
687  // Preallocate space in edge->inputs_ to be filled in below.
688  vector<Node*>::iterator implicit_dep =
689  PreallocateSpace(edge, depfile_ins->size());
690 
691  // Add all its in-edges.
692  for (std::vector<StringPiece>::iterator i = depfile_ins->begin();
693  i != depfile_ins->end(); ++i, ++implicit_dep) {
694  uint64_t slash_bits;
695  CanonicalizePath(const_cast<char*>(i->str_), &i->len_, &slash_bits);
696  Node* node = state_->GetNode(*i, slash_bits);
697  *implicit_dep = node;
698  node->AddOutEdge(edge);
699  CreatePhonyInEdge(node);
700  }
701 
702  return true;
703 }
704 
705 bool ImplicitDepLoader::LoadDepsFromLog(Edge* edge, string* err) {
706  // NOTE: deps are only supported for single-target edges.
707  Node* output = edge->outputs_[0];
708  DepsLog::Deps* deps = deps_log_ ? deps_log_->GetDeps(output) : NULL;
709  if (!deps) {
710  EXPLAIN("deps for '%s' are missing", output->path().c_str());
711  return false;
712  }
713 
714  // Deps are invalid if the output is newer than the deps.
715  if (output->mtime() > deps->mtime) {
716  EXPLAIN("stored deps info out of date for '%s' (%" PRId64 " vs %" PRId64 ")",
717  output->path().c_str(), deps->mtime, output->mtime());
718  return false;
719  }
720 
721  vector<Node*>::iterator implicit_dep =
722  PreallocateSpace(edge, deps->node_count);
723  for (int i = 0; i < deps->node_count; ++i, ++implicit_dep) {
724  Node* node = deps->nodes[i];
725  *implicit_dep = node;
726  node->AddOutEdge(edge);
727  CreatePhonyInEdge(node);
728  }
729  return true;
730 }
731 
732 vector<Node*>::iterator ImplicitDepLoader::PreallocateSpace(Edge* edge,
733  int count) {
734  edge->inputs_.insert(edge->inputs_.end() - edge->order_only_deps_,
735  (size_t)count, 0);
736  edge->implicit_deps_ += count;
737  return edge->inputs_.end() - edge->order_only_deps_ - count;
738 }
739 
741  if (node->in_edge())
742  return;
743 
744  Edge* phony_edge = state_->AddEdge(&State::kPhonyRule);
745  phony_edge->generated_by_dep_loader_ = true;
746  node->set_in_edge(phony_edge);
747  phony_edge->outputs_.push_back(node);
748 
749  // RecomputeDirty might not be called for phony_edge if a previous call
750  // to RecomputeDirty had caused the file to be stat'ed. Because previous
751  // invocations of RecomputeDirty would have seen this node without an
752  // input edge (and therefore ready), we have to set outputs_ready_ to true
753  // to avoid a potential stuck build. If we do call RecomputeDirty for
754  // this node, it will simply set outputs_ready_ to the correct value.
755  phony_edge->outputs_ready_ = true;
756 }
bool dyndep_pending() const
Definition: graph.h:101
bool RecomputeDirty(Node *node, std::vector< Node *> *validation_nodes, std::string *err)
Update the |dirty_| state of the given nodes by transitively inspecting their input edges...
Definition: graph.cc:50
An Env for an Edge, providing $in and $out.
Definition: graph.cc:384
bool Stat(DiskInterface *disk_interface, std::string *err)
Return false on error.
Definition: graph.cc:34
std::string MakePathList(const Node *const *span, size_t size, char sep) const
Given a span of Nodes, construct a list of paths suitable for a command line.
Definition: graph.cc:439
bool RecomputeOutputDirty(const Edge *edge, const Node *most_recent_input, const std::string &command, Node *output)
Recompute whether a given single output should be marked dirty.
Definition: graph.cc:278
int order_only_deps_
Definition: graph.h:229
void Dump(const char *prefix="") const
Definition: graph.cc:515
int implicit_deps_
Definition: graph.h:228
bool generated_by_dep_loader_
Definition: graph.h:213
Store data loaded from one dyndep file.
Definition: dyndep.h:40
VisitMark mark_
Definition: graph.h:208
void Dump(const char *prefix="") const
Definition: graph.cc:574
Edge * in_edge() const
Definition: graph.h:104
Parser for the dependency information emitted by gcc&#39;s -M flags.
std::vector< Node * > validations_
Definition: graph.h:205
void GetWin32EscapedString(const string &input, string *result)
Definition: util.cc:303
bool RecomputeOutputsDirty(Edge *edge, Node *most_recent_input, bool *dirty, std::string *err)
Recompute whether any output of the edge is dirty, if so sets |*dirty|.
Definition: graph.cc:265
StringPiece represents a slice of a string whose memory is managed externally.
Definition: string_piece.h:25
void set_dirty(bool dirty)
Definition: graph.h:98
Information about a node in the dependency graph: the file, whether it&#39;s dirty, mtime, etc.
Definition: graph.h:39
bool Parse(std::string *content, std::string *err)
Parse an input file.
virtual bool ProcessDepfileDeps(Edge *edge, std::vector< StringPiece > *depfile_ins, std::string *err)
Process loaded implicit dependencies for edge and update the graph.
Definition: graph.cc:685
void GetShellEscapedString(const string &input, string *result)
Definition: util.cc:276
bool outputs_ready() const
Definition: graph.h:218
std::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 ...
Definition: graph.cc:732
virtual string LookupVariable(const string &var)
Definition: graph.cc:402
Interface for accessing the disk.
bool StatIfNecessary(DiskInterface *disk_interface, std::string *err)
Return false on error.
Definition: graph.h:57
Node ** nodes
Definition: deps_log.h:85
bool LoadDyndeps(Node *node, std::string *err) const
Load a dyndep file from the given node&#39;s path and update the build graph with the new information...
std::vector< Node * > outputs_
Definition: graph.h:204
void AddOutEdge(Edge *edge)
Definition: graph.h:112
bool LoadDepsFromLog(Edge *edge, std::string *err)
Load implicit dependencies for edge from the DepsLog.
Definition: graph.cc:705
#define PRId64
Definition: win32port.h:33
An edge in the dependency graph; links between Nodes using Rules.
Definition: graph.h:164
bool LoadDepFile(Edge *edge, const std::string &path, std::string *err)
Load implicit dependencies for edge from a depfile attribute.
Definition: graph.cc:622
std::string PathDecanonicalized() const
Get |path()| but use slash_bits to convert back to original slash styles.
Definition: graph.h:88
std::vector< StringPiece > outs_
bool is_order_only(size_t index)
Definition: graph.h:234
const std::string & path() const
Definition: graph.h:86
vector< string > lookups_
Definition: graph.cc:396
EscapeKind escape_in_out_
Definition: graph.cc:398
void MarkDirty()
Definition: graph.h:99
EscapeKind
Definition: graph.cc:385
uint64_t command_hash
Definition: build_log.h:60
bool outputs_ready_
Definition: graph.h:210
bool RecomputeNodeDirty(Node *node, std::vector< Node *> *stack, std::vector< Node *> *validation_nodes, std::string *err)
Definition: graph.cc:83
bool recursive_
Definition: graph.cc:399
int node_count
Definition: deps_log.h:84
void UpdatePhonyMtime(TimeStamp mtime)
If the file doesn&#39;t exist, set the mtime_ from its dependencies.
Definition: graph.cc:44
std::vector< StringPiece > ins_
std::string GetUnescapedRspfile() const
Like GetBinding("rspfile"), but without shell escaping.
Definition: graph.cc:510
bool VerifyDAG(Node *node, std::vector< Node *> *stack, std::string *err)
Definition: graph.cc:226
static Pool kConsolePool
Definition: state.h:94
void CreatePhonyInEdge(Node *node)
If we don&#39;t have a edge that generates this input already, create one; this makes us not abort if the...
Definition: graph.cc:740
int64_t TimeStamp
Definition: timestamp.h:31
bool LoadDeps(Edge *edge, std::string *err)
Load implicit dependencies for edge.
Definition: graph.cc:598
#define METRIC_RECORD(name)
The primary interface to metrics.
Definition: metrics.h:84
std::vector< Node * > inputs_
Definition: graph.h:203
std::string GetUnescapedDepfile() const
Like GetBinding("depfile"), but without shell escaping.
Definition: graph.cc:500
bool status_known() const
Definition: graph.h:82
std::vector< StringPiece >::iterator i_
Definition: graph.cc:619
EdgeEnv(const Edge *const edge, const EscapeKind escape)
Definition: graph.cc:387
std::string GetBinding(const std::string &key) const
Returns the shell-escaped value of |key|.
Definition: graph.cc:491
void Fatal(const char *msg,...)
Log a fatal message and exit.
Definition: util.cc:65
TimeStamp mtime() const
Definition: graph.h:95
TimeStamp mtime
Definition: build_log.h:63
static uint64_t HashCommand(StringPiece command)
Definition: build_log.cc:111
bool operator()(const Node *node) const
Definition: graph.cc:614
std::string EvaluateCommand(bool incl_rsp_file=false) const
Expand all variables in a command and return it as a string.
Definition: graph.cc:481
bool AllInputsReady() const
Return true if all inputs&#39; in-edges are ready.
Definition: graph.cc:374
bool maybe_phonycycle_diagnostic() const
Definition: graph.cc:551
void CanonicalizePath(string *path, uint64_t *slash_bits)
Definition: util.cc:122
void set_in_edge(Edge *edge)
Definition: graph.h:105
bool deps_loaded_
Definition: graph.h:211
unsigned long long uint64_t
Definition: win32port.h:29
TimeStamp mtime
Definition: deps_log.h:83
bool is_phony() const
Definition: graph.cc:543
matches(std::vector< StringPiece >::iterator i)
Definition: graph.cc:612
bool use_console() const
Definition: graph.cc:547
virtual TimeStamp Stat(const std::string &path, std::string *err) const =0
stat() a file, returning the mtime, or 0 if missing and -1 on other errors.
bool GetBindingBool(const std::string &key) const
Definition: graph.cc:496
void CollectInputs(bool shell_escape, std::vector< std::string > *out) const
Definition: graph.cc:459
A tokenized string that contains variable references.
Definition: eval_env.h:34
An interface for a scope for variable (e.g. "$foo") lookups.
Definition: eval_env.h:27
std::string GetUnescapedDyndep() const
Like GetBinding("dyndep"), but without shell escaping.
Definition: graph.cc:505
bool exists() const
Definition: graph.h:78
Node * dyndep_
Definition: graph.h:206
bool deps_missing_
Definition: graph.h:212
#define EXPLAIN(fmt,...)
Definition: debug_flags.h:20
const Edge *const edge_
Definition: graph.cc:397
static const Rule kPhonyRule
Definition: state.h:95