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
32using namespace std;
33
34bool Node::Stat(DiskInterface* disk_interface, string* err) {
35 mtime_ = disk_interface->Stat(path_, err);
36 if (mtime_ == -1) {
37 return false;
38 }
40 return true;
41}
42
44 if (!exists()) {
45 mtime_ = std::max(mtime_, mtime);
46 }
47}
48
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
82bool 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 explanations_.Record(node, "%s has no in-edge and is missing",
95 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.
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 explanations_->Record() 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 explanations_.Record(node, "%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
226bool 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
265bool 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 explanations_.Record(
287 output, "output %s of phony edge with no inputs doesn't exist",
288 output->path().c_str());
289 return true;
290 }
291
292 // Update the mtime with the newest input. Dependents can thus call mtime()
293 // on the fake node and get the latest mtime of the dependencies
294 if (most_recent_input) {
295 output->UpdatePhonyMtime(most_recent_input->mtime());
296 }
297
298 // Phony edges are clean, nothing to do
299 return false;
300 }
301
302 // Dirty if we're missing the output.
303 if (!output->exists()) {
304 explanations_.Record(output, "output %s doesn't exist",
305 output->path().c_str());
306 return true;
307 }
308
309 BuildLog::LogEntry* entry = 0;
310
311 // If this is a restat rule, we may have cleaned the output in a
312 // previous run and stored the command start time in the build log.
313 // We don't want to consider a restat rule's outputs as dirty unless
314 // an input changed since the last run, so we'll skip checking the
315 // output file's actual mtime and simply check the recorded mtime from
316 // the log against the most recent input's mtime (see below)
317 bool used_restat = false;
318 if (edge->GetBindingBool("restat") && build_log() &&
319 (entry = build_log()->LookupByOutput(output->path()))) {
320 used_restat = true;
321 }
322
323 // Dirty if the output is older than the input.
324 if (!used_restat && most_recent_input && output->mtime() < most_recent_input->mtime()) {
325 explanations_.Record(output,
326 "output %s older than most recent input %s "
327 "(%" PRId64 " vs %" PRId64 ")",
328 output->path().c_str(),
329 most_recent_input->path().c_str(), output->mtime(),
330 most_recent_input->mtime());
331 return true;
332 }
333
334 if (build_log()) {
335 bool generator = edge->GetBindingBool("generator");
336 if (entry || (entry = build_log()->LookupByOutput(output->path()))) {
337 if (!generator &&
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 explanations_.Record(output, "command line changed for %s",
343 output->path().c_str());
344 return true;
345 }
346 if (most_recent_input && entry->mtime < most_recent_input->mtime()) {
347 // May also be dirty due to the mtime in the log being older than the
348 // mtime of the most recent input. This can occur even when the mtime
349 // on disk is newer if a previous run wrote to the output file but
350 // exited with an error or was interrupted. If this was a restat rule,
351 // then we only check the recorded mtime against the most recent input
352 // mtime and ignore the actual output's mtime above.
353 explanations_.Record(
354 output,
355 "recorded mtime of %s older than most recent input %s (%" PRId64
356 " vs %" PRId64 ")",
357 output->path().c_str(), most_recent_input->path().c_str(),
358 entry->mtime, most_recent_input->mtime());
359 return true;
360 }
361 }
362 if (!entry && !generator) {
363 explanations_.Record(output, "command line not found in log for %s",
364 output->path().c_str());
365 return true;
366 }
367 }
368
369 return false;
370}
371
372bool DependencyScan::LoadDyndeps(Node* node, string* err) const {
373 return dyndep_loader_.LoadDyndeps(node, err);
374}
375
377 string* err) const {
378 return dyndep_loader_.LoadDyndeps(node, ddf, err);
379}
380
382 for (vector<Node*>::const_iterator i = inputs_.begin();
383 i != inputs_.end(); ++i) {
384 if ((*i)->in_edge() && !(*i)->in_edge()->outputs_ready())
385 return false;
386 }
387 return true;
388}
389
390/// An Env for an Edge, providing $in and $out.
391struct EdgeEnv : public Env {
393
394 EdgeEnv(const Edge* const edge, const EscapeKind escape)
395 : edge_(edge), escape_in_out_(escape), recursive_(false) {}
396 virtual string LookupVariable(const string& var);
397
398 /// Given a span of Nodes, construct a list of paths suitable for a command
399 /// line.
400 std::string MakePathList(const Node* const* span, size_t size, char sep) const;
401
402 private:
403 std::vector<std::string> lookups_;
404 const Edge* const edge_;
407};
408
409string EdgeEnv::LookupVariable(const string& var) {
410 if (var == "in" || var == "in_newline") {
411 int explicit_deps_count =
412 static_cast<int>(edge_->inputs_.size() - edge_->implicit_deps_ -
413 edge_->order_only_deps_);
414 return MakePathList(edge_->inputs_.data(), explicit_deps_count,
415 var == "in" ? ' ' : '\n');
416 } else if (var == "out") {
417 int explicit_outs_count =
418 static_cast<int>(edge_->outputs_.size() - edge_->implicit_outs_);
419 return MakePathList(&edge_->outputs_[0], explicit_outs_count, ' ');
420 }
421
422 // Technical note about the lookups_ vector.
423 //
424 // This is used to detect cycles during recursive variable expansion
425 // which can be seen as a graph traversal problem. Consider the following
426 // example:
427 //
428 // rule something
429 // command = $foo $foo $var1
430 // var1 = $var2
431 // var2 = $var3
432 // var3 = $var1
433 // foo = FOO
434 //
435 // Each variable definition can be seen as a node in a graph that looks
436 // like the following:
437 //
438 // command --> foo
439 // |
440 // v
441 // var1 <-----.
442 // | |
443 // v |
444 // var2 ---> var3
445 //
446 // The lookups_ vector is used as a stack of visited nodes/variables
447 // during recursive expansion. Entering a node adds an item to the
448 // stack, leaving the node removes it.
449 //
450 // The recursive_ flag is used as a small performance optimization
451 // to never record the starting node in the stack when beginning a new
452 // expansion, since in most cases, expansions are not recursive
453 // at all.
454 //
455 if (recursive_) {
456 auto it = std::find(lookups_.begin(), lookups_.end(), var);
457 if (it != lookups_.end()) {
458 std::string cycle;
459 for (; it != lookups_.end(); ++it)
460 cycle.append(*it + " -> ");
461 cycle.append(var);
462 Fatal(("cycle in rule variables: " + cycle).c_str());
463 }
464 }
465
466 // See notes on BindingEnv::LookupWithFallback.
467 const EvalString* eval = edge_->rule_->GetBinding(var);
468 bool record_varname = recursive_ && eval;
469 if (record_varname)
470 lookups_.push_back(var);
471
472 // In practice, variables defined on rules never use another rule variable.
473 // For performance, only start checking for cycles after the first lookup.
474 recursive_ = true;
475 std::string result = edge_->env_->LookupWithFallback(var, eval, this);
476 if (record_varname)
477 lookups_.pop_back();
478 return result;
479}
480
481std::string EdgeEnv::MakePathList(const Node* const* const span,
482 const size_t size, const char sep) const {
483 string result;
484 for (const Node* const* i = span; i != span + size; ++i) {
485 if (!result.empty())
486 result.push_back(sep);
487 const string& path = (*i)->PathDecanonicalized();
489#ifdef _WIN32
490 GetWin32EscapedString(path, &result);
491#else
492 GetShellEscapedString(path, &result);
493#endif
494 } else {
495 result.append(path);
496 }
497 }
498 return result;
499}
500
501std::string Edge::EvaluateCommand(const bool incl_rsp_file) const {
502 string command = GetBinding("command");
503 if (incl_rsp_file) {
504 string rspfile_content = GetBinding("rspfile_content");
505 if (!rspfile_content.empty())
506 command += ";rspfile=" + rspfile_content;
507 }
508 return command;
509}
510
511std::string Edge::GetBinding(const std::string& key) const {
513 return env.LookupVariable(key);
514}
515
516bool Edge::GetBindingBool(const string& key) const {
517 return !GetBinding(key).empty();
518}
519
522 return env.LookupVariable("depfile");
523}
524
527 return env.LookupVariable("dyndep");
528}
529
530std::string Edge::GetUnescapedRspfile() const {
532 return env.LookupVariable("rspfile");
533}
534
535void Edge::Dump(const char* prefix) const {
536 printf("%s[ ", prefix);
537 for (vector<Node*>::const_iterator i = inputs_.begin();
538 i != inputs_.end() && *i != NULL; ++i) {
539 printf("%s ", (*i)->path().c_str());
540 }
541 printf("--%s-> ", rule_->name().c_str());
542 for (vector<Node*>::const_iterator i = outputs_.begin();
543 i != outputs_.end() && *i != NULL; ++i) {
544 printf("%s ", (*i)->path().c_str());
545 }
546 if (!validations_.empty()) {
547 printf(" validations ");
548 for (std::vector<Node*>::const_iterator i = validations_.begin();
549 i != validations_.end() && *i != NULL; ++i) {
550 printf("%s ", (*i)->path().c_str());
551 }
552 }
553 if (pool_) {
554 if (!pool_->name().empty()) {
555 printf("(in pool '%s')", pool_->name().c_str());
556 }
557 } else {
558 printf("(null pool?)");
559 }
560 printf("] 0x%p\n", this);
561}
562
563bool Edge::is_phony() const {
564 return rule_->IsPhony();
565}
566
567bool Edge::use_console() const {
568 return pool() == &State::kConsolePool;
569}
570
572 // CMake 2.8.12.x and 3.0.x produced self-referencing phony rules
573 // of the form "build a: phony ... a ...". Restrict our
574 // "phonycycle" diagnostic option to the form it used.
575 return is_phony() && outputs_.size() == 1 && implicit_outs_ == 0 &&
576 implicit_deps_ == 0;
577}
578
579// static
580string Node::PathDecanonicalized(const string& path, uint64_t slash_bits) {
581 string result = path;
582#ifdef _WIN32
583 uint64_t mask = 1;
584 for (char* c = &result[0]; (c = strchr(c, '/')) != NULL;) {
585 if (slash_bits & mask)
586 *c = '\\';
587 c++;
588 mask <<= 1;
589 }
590#endif
591 return result;
592}
593
594void Node::Dump(const char* prefix) const {
595 printf("%s <%s 0x%p> mtime: %" PRId64 "%s, (:%s), ",
596 prefix, path().c_str(), this,
597 mtime(), exists() ? "" : " (:missing)",
598 dirty() ? " dirty" : " clean");
599 if (in_edge()) {
600 in_edge()->Dump("in-edge: ");
601 } else {
602 printf("no in-edge\n");
603 }
604 printf(" out edges:\n");
605 for (vector<Edge*>::const_iterator e = out_edges().begin();
606 e != out_edges().end() && *e != NULL; ++e) {
607 (*e)->Dump(" +- ");
608 }
609 if (!validation_out_edges().empty()) {
610 printf(" validation out edges:\n");
611 for (std::vector<Edge*>::const_iterator e = validation_out_edges().begin();
612 e != validation_out_edges().end() && *e != NULL; ++e) {
613 (*e)->Dump(" +- ");
614 }
615 }
616}
617
618bool ImplicitDepLoader::LoadDeps(Edge* edge, string* err) {
619 string deps_type = edge->GetBinding("deps");
620 if (!deps_type.empty())
621 return LoadDepsFromLog(edge, err);
622
623 string depfile = edge->GetUnescapedDepfile();
624 if (!depfile.empty())
625 return LoadDepFile(edge, depfile, err);
626
627 // No deps to load.
628 return true;
629}
630
631struct matches {
632 explicit matches(std::vector<StringPiece>::iterator i) : i_(i) {}
633
634 bool operator()(const Node* node) const {
635 StringPiece opath = StringPiece(node->path());
636 return *i_ == opath;
637 }
638
639 std::vector<StringPiece>::iterator i_;
640};
641
642bool ImplicitDepLoader::LoadDepFile(Edge* edge, const string& path,
643 string* err) {
644 METRIC_RECORD("depfile load");
645 // Read depfile content. Treat a missing depfile as empty.
646 string content;
647 switch (disk_interface_->ReadFile(path, &content, err)) {
649 break;
651 err->clear();
652 break;
654 *err = "loading '" + path + "': " + *err;
655 return false;
656 }
657 // On a missing depfile: return false and empty *err.
658 Node* first_output = edge->outputs_[0];
659 if (content.empty()) {
660 explanations_.Record(first_output, "depfile '%s' is missing", path.c_str());
661 return false;
662 }
663
667 string depfile_err;
668 if (!depfile.Parse(&content, &depfile_err)) {
669 *err = path + ": " + depfile_err;
670 return false;
671 }
672
673 if (depfile.outs_.empty()) {
674 *err = path + ": no outputs declared";
675 return false;
676 }
677
678 uint64_t unused;
679 std::vector<StringPiece>::iterator primary_out = depfile.outs_.begin();
680 CanonicalizePath(const_cast<char*>(primary_out->str_), &primary_out->len_,
681 &unused);
682
683 // Check that this depfile matches the edge's output, if not return false to
684 // mark the edge as dirty.
685 StringPiece opath = StringPiece(first_output->path());
686 if (opath != *primary_out) {
687 explanations_.Record(first_output,
688 "expected depfile '%s' to mention '%s', got '%s'",
689 path.c_str(), first_output->path().c_str(),
690 primary_out->AsString().c_str());
691 return false;
692 }
693
694 // Ensure that all mentioned outputs are outputs of the edge.
695 for (std::vector<StringPiece>::iterator o = depfile.outs_.begin();
696 o != depfile.outs_.end(); ++o) {
697 matches m(o);
698 if (std::find_if(edge->outputs_.begin(), edge->outputs_.end(), m) == edge->outputs_.end()) {
699 *err = path + ": depfile mentions '" + o->AsString() + "' as an output, but no such output was declared";
700 return false;
701 }
702 }
703
704 return ProcessDepfileDeps(edge, &depfile.ins_, err);
705}
706
708 Edge* edge, std::vector<StringPiece>* depfile_ins, std::string* err) {
709 // Preallocate space in edge->inputs_ to be filled in below.
710 vector<Node*>::iterator implicit_dep =
711 PreallocateSpace(edge, static_cast<int>(depfile_ins->size()));
712
713 // Add all its in-edges.
714 for (std::vector<StringPiece>::iterator i = depfile_ins->begin();
715 i != depfile_ins->end(); ++i, ++implicit_dep) {
716 uint64_t slash_bits;
717 CanonicalizePath(const_cast<char*>(i->str_), &i->len_, &slash_bits);
718 Node* node = state_->GetNode(*i, slash_bits);
719 *implicit_dep = node;
720 node->AddOutEdge(edge);
721 }
722
723 return true;
724}
725
726bool ImplicitDepLoader::LoadDepsFromLog(Edge* edge, string* err) {
727 // NOTE: deps are only supported for single-target edges.
728 Node* output = edge->outputs_[0];
729 DepsLog::Deps* deps = deps_log_ ? deps_log_->GetDeps(output) : NULL;
730 if (!deps) {
731 explanations_.Record(output, "deps for '%s' are missing",
732 output->path().c_str());
733 return false;
734 }
735
736 // Deps are invalid if the output is newer than the deps.
737 if (output->mtime() > deps->mtime) {
738 explanations_.Record(output,
739 "stored deps info out of date for '%s' (%" PRId64
740 " vs %" PRId64 ")",
741 output->path().c_str(), deps->mtime, output->mtime());
742 return false;
743 }
744
745 Node** nodes = deps->nodes;
746 size_t node_count = deps->node_count;
747 edge->inputs_.insert(edge->inputs_.end() - edge->order_only_deps_,
748 nodes, nodes + node_count);
749 edge->implicit_deps_ += node_count;
750 for (size_t i = 0; i < node_count; ++i) {
751 nodes[i]->AddOutEdge(edge);
752 }
753 return true;
754}
755
756vector<Node*>::iterator ImplicitDepLoader::PreallocateSpace(Edge* edge,
757 int count) {
758 edge->inputs_.insert(edge->inputs_.end() - edge->order_only_deps_,
759 (size_t)count, 0);
760 edge->implicit_deps_ += count;
761 return edge->inputs_.end() - edge->order_only_deps_ - count;
762}
763
765 const Edge* edge = node->in_edge();
766
767 if (!edge) // A source file.
768 return;
769
770 // Add inputs of the producing edge to the result,
771 // except if they are themselves produced by a phony
772 // edge.
773 for (const Node* input : edge->inputs_) {
774 if (!visited_nodes_.insert(input).second)
775 continue;
776
777 VisitNode(input);
778
779 const Edge* input_edge = input->in_edge();
780 if (!(input_edge && input_edge->is_phony())) {
781 inputs_.push_back(input);
782 }
783 }
784}
785
786std::vector<std::string> InputsCollector::GetInputsAsStrings(
787 bool shell_escape) const {
788 std::vector<std::string> result;
789 result.reserve(inputs_.size());
790
791 for (const Node* input : inputs_) {
792 std::string unescaped = input->PathDecanonicalized();
793 if (shell_escape) {
794 std::string path;
795#ifdef _WIN32
796 GetWin32EscapedString(unescaped, &path);
797#else
798 GetShellEscapedString(unescaped, &path);
799#endif
800 result.push_back(std::move(path));
801 } else {
802 result.push_back(std::move(unescaped));
803 }
804 }
805 return result;
806}
#define METRIC_RECORD(name)
The primary interface to metrics.
Definition metrics.h:83
Definition hash_map.h:26
TimeStamp mtime
Definition build_log.h:65
uint64_t command_hash
Definition build_log.h:62
static uint64_t HashCommand(StringPiece command)
Definition build_log.cc:60
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
bool RecomputeNodeDirty(Node *node, std::vector< Node * > *stack, std::vector< Node * > *validation_nodes, std::string *err)
Definition graph.cc:82
bool VerifyDAG(Node *node, std::vector< Node * > *stack, std::string *err)
Definition graph.cc:226
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
DiskInterface * disk_interface_
Definition graph.h:387
bool LoadDyndeps(Node *node, std::string *err) const
Load a dyndep file from the given node's path and update the build graph with the new information.
OptionalExplanations explanations_
Definition graph.h:390
DyndepLoader dyndep_loader_
Definition graph.h:389
BuildLog * build_log() const
Definition graph.h:356
ImplicitDepLoader dep_loader_
Definition graph.h:388
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:49
Parser for the dependency information emitted by gcc's -M flags.
bool Parse(std::string *content, std::string *err)
Parse an input file.
std::vector< StringPiece > outs_
std::vector< StringPiece > ins_
TimeStamp mtime
Definition deps_log.h:84
Node ** nodes
Definition deps_log.h:86
Interface for accessing the disk.
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.
Store data loaded from one dyndep file.
Definition dyndep.h:42
bool LoadDyndeps(Node *node, std::string *err) const
Load a dyndep file from the given node's path and update the build graph with the new information.
Definition dyndep.cc:30
An Env for an Edge, providing $in and $out.
Definition graph.cc:391
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:481
std::vector< std::string > lookups_
Definition graph.cc:403
const Edge *const edge_
Definition graph.cc:404
virtual string LookupVariable(const string &var)
Definition graph.cc:409
bool recursive_
Definition graph.cc:406
EscapeKind escape_in_out_
Definition graph.cc:405
EscapeKind
Definition graph.cc:392
@ kShellEscape
Definition graph.cc:392
@ kDoNotEscape
Definition graph.cc:392
EdgeEnv(const Edge *const edge, const EscapeKind escape)
Definition graph.cc:394
An edge in the dependency graph; links between Nodes using Rules.
Definition graph.h:175
std::string GetBinding(const std::string &key) const
Returns the shell-escaped value of |key|.
Definition graph.cc:511
bool maybe_phonycycle_diagnostic() const
Definition graph.cc:571
std::string GetUnescapedDyndep() const
Like GetBinding("dyndep"), but without shell escaping.
Definition graph.cc:525
std::vector< Node * > outputs_
Definition graph.h:217
VisitMark mark_
Definition graph.h:221
bool outputs_ready() const
Definition graph.h:233
int implicit_deps_
Definition graph.h:243
Node * dyndep_
Definition graph.h:219
bool is_order_only(size_t index)
Definition graph.h:249
const Rule * rule_
Definition graph.h:214
@ VisitInStack
Definition graph.h:178
@ VisitDone
Definition graph.h:179
int order_only_deps_
Definition graph.h:244
Pool * pool() const
Definition graph.h:231
bool is_phony() const
Definition graph.cc:563
bool GetBindingBool(const std::string &key) const
Definition graph.cc:516
Pool * pool_
Definition graph.h:215
bool deps_loaded_
Definition graph.h:225
int implicit_outs_
Definition graph.h:258
std::string EvaluateCommand(bool incl_rsp_file=false) const
Expand all variables in a command and return it as a string.
Definition graph.cc:501
void Dump(const char *prefix="") const
Definition graph.cc:535
bool use_console() const
Definition graph.cc:567
std::vector< Node * > validations_
Definition graph.h:218
std::vector< Node * > inputs_
Definition graph.h:216
bool deps_missing_
Definition graph.h:226
std::string GetUnescapedRspfile() const
Like GetBinding("rspfile"), but without shell escaping.
Definition graph.cc:530
std::string GetUnescapedDepfile() const
Like GetBinding("depfile"), but without shell escaping.
Definition graph.cc:520
bool AllInputsReady() const
Return true if all inputs' in-edges are ready.
Definition graph.cc:381
bool outputs_ready_
Definition graph.h:224
An interface for a scope for variable (e.g. "$foo") lookups.
Definition eval_env.h:28
A tokenized string that contains variable references.
Definition eval_env.h:35
bool LoadDepFile(Edge *edge, const std::string &path, std::string *err)
Load implicit dependencies for edge from a depfile attribute.
Definition graph.cc:642
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:756
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:707
bool LoadDeps(Edge *edge, std::string *err)
Load implicit dependencies for edge.
Definition graph.cc:618
bool LoadDepsFromLog(Edge *edge, std::string *err)
Load implicit dependencies for edge from the DepsLog.
Definition graph.cc:726
State * state_
Definition graph.h:322
DepsLog * deps_log_
Definition graph.h:324
DiskInterface * disk_interface_
Definition graph.h:323
OptionalExplanations explanations_
Definition graph.h:326
DepfileParserOptions const * depfile_parser_options_
Definition graph.h:325
void VisitNode(const Node *node)
Visit a single.
Definition graph.cc:764
std::vector< const Node * > inputs_
Definition graph.h:462
std::set< const Node * > visited_nodes_
Definition graph.h:463
std::vector< std::string > GetInputsAsStrings(bool shell_escape=false) const
Same as inputs(), but returns the list of visited nodes as a list of strings, with optional shell esc...
Definition graph.cc:786
Information about a node in the dependency graph: the file, whether it's dirty, mtime,...
Definition graph.h:42
void set_dirty(bool dirty)
Definition graph.h:94
const std::string & path() const
Definition graph.h:82
void UpdatePhonyMtime(TimeStamp mtime)
If the file doesn't exist, set the mtime_ from its dependencies.
Definition graph.cc:43
Edge * in_edge() const
Definition graph.h:100
void Dump(const char *prefix="") const
Definition graph.cc:594
TimeStamp mtime_
Possible values of mtime_: -1: file hasn't been examined 0: we looked, and file doesn't exist >0: act...
Definition graph.h:132
bool dirty() const
Definition graph.h:93
const std::vector< Edge * > & validation_out_edges() const
Definition graph.h:115
@ ExistenceStatusMissing
The file doesn't exist. mtime_ will be the latest mtime of its dependencies.
Definition graph.h:138
@ ExistenceStatusExists
The path is an actual file. mtime_ will be the file's mtime.
Definition graph.h:140
void AddOutEdge(Edge *edge)
Definition graph.h:116
bool status_known() const
Definition graph.h:78
bool dyndep_pending() const
Definition graph.h:97
bool exists() const
Definition graph.h:74
ExistenceStatus exists_
Definition graph.h:142
std::string PathDecanonicalized() const
Get |path()| but use slash_bits to convert back to original slash styles.
Definition graph.h:84
TimeStamp mtime() const
Definition graph.h:91
bool StatIfNecessary(DiskInterface *disk_interface, std::string *err)
Return false on error.
Definition graph.h:53
std::string path_
Definition graph.h:122
const std::vector< Edge * > & out_edges() const
Definition graph.h:114
bool Stat(DiskInterface *disk_interface, std::string *err)
Return false on error.
Definition graph.cc:34
uint64_t slash_bits() const
Definition graph.h:89
static Pool kConsolePool
Definition state.h:97
StringPiece represents a slice of a string whose memory is managed externally.
std::vector< StringPiece >::iterator i_
Definition graph.cc:639
bool operator()(const Node *node) const
Definition graph.cc:634
matches(std::vector< StringPiece >::iterator i)
Definition graph.cc:632
int64_t TimeStamp
Definition timestamp.h:31
void GetWin32EscapedString(const string &input, string *result)
Definition util.cc:380
void GetShellEscapedString(const string &input, string *result)
Definition util.cc:353
void CanonicalizePath(string *path, uint64_t *slash_bits)
Definition util.cc:124
void Fatal(const char *msg,...)
Log a fatal message and exit.
Definition util.cc:67
unsigned long long uint64_t
Definition win32port.h:29
#define PRId64
Definition win32port.h:33