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