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