46 for (
int i = 0; i < count; ++i) {
58 EXPECT_TRUE(plan_.
AddTarget(GetNode(node), &err));
64 void TestPoolWithDepthOne(
const char *test_case);
69 "build out: cat mid\n"
70 "build mid: cat in\n"));
71 GetNode(
"mid")->MarkDirty();
72 GetNode(
"out")->MarkDirty();
73 PrepareForTarget(
"out");
75 Edge* edge = plan_.FindWork();
77 ASSERT_EQ(
"in", edge->
inputs_[0]->path());
78 ASSERT_EQ(
"mid", edge->
outputs_[0]->path());
80 ASSERT_FALSE(plan_.FindWork());
86 edge = plan_.FindWork();
88 ASSERT_EQ(
"mid", edge->
inputs_[0]->path());
89 ASSERT_EQ(
"out", edge->
outputs_[0]->path());
94 ASSERT_FALSE(plan_.more_to_do());
95 edge = plan_.FindWork();
102 "build out: cat mid1 mid2\n"
103 "build mid1 mid2: cat in\n"));
104 GetNode(
"mid1")->MarkDirty();
105 GetNode(
"mid2")->MarkDirty();
106 GetNode(
"out")->MarkDirty();
107 PrepareForTarget(
"out");
110 edge = plan_.FindWork();
116 edge = plan_.FindWork();
121 edge = plan_.FindWork();
128 "build out: cat b1 b2\n"
131 "build a1 a2: cat in\n"));
132 GetNode(
"a1")->MarkDirty();
133 GetNode(
"a2")->MarkDirty();
134 GetNode(
"b1")->MarkDirty();
135 GetNode(
"b2")->MarkDirty();
136 GetNode(
"out")->MarkDirty();
137 PrepareForTarget(
"out");
140 edge = plan_.FindWork();
146 edge = plan_.FindWork();
151 edge = plan_.FindWork();
156 edge = plan_.FindWork();
161 edge = plan_.FindWork();
168 "build out: cat a1 a2\n"
169 "build a1: cat mid\n"
170 "build a2: cat mid\n"
171 "build mid: cat in\n"));
172 GetNode(
"mid")->MarkDirty();
173 GetNode(
"a1")->MarkDirty();
174 GetNode(
"a2")->MarkDirty();
175 GetNode(
"out")->MarkDirty();
176 PrepareForTarget(
"out");
179 edge = plan_.FindWork();
185 edge = plan_.FindWork();
190 edge = plan_.FindWork();
195 edge = plan_.FindWork();
200 edge = plan_.FindWork();
205 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state_, test_case));
206 GetNode(
"out1")->MarkDirty();
207 GetNode(
"out2")->MarkDirty();
209 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out1"), &err));
211 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out2"), &err));
213 plan_.PrepareQueue();
214 ASSERT_TRUE(plan_.more_to_do());
216 Edge* edge = plan_.FindWork();
218 ASSERT_EQ(
"in", edge->
inputs_[0]->path());
219 ASSERT_EQ(
"out1", edge->
outputs_[0]->path());
222 ASSERT_FALSE(plan_.FindWork());
227 edge = plan_.FindWork();
229 ASSERT_EQ(
"in", edge->
inputs_[0]->path());
230 ASSERT_EQ(
"out2", edge->
outputs_[0]->path());
232 ASSERT_FALSE(plan_.FindWork());
237 ASSERT_FALSE(plan_.more_to_do());
238 edge = plan_.FindWork();
243 TestPoolWithDepthOne(
247 " command = cat $in > $out\n"
249 "build out1: poolcat in\n"
250 "build out2: poolcat in\n");
254 TestPoolWithDepthOne(
256 " command = cat $in > $out\n"
258 "build out1: poolcat in\n"
259 "build out2: poolcat in\n");
269 " command = cat $in > $out\n"
272 " command = cat $in > $out\n"
274 "build out1: foocat in\n"
275 "build out2: foocat in\n"
276 "build out3: foocat in\n"
277 "build outb1: bazcat in\n"
278 "build outb2: bazcat in\n"
279 "build outb3: bazcat in\n"
281 "build allTheThings: cat out1 out2 out3 outb1 outb2 outb3\n"
284 for (
int i = 0; i < 3; ++i) {
285 GetNode(
"out" +
string(1,
'1' +
static_cast<char>(i)))->MarkDirty();
286 GetNode(
"outb" +
string(1,
'1' +
static_cast<char>(i)))->MarkDirty();
288 GetNode(
"allTheThings")->MarkDirty();
289 PrepareForTarget(
"allTheThings");
292 FindWorkSorted(&edges, 5);
294 for (
int i = 0; i < 4; ++i) {
295 Edge *edge = edges[i];
296 ASSERT_EQ(
"in", edge->
inputs_[0]->path());
297 string base_name(i < 2 ?
"out" :
"outb");
298 ASSERT_EQ(base_name +
string(1,
'1' + (i % 2)), edge->
outputs_[0]->path());
302 Edge* edge = edges[4];
304 ASSERT_EQ(
"in", edge->
inputs_[0]->path());
305 ASSERT_EQ(
"outb3", edge->
outputs_[0]->path());
314 Edge* out3 = plan_.FindWork();
316 ASSERT_EQ(
"in", out3->
inputs_[0]->path());
317 ASSERT_EQ(
"out3", out3->
outputs_[0]->path());
319 ASSERT_FALSE(plan_.FindWork());
324 ASSERT_FALSE(plan_.FindWork());
326 for (deque<Edge*>::iterator it = edges.begin(); it != edges.end(); ++it) {
331 Edge* last = plan_.FindWork();
333 ASSERT_EQ(
"allTheThings", last->
outputs_[0]->path());
338 ASSERT_FALSE(plan_.more_to_do());
339 ASSERT_FALSE(plan_.FindWork());
347 " command = touch foo.cpp\n"
349 " command = touch bar.cpp\n"
351 " command = echo $out > $out\n"
352 "build foo.cpp.obj: echo foo.cpp || foo.cpp\n"
354 "build bar.cpp.obj: echo bar.cpp || bar.cpp\n"
356 "build libfoo.a: echo foo.cpp.obj bar.cpp.obj\n"
357 "build foo.cpp: gen_foo\n"
358 "build bar.cpp: gen_bar\n"
359 "build all: phony libfoo.a\n"));
360 GetNode(
"foo.cpp")->MarkDirty();
361 GetNode(
"foo.cpp.obj")->MarkDirty();
362 GetNode(
"bar.cpp")->MarkDirty();
363 GetNode(
"bar.cpp.obj")->MarkDirty();
364 GetNode(
"libfoo.a")->MarkDirty();
365 GetNode(
"all")->MarkDirty();
366 PrepareForTarget(
"all");
370 deque<Edge*> initial_edges;
371 FindWorkSorted(&initial_edges, 2);
373 edge = initial_edges[1];
374 ASSERT_EQ(
"foo.cpp", edge->
outputs_[0]->path());
379 edge = plan_.FindWork();
381 ASSERT_FALSE(plan_.FindWork());
382 ASSERT_EQ(
"foo.cpp", edge->
inputs_[0]->path());
383 ASSERT_EQ(
"foo.cpp", edge->
inputs_[1]->path());
384 ASSERT_EQ(
"foo.cpp.obj", edge->
outputs_[0]->path());
388 edge = initial_edges[0];
389 ASSERT_EQ(
"bar.cpp", edge->
outputs_[0]->path());
393 edge = plan_.FindWork();
395 ASSERT_FALSE(plan_.FindWork());
396 ASSERT_EQ(
"bar.cpp", edge->
inputs_[0]->path());
397 ASSERT_EQ(
"bar.cpp", edge->
inputs_[1]->path());
398 ASSERT_EQ(
"bar.cpp.obj", edge->
outputs_[0]->path());
402 edge = plan_.FindWork();
404 ASSERT_FALSE(plan_.FindWork());
405 ASSERT_EQ(
"foo.cpp.obj", edge->
inputs_[0]->path());
406 ASSERT_EQ(
"bar.cpp.obj", edge->
inputs_[1]->path());
407 ASSERT_EQ(
"libfoo.a", edge->
outputs_[0]->path());
411 edge = plan_.FindWork();
413 ASSERT_FALSE(plan_.FindWork());
414 ASSERT_EQ(
"libfoo.a", edge->
inputs_[0]->path());
415 ASSERT_EQ(
"all", edge->
outputs_[0]->path());
419 edge = plan_.FindWork();
421 ASSERT_FALSE(plan_.more_to_do());
429 " command = cat $in > $out\n"
431 "build out1: poolcat in\n"
432 "build out2: poolcat in\n"));
433 GetNode(
"out1")->MarkDirty();
434 GetNode(
"out2")->MarkDirty();
436 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out1"), &err));
438 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out2"), &err));
440 plan_.PrepareQueue();
441 ASSERT_TRUE(plan_.more_to_do());
443 Edge* edge = plan_.FindWork();
445 ASSERT_EQ(
"in", edge->
inputs_[0]->path());
446 ASSERT_EQ(
"out1", edge->
outputs_[0]->path());
449 ASSERT_FALSE(plan_.FindWork());
454 edge = plan_.FindWork();
456 ASSERT_EQ(
"in", edge->
inputs_[0]->path());
457 ASSERT_EQ(
"out2", edge->
outputs_[0]->path());
459 ASSERT_FALSE(plan_.FindWork());
464 ASSERT_TRUE(plan_.more_to_do());
465 edge = plan_.FindWork();
482 " command = unused\n"
483 "build out: r a0 b0 c0\n"
489 GetNode(
"a1")->MarkDirty();
490 GetNode(
"a0")->MarkDirty();
491 GetNode(
"b0")->MarkDirty();
492 GetNode(
"c0")->MarkDirty();
493 GetNode(
"out")->MarkDirty();
495 PrepareForTarget(
"out", &log);
497 EXPECT_EQ(GetNode(
"out")->in_edge()->critical_path_weight(), 1);
498 EXPECT_EQ(GetNode(
"a0")->in_edge()->critical_path_weight(), 2);
499 EXPECT_EQ(GetNode(
"b0")->in_edge()->critical_path_weight(), 2);
500 EXPECT_EQ(GetNode(
"c0")->in_edge()->critical_path_weight(), 2);
501 EXPECT_EQ(GetNode(
"a1")->in_edge()->critical_path_weight(), 3);
503 const int n_edges = 5;
504 const char *expected_order[n_edges] = {
505 "a1",
"a0",
"b0",
"c0",
"out"};
506 for (
int i = 0; i < n_edges; ++i) {
507 Edge* edge = plan_.FindWork();
508 ASSERT_TRUE(edge !=
nullptr);
509 EXPECT_EQ(expected_order[i], edge->
outputs_[0]->path());
516 EXPECT_FALSE(plan_.FindWork());
522 max_active_edges_(1), fs_(fs) {}
525 virtual size_t CanRunMore()
const;
526 virtual bool StartCommand(
Edge* edge);
527 virtual bool WaitForCommand(Result* result);
528 virtual vector<Edge*> GetActiveEdges();
529 virtual void Abort();
538 BuildTest() : config_(MakeConfig()), command_runner_(&fs_), status_(config_),
539 builder_(&state_, config_, NULL, NULL, &fs_, &status_, 0) {
543 : config_(MakeConfig()), command_runner_(&fs_), status_(config_),
544 builder_(&state_, config_, NULL, log, &fs_, &status_, 0) {}
547 StateTestWithBuiltinRules::SetUp();
549 builder_.command_runner_.reset(&command_runner_);
551 "build cat1: cat in1\n"
552 "build cat2: cat in1 in2\n"
553 "build cat12: cat cat1 cat2\n");
555 fs_.Create(
"in1",
"");
556 fs_.Create(
"in2",
"");
560 builder_.command_runner_.release();
568 void RebuildTarget(
const string& target,
const char* manifest,
569 const char* log_path = NULL,
const char* deps_path = NULL,
570 State* state = NULL);
573 void Dirty(
const string& path);
589 const char* log_path,
const char* deps_path,
591 State local_state, *pstate = &local_state;
594 ASSERT_NO_FATAL_FAILURE(AddCatRule(pstate));
598 BuildLog build_log, *pbuild_log = NULL;
600 ASSERT_TRUE(build_log.
Load(log_path, &err));
601 ASSERT_TRUE(build_log.
OpenForWrite(log_path, *
this, &err));
603 pbuild_log = &build_log;
606 DepsLog deps_log, *pdeps_log = NULL;
608 ASSERT_TRUE(deps_log.
Load(deps_path, pstate, &err));
611 pdeps_log = &deps_log;
614 Builder builder(pstate, config_, pbuild_log, pdeps_log, &fs_, &status_, 0);
615 EXPECT_TRUE(builder.
AddTarget(target, &err));
617 command_runner_.commands_ran_.clear();
627 if (active_edges_.size() < max_active_edges_)
634 assert(active_edges_.size() < max_active_edges_);
635 assert(find(active_edges_.begin(), active_edges_.end(), edge)
636 == active_edges_.end());
640 edge->
rule().
name() ==
"cat_rsp_out" ||
642 edge->
rule().
name() ==
"cp_multi_msvc" ||
643 edge->
rule().
name() ==
"cp_multi_gcc" ||
645 edge->
rule().
name() ==
"touch-interrupt" ||
646 edge->
rule().
name() ==
"touch-fail-tick2") {
647 for (vector<Node*>::iterator out = edge->
outputs_.begin();
648 out != edge->
outputs_.end(); ++out) {
649 fs_->Create((*out)->path(),
"");
651 }
else if (edge->
rule().
name() ==
"true" ||
653 edge->
rule().
name() ==
"interrupt" ||
656 }
else if (edge->
rule().
name() ==
"cp") {
657 assert(!edge->
inputs_.empty());
661 if (fs_->ReadFile(edge->
inputs_[0]->path(), &content, &err) ==
663 fs_->WriteFile(edge->
outputs_[0]->path(), content,
false);
664 }
else if (edge->
rule().
name() ==
"touch-implicit-dep-out") {
665 string dep = edge->
GetBinding(
"test_dependency");
667 fs_->Create(dep,
"");
669 for (vector<Node*>::iterator out = edge->
outputs_.begin();
670 out != edge->
outputs_.end(); ++out) {
671 fs_->Create((*out)->path(),
"");
673 }
else if (edge->
rule().
name() ==
"touch-out-implicit-dep") {
674 string dep = edge->
GetBinding(
"test_dependency");
675 for (vector<Node*>::iterator out = edge->
outputs_.begin();
676 out != edge->
outputs_.end(); ++out) {
677 fs_->Create((*out)->path(),
"");
680 fs_->Create(dep,
"");
681 }
else if (edge->
rule().
name() ==
"generate-depfile") {
682 string dep = edge->
GetBinding(
"test_dependency");
687 fs_->Create(dep,
"");
690 for (vector<Node*>::iterator out = edge->
outputs_.begin();
691 out != edge->
outputs_.end(); ++out) {
692 contents += (*out)->path() +
": " + dep +
"\n";
693 fs_->Create((*out)->path(),
"");
695 fs_->Create(depfile, contents);
696 }
else if (edge->
rule().
name() ==
"long-cc") {
697 string dep = edge->
GetBinding(
"test_dependency");
700 for (vector<Node*>::iterator out = edge->
outputs_.begin();
701 out != edge->
outputs_.end(); ++out) {
705 fs_->Create((*out)->path(),
"");
706 contents += (*out)->path() +
": " + dep +
"\n";
708 if (!dep.empty() && !depfile.empty())
709 fs_->Create(depfile, contents);
711 printf(
"unknown command\n");
715 active_edges_.push_back(edge);
718 sort(active_edges_.begin(), active_edges_.end(),
725 if (active_edges_.empty())
731 vector<Edge*>::iterator edge_iter = active_edges_.end() - 1;
733 Edge* edge = *edge_iter;
736 if (edge->
rule().
name() ==
"interrupt" ||
737 edge->
rule().
name() ==
"touch-interrupt") {
742 if (edge->
rule().
name() ==
"console") {
747 active_edges_.erase(edge_iter);
751 if (edge->
rule().
name() ==
"cp_multi_msvc") {
752 const std::string prefix = edge->
GetBinding(
"msvc_deps_prefix");
753 for (std::vector<Node*>::iterator in = edge->
inputs_.begin();
754 in != edge->
inputs_.end(); ++in) {
755 result->
output += prefix + (*in)->path() +
'\n';
759 if (edge->
rule().
name() ==
"fail" ||
760 (edge->
rule().
name() ==
"touch-fail-tick2" && fs_->now_ == 2))
769 if (edge->
rule().
name() ==
"long-cc") {
770 string dep = edge->
GetBinding(
"test_dependency");
772 fs_->files_[dep].mtime = 3;
774 fs_->files_[dep].mtime = 9;
780 const string& verify_active_edge = edge->
GetBinding(
"verify_active_edge");
781 if (!verify_active_edge.empty()) {
782 bool verify_active_edge_found =
false;
783 for (vector<Edge*>::iterator i = active_edges_.begin();
784 i != active_edges_.end(); ++i) {
785 if (!(*i)->outputs_.empty() &&
786 (*i)->outputs_[0]->path() == verify_active_edge) {
787 verify_active_edge_found =
true;
790 EXPECT_TRUE(verify_active_edge_found);
793 active_edges_.erase(edge_iter);
798 return active_edges_;
802 active_edges_.clear();
806 Node* node = GetNode(path);
817 EXPECT_TRUE(builder_.AlreadyUpToDate());
825 EXPECT_TRUE(builder_.AddTarget(
"cat1", &err));
830 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
831 EXPECT_EQ(
"cat in1 > cat1", command_runner_.commands_ran_[0]);
839 EXPECT_TRUE(builder_.AddTarget(
"cat1", &err));
844 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
845 EXPECT_EQ(
"cat in1 > cat1", command_runner_.commands_ran_[0]);
850 EXPECT_TRUE(builder_.AddTarget(
"cat12", &err));
854 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
857 EXPECT_TRUE((command_runner_.commands_ran_[0] ==
"cat in1 > cat1" &&
858 command_runner_.commands_ran_[1] ==
"cat in1 in2 > cat2") ||
859 (command_runner_.commands_ran_[1] ==
"cat in1 > cat1" &&
860 command_runner_.commands_ran_[0] ==
"cat in1 in2 > cat2"));
862 EXPECT_EQ(
"cat cat1 cat2 > cat12", command_runner_.commands_ran_[2]);
868 fs_.Create(
"in2",
"");
870 EXPECT_TRUE(builder_.AddTarget(
"cat12", &err));
874 ASSERT_EQ(5u, command_runner_.commands_ran_.size());
875 EXPECT_EQ(
"cat in1 in2 > cat2", command_runner_.commands_ran_[3]);
876 EXPECT_EQ(
"cat cat1 cat2 > cat12", command_runner_.commands_ran_[4]);
882 " command = touch $out\n"
883 "build out1 out2: touch in.txt\n"));
885 fs_.Create(
"in.txt",
"");
888 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
892 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
893 EXPECT_EQ(
"touch out1 out2", command_runner_.commands_ran_[0]);
899 " command = touch $out $out.imp\n"
900 "build out | out.imp: touch in.txt\n"));
901 fs_.Create(
"in.txt",
"");
904 EXPECT_TRUE(builder_.AddTarget(
"out.imp", &err));
908 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
909 EXPECT_EQ(
"touch out out.imp", command_runner_.commands_ran_[0]);
917 " command = touch $out\n"
918 "build in1 otherfile: touch in\n"
919 "build out: touch in | in1\n"));
921 fs_.Create(
"in",
"");
923 fs_.Create(
"in1",
"");
926 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
937 "build c5: cat c4\n"));
939 fs_.Create(
"c1",
"");
942 EXPECT_TRUE(builder_.AddTarget(
"c5", &err));
946 ASSERT_EQ(4u, command_runner_.commands_ran_.size());
949 command_runner_.commands_ran_.clear();
951 EXPECT_TRUE(builder_.AddTarget(
"c5", &err));
953 EXPECT_TRUE(builder_.AlreadyUpToDate());
957 fs_.Create(
"c3",
"");
959 command_runner_.commands_ran_.clear();
961 EXPECT_TRUE(builder_.AddTarget(
"c5", &err));
963 EXPECT_FALSE(builder_.AlreadyUpToDate());
965 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
972 EXPECT_FALSE(builder_.AddTarget(
"cat1", &err));
973 EXPECT_EQ(
"'in1', needed by 'cat1', missing and no known rule to make it",
980 EXPECT_FALSE(builder_.AddTarget(
"meow", &err));
981 EXPECT_EQ(
"unknown target: 'meow'", err);
988 EXPECT_FALSE(builder_.AddTarget(
"in1", &err));
989 EXPECT_EQ(
"'in1' missing and no known rule to make it", err);
997 "build subdir\\dir2\\file: cat in1\n"));
1000 "build subdir/dir2/file: cat in1\n"));
1002 EXPECT_TRUE(builder_.AddTarget(
"subdir/dir2/file", &err));
1007 ASSERT_EQ(2u, fs_.directories_made_.size());
1008 EXPECT_EQ(
"subdir", fs_.directories_made_[0]);
1009 EXPECT_EQ(
"subdir/dir2", fs_.directories_made_[1]);
1015 "rule cc\n command = cc $in\n depfile = $out.d\n"
1016 "build fo$ o.o: cc foo.c\n"));
1017 fs_.Create(
"foo.c",
"");
1019 EXPECT_TRUE(builder_.AddTarget(
"fo o.o", &err));
1021 ASSERT_EQ(1u, fs_.files_read_.size());
1022 EXPECT_EQ(
"fo o.o.d", fs_.files_read_[0]);
1027 int orig_edges =
static_cast<int>(state_.edges_.size());
1029 "rule cc\n command = cc $in\n depfile = $out.d\n"
1030 "build foo.o: cc foo.c\n"));
1031 Edge* edge = state_.edges_.back();
1033 fs_.Create(
"foo.c",
"");
1034 GetNode(
"bar.h")->MarkDirty();
1035 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
1036 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
1038 ASSERT_EQ(1u, fs_.files_read_.size());
1039 EXPECT_EQ(
"foo.o.d", fs_.files_read_[0]);
1043 ASSERT_EQ(orig_edges + 1, (
int)state_.edges_.size());
1047 ASSERT_FALSE(state_.LookupNode(
"foo.o")->generated_by_dep_loader());
1048 ASSERT_FALSE(state_.LookupNode(
"foo.c")->generated_by_dep_loader());
1049 ASSERT_TRUE(state_.LookupNode(
"blah.h"));
1050 ASSERT_TRUE(state_.LookupNode(
"blah.h")->generated_by_dep_loader());
1051 ASSERT_TRUE(state_.LookupNode(
"bar.h"));
1052 ASSERT_TRUE(state_.LookupNode(
"bar.h")->generated_by_dep_loader());
1055 ASSERT_EQ(3u, edge->
inputs_.size());
1064 "rule cc\n command = cc $in\n depfile = $out.d\n"
1065 "build foo.o: cc foo.c\n"));
1066 fs_.Create(
"foo.c",
"");
1067 fs_.Create(
"foo.o.d",
"randomtext\n");
1068 EXPECT_FALSE(builder_.AddTarget(
"foo.o", &err));
1069 EXPECT_EQ(
"foo.o.d: expected ':' in depfile", err);
1076 " command = touch $out\n"
1078 "build b: touch || c\n"
1079 "build a: touch | b || c\n"));
1081 vector<Edge*> c_out = GetNode(
"c")->out_edges();
1082 ASSERT_EQ(2u, c_out.size());
1083 EXPECT_EQ(
"b", c_out[0]->outputs_[0]->path());
1084 EXPECT_EQ(
"a", c_out[1]->outputs_[0]->path());
1086 fs_.Create(
"b",
"");
1087 EXPECT_TRUE(builder_.AddTarget(
"a", &err));
1092 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1098 "rule cc\n command = cc $in\n depfile = $out.d\n"
1099 "build foo.o: cc foo.c || otherfile\n"));
1100 Edge* edge = state_.edges_.back();
1102 fs_.Create(
"foo.c",
"");
1103 fs_.Create(
"otherfile",
"");
1104 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
1105 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
1109 ASSERT_EQ(4u, edge->
inputs_.size());
1114 EXPECT_EQ(
"foo.c", edge->
inputs_[0]->path());
1115 EXPECT_EQ(
"blah.h", edge->
inputs_[1]->path());
1116 EXPECT_EQ(
"bar.h", edge->
inputs_[2]->path());
1117 EXPECT_EQ(
"otherfile", edge->
inputs_[3]->path());
1125 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1130 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
1133 fs_.Create(
"blah.h",
"");
1134 fs_.Create(
"bar.h",
"");
1135 command_runner_.commands_ran_.clear();
1137 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
1140 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1145 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
1148 fs_.Create(
"otherfile",
"");
1149 command_runner_.commands_ran_.clear();
1151 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
1153 EXPECT_TRUE(builder_.AlreadyUpToDate());
1156 fs_.RemoveFile(
"bar.h");
1157 command_runner_.commands_ran_.clear();
1159 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
1162 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1168 "rule cc\n command = cc $in\n"
1169 "rule true\n command = true\n"
1170 "build oo.h: cc oo.h.in\n"
1171 "build foo.o: cc foo.c || oo.h\n"));
1173 fs_.Create(
"foo.c",
"");
1174 fs_.Create(
"oo.h.in",
"");
1177 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
1180 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1183 command_runner_.commands_ran_.clear();
1185 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
1187 EXPECT_TRUE(builder_.AlreadyUpToDate());
1190 fs_.RemoveFile(
"oo.h");
1191 command_runner_.commands_ran_.clear();
1193 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
1196 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1197 ASSERT_EQ(
"cc oo.h.in", command_runner_.commands_ran_[0]);
1202 fs_.Create(
"oo.h.in",
"");
1203 command_runner_.commands_ran_.clear();
1205 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
1208 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1209 ASSERT_EQ(
"cc oo.h.in", command_runner_.commands_ran_[0]);
1215 int orig_edges = state_.edges_.size();
1217 "rule cc\n command = cc $in\n depfile = $out.d\n"
1218 "build gen/stuff\\things/foo.o: cc x\\y/z\\foo.c\n"));
1220 fs_.Create(
"x/y/z/foo.c",
"");
1221 GetNode(
"bar.h")->MarkDirty();
1223 fs_.Create(
"gen/stuff\\things/foo.o.d",
1224 "gen\\stuff\\things\\foo.o: blah.h bar.h\n");
1225 EXPECT_TRUE(builder_.AddTarget(
"gen/stuff/things/foo.o", &err));
1227 ASSERT_EQ(1u, fs_.files_read_.size());
1229 EXPECT_EQ(
"gen/stuff\\things/foo.o.d", fs_.files_read_[0]);
1232 ASSERT_EQ(orig_edges + 1, (
int)state_.edges_.size());
1234 Edge* edge = state_.edges_.back();
1235 ASSERT_EQ(3u, edge->
inputs_.size());
1246 "build out: cat bar.cc\n"
1247 "build all: phony out\n"));
1248 fs_.Create(
"bar.cc",
"");
1250 EXPECT_TRUE(builder_.AddTarget(
"all", &err));
1254 EXPECT_FALSE(builder_.AlreadyUpToDate());
1257 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1263 "build out: cat bar.cc\n"
1264 "build all: phony out\n"));
1265 fs_.Create(
"bar.cc",
"");
1266 fs_.Create(
"out",
"");
1268 EXPECT_TRUE(builder_.AddTarget(
"all", &err));
1270 EXPECT_TRUE(builder_.AlreadyUpToDate());
1279 "build a: phony a\n"));
1281 EXPECT_TRUE(builder_.AddTarget(
"a", &err));
1283 EXPECT_TRUE(builder_.AlreadyUpToDate());
1315 " command = touch $out\n"
1316 "build notreal: phony blank\n"
1317 "build phony1: phony notreal\n"
1318 "build phony2: phony\n"
1319 "build phony3: phony blank\n"
1320 "build phony4: phony notreal\n"
1321 "build phony5: phony\n"
1322 "build phony6: phony blank\n"
1324 "build test1: touch phony1\n"
1325 "build test2: touch phony2\n"
1326 "build test3: touch phony3\n"
1327 "build test4: touch phony4\n"
1328 "build test5: touch phony5\n"
1329 "build test6: touch phony6\n"
1337 EXPECT_TRUE(builder_.
AddTarget(
"test1", &err));
1339 EXPECT_TRUE(builder_.
AddTarget(
"test2", &err));
1341 EXPECT_TRUE(builder_.
AddTarget(
"test3", &err));
1343 EXPECT_TRUE(builder_.
AddTarget(
"test4", &err));
1345 EXPECT_TRUE(builder_.
AddTarget(
"test5", &err));
1347 EXPECT_TRUE(builder_.
AddTarget(
"test6", &err));
1353 ci +=
static_cast<char>(
'0' + i);
1356 if (i != 2 && i != 5) {
1365 EXPECT_TRUE(builder_.
AddTarget(
"test" + ci, &err));
1377 EXPECT_TRUE(builder_.
AddTarget(
"test" + ci, &err));
1386 EXPECT_EQ(
string(
"touch test") + ci, command_runner_.
commands_ran_[0]);
1391 EXPECT_FALSE(phonyNode->
exists());
1392 EXPECT_FALSE(phonyNode->
dirty());
1394 EXPECT_GT(phonyNode->
mtime(), startTime);
1395 EXPECT_EQ(phonyNode->
mtime(), inputTime);
1396 ASSERT_TRUE(testNode->
Stat(&fs_, &err));
1397 EXPECT_TRUE(testNode->
exists());
1398 EXPECT_GT(testNode->
mtime(), startTime);
1406 EXPECT_TRUE(builder_.
AddTarget(
"test" + ci, &err));
1412 EXPECT_EQ(
"touch test" + ci, command_runner_.
commands_ran_[0]);
1416 EXPECT_TRUE(builder_.
AddTarget(
"test" + ci, &err));
1422 EXPECT_EQ(
"touch test" + ci, command_runner_.
commands_ran_[0]);
1437 "build out1: fail\n"));
1440 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1444 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1445 ASSERT_EQ(
"subcommand failed", err);
1452 "build out1: fail\n"
1453 "build out2: fail\n"
1454 "build out3: fail\n"
1455 "build all: phony out1 out2 out3\n"));
1458 config_.failures_allowed = 3;
1461 EXPECT_TRUE(builder_.AddTarget(
"all", &err));
1465 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1466 ASSERT_EQ(
"subcommands failed", err);
1473 "build out1: fail\n"
1474 "build out2: fail\n"
1475 "build out3: fail\n"
1476 "build final: cat out1 out2 out3\n"));
1479 config_.failures_allowed = 11;
1482 EXPECT_TRUE(builder_.AddTarget(
"final", &err));
1486 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1487 ASSERT_EQ(
"cannot make progress due to previous errors", err);
1496 " pool = failpool\n"
1497 "build out1: fail\n"
1498 "build out2: fail\n"
1499 "build out3: fail\n"
1500 "build final: cat out1 out2 out3\n"));
1503 config_.failures_allowed = 11;
1506 EXPECT_TRUE(builder_.AddTarget(
"final", &err));
1510 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1511 ASSERT_EQ(
"cannot make progress due to previous errors", err);
1515 fs_.Create(
"x",
"");
1517 const char* manifest =
1521 " command = touch $out\n"
1522 " pool = some_pool\n"
1524 " command = touch grit\n"
1526 "build B.d.stamp: cc | x\n"
1527 "build C.stamp: touch B.d.stamp\n"
1528 "build final.stamp: touch || C.stamp\n";
1530 RebuildTarget(
"final.stamp", manifest);
1532 fs_.RemoveFile(
"B.d.stamp");
1535 RebuildTarget(
"final.stamp", manifest, NULL, NULL, &save_state);
1541 builder_.SetBuildLog(&build_log_);
1550 " command = touch $out\n"
1552 "build out.imp: touch | in\n"));
1553 fs_.Create(
"out.imp",
"");
1555 fs_.Create(
"in",
"");
1559 EXPECT_TRUE(builder_.AddTarget(
"out.imp", &err));
1560 EXPECT_FALSE(builder_.AlreadyUpToDate());
1562 EXPECT_TRUE(GetNode(
"out.imp")->dirty());
1567 "rule touch-implicit-dep-out\n"
1568 " command = sleep 1 ; touch $test_dependency ; sleep 1 ; touch $out\n"
1570 "build out.imp: touch-implicit-dep-out | inimp inimp2\n"
1571 " test_dependency = inimp\n"));
1572 fs_.Create(
"inimp",
"");
1573 fs_.Create(
"out.imp",
"");
1575 fs_.Create(
"inimp2",
"");
1580 EXPECT_TRUE(builder_.AddTarget(
"out.imp", &err));
1581 EXPECT_FALSE(builder_.AlreadyUpToDate());
1584 EXPECT_TRUE(builder_.AlreadyUpToDate());
1586 command_runner_.commands_ran_.clear();
1589 builder_.plan_.Reset();
1591 EXPECT_TRUE(builder_.AddTarget(
"out.imp", &err));
1592 EXPECT_TRUE(builder_.AlreadyUpToDate());
1593 EXPECT_FALSE(GetNode(
"out.imp")->dirty());
1595 command_runner_.commands_ran_.clear();
1598 builder_.plan_.Reset();
1601 fs_.Create(
"inimp",
"");
1603 EXPECT_TRUE(builder_.AddTarget(
"out.imp", &err));
1604 EXPECT_FALSE(builder_.AlreadyUpToDate());
1607 EXPECT_TRUE(builder_.AlreadyUpToDate());
1609 command_runner_.commands_ran_.clear();
1612 builder_.plan_.Reset();
1614 EXPECT_TRUE(builder_.AddTarget(
"out.imp", &err));
1615 EXPECT_TRUE(builder_.AlreadyUpToDate());
1616 EXPECT_FALSE(GetNode(
"out.imp")->dirty());
1623 "build out1: cc in\n"));
1627 fs_.Create(
"in",
"");
1628 fs_.Create(
"out1",
"");
1633 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1634 EXPECT_FALSE(builder_.AlreadyUpToDate());
1636 command_runner_.commands_ran_.clear();
1639 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1641 EXPECT_TRUE(builder_.AlreadyUpToDate());
1646 "rule touch-fail-tick2\n"
1647 " command = touch-fail-tick2\n"
1648 "build out1: touch-fail-tick2 in\n"));
1652 fs_.Create(
"in",
"");
1655 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1658 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1660 command_runner_.commands_ran_.clear();
1663 builder_.plan_.Reset();
1666 fs_.Create(
"in",
"");
1669 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1671 EXPECT_EQ(
"subcommand failed", err);
1672 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1674 command_runner_.commands_ran_.clear();
1677 builder_.plan_.Reset();
1682 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1683 EXPECT_FALSE(builder_.AlreadyUpToDate());
1685 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1692 " command = touch\n"
1693 "build out1: touch\n"
1694 "build out2: touch in\n"));
1698 fs_.Create(
"in",
"");
1700 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1701 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1704 EXPECT_EQ(2u, command_runner_.commands_ran_.size());
1706 command_runner_.commands_ran_.clear();
1711 fs_.Create(
"in",
"");
1713 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1714 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1717 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1728 "build out1: cc in\n"
1729 "build out2: true out1\n"
1730 "build out3: cat out2\n"));
1732 fs_.Create(
"out1",
"");
1733 fs_.Create(
"out2",
"");
1734 fs_.Create(
"out3",
"");
1738 fs_.Create(
"in",
"");
1744 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1748 EXPECT_EQ(
size_t(3), command_runner_.commands_ran_.size());
1749 EXPECT_EQ(3, builder_.plan_.command_edge_count());
1750 command_runner_.commands_ran_.clear();
1755 fs_.Create(
"in",
"");
1758 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1761 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1765 command_runner_.commands_ran_.clear();
1767 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1769 EXPECT_TRUE(builder_.AlreadyUpToDate());
1773 fs_.Create(
"in",
"");
1777 command_runner_.commands_ran_.clear();
1779 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1782 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1796 "build out1: true in\n"
1797 "build out2: cc out1\n"));
1799 fs_.Create(
"in",
"");
1800 fs_.Create(
"out2",
"");
1806 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1810 command_runner_.commands_ran_.clear();
1814 fs_.Create(
"in",
"");
1815 fs_.Create(
"out2",
"");
1820 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1823 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1832 " command = touch\n"
1833 "build out1: true in\n"
1834 "build out2 out3: touch out1\n"
1835 "build out4: touch out2\n"
1839 fs_.Create(
"in",
"");
1842 EXPECT_TRUE(builder_.AddTarget(
"out4", &err));
1846 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1849 fs_.Create(
"in",
"");
1850 fs_.RemoveFile(
"out3");
1857 command_runner_.commands_ran_.clear();
1859 EXPECT_TRUE(builder_.AddTarget(
"out4", &err));
1863 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1872 " depfile = $out.d\n"
1876 "build out1: true in\n"
1877 "build out2: cc out1\n"));
1880 fs_.Create(
"in",
"");
1885 fs_.Create(
"out1.d",
"out1: will.be.deleted restat.file\n");
1886 fs_.Create(
"will.be.deleted",
"");
1887 fs_.Create(
"restat.file",
"");
1891 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1894 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1899 ASSERT_TRUE(NULL != log_entry);
1900 ASSERT_EQ(restat_mtime, log_entry->
mtime);
1904 fs_.RemoveFile(
"will.be.deleted");
1907 command_runner_.commands_ran_.clear();
1909 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1912 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1915 log_entry = build_log_.LookupByOutput(
"out1");
1916 ASSERT_TRUE(NULL != log_entry);
1917 ASSERT_EQ(restat_mtime, log_entry->
mtime);
1922 "rule generate-depfile\n"
1923 " command = sleep 1 ; touch $touch_dependency; touch $out ; echo \"$out: $test_dependency\" > $depfile\n"
1924 "build out1: generate-depfile || cat1\n"
1925 " test_dependency = in2\n"
1926 " touch_dependency = 1\n"
1928 " depfile = out.d\n"));
1935 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1939 EXPECT_EQ(
size_t(2), command_runner_.commands_ran_.size());
1940 EXPECT_EQ(2, builder_.plan_.command_edge_count());
1942 ASSERT_TRUE(NULL != log_entry);
1943 ASSERT_EQ(2u, log_entry->
mtime);
1945 command_runner_.commands_ran_.clear();
1948 builder_.plan_.Reset();
1951 fs_.Create(
"in1",
"");
1957 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1959 EXPECT_TRUE(!state_.GetNode(
"out1", 0)->dirty());
1962 EXPECT_EQ(
size_t(1), command_runner_.commands_ran_.size());
1963 EXPECT_EQ(1, builder_.plan_.command_edge_count());
1968 "rule generate-depfile\n"
1969 " command = touch $out ; echo \"$out: $test_dependency\" > $depfile\n"
1970 "build out: generate-depfile\n"
1971 " test_dependency = inimp\n"
1972 " depfile = out.d\n"));
1973 fs_.Create(
"inimp",
"");
1978 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1979 EXPECT_FALSE(builder_.AlreadyUpToDate());
1982 EXPECT_TRUE(builder_.AlreadyUpToDate());
1984 command_runner_.commands_ran_.clear();
1987 builder_.plan_.Reset();
1989 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1990 EXPECT_TRUE(builder_.AlreadyUpToDate());
1995 config_.dry_run =
true;
2007 "build out1: cc in\n"
2008 "build out2: true out1\n"
2009 "build out3: cat out2\n"));
2011 fs_.Create(
"out1",
"");
2012 fs_.Create(
"out2",
"");
2013 fs_.Create(
"out3",
"");
2017 fs_.Create(
"in",
"");
2022 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
2025 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
2031 " command = touch $out\n"
2033 " command = cp $in $out\n"
2034 "build dd: cp dd-in\n"
2035 "build out: touch || dd\n"
2037 "build out-copy: cp out\n"
2040 "ninja_dyndep_version = 1\n"
2041 "build out: dyndep\n"
2045 EXPECT_TRUE(builder_.AddTarget(
"out-copy", &err));
2048 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
2057 " command = cat $rspfile > $out\n"
2058 " rspfile = $rspfile\n"
2059 " rspfile_content = $long_command\n"
2060 "rule cat_rsp_out\n"
2061 " command = cat $rspfile > $out\n"
2062 " rspfile = $out.rsp\n"
2063 " rspfile_content = $long_command\n"
2064 "build out1: cat in\n"
2065 "build out2: cat_rsp in\n"
2066 " rspfile = out 2.rsp\n"
2067 " long_command = Some very long command\n"
2068 "build out$ 3: cat_rsp_out in\n"
2069 " long_command = Some very long command\n"));
2071 fs_.Create(
"out1",
"");
2072 fs_.Create(
"out2",
"");
2073 fs_.Create(
"out 3",
"");
2077 fs_.Create(
"in",
"");
2080 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
2082 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
2084 EXPECT_TRUE(builder_.AddTarget(
"out 3", &err));
2087 size_t files_created = fs_.files_created_.size();
2088 size_t files_removed = fs_.files_removed_.size();
2091 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
2094 ASSERT_EQ(files_created + 3, fs_.files_created_.size());
2095 ASSERT_EQ(1u, fs_.files_created_.count(
"out 2.rsp"));
2096 ASSERT_EQ(1u, fs_.files_created_.count(
"out 3.rsp"));
2097 ASSERT_EQ(1u, fs_.files_created_.count(
".ninja_lock"));
2100 ASSERT_EQ(files_removed + 2, fs_.files_removed_.size());
2101 ASSERT_EQ(1u, fs_.files_removed_.count(
"out 2.rsp"));
2102 ASSERT_EQ(1u, fs_.files_removed_.count(
"out 3.rsp"));
2110 " rspfile = $rspfile\n"
2111 " rspfile_content = $long_command\n"
2112 "build out: fail in\n"
2113 " rspfile = out.rsp\n"
2114 " long_command = Another very long command\n"));
2116 fs_.Create(
"out",
"");
2118 fs_.Create(
"in",
"");
2121 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
2124 size_t files_created = fs_.files_created_.size();
2125 size_t files_removed = fs_.files_removed_.size();
2128 ASSERT_EQ(
"subcommand failed", err);
2129 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2132 ASSERT_EQ(files_created + 2, fs_.files_created_.size());
2133 ASSERT_EQ(1u, fs_.files_created_.count(
"out.rsp"));
2134 ASSERT_EQ(1u, fs_.files_created_.count(
".ninja_lock"));
2137 ASSERT_EQ(files_removed, fs_.files_removed_.size());
2138 ASSERT_EQ(0u, fs_.files_removed_.count(
"out.rsp"));
2141 ASSERT_EQ(
"Another very long command", fs_.files_[
"out.rsp"].contents);
2149 " command = cat $rspfile > $out\n"
2150 " rspfile = $rspfile\n"
2151 " rspfile_content = $long_command\n"
2152 "build out: cat_rsp in\n"
2153 " rspfile = out.rsp\n"
2154 " long_command = Original very long command\n"));
2156 fs_.Create(
"out",
"");
2158 fs_.Create(
"in",
"");
2161 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
2166 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2169 command_runner_.commands_ran_.clear();
2171 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
2173 ASSERT_TRUE(builder_.AlreadyUpToDate());
2178 ASSERT_TRUE(NULL != log_entry);
2180 "cat out.rsp > out;rspfile=Original very long command",
2184 command_runner_.commands_ran_.clear();
2186 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
2189 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
2195 " command = interrupt\n"
2196 "rule touch-interrupt\n"
2197 " command = touch-interrupt\n"
2198 "build out1: interrupt in1\n"
2199 "build out2: touch-interrupt in2\n"));
2201 fs_.Create(
"out1",
"");
2202 fs_.Create(
"out2",
"");
2204 fs_.Create(
"in1",
"");
2205 fs_.Create(
"in2",
"");
2209 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
2212 EXPECT_EQ(
"interrupted by user", err);
2214 EXPECT_GT(fs_.Stat(
"out1", &err), 0);
2218 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
2221 EXPECT_EQ(
"interrupted by user", err);
2223 EXPECT_EQ(0, fs_.Stat(
"out2", &err));
2227 const string kTooLongToStat(400,
'i');
2229 (
"build " + kTooLongToStat +
": cat in\n").c_str()));
2230 fs_.Create(
"in",
"");
2233 fs_.files_[kTooLongToStat].mtime = -1;
2234 fs_.files_[kTooLongToStat].stat_error =
"stat failed";
2237 EXPECT_FALSE(builder_.AddTarget(kTooLongToStat, &err));
2238 EXPECT_EQ(
"stat failed", err);
2243 "build nonexistent: phony\n"
2244 "build out1: cat || nonexistent\n"
2245 "build out2: cat nonexistent\n"));
2246 fs_.Create(
"out1",
"");
2247 fs_.Create(
"out2",
"");
2252 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
2254 EXPECT_TRUE(builder_.AlreadyUpToDate());
2258 command_runner_.commands_ran_.clear();
2260 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
2264 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2272 "build out: cc\n"));
2276 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
2278 EXPECT_FALSE(builder_.AlreadyUpToDate());
2281 ASSERT_EQ(
"subcommand failed", err);
2282 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2286 status_.BuildStarted();
2288 EXPECT_EQ(
"[%/e0.000]", status_.FormatProgressStatus(
"[%%/e%e]", 0));
2292 status_.BuildStarted();
2294 EXPECT_EQ(
"[%/e00:00]", status_.FormatProgressStatus(
"[%%/e%w]", 0));
2298 status_.BuildStarted();
2300 EXPECT_EQ(
"[%/E?]", status_.FormatProgressStatus(
"[%%/E%E]", 0));
2304 status_.BuildStarted();
2306 EXPECT_EQ(
"[%/p 0%]", status_.FormatProgressStatus(
"[%%/p%p]", 0));
2310 EXPECT_EQ(
"[%/s0/t0/r0/u0/f0]",
2311 status_.FormatProgressStatus(
"[%%/s%s/t%t/r%r/u%u/f%f]", 0));
2316 "build bad_deps.o: cat in1\n"
2318 " depfile = in1.d\n"));
2321 EXPECT_TRUE(builder_.AddTarget(
"bad_deps.o", &err));
2326 fs_.Create(
"in1.d",
"AAA BBB");
2329 EXPECT_EQ(
"subcommand failed", err);
2334 :
BuildTest(&log_), deps_log_file_(
"ninja_deps") {}
2343 temp_dir_.CreateAndEnter(
"BuildWithQueryDepsLogTest");
2346 ASSERT_TRUE(log_.OpenForWrite(deps_log_file_.path(), &err));
2359 "rule cp_multi_msvc\n"
2360 " command = echo 'using $in' && for file in $out; do cp $in $$file; done\n"
2362 " msvc_deps_prefix = using \n"
2363 "build out1 out2: cp_multi_msvc in1\n"));
2366 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
2370 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2371 EXPECT_EQ(
"echo 'using in1' && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
2373 Node* out1_node = state_.LookupNode(
"out1");
2376 EXPECT_EQ(
"in1", out1_deps->
nodes[0]->
path());
2378 Node* out2_node = state_.LookupNode(
"out2");
2381 EXPECT_EQ(
"in1", out2_deps->
nodes[0]->
path());
2387 "rule cp_multi_gcc\n"
2388 " command = echo '$out: $in' > in.d && for file in $out; do cp in1 $$file; done\n"
2391 "build out1 out2: cp_multi_gcc in1 in2\n"));
2394 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
2396 fs_.Create(
"in.d",
"out1 out2: in1 in2");
2399 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2400 EXPECT_EQ(
"echo 'out1 out2: in1 in2' > in.d && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
2402 Node* out1_node = state_.LookupNode(
"out1");
2405 EXPECT_EQ(
"in1", out1_deps->
nodes[0]->
path());
2406 EXPECT_EQ(
"in2", out1_deps->
nodes[1]->
path());
2408 Node* out2_node = state_.LookupNode(
"out2");
2411 EXPECT_EQ(
"in1", out2_deps->
nodes[0]->
path());
2412 EXPECT_EQ(
"in2", out2_deps->
nodes[1]->
path());
2418 "rule cp_multi_gcc\n"
2419 " command = echo '$out: in1\\n$out: in2' > in.d && for file in $out; do cp in1 $$file; done\n"
2422 "build out1 out2: cp_multi_gcc in1 in2\n"));
2425 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
2427 fs_.Create(
"in.d",
"out1 out2: in1\nout1 out2: in2");
2430 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2431 EXPECT_EQ(
"echo 'out1 out2: in1\\nout1 out2: in2' > in.d && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
2433 Node* out1_node = state_.LookupNode(
"out1");
2436 EXPECT_EQ(
"in1", out1_deps->
nodes[0]->
path());
2437 EXPECT_EQ(
"in2", out1_deps->
nodes[1]->
path());
2439 Node* out2_node = state_.LookupNode(
"out2");
2442 EXPECT_EQ(
"in1", out2_deps->
nodes[0]->
path());
2443 EXPECT_EQ(
"in2", out2_deps->
nodes[1]->
path());
2449 "rule cp_multi_gcc\n"
2450 " command = echo 'out1: $in\\nout2: $in' > in.d && for file in $out; do cp in1 $$file; done\n"
2453 "build out1 out2: cp_multi_gcc in1 in2\n"));
2456 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
2458 fs_.Create(
"in.d",
"out1: in1 in2\nout2: in1 in2");
2461 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2462 EXPECT_EQ(
"echo 'out1: in1 in2\\nout2: in1 in2' > in.d && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
2464 Node* out1_node = state_.LookupNode(
"out1");
2467 EXPECT_EQ(
"in1", out1_deps->
nodes[0]->
path());
2468 EXPECT_EQ(
"in2", out1_deps->
nodes[1]->
path());
2470 Node* out2_node = state_.LookupNode(
"out2");
2473 EXPECT_EQ(
"in1", out2_deps->
nodes[0]->
path());
2474 EXPECT_EQ(
"in2", out2_deps->
nodes[1]->
path());
2480 "rule cp_multi_gcc\n"
2481 " command = echo 'out1: $in' > in.d && for file in $out; do cp in1 $$file; done\n"
2484 "build out1 out2: cp_multi_gcc in1 in2\n"));
2487 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
2489 fs_.Create(
"in.d",
"out1: in1 in2");
2492 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2493 EXPECT_EQ(
"echo 'out1: in1 in2' > in.d && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
2495 Node* out1_node = state_.LookupNode(
"out1");
2498 EXPECT_EQ(
"in1", out1_deps->
nodes[0]->
path());
2499 EXPECT_EQ(
"in2", out1_deps->
nodes[1]->
path());
2501 Node* out2_node = state_.LookupNode(
"out2");
2504 EXPECT_EQ(
"in1", out2_deps->
nodes[0]->
path());
2505 EXPECT_EQ(
"in2", out2_deps->
nodes[1]->
path());
2513 "rule cp_multi_gcc\n"
2514 " command = echo 'out2: $in' > in.d && for file in $out; do cp in1 $$file; done\n"
2517 "build out1 out2: cp_multi_gcc in1 in2\n"));
2520 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
2522 fs_.Create(
"in.d",
"out2: in1 in2");
2525 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2526 EXPECT_EQ(
"echo 'out2: in1 in2' > in.d && for file in out1 out2; do cp in1 $file; done", command_runner_.commands_ran_[0]);
2528 Node* out1_node = state_.LookupNode(
"out1");
2531 EXPECT_EQ(
"in1", out1_deps->
nodes[0]->
path());
2532 EXPECT_EQ(
"in2", out1_deps->
nodes[1]->
path());
2534 Node* out2_node = state_.LookupNode(
"out2");
2537 EXPECT_EQ(
"in1", out2_deps->
nodes[0]->
path());
2538 EXPECT_EQ(
"in2", out2_deps->
nodes[1]->
path());
2547 : build_log_file_(
"build_log"), deps_log_file_(
"ninja_deps") {}
2552 temp_dir_.CreateAndEnter(
"BuildWithDepsLogTest");
2556 temp_dir_.Cleanup();
2571 const char* manifest =
2572 "build out: cat in1\n"
2574 " depfile = in1.d\n";
2578 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
2579 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
2583 ASSERT_TRUE(deps_log.
OpenForWrite(deps_log_file_.path(), &err));
2586 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2588 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
2590 fs_.Create(
"in1.d",
"out: in2");
2595 EXPECT_EQ(0, fs_.Stat(
"in1.d", &err));
2597 fs_.Create(
"in1.d",
"out: in2");
2604 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
2605 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
2609 fs_.Create(
"in2",
"");
2613 ASSERT_TRUE(deps_log.
Load(deps_log_file_.path(), &state, &err));
2614 ASSERT_TRUE(deps_log.
OpenForWrite(deps_log_file_.path(), &err));
2616 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2618 command_runner_.commands_ran_.clear();
2619 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
2626 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
2639 const char* manifest =
2640 "build out: cat in1\n"
2642 " depfile = in1.d\n";
2645 fs_.Create(
"in1",
"");
2646 fs_.Create(
"in1.d",
"out: ");
2649 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
2650 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
2654 ASSERT_TRUE(deps_log.
OpenForWrite(deps_log_file_.path(), &err));
2657 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2659 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
2671 fs_.Create(
"in1",
"");
2672 fs_.Create(
"out",
"");
2675 EXPECT_EQ(0, fs_.Stat(
"in1.d", &err));
2679 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
2680 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
2683 ASSERT_TRUE(deps_log.
Load(deps_log_file_.path(), &state, &err));
2684 ASSERT_TRUE(deps_log.
OpenForWrite(deps_log_file_.path(), &err));
2686 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2688 command_runner_.commands_ran_.clear();
2689 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
2693 fs_.Create(
"in1.d",
"out: ");
2700 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
2707 const char* manifest =
2708 "build out: cat in1\n"
2710 " depfile = in1.d\n";
2712 fs_.Create(
"out",
"");
2714 fs_.Create(
"in1",
"");
2717 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
2718 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
2721 config_.dry_run =
true;
2722 Builder builder(&state, config_, NULL, NULL, &fs_, &status_, 0);
2724 command_runner_.commands_ran_.clear();
2727 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
2730 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2737 const char* manifest =
2739 " command = long-cc\n"
2740 "build out: long-cc in1\n"
2741 " test_dependency = in1\n";
2744 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
2745 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
2748 ASSERT_TRUE(build_log.
Load(build_log_file_.path(), &err));
2749 ASSERT_TRUE(build_log.
OpenForWrite(build_log_file_.path(), *
this, &err));
2752 ASSERT_TRUE(deps_log.
Load(deps_log_file_.path(), &state, &err));
2753 ASSERT_TRUE(deps_log.
OpenForWrite(deps_log_file_.path(), &err));
2757 Builder builder(&state, config_, &build_log, &deps_log, &fs_, &status_, 0);
2759 command_runner_.commands_ran_.clear();
2762 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
2765 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2770 ASSERT_TRUE(NULL != log_entry);
2771 ASSERT_EQ(1u, log_entry->
mtime);
2777 Builder builder(&state, config_, &build_log, &deps_log, &fs_, &status_, 0);
2779 command_runner_.commands_ran_.clear();
2784 command_runner_.commands_ran_.clear();
2786 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
2789 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2793 ASSERT_TRUE(NULL != log_entry);
2794 ASSERT_TRUE(fs_.files_[
"in1"].mtime < log_entry->
mtime);
2799 Builder builder(&state, config_, &build_log, &deps_log, &fs_, &status_, 0);
2801 command_runner_.commands_ran_.clear();
2804 command_runner_.commands_ran_.clear();
2806 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
2816 const char* manifest =
2818 " command = long-cc\n"
2819 "build out: long-cc\n"
2821 " depfile = out.d\n"
2822 " test_dependency = header.h\n";
2824 fs_.Create(
"header.h",
"");
2827 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
2830 ASSERT_TRUE(build_log.
Load(build_log_file_.path(), &err));
2831 ASSERT_TRUE(build_log.
OpenForWrite(build_log_file_.path(), *
this, &err));
2834 ASSERT_TRUE(deps_log.
Load(deps_log_file_.path(), &state, &err));
2835 ASSERT_TRUE(deps_log.
OpenForWrite(deps_log_file_.path(), &err));
2838 Builder builder(&state, config_, &build_log, &deps_log, &fs_, &status_, 0);
2842 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
2845 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2850 ASSERT_TRUE(NULL != log_entry);
2851 ASSERT_EQ(1u, log_entry->
mtime);
2859 Builder builder(&state, config_, &build_log, &deps_log, &fs_, &status_, 0);
2861 command_runner_.commands_ran_.clear();
2864 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
2867 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2875 Builder builder(&state, config_, &build_log, &deps_log, &fs_, &status_, 0);
2877 command_runner_.commands_ran_.clear();
2880 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
2888 fs_.Create(
"header.h",
"");
2889 ASSERT_EQ(fs_.now_, 7);
2894 Builder builder(&state, config_, &build_log, &deps_log, &fs_, &status_, 0);
2896 command_runner_.commands_ran_.clear();
2899 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
2902 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2910 Builder builder(&state, config_, &build_log, &deps_log, &fs_, &status_, 0);
2912 command_runner_.commands_ran_.clear();
2915 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
2918 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
2926 Builder builder(&state, config_, &build_log, &deps_log, &fs_, &status_, 0);
2928 command_runner_.commands_ran_.clear();
2931 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
2945 "build header.h: true header.in\n"
2946 "build out: cat in1\n"
2947 " depfile = in1.d\n"));
2949 fs_.Create(
"header.h",
"");
2950 fs_.Create(
"in1.d",
"out: header.h");
2952 fs_.Create(
"header.in",
"");
2955 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
2966 const char* manifest =
2970 "build header.h: true header.in\n"
2971 "build out: cat in1\n"
2973 " depfile = in1.d\n";
2976 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
2977 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
2981 ASSERT_TRUE(deps_log.
OpenForWrite(deps_log_file_.path(), &err));
2984 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
2986 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
2988 fs_.Create(
"in1.d",
"out: header.h");
2998 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
2999 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
3003 fs_.Create(
"header.in",
"");
3007 ASSERT_TRUE(deps_log.
Load(deps_log_file_.path(), &state, &err));
3008 ASSERT_TRUE(deps_log.
OpenForWrite(deps_log_file_.path(), &err));
3010 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
3012 command_runner_.commands_ran_.clear();
3013 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
3020 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
3028 const char* manifest =
3029 "rule cc\n command = cc $in\n depfile = $out.d\n deps = gcc\n"
3030 "build fo$ o.o: cc foo.c\n";
3032 fs_.Create(
"foo.c",
"");
3036 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
3040 ASSERT_TRUE(deps_log.
OpenForWrite(deps_log_file_.path(), &err));
3043 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
3045 EXPECT_TRUE(builder.
AddTarget(
"fo o.o", &err));
3047 fs_.Create(
"fo o.o.d",
"fo\\ o.o: blah.h bar.h\n");
3057 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
3060 ASSERT_TRUE(deps_log.
Load(deps_log_file_.path(), &state, &err));
3061 ASSERT_TRUE(deps_log.
OpenForWrite(deps_log_file_.path(), &err));
3064 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
3070 EXPECT_TRUE(builder.
AddTarget(
"fo o.o", &err));
3075 ASSERT_EQ(1u, state.
edges_.size());
3077 ASSERT_EQ(3u, edge->
inputs_.size());
3089 const char* manifest =
3090 "rule touch-out-implicit-dep\n"
3091 " command = touch $out ; sleep 1 ; touch $test_dependency\n"
3092 "rule generate-depfile\n"
3093 " command = touch $out ; echo \"$out: $test_dependency\" > $depfile\n"
3094 "build out1: touch-out-implicit-dep in1\n"
3095 " test_dependency = inimp\n"
3096 "build out2: generate-depfile in1 || out1\n"
3097 " test_dependency = inimp\n"
3098 " depfile = out2.d\n"
3101 fs_.Create(
"in1",
"");
3108 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
3111 ASSERT_TRUE(deps_log.
OpenForWrite(deps_log_file_.path(), &err));
3114 Builder builder(&state, config_, &build_log, &deps_log, &fs_, &status_, 0);
3116 EXPECT_TRUE(builder.
AddTarget(
"out2", &err));
3127 fs_.Create(
"in1",
"");
3131 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
3134 ASSERT_TRUE(deps_log.
Load(deps_log_file_.path(), &state, &err));
3135 ASSERT_TRUE(deps_log.
OpenForWrite(deps_log_file_.path(), &err));
3138 Builder builder(&state, config_, &build_log, &deps_log, &fs_, &status_, 0);
3140 EXPECT_TRUE(builder.
AddTarget(
"out2", &err));
3154 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
3157 ASSERT_TRUE(deps_log.
Load(deps_log_file_.path(), &state, &err));
3158 ASSERT_TRUE(deps_log.
OpenForWrite(deps_log_file_.path(), &err));
3161 Builder builder(&state, config_, &build_log, &deps_log, &fs_, &status_, 0);
3163 EXPECT_TRUE(builder.
AddTarget(
"out2", &err));
3174 const char* manifest =
3175 "rule cc\n command = cc $in\n depfile = $out.d\n deps = gcc\n"
3176 "build a/b\\c\\d/e/fo$ o.o: cc x\\y/z\\foo.c\n";
3178 fs_.Create(
"x/y/z/foo.c",
"");
3182 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
3186 ASSERT_TRUE(deps_log.
OpenForWrite(deps_log_file_.path(), &err));
3189 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
3190 builder.command_runner_.reset(&command_runner_);
3191 EXPECT_TRUE(builder.AddTarget(
"a/b/c/d/e/fo o.o", &err));
3194 fs_.Create(
"a/b\\c\\d/e/fo o.o.d",
3195 "a\\b\\c\\d\\e\\fo\\ o.o: blah.h bar.h\n");
3200 builder.command_runner_.release();
3205 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
3208 ASSERT_TRUE(deps_log.
Load(deps_log_file_.path(), &state, &err));
3209 ASSERT_TRUE(deps_log.
OpenForWrite(deps_log_file_.path(), &err));
3212 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
3213 builder.command_runner_.reset(&command_runner_);
3216 EXPECT_TRUE(builder.AddTarget(
"a/b/c/d/e/fo o.o", &err));
3220 ASSERT_EQ(1u, state.
edges_.size());
3223 ASSERT_EQ(3u, edge->
inputs_.size());
3230 builder.command_runner_.release();
3238 const char* manifest =
3242 "build header.h: true header.in\n"
3243 "build out: cat header.h\n"
3244 " depfile = out.d\n";
3246 fs_.Create(
"header.h",
"");
3248 fs_.Create(
"out",
"");
3249 fs_.Create(
"header.in",
"");
3255 RebuildTarget(
"out", manifest);
3256 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
3263 const char* manifest =
3267 "build header.h: true header.in\n"
3268 "build out: cat header.h\n"
3270 " depfile = out.d\n";
3273 fs_.Create(
"header.in",
"");
3274 fs_.Create(
"out.d",
"out: header.h");
3275 fs_.Create(
"header.h",
"");
3277 RebuildTarget(
"out", manifest, build_log_file_.c_str(),
3278 deps_log_file_.c_str());
3279 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
3282 RebuildTarget(
"out", manifest, build_log_file_.c_str(),
3283 deps_log_file_.c_str());
3284 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
3290 fs_.Create(
"header.in",
"");
3295 RebuildTarget(
"out", manifest, build_log_file_.c_str(), deps2_file_.
c_str());
3296 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
3299 RebuildTarget(
"out", manifest, build_log_file_.c_str(), deps2_file_.
c_str());
3300 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
3305 fs_.Create(
"header.in",
"");
3306 fs_.Create(
"out",
"");
3307 RebuildTarget(
"out", manifest, build_log_file_.c_str(), deps2_file_.
c_str());
3308 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
3311 RebuildTarget(
"out", manifest, build_log_file_.c_str(), deps2_file_.
c_str());
3312 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
3317 const char* manifest =
3319 " command = cc $in\n"
3320 " depfile = $out.d\n"
3321 "build foo.o: cc foo.c\n";
3323 fs_.Create(
"foo.c",
"");
3324 fs_.Create(
"foo.o",
"");
3325 fs_.Create(
"header.h",
"");
3326 fs_.Create(
"foo.o.d",
"bar.o.d: header.h\n");
3331 RebuildTarget(
"foo.o", manifest, build_log.
c_str(), deps_file.
c_str());
3332 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3338 " command = console\n"
3340 "build cons: console in.txt\n"));
3342 fs_.Create(
"in.txt",
"");
3345 EXPECT_TRUE(builder_.AddTarget(
"cons", &err));
3349 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3357 " command = touch $out\n"
3358 "build out: touch || dd\n"
3363 EXPECT_FALSE(builder_.AddTarget(
"out", &err));
3364 EXPECT_EQ(
"loading 'dd': No such file or directory", err);
3373 " command = touch $out $out.imp\n"
3374 "build tmp: touch || dd\n"
3376 "build out: touch || dd\n"
3380 "ninja_dyndep_version = 1\n"
3381 "build out | out.imp: dyndep | tmp.imp\n"
3382 "build tmp | tmp.imp: dyndep\n"
3386 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
3390 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
3391 EXPECT_EQ(
"touch tmp tmp.imp", command_runner_.commands_ran_[0]);
3392 EXPECT_EQ(
"touch out out.imp", command_runner_.commands_ran_[1]);
3400 " command = touch $out\n"
3401 "build out: touch || dd\n"
3405 "build out: dyndep\n"
3409 EXPECT_FALSE(builder_.AddTarget(
"out", &err));
3410 EXPECT_EQ(
"dd:1: expected 'ninja_dyndep_version = ...'\n", err);
3418 " command = unused\n"
3419 "build out: r in || dd\n"
3421 "build in: r circ\n"
3424 "ninja_dyndep_version = 1\n"
3425 "build out | circ: dyndep\n"
3427 fs_.Create(
"out",
"");
3430 EXPECT_FALSE(builder_.AddTarget(
"out", &err));
3431 EXPECT_EQ(
"dependency cycle: circ -> in -> circ", err);
3438 " command = touch $out\n"
3440 " command = cp $in $out\n"
3441 "build dd: cp dd-in\n"
3442 "build out: touch || dd\n"
3446 "ninja_dyndep_version = 1\n"
3447 "build out: dyndep\n"
3451 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
3454 size_t files_created = fs_.files_created_.size();
3458 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
3459 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3460 EXPECT_EQ(
"touch out", command_runner_.commands_ran_[1]);
3461 ASSERT_EQ(2u, fs_.files_read_.size());
3462 EXPECT_EQ(
"dd-in", fs_.files_read_[0]);
3463 EXPECT_EQ(
"dd", fs_.files_read_[1]);
3464 ASSERT_EQ(3u + files_created, fs_.files_created_.size());
3465 EXPECT_EQ(1u, fs_.files_created_.count(
"dd"));
3466 EXPECT_EQ(1u, fs_.files_created_.count(
"out"));
3467 EXPECT_EQ(1u, fs_.files_created_.count(
".ninja_lock"));
3475 " command = touch $out\n"
3477 " command = cp $in $out\n"
3478 "build dd: cp dd-in\n"
3479 "build out: touch || dd\n"
3483 "build out: dyndep\n"
3487 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
3491 EXPECT_EQ(
"dd:1: expected 'ninja_dyndep_version = ...'\n", err);
3499 " command = touch $out\n"
3501 " command = cp $in $out\n"
3502 "build dd: cp dd-in\n"
3503 "build unrelated: touch || dd\n"
3504 "build out: touch unrelated || dd\n"
3508 "ninja_dyndep_version = 1\n"
3509 "build out: dyndep\n"
3512 fs_.Create(
"out",
"");
3515 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
3520 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3521 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3522 EXPECT_EQ(
"touch unrelated", command_runner_.commands_ran_[1]);
3523 EXPECT_EQ(
"touch out", command_runner_.commands_ran_[2]);
3531 " command = touch $out $out.imp\n"
3533 " command = cp $in $out\n"
3534 "build dd: cp dd-in\n"
3535 "build out: touch in || dd\n"
3538 fs_.Create(
"in",
"");
3540 "ninja_dyndep_version = 1\n"
3541 "build out | out.imp: dyndep\n"
3544 fs_.Create(
"out",
"");
3547 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
3552 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
3553 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3554 EXPECT_EQ(
"touch out out.imp", command_runner_.commands_ran_[1]);
3562 " command = touch $out $out.imp\n"
3564 " command = cp $in $out\n"
3565 "build dd: cp dd-in\n"
3566 "build out1 | out-twice.imp: touch in\n"
3567 "build out2: touch in || dd\n"
3570 fs_.Create(
"in",
"");
3572 "ninja_dyndep_version = 1\n"
3573 "build out2 | out-twice.imp: dyndep\n"
3576 fs_.Create(
"out1",
"");
3577 fs_.Create(
"out2",
"");
3580 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
3581 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
3585 EXPECT_EQ(
"multiple rules generate out-twice.imp", err);
3594 " command = touch $out $out.imp\n"
3596 " command = cp $in $out\n"
3597 "build dd1: cp dd1-in\n"
3598 "build out1: touch || dd1\n"
3600 "build dd2: cp dd2-in || dd1\n"
3601 "build out2: touch || dd2\n"
3604 fs_.Create(
"out1",
"");
3605 fs_.Create(
"out2",
"");
3606 fs_.Create(
"dd1-in",
3607 "ninja_dyndep_version = 1\n"
3608 "build out1 | out-twice.imp: dyndep\n"
3610 fs_.Create(
"dd2-in",
"");
3612 "ninja_dyndep_version = 1\n"
3613 "build out2 | out-twice.imp: dyndep\n"
3616 fs_.Create(
"out1",
"");
3617 fs_.Create(
"out2",
"");
3620 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
3621 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
3625 EXPECT_EQ(
"multiple rules generate out-twice.imp", err);
3633 " command = touch $out\n"
3635 " command = cp $in $out\n"
3636 "build dd: cp dd-in\n"
3638 "build out: touch || dd\n"
3642 "ninja_dyndep_version = 1\n"
3643 "build out: dyndep | in\n"
3646 fs_.Create(
"out",
"");
3649 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
3654 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3655 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3656 EXPECT_EQ(
"touch in", command_runner_.commands_ran_[1]);
3657 EXPECT_EQ(
"touch out", command_runner_.commands_ran_[2]);
3665 " command = touch $out\n"
3667 " command = cp $in $out\n"
3668 "build dd: cp dd-in\n"
3669 "build out: touch || dd\n"
3673 "ninja_dyndep_version = 1\n"
3674 "build out: dyndep |@ validation\n"
3678 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
3683 string err_first_line = err.substr(0, err.find(
"\n"));
3684 EXPECT_EQ(
"dd:2: expected newline, got '|@'", err_first_line);
3692 " command = touch $out\n"
3694 " command = cp $in $out\n"
3695 "build dd: cp dd-in\n"
3696 "build in: touch |@ validation\n"
3697 "build validation: touch in out\n"
3698 "build out: touch || dd\n"
3702 "ninja_dyndep_version = 1\n"
3703 "build out: dyndep | in\n"
3706 fs_.Create(
"out",
"");
3709 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
3714 ASSERT_EQ(4u, command_runner_.commands_ran_.size());
3715 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3716 EXPECT_EQ(
"touch in", command_runner_.commands_ran_[1]);
3717 EXPECT_EQ(
"touch out", command_runner_.commands_ran_[2]);
3718 EXPECT_EQ(
"touch validation", command_runner_.commands_ran_[3]);
3727 " command = touch $out $out.imp\n"
3729 " command = cp $in $out\n"
3730 "build dd: cp dd-in\n"
3731 "build tmp: touch || dd\n"
3733 "build out: touch || dd\n"
3737 "ninja_dyndep_version = 1\n"
3738 "build out | out.imp: dyndep | tmp.imp\n"
3739 "build tmp | tmp.imp: dyndep\n"
3743 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
3747 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3748 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3749 EXPECT_EQ(
"touch tmp tmp.imp", command_runner_.commands_ran_[1]);
3750 EXPECT_EQ(
"touch out out.imp", command_runner_.commands_ran_[2]);
3759 " command = touch $out $out.imp\n"
3761 " command = cp $in $out\n"
3762 "build dd: cp dd-in\n"
3763 "build tmp: touch || dd\n"
3765 "build out: cp tmp\n"
3766 " depfile = out.d\n"
3768 fs_.Create(
"out.d",
"out: tmp.imp\n");
3770 "ninja_dyndep_version = 1\n"
3771 "build tmp | tmp.imp: dyndep\n"
3775 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
3779 ASSERT_FALSE(GetNode(
"tmp.imp")->in_edge());
3785 ASSERT_FALSE(GetNode(
"tmp.imp")->in_edge()->is_phony());
3787 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3788 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3789 EXPECT_EQ(
"touch tmp tmp.imp", command_runner_.commands_ran_[1]);
3790 EXPECT_EQ(
"cp tmp out", command_runner_.commands_ran_[2]);
3791 EXPECT_EQ(1u, fs_.files_created_.count(
"tmp.imp"));
3792 EXPECT_TRUE(builder_.AlreadyUpToDate());
3800 " command = touch $out $out.imp\n"
3802 " command = cp $in $out\n"
3803 "build dd: cp dd-in\n"
3804 "build tmp: touch || dd\n"
3806 "build out: touch tmp || dd\n"
3809 fs_.Create(
"tmp",
"");
3810 fs_.Create(
"out",
"");
3812 "ninja_dyndep_version = 1\n"
3813 "build out: dyndep\n"
3814 "build tmp | tmp.imp: dyndep\n"
3818 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
3822 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3823 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3824 EXPECT_EQ(
"touch tmp tmp.imp", command_runner_.commands_ran_[1]);
3825 EXPECT_EQ(
"touch out out.imp", command_runner_.commands_ran_[2]);
3833 " command = touch $out $out.imp\n"
3835 " command = cp $in $out\n"
3836 "build dd: cp dd-in\n"
3837 "build tmp: touch || dd\n"
3839 "build out: touch tmp\n"
3841 fs_.Create(
"tmp",
"");
3842 fs_.Create(
"out",
"");
3844 "ninja_dyndep_version = 1\n"
3845 "build tmp | tmp.imp: dyndep\n"
3849 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
3853 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3854 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3855 EXPECT_EQ(
"touch tmp tmp.imp", command_runner_.commands_ran_[1]);
3856 EXPECT_EQ(
"touch out out.imp", command_runner_.commands_ran_[2]);
3864 " command = unused\n"
3866 " command = cp $in $out\n"
3867 "build dd: cp dd-in\n"
3868 "build out: r in || dd\n"
3869 " depfile = out.d\n"
3871 "build in: r || dd\n"
3874 fs_.Create(
"out.d",
"out: inimp\n");
3876 "ninja_dyndep_version = 1\n"
3877 "build out | circ: dyndep\n"
3878 "build in: dyndep | circ\n"
3880 fs_.Create(
"out",
"");
3883 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
3889 EXPECT_TRUE(err ==
"dependency cycle: circ -> in -> circ" ||
3890 err ==
"dependency cycle: in -> circ -> in");
3900 " command = cp $in $out\n"
3901 "build dd: cp dd-in\n"
3902 "build out1: true in || dd\n"
3904 "build out2: cat out1\n"));
3906 fs_.Create(
"out1",
"");
3907 fs_.Create(
"out2",
"");
3909 "ninja_dyndep_version = 1\n"
3910 "build out1: dyndep\n"
3914 fs_.Create(
"in",
"");
3920 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
3924 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3925 EXPECT_EQ(
"cp dd-in dd", command_runner_.commands_ran_[0]);
3926 EXPECT_EQ(
"true", command_runner_.commands_ran_[1]);
3927 EXPECT_EQ(
"cat out1 > out2", command_runner_.commands_ran_[2]);
3929 command_runner_.commands_ran_.clear();
3932 fs_.Create(
"in",
"");
3936 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
3939 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
3940 EXPECT_EQ(
"true", command_runner_.commands_ran_[0]);
3949 " command = touch $out $out.imp\n"
3951 " command = cp $in $out\n"
3952 "build out1 | out1.imp: touch\n"
3953 "build zdd: cp zdd-in\n"
3954 " verify_active_edge = out1\n"
3955 "build out2: cp out1 || zdd\n"
3958 fs_.Create(
"zdd-in",
3959 "ninja_dyndep_version = 1\n"
3960 "build out2: dyndep | out1.imp\n"
3965 command_runner_.max_active_edges_ = 2;
3976 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
3977 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
3981 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
3984 EXPECT_TRUE((command_runner_.commands_ran_[0] ==
"touch out1 out1.imp" &&
3985 command_runner_.commands_ran_[1] ==
"cp zdd-in zdd") ||
3986 (command_runner_.commands_ran_[1] ==
"touch out1 out1.imp" &&
3987 command_runner_.commands_ran_[0] ==
"cp zdd-in zdd"));
3988 EXPECT_EQ(
"cp out1 out2", command_runner_.commands_ran_[2]);
3996 " command = touch $out $out.imp\n"
3998 " command = cp $in $out\n"
3999 "build dd1: cp dd1-in\n"
4000 "build out1 | out1.imp: touch || dd1\n"
4002 "build dd2: cp dd2-in || dd1\n"
4003 "build out2: touch || dd2\n"
4006 fs_.Create(
"out1.imp",
"");
4007 fs_.Create(
"out2",
"");
4008 fs_.Create(
"out2.imp",
"");
4009 fs_.Create(
"dd1-in",
4010 "ninja_dyndep_version = 1\n"
4011 "build out1: dyndep\n"
4013 fs_.Create(
"dd2-in",
"");
4015 "ninja_dyndep_version = 1\n"
4016 "build out2 | out2.imp: dyndep | out1.imp\n"
4028 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
4032 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
4033 EXPECT_EQ(
"cp dd1-in dd1", command_runner_.commands_ran_[0]);
4034 EXPECT_EQ(
"touch out1 out1.imp", command_runner_.commands_ran_[1]);
4035 EXPECT_EQ(
"touch out2 out2.imp", command_runner_.commands_ran_[2]);
4044 " command = touch $out $out.imp\n"
4046 " command = cp $in $out\n"
4047 "build dd1: cp dd1-in\n"
4048 "build out1: touch || dd1\n"
4050 "build dd2: cp dd2-in || out1\n"
4051 "build out2: touch || dd2\n"
4054 fs_.Create(
"out1.imp",
"");
4055 fs_.Create(
"out2",
"");
4056 fs_.Create(
"out2.imp",
"");
4057 fs_.Create(
"dd1-in",
4058 "ninja_dyndep_version = 1\n"
4059 "build out1 | out1.imp: dyndep\n"
4061 fs_.Create(
"dd2-in",
"");
4063 "ninja_dyndep_version = 1\n"
4064 "build out2 | out2.imp: dyndep | out1.imp\n"
4073 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
4077 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
4078 EXPECT_EQ(
"cp dd1-in dd1", command_runner_.commands_ran_[0]);
4079 EXPECT_EQ(
"touch out1 out1.imp", command_runner_.commands_ran_[1]);
4080 EXPECT_EQ(
"touch out2 out2.imp", command_runner_.commands_ran_[2]);
4088 " command = touch $out\n"
4090 " command = cp $in $out\n"
4091 "build dd0: cp dd0-in\n"
4092 "build dd1: cp dd1-in\n"
4094 "build tmp: touch || dd0\n"
4096 "build out: touch || dd1\n"
4099 fs_.Create(
"dd1-in",
4100 "ninja_dyndep_version = 1\n"
4101 "build out: dyndep | tmp\n"
4103 fs_.Create(
"dd0-in",
"");
4105 "ninja_dyndep_version = 1\n"
4106 "build tmp: dyndep | in\n"
4109 fs_.Create(
"out",
"");
4112 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
4117 ASSERT_EQ(4u, command_runner_.commands_ran_.size());
4118 EXPECT_EQ(
"cp dd1-in dd1", command_runner_.commands_ran_[0]);
4119 EXPECT_EQ(
"touch in", command_runner_.commands_ran_[1]);
4120 EXPECT_EQ(
"touch tmp", command_runner_.commands_ran_[2]);
4121 EXPECT_EQ(
"touch out", command_runner_.commands_ran_[3]);
4129 " command = touch $out\n"
4131 " command = cp $in $out\n"
4132 "build dd0: cp dd0-in\n"
4133 "build dd1: cp dd1-in\n"
4135 "build tmp: touch || dd0\n"
4137 "build out: touch || dd1\n"
4140 fs_.Create(
"dd1-in",
4141 "ninja_dyndep_version = 1\n"
4142 "build out: dyndep | tmp\n"
4144 fs_.Create(
"dd0-in",
4145 "ninja_dyndep_version = 1\n"
4146 "build tmp: dyndep | in\n"
4149 fs_.Create(
"out",
"");
4152 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
4157 ASSERT_EQ(5u, command_runner_.commands_ran_.size());
4158 EXPECT_EQ(
"cp dd1-in dd1", command_runner_.commands_ran_[0]);
4159 EXPECT_EQ(
"cp dd0-in dd0", command_runner_.commands_ran_[1]);
4160 EXPECT_EQ(
"touch in", command_runner_.commands_ran_[2]);
4161 EXPECT_EQ(
"touch tmp", command_runner_.commands_ran_[3]);
4162 EXPECT_EQ(
"touch out", command_runner_.commands_ran_[4]);
4167 "build out: cat in |@ validate\n"
4168 "build validate: cat in2\n"));
4170 fs_.Create(
"in",
"");
4171 fs_.Create(
"in2",
"");
4174 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
4180 EXPECT_EQ(2u, command_runner_.commands_ran_.size());
4185 fs_.Create(
"in",
"");
4188 command_runner_.commands_ran_.clear();
4190 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
4196 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
4197 EXPECT_EQ(
"cat in > out", command_runner_.commands_ran_[0]);
4202 fs_.Create(
"in2",
"");
4205 command_runner_.commands_ran_.clear();
4207 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
4213 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
4214 EXPECT_EQ(
"cat in2 > validate", command_runner_.commands_ran_[0]);
4219 "build out: cat in |@ validate\n"
4220 "build validate: cat in2 | out\n"));
4222 fs_.Create(
"in",
"");
4223 fs_.Create(
"in2",
"");
4226 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
4232 EXPECT_EQ(2u, command_runner_.commands_ran_.size());
4236 fs_.Create(
"in",
"");
4239 command_runner_.commands_ran_.clear();
4241 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
4247 EXPECT_EQ(2u, command_runner_.commands_ran_.size());
4252 fs_.Create(
"in2",
"");
4255 command_runner_.commands_ran_.clear();
4257 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
4263 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
4264 EXPECT_EQ(
"cat in2 > validate", command_runner_.commands_ran_[0]);
4268 const char* manifest =
4269 "build out: cat in |@ validate\n"
4270 "build validate: cat in2 | out\n"
4271 "build out2: cat in3\n"
4273 " depfile = out2.d\n";
4278 fs_.Create(
"in",
"");
4279 fs_.Create(
"in2",
"");
4280 fs_.Create(
"in3",
"");
4281 fs_.Create(
"out2.d",
"out: out");
4284 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
4285 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
4288 ASSERT_TRUE(deps_log.
OpenForWrite(deps_log_file_.path(), &err));
4291 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
4294 EXPECT_TRUE(builder.
AddTarget(
"out2", &err));
4301 ASSERT_EQ(command_runner_.commands_ran_.size(),
size_t(1));
4302 EXPECT_EQ(
"cat in3 > out2", command_runner_.commands_ran_[0]);
4305 EXPECT_EQ(0, fs_.Stat(
"out2.d", &err));
4312 command_runner_.commands_ran_.clear();
4315 fs_.Create(
"in2",
"");
4316 fs_.Create(
"in3",
"");
4319 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
4320 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
4323 ASSERT_TRUE(deps_log.
Load(deps_log_file_.path(), &state, &err));
4324 ASSERT_TRUE(deps_log.
OpenForWrite(deps_log_file_.path(), &err));
4327 Builder builder(&state, config_, NULL, &deps_log, &fs_, &status_, 0);
4330 EXPECT_TRUE(builder.
AddTarget(
"out2", &err));
4337 ASSERT_EQ(command_runner_.commands_ran_.size(),
size_t(3));
4339 EXPECT_EQ(
"cat in > out", command_runner_.commands_ran_[0]);
4348 "build out: cat in |@ out2\n"
4349 "build out2: cat in2 |@ out\n"));
4351 fs_.Create(
"in",
"");
4352 fs_.Create(
"in2",
"");
4355 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
4361 EXPECT_EQ(2u, command_runner_.commands_ran_.size());
4365 fs_.Create(
"in",
"");
4368 command_runner_.commands_ran_.clear();
4370 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
4376 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
4377 EXPECT_EQ(
"cat in > out", command_runner_.commands_ran_[0]);
4381 fs_.Create(
"in2",
"");
4384 command_runner_.commands_ran_.clear();
4386 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
4392 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
4393 EXPECT_EQ(
"cat in2 > out2", command_runner_.commands_ran_[0]);
4398 "build out: cat in |@ validate\n"
4399 "build validate: cat validate_in | out\n"
4400 "build validate_in: cat validate\n"));
4402 fs_.Create(
"in",
"");
4405 EXPECT_FALSE(builder_.AddTarget(
"out", &err));
4406 EXPECT_EQ(
"dependency cycle: validate -> validate_in -> validate", err);
void TestPhonyUseCase(BuildTest *t, int i)
Options (e.g. verbosity, parallelism) passed to a build.
Can answer questions about the manifest for the BuildLog.
Store a log of every command ran for every build.
LogEntry * LookupByOutput(const std::string &path)
Lookup a previously-run command by its output path.
LoadStatus Load(const std::string &path, std::string *err)
Load the on-disk log.
bool OpenForWrite(const std::string &path, const BuildLogUser &user, std::string *err)
Prepares writing to the log file without actually opening it - that will happen when/if it's needed.
void Dirty(const string &path)
FakeCommandRunner command_runner_
void RebuildTarget(const string &target, const char *manifest, const char *log_path=NULL, const char *deps_path=NULL, State *state=NULL)
Rebuild target in the 'working tree' (fs_).
virtual bool IsPathDead(StringPiece s) const
Return if a given output is no longer part of the build manifest.
Tests of builds involving deps logs necessarily must span multiple builds.
void * builder_
Shadow parent class builder_ so we don't accidentally use it.
ScopedFilePath build_log_file_
ScopedFilePath deps_log_file_
ScopedFilePath deps_log_file_
~BuildWithQueryDepsLogTest()
BuildWithQueryDepsLogTest()
Builder wraps the build process: starting commands, updating status.
bool AlreadyUpToDate() const
Returns true if the build targets are already up to date.
ExitStatus Build(std::string *err)
Run the build.
std::unique_ptr< CommandRunner > command_runner_
Node * AddTarget(const std::string &name, std::string *err)
The result of waiting for a command.
CommandRunner is an interface that wraps running the build subcommands.
static bool cmp(const Edge *a, const Edge *b)
As build commands run they can output extra dependency information (e.g.
bool OpenForWrite(const std::string &path, std::string *err)
LoadStatus Load(const std::string &path, State *state, std::string *err)
An edge in the dependency graph; links between Nodes using Rules.
std::string GetBinding(const std::string &key) const
Returns the shell-escaped value of |key|.
std::vector< Node * > outputs_
bool GetBindingBool(const std::string &key) const
std::string EvaluateCommand(bool incl_rsp_file=false) const
Expand all variables in a command and return it as a string.
const Rule & rule() const
std::vector< Node * > inputs_
std::string GetUnescapedDepfile() const
Like GetBinding("depfile"), but without shell escaping.
Fake implementation of CommandRunner, useful for tests.
virtual bool WaitForCommand(Result *result)
Wait for a command to complete, or return false if interrupted.
virtual vector< Edge * > GetActiveEdges()
vector< Edge * > active_edges_
virtual size_t CanRunMore() const
virtual bool StartCommand(Edge *edge)
vector< string > commands_ran_
FakeCommandRunner(VirtualFileSystem *fs)
Information about a node in the dependency graph: the file, whether it's dirty, mtime,...
const std::string & path() const
void MarkMissing()
Mark the Node as already-stat()ed and missing.
bool Stat(DiskInterface *disk_interface, std::string *err)
Return false on error.
Fixture for tests involving Plan.
void PrepareForTarget(const char *node, BuildLog *log=NULL)
void TestPoolWithDepthOne(const char *test_case)
void FindWorkSorted(deque< Edge * > *ret, int count)
Because FindWork does not return Edges in any sort of predictable order,.
Plan stores the state of a build plan: what we intend to build, which steps we're ready to execute.
bool AddTarget(const Node *target, std::string *err)
Add a target to our plan (including all its dependencies).
bool more_to_do() const
Returns true if there's more work to be done.
const std::string & name() const
A class that records a file path and ensures that it is removed on destruction.
const char * c_str() const
A base test fixture that includes a State object with a builtin "cat" rule.
Node * GetNode(const std::string &path)
Short way to get a Node by its path from state_.
Global state (file status) for a single run.
std::vector< Edge * > edges_
All the edges of the graph.
Node * GetNode(StringPiece path, uint64_t slash_bits)
Pool * LookupPool(const std::string &pool_name)
Implementation of the Status interface that prints the status as human-readable strings to stdout.
StringPiece represents a slice of a string whose memory is managed externally.
An implementation of DiskInterface that uses an in-memory representation of disk state.
int Tick()
Tick "time" forwards; subsequent file operations will be newer than previous ones.
int now_
A simple fake timestamp for file operations.
void Create(const std::string &path, const std::string &contents)
"Create" a file with contents.
void AssertParse(State *state, const char *input, ManifestParserOptions opts)
void AssertHash(const char *expected, uint64_t actual)