• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Stat(DiskInterface * disk_interface,string * err)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 
UpdatePhonyMtime(TimeStamp mtime)44 void Node::UpdatePhonyMtime(TimeStamp mtime) {
45   if (!exists()) {
46     mtime_ = std::max(mtime_, mtime);
47   }
48 }
49 
RecomputeDirty(Node * initial_node,std::vector<Node * > * validation_nodes,string * err)50 bool DependencyScan::RecomputeDirty(Node* initial_node,
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 
RecomputeNodeDirty(Node * node,std::vector<Node * > * stack,std::vector<Node * > * validation_nodes,string * err)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 
VerifyDAG(Node * node,vector<Node * > * stack,string * err)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 
RecomputeOutputsDirty(Edge * edge,Node * most_recent_input,bool * outputs_dirty,string * err)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 
RecomputeOutputDirty(const Edge * edge,const Node * most_recent_input,const string & command,Node * output)278 bool DependencyScan::RecomputeOutputDirty(const Edge* edge,
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 
LoadDyndeps(Node * node,string * err) const365 bool DependencyScan::LoadDyndeps(Node* node, string* err) const {
366   return dyndep_loader_.LoadDyndeps(node, err);
367 }
368 
LoadDyndeps(Node * node,DyndepFile * ddf,string * err) const369 bool DependencyScan::LoadDyndeps(Node* node, DyndepFile* ddf,
370                                  string* err) const {
371   return dyndep_loader_.LoadDyndeps(node, ddf, err);
372 }
373 
AllInputsReady() const374 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 
EdgeEnvEdgeEnv387   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_;
398   EscapeKind escape_in_out_;
399   bool recursive_;
400 };
401 
LookupVariable(const string & var)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 
MakePathList(const Node * const * const span,const size_t size,const char sep) const439 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 
CollectInputs(bool shell_escape,std::vector<std::string> * out) const459 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 
EvaluateCommand(const bool incl_rsp_file) const481 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 
GetBinding(const std::string & key) const491 std::string Edge::GetBinding(const std::string& key) const {
492   EdgeEnv env(this, EdgeEnv::kShellEscape);
493   return env.LookupVariable(key);
494 }
495 
GetBindingBool(const string & key) const496 bool Edge::GetBindingBool(const string& key) const {
497   return !GetBinding(key).empty();
498 }
499 
GetUnescapedDepfile() const500 string Edge::GetUnescapedDepfile() const {
501   EdgeEnv env(this, EdgeEnv::kDoNotEscape);
502   return env.LookupVariable("depfile");
503 }
504 
GetUnescapedDyndep() const505 string Edge::GetUnescapedDyndep() const {
506   EdgeEnv env(this, EdgeEnv::kDoNotEscape);
507   return env.LookupVariable("dyndep");
508 }
509 
GetUnescapedRspfile() const510 std::string Edge::GetUnescapedRspfile() const {
511   EdgeEnv env(this, EdgeEnv::kDoNotEscape);
512   return env.LookupVariable("rspfile");
513 }
514 
Dump(const char * prefix) const515 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 
is_phony() const543 bool Edge::is_phony() const {
544   return rule_ == &State::kPhonyRule;
545 }
546 
use_console() const547 bool Edge::use_console() const {
548   return pool() == &State::kConsolePool;
549 }
550 
maybe_phonycycle_diagnostic() const551 bool Edge::maybe_phonycycle_diagnostic() const {
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
PathDecanonicalized(const string & path,uint64_t slash_bits)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 
Dump(const char * prefix) const574 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 
LoadDeps(Edge * edge,string * err)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 {
matchesmatches612   explicit matches(std::vector<StringPiece>::iterator i) : i_(i) {}
613 
operator ()matches614   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 
LoadDepFile(Edge * edge,const string & path,string * err)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;
630   case DiskInterface::NotFound:
631     err->clear();
632     break;
633   case DiskInterface::OtherError:
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_
645                         : DepfileParserOptions());
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 
ProcessDepfileDeps(Edge * edge,std::vector<StringPiece> * depfile_ins,std::string * err)685 bool ImplicitDepLoader::ProcessDepfileDeps(
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 
LoadDepsFromLog(Edge * edge,string * err)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 
PreallocateSpace(Edge * edge,int count)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 
CreatePhonyInEdge(Node * node)740 void ImplicitDepLoader::CreatePhonyInEdge(Node* node) {
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 }
757