32 struct CompareEdgesByOutput {
33 static bool cmp(
const Edge* a,
const Edge* b) {
38 for (
int i = 0; i < count; ++i) {
45 sort(ret->begin(), ret->end(), CompareEdgesByOutput::cmp);
53 "build out: cat mid\n"
54 "build mid: cat in\n");
55 GetNode(
"mid")->MarkDirty();
56 GetNode(
"out")->MarkDirty();
58 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out"), &err));
60 ASSERT_TRUE(plan_.more_to_do());
62 Edge* edge = plan_.FindWork();
64 ASSERT_EQ(
"in", edge->inputs_[0]->path());
65 ASSERT_EQ(
"mid", edge->outputs_[0]->path());
67 ASSERT_FALSE(plan_.FindWork());
69 plan_.EdgeFinished(edge);
71 edge = plan_.FindWork();
73 ASSERT_EQ(
"mid", edge->inputs_[0]->path());
74 ASSERT_EQ(
"out", edge->outputs_[0]->path());
76 plan_.EdgeFinished(edge);
78 ASSERT_FALSE(plan_.more_to_do());
79 edge = plan_.FindWork();
86 "build out: cat mid1 mid2\n"
87 "build mid1 mid2: cat in\n");
88 GetNode(
"mid1")->MarkDirty();
89 GetNode(
"mid2")->MarkDirty();
90 GetNode(
"out")->MarkDirty();
93 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out"), &err));
95 ASSERT_TRUE(plan_.more_to_do());
98 edge = plan_.FindWork();
100 plan_.EdgeFinished(edge);
102 edge = plan_.FindWork();
104 plan_.EdgeFinished(edge);
106 edge = plan_.FindWork();
113 "build out: cat b1 b2\n"
116 "build a1 a2: cat in\n");
117 GetNode(
"a1")->MarkDirty();
118 GetNode(
"a2")->MarkDirty();
119 GetNode(
"b1")->MarkDirty();
120 GetNode(
"b2")->MarkDirty();
121 GetNode(
"out")->MarkDirty();
123 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out"), &err));
125 ASSERT_TRUE(plan_.more_to_do());
128 edge = plan_.FindWork();
130 plan_.EdgeFinished(edge);
132 edge = plan_.FindWork();
134 plan_.EdgeFinished(edge);
136 edge = plan_.FindWork();
138 plan_.EdgeFinished(edge);
140 edge = plan_.FindWork();
142 plan_.EdgeFinished(edge);
144 edge = plan_.FindWork();
151 "build out: cat a1 a2\n"
152 "build a1: cat mid\n"
153 "build a2: cat mid\n"
154 "build mid: cat in\n");
155 GetNode(
"mid")->MarkDirty();
156 GetNode(
"a1")->MarkDirty();
157 GetNode(
"a2")->MarkDirty();
158 GetNode(
"out")->MarkDirty();
161 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out"), &err));
163 ASSERT_TRUE(plan_.more_to_do());
166 edge = plan_.FindWork();
168 plan_.EdgeFinished(edge);
170 edge = plan_.FindWork();
172 plan_.EdgeFinished(edge);
174 edge = plan_.FindWork();
176 plan_.EdgeFinished(edge);
178 edge = plan_.FindWork();
180 plan_.EdgeFinished(edge);
182 edge = plan_.FindWork();
188 "build out: cat mid\n"
189 "build mid: cat in\n"
190 "build in: cat pre\n"
191 "build pre: cat out\n");
192 GetNode(
"out")->MarkDirty();
193 GetNode(
"mid")->MarkDirty();
194 GetNode(
"in")->MarkDirty();
195 GetNode(
"pre")->MarkDirty();
198 EXPECT_FALSE(plan_.AddTarget(GetNode(
"out"), &err));
199 ASSERT_EQ(
"dependency cycle: out -> mid -> in -> pre -> out", err);
215 ASSERT_EQ(
"in", edge->inputs_[0]->path());
216 ASSERT_EQ(
"out1", edge->outputs_[0]->path());
225 ASSERT_EQ(
"in", edge->inputs_[0]->path());
226 ASSERT_EQ(
"out2", edge->outputs_[0]->path());
238 TestPoolWithDepthOne(
242 " command = cat $in > $out\n"
244 "build out1: poolcat in\n"
245 "build out2: poolcat in\n");
249 TestPoolWithDepthOne(
251 " command = cat $in > $out\n"
253 "build out1: poolcat in\n"
254 "build out2: poolcat in\n");
264 " command = cat $in > $out\n"
267 " command = cat $in > $out\n"
269 "build out1: foocat in\n"
270 "build out2: foocat in\n"
271 "build out3: foocat in\n"
272 "build outb1: bazcat in\n"
273 "build outb2: bazcat in\n"
274 "build outb3: bazcat in\n"
276 "build allTheThings: cat out1 out2 out3 outb1 outb2 outb3\n"
279 for (
int i = 0; i < 3; ++i) {
280 GetNode(
"out" +
string(1,
'1' + static_cast<char>(i)))->MarkDirty();
281 GetNode(
"outb" +
string(1,
'1' + static_cast<char>(i)))->MarkDirty();
283 GetNode(
"allTheThings")->MarkDirty();
286 EXPECT_TRUE(plan_.AddTarget(GetNode(
"allTheThings"), &err));
290 FindWorkSorted(&edges, 5);
292 for (
int i = 0; i < 4; ++i) {
293 Edge *edge = edges[i];
294 ASSERT_EQ(
"in", edge->
inputs_[0]->path());
295 string base_name(i < 2 ?
"out" :
"outb");
296 ASSERT_EQ(base_name +
string(1,
'1' + (i % 2)), edge->
outputs_[0]->path());
300 Edge* edge = edges[4];
302 ASSERT_EQ(
"in", edge->
inputs_[0]->path());
303 ASSERT_EQ(
"outb3", edge->
outputs_[0]->path());
306 plan_.EdgeFinished(edges.front());
310 Edge* out3 = plan_.FindWork();
312 ASSERT_EQ(
"in", out3->
inputs_[0]->path());
313 ASSERT_EQ(
"out3", out3->
outputs_[0]->path());
315 ASSERT_FALSE(plan_.FindWork());
317 plan_.EdgeFinished(out3);
319 ASSERT_FALSE(plan_.FindWork());
321 for (deque<Edge*>::iterator it = edges.begin(); it != edges.end(); ++it) {
322 plan_.EdgeFinished(*it);
325 Edge* last = plan_.FindWork();
327 ASSERT_EQ(
"allTheThings", last->
outputs_[0]->path());
329 plan_.EdgeFinished(last);
331 ASSERT_FALSE(plan_.more_to_do());
332 ASSERT_FALSE(plan_.FindWork());
340 " command = touch foo.cpp\n"
342 " command = touch bar.cpp\n"
344 " command = echo $out > $out\n"
345 "build foo.cpp.obj: echo foo.cpp || foo.cpp\n"
347 "build bar.cpp.obj: echo bar.cpp || bar.cpp\n"
349 "build libfoo.a: echo foo.cpp.obj bar.cpp.obj\n"
350 "build foo.cpp: gen_foo\n"
351 "build bar.cpp: gen_bar\n"
352 "build all: phony libfoo.a\n"));
353 GetNode(
"foo.cpp")->MarkDirty();
354 GetNode(
"foo.cpp.obj")->MarkDirty();
355 GetNode(
"bar.cpp")->MarkDirty();
356 GetNode(
"bar.cpp.obj")->MarkDirty();
357 GetNode(
"libfoo.a")->MarkDirty();
358 GetNode(
"all")->MarkDirty();
360 EXPECT_TRUE(plan_.AddTarget(GetNode(
"all"), &err));
362 ASSERT_TRUE(plan_.more_to_do());
366 deque<Edge*> initial_edges;
367 FindWorkSorted(&initial_edges, 2);
369 edge = initial_edges[1];
370 ASSERT_EQ(
"foo.cpp", edge->outputs_[0]->path());
371 plan_.EdgeFinished(edge);
373 edge = plan_.FindWork();
375 ASSERT_FALSE(plan_.FindWork());
376 ASSERT_EQ(
"foo.cpp", edge->inputs_[0]->path());
377 ASSERT_EQ(
"foo.cpp", edge->inputs_[1]->path());
378 ASSERT_EQ(
"foo.cpp.obj", edge->outputs_[0]->path());
379 plan_.EdgeFinished(edge);
381 edge = initial_edges[0];
382 ASSERT_EQ(
"bar.cpp", edge->outputs_[0]->path());
383 plan_.EdgeFinished(edge);
385 edge = plan_.FindWork();
387 ASSERT_FALSE(plan_.FindWork());
388 ASSERT_EQ(
"bar.cpp", edge->inputs_[0]->path());
389 ASSERT_EQ(
"bar.cpp", edge->inputs_[1]->path());
390 ASSERT_EQ(
"bar.cpp.obj", edge->outputs_[0]->path());
391 plan_.EdgeFinished(edge);
393 edge = plan_.FindWork();
395 ASSERT_FALSE(plan_.FindWork());
396 ASSERT_EQ(
"foo.cpp.obj", edge->inputs_[0]->path());
397 ASSERT_EQ(
"bar.cpp.obj", edge->inputs_[1]->path());
398 ASSERT_EQ(
"libfoo.a", edge->outputs_[0]->path());
399 plan_.EdgeFinished(edge);
401 edge = plan_.FindWork();
403 ASSERT_FALSE(plan_.FindWork());
404 ASSERT_EQ(
"libfoo.a", edge->inputs_[0]->path());
405 ASSERT_EQ(
"all", edge->outputs_[0]->path());
406 plan_.EdgeFinished(edge);
408 edge = plan_.FindWork();
410 ASSERT_FALSE(plan_.more_to_do());
423 virtual void Abort();
437 StateTestWithBuiltinRules::SetUp();
441 "build cat1: cat in1\n"
442 "build cat2: cat in1 in2\n"
443 "build cat12: cat cat1 cat2\n");
458 void RebuildTarget(
const string& target,
const char* manifest,
459 const char* log_path = NULL,
460 const char* deps_path = NULL);
463 void Dirty(
const string& path);
480 const char* log_path,
const char* deps_path) {
486 BuildLog build_log, *pbuild_log = NULL;
488 ASSERT_TRUE(build_log.
Load(log_path, &err));
489 ASSERT_TRUE(build_log.
OpenForWrite(log_path, *
this, &err));
491 pbuild_log = &build_log;
494 DepsLog deps_log, *pdeps_log = NULL;
496 ASSERT_TRUE(deps_log.
Load(deps_path, &state, &err));
499 pdeps_log = &deps_log;
503 EXPECT_TRUE(builder.
AddTarget(target, &err));
508 bool build_res = builder.
Build(&err);
509 EXPECT_TRUE(build_res) <<
"builder.Build(&err)";
524 edge->
rule().
name() ==
"cat_rsp_out" ||
527 edge->
rule().
name() ==
"touch-interrupt") {
528 for (vector<Node*>::iterator out = edge->
outputs_.begin();
529 out != edge->
outputs_.end(); ++out) {
532 }
else if (edge->
rule().
name() ==
"true" ||
534 edge->
rule().
name() ==
"interrupt" ||
538 printf(
"unknown command\n");
553 if (edge->
rule().
name() ==
"interrupt" ||
554 edge->
rule().
name() ==
"touch-interrupt") {
559 if (edge->
rule().
name() ==
"console") {
599 EXPECT_TRUE(builder_.AlreadyUpToDate());
607 EXPECT_TRUE(builder_.AddTarget(
"cat1", &err));
609 EXPECT_TRUE(builder_.Build(&err));
612 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
613 EXPECT_EQ(
"cat in1 > cat1", command_runner_.commands_ran_[0]);
621 EXPECT_TRUE(builder_.AddTarget(
"cat1", &err));
623 EXPECT_TRUE(builder_.Build(&err));
626 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
627 EXPECT_EQ(
"cat in1 > cat1", command_runner_.commands_ran_[0]);
632 EXPECT_TRUE(builder_.AddTarget(
"cat12", &err));
634 EXPECT_TRUE(builder_.Build(&err));
636 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
639 EXPECT_TRUE((command_runner_.commands_ran_[0] ==
"cat in1 > cat1" &&
640 command_runner_.commands_ran_[1] ==
"cat in1 in2 > cat2") ||
641 (command_runner_.commands_ran_[1] ==
"cat in1 > cat1" &&
642 command_runner_.commands_ran_[0] ==
"cat in1 in2 > cat2"));
644 EXPECT_EQ(
"cat cat1 cat2 > cat12", command_runner_.commands_ran_[2]);
650 fs_.Create(
"in2",
"");
652 EXPECT_TRUE(builder_.AddTarget(
"cat12", &err));
654 EXPECT_TRUE(builder_.Build(&err));
656 ASSERT_EQ(5u, command_runner_.commands_ran_.size());
657 EXPECT_EQ(
"cat in1 in2 > cat2", command_runner_.commands_ran_[3]);
658 EXPECT_EQ(
"cat cat1 cat2 > cat12", command_runner_.commands_ran_[4]);
664 " command = touch $out\n"
665 "build out1 out2: touch in.txt\n"));
667 fs_.Create(
"in.txt",
"");
670 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
672 EXPECT_TRUE(builder_.Build(&err));
674 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
675 EXPECT_EQ(
"touch out1 out2", command_runner_.commands_ran_[0]);
683 " command = touch $out\n"
684 "build in1 otherfile: touch in\n"
685 "build out: touch in | in1\n"));
687 fs_.Create(
"in",
"");
689 fs_.Create(
"in1",
"");
692 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
694 EXPECT_TRUE(builder_.Build(&err));
703 "build c5: cat c4\n"));
705 fs_.Create(
"c1",
"");
708 EXPECT_TRUE(builder_.AddTarget(
"c5", &err));
710 EXPECT_TRUE(builder_.Build(&err));
712 ASSERT_EQ(4u, command_runner_.commands_ran_.size());
715 command_runner_.commands_ran_.clear();
717 EXPECT_TRUE(builder_.AddTarget(
"c5", &err));
719 EXPECT_TRUE(builder_.AlreadyUpToDate());
723 fs_.Create(
"c3",
"");
725 command_runner_.commands_ran_.clear();
727 EXPECT_TRUE(builder_.AddTarget(
"c5", &err));
729 EXPECT_FALSE(builder_.AlreadyUpToDate());
730 EXPECT_TRUE(builder_.Build(&err));
731 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
738 EXPECT_FALSE(builder_.AddTarget(
"cat1", &err));
739 EXPECT_EQ(
"'in1', needed by 'cat1', missing and no known rule to make it",
746 EXPECT_FALSE(builder_.AddTarget(
"meow", &err));
747 EXPECT_EQ(
"unknown target: 'meow'", err);
755 "build subdir\\dir2\\file: cat in1\n"));
756 EXPECT_TRUE(builder_.AddTarget(
"subdir\\dir2\\file", &err));
759 "build subdir/dir2/file: cat in1\n"));
760 EXPECT_TRUE(builder_.AddTarget(
"subdir/dir2/file", &err));
764 EXPECT_TRUE(builder_.Build(&err));
766 ASSERT_EQ(2u, fs_.directories_made_.size());
767 EXPECT_EQ(
"subdir", fs_.directories_made_[0]);
769 EXPECT_EQ(
"subdir\\dir2", fs_.directories_made_[1]);
771 EXPECT_EQ(
"subdir/dir2", fs_.directories_made_[1]);
778 "rule cc\n command = cc $in\n depfile = $out.d\n"
779 "build fo$ o.o: cc foo.c\n"));
780 fs_.Create(
"foo.c",
"");
782 EXPECT_TRUE(builder_.AddTarget(
"fo o.o", &err));
784 ASSERT_EQ(1u, fs_.files_read_.size());
785 EXPECT_EQ(
"fo o.o.d", fs_.files_read_[0]);
790 int orig_edges = state_.edges_.size();
792 "rule cc\n command = cc $in\n depfile = $out.d\n"
793 "build foo.o: cc foo.c\n"));
794 Edge* edge = state_.edges_.back();
796 fs_.Create(
"foo.c",
"");
797 GetNode(
"bar.h")->MarkDirty();
798 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
799 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
801 ASSERT_EQ(1u, fs_.files_read_.size());
802 EXPECT_EQ(
"foo.o.d", fs_.files_read_[0]);
806 ASSERT_EQ(orig_edges + 3, (
int)state_.edges_.size());
808 ASSERT_EQ(3u, edge->
inputs_.size());
817 "rule cc\n command = cc $in\n depfile = $out.d\n"
818 "build foo.o: cc foo.c\n"));
819 fs_.Create(
"foo.c",
"");
820 fs_.Create(
"foo.o.d",
"randomtext\n");
821 EXPECT_FALSE(builder_.AddTarget(
"foo.o", &err));
822 EXPECT_EQ(
"expected depfile 'foo.o.d' to mention 'foo.o', got 'randomtext'",
829 "rule cc\n command = cc $in\n depfile = $out.d\n"
830 "build foo.o: cc foo.c || otherfile\n"));
831 Edge* edge = state_.edges_.back();
833 fs_.Create(
"foo.c",
"");
834 fs_.Create(
"otherfile",
"");
835 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
836 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
840 ASSERT_EQ(4u, edge->
inputs_.size());
845 EXPECT_EQ(
"foo.c", edge->
inputs_[0]->path());
846 EXPECT_EQ(
"blah.h", edge->
inputs_[1]->path());
847 EXPECT_EQ(
"bar.h", edge->
inputs_[2]->path());
848 EXPECT_EQ(
"otherfile", edge->
inputs_[3]->path());
854 EXPECT_TRUE(builder_.Build(&err));
856 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
861 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
864 fs_.Create(
"blah.h",
"");
865 fs_.Create(
"bar.h",
"");
866 command_runner_.commands_ran_.clear();
868 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
869 EXPECT_TRUE(builder_.Build(&err));
871 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
876 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
879 fs_.Create(
"otherfile",
"");
880 command_runner_.commands_ran_.clear();
882 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
884 EXPECT_TRUE(builder_.AlreadyUpToDate());
887 fs_.RemoveFile(
"bar.h");
888 command_runner_.commands_ran_.clear();
890 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
891 EXPECT_TRUE(builder_.Build(&err));
893 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
899 "rule cc\n command = cc $in\n"
900 "rule true\n command = true\n"
901 "build oo.h: cc oo.h.in\n"
902 "build foo.o: cc foo.c || oo.h\n"));
904 fs_.Create(
"foo.c",
"");
905 fs_.Create(
"oo.h.in",
"");
908 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
909 EXPECT_TRUE(builder_.Build(&err));
911 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
914 command_runner_.commands_ran_.clear();
916 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
918 EXPECT_TRUE(builder_.AlreadyUpToDate());
921 fs_.RemoveFile(
"oo.h");
922 command_runner_.commands_ran_.clear();
924 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
925 EXPECT_TRUE(builder_.Build(&err));
927 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
928 ASSERT_EQ(
"cc oo.h.in", command_runner_.commands_ran_[0]);
933 fs_.Create(
"oo.h.in",
"");
934 command_runner_.commands_ran_.clear();
936 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
937 EXPECT_TRUE(builder_.Build(&err));
939 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
940 ASSERT_EQ(
"cc oo.h.in", command_runner_.commands_ran_[0]);
946 "build out: cat bar.cc\n"
947 "build all: phony out\n"));
948 fs_.Create(
"bar.cc",
"");
950 EXPECT_TRUE(builder_.AddTarget(
"all", &err));
954 EXPECT_FALSE(builder_.AlreadyUpToDate());
955 EXPECT_TRUE(builder_.Build(&err));
957 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
963 "build out: cat bar.cc\n"
964 "build all: phony out\n"));
965 fs_.Create(
"bar.cc",
"");
966 fs_.Create(
"out",
"");
968 EXPECT_TRUE(builder_.AddTarget(
"all", &err));
970 EXPECT_TRUE(builder_.AlreadyUpToDate());
977 "build out1: fail\n"));
980 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
983 EXPECT_FALSE(builder_.Build(&err));
984 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
985 ASSERT_EQ(
"subcommand failed", err);
995 "build all: phony out1 out2 out3\n"));
998 config_.failures_allowed = 3;
1001 EXPECT_TRUE(builder_.AddTarget(
"all", &err));
1004 EXPECT_FALSE(builder_.Build(&err));
1005 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1006 ASSERT_EQ(
"subcommands failed", err);
1013 "build out1: fail\n"
1014 "build out2: fail\n"
1015 "build out3: fail\n"
1016 "build final: cat out1 out2 out3\n"));
1019 config_.failures_allowed = 11;
1022 EXPECT_TRUE(builder_.AddTarget(
"final", &err));
1025 EXPECT_FALSE(builder_.Build(&err));
1026 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1027 ASSERT_EQ(
"cannot make progress due to previous errors", err);
1042 "build out1: cc in\n"));
1046 fs_.Create(
"in",
"");
1047 fs_.Create(
"out1",
"");
1052 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1053 EXPECT_FALSE(builder_.AlreadyUpToDate());
1055 command_runner_.commands_ran_.clear();
1058 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1059 EXPECT_TRUE(builder_.Build(&err));
1060 EXPECT_TRUE(builder_.AlreadyUpToDate());
1071 "build out1: cc in\n"
1072 "build out2: true out1\n"
1073 "build out3: cat out2\n"));
1075 fs_.Create(
"out1",
"");
1076 fs_.Create(
"out2",
"");
1077 fs_.Create(
"out3",
"");
1081 fs_.Create(
"in",
"");
1087 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1089 EXPECT_TRUE(builder_.Build(&err));
1091 EXPECT_EQ(
"[3/3]", builder_.status_->FormatProgressStatus(
"[%s/%t]"));
1092 command_runner_.commands_ran_.clear();
1097 fs_.Create(
"in",
"");
1100 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1102 EXPECT_TRUE(builder_.Build(&err));
1103 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1107 command_runner_.commands_ran_.clear();
1109 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1111 EXPECT_TRUE(builder_.AlreadyUpToDate());
1115 fs_.Create(
"in",
"");
1119 command_runner_.commands_ran_.clear();
1121 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1123 EXPECT_TRUE(builder_.Build(&err));
1124 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1138 "build out1: true in\n"
1139 "build out2: cc out1\n"));
1141 fs_.Create(
"in",
"");
1142 fs_.Create(
"out2",
"");
1148 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1150 EXPECT_TRUE(builder_.Build(&err));
1152 command_runner_.commands_ran_.clear();
1156 fs_.Create(
"in",
"");
1157 fs_.Create(
"out2",
"");
1162 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1164 EXPECT_TRUE(builder_.Build(&err));
1165 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1174 " command = touch\n"
1175 "build out1: true in\n"
1176 "build out2 out3: touch out1\n"
1177 "build out4: touch out2\n"
1181 fs_.Create(
"in",
"");
1184 EXPECT_TRUE(builder_.AddTarget(
"out4", &err));
1186 EXPECT_TRUE(builder_.Build(&err));
1188 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1191 fs_.Create(
"in",
"");
1192 fs_.RemoveFile(
"out3");
1199 command_runner_.commands_ran_.clear();
1201 EXPECT_TRUE(builder_.AddTarget(
"out4", &err));
1203 EXPECT_TRUE(builder_.Build(&err));
1205 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1214 " depfile = $out.d\n"
1218 "build out1: true in\n"
1219 "build out2: cc out1\n"));
1222 fs_.Create(
"in",
"");
1227 fs_.Create(
"out1.d",
"out1: will.be.deleted restat.file\n");
1228 fs_.Create(
"will.be.deleted",
"");
1229 fs_.Create(
"restat.file",
"");
1233 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1235 EXPECT_TRUE(builder_.Build(&err));
1236 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1241 ASSERT_TRUE(NULL != log_entry);
1242 ASSERT_EQ(restat_mtime, log_entry->restat_mtime);
1246 fs_.RemoveFile(
"will.be.deleted");
1249 command_runner_.commands_ran_.clear();
1251 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1253 EXPECT_TRUE(builder_.Build(&err));
1254 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1257 log_entry = build_log_.LookupByOutput(
"out1");
1258 ASSERT_TRUE(NULL != log_entry);
1259 ASSERT_EQ(restat_mtime, log_entry->restat_mtime);
1276 "build out1: cc in\n"
1277 "build out2: true out1\n"
1278 "build out3: cat out2\n"));
1280 fs_.Create(
"out1",
"");
1281 fs_.Create(
"out2",
"");
1282 fs_.Create(
"out3",
"");
1286 fs_.Create(
"in",
"");
1291 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1293 EXPECT_TRUE(builder_.Build(&err));
1294 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1303 " command = cat $rspfile > $out\n"
1304 " rspfile = $rspfile\n"
1305 " rspfile_content = $long_command\n"
1306 "rule cat_rsp_out\n"
1307 " command = cat $rspfile > $out\n"
1308 " rspfile = $out.rsp\n"
1309 " rspfile_content = $long_command\n"
1310 "build out1: cat in\n"
1311 "build out2: cat_rsp in\n"
1312 " rspfile = out 2.rsp\n"
1313 " long_command = Some very long command\n"
1314 "build out$ 3: cat_rsp_out in\n"
1315 " long_command = Some very long command\n"));
1317 fs_.Create(
"out1",
"");
1318 fs_.Create(
"out2",
"");
1319 fs_.Create(
"out 3",
"");
1323 fs_.Create(
"in",
"");
1326 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1328 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1330 EXPECT_TRUE(builder_.AddTarget(
"out 3", &err));
1333 size_t files_created = fs_.files_created_.size();
1334 size_t files_removed = fs_.files_removed_.size();
1336 EXPECT_TRUE(builder_.Build(&err));
1337 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1340 ASSERT_EQ(files_created + 2, fs_.files_created_.size());
1341 ASSERT_EQ(1u, fs_.files_created_.count(
"out 2.rsp"));
1342 ASSERT_EQ(1u, fs_.files_created_.count(
"out 3.rsp"));
1345 ASSERT_EQ(files_removed + 2, fs_.files_removed_.size());
1346 ASSERT_EQ(1u, fs_.files_removed_.count(
"out 2.rsp"));
1347 ASSERT_EQ(1u, fs_.files_removed_.count(
"out 3.rsp"));
1355 " rspfile = $rspfile\n"
1356 " rspfile_content = $long_command\n"
1357 "build out: fail in\n"
1358 " rspfile = out.rsp\n"
1359 " long_command = Another very long command\n"));
1361 fs_.Create(
"out",
"");
1363 fs_.Create(
"in",
"");
1366 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1369 size_t files_created = fs_.files_created_.size();
1370 size_t files_removed = fs_.files_removed_.size();
1372 EXPECT_FALSE(builder_.Build(&err));
1373 ASSERT_EQ(
"subcommand failed", err);
1374 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1377 ASSERT_EQ(files_created + 1, fs_.files_created_.size());
1378 ASSERT_EQ(1u, fs_.files_created_.count(
"out.rsp"));
1381 ASSERT_EQ(files_removed, fs_.files_removed_.size());
1382 ASSERT_EQ(0u, fs_.files_removed_.count(
"out.rsp"));
1385 ASSERT_EQ(
"Another very long command", fs_.files_[
"out.rsp"].contents);
1393 " command = cat $rspfile > $out\n"
1394 " rspfile = $rspfile\n"
1395 " rspfile_content = $long_command\n"
1396 "build out: cat_rsp in\n"
1397 " rspfile = out.rsp\n"
1398 " long_command = Original very long command\n"));
1400 fs_.Create(
"out",
"");
1402 fs_.Create(
"in",
"");
1405 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1409 EXPECT_TRUE(builder_.Build(&err));
1410 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1413 command_runner_.commands_ran_.clear();
1415 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1417 ASSERT_TRUE(builder_.AlreadyUpToDate());
1422 ASSERT_TRUE(NULL != log_entry);
1424 "cat out.rsp > out;rspfile=Original very long command",
1425 log_entry->command_hash));
1426 log_entry->command_hash++;
1428 command_runner_.commands_ran_.clear();
1430 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1432 EXPECT_TRUE(builder_.Build(&err));
1433 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1439 " command = interrupt\n"
1440 "rule touch-interrupt\n"
1441 " command = touch-interrupt\n"
1442 "build out1: interrupt in1\n"
1443 "build out2: touch-interrupt in2\n"));
1445 fs_.Create(
"out1",
"");
1446 fs_.Create(
"out2",
"");
1448 fs_.Create(
"in1",
"");
1449 fs_.Create(
"in2",
"");
1453 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1455 EXPECT_FALSE(builder_.Build(&err));
1456 EXPECT_EQ(
"interrupted by user", err);
1458 EXPECT_GT(fs_.Stat(
"out1"), 0);
1462 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1464 EXPECT_FALSE(builder_.Build(&err));
1465 EXPECT_EQ(
"interrupted by user", err);
1467 EXPECT_EQ(0, fs_.Stat(
"out2"));
1472 "build nonexistent: phony\n"
1473 "build out1: cat || nonexistent\n"
1474 "build out2: cat nonexistent\n"));
1475 fs_.Create(
"out1",
"");
1476 fs_.Create(
"out2",
"");
1481 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1483 EXPECT_TRUE(builder_.AlreadyUpToDate());
1487 command_runner_.commands_ran_.clear();
1489 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1491 EXPECT_TRUE(builder_.Build(&err));
1493 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1501 "build out: cc\n"));
1505 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1507 EXPECT_FALSE(builder_.AlreadyUpToDate());
1509 EXPECT_FALSE(builder_.Build(&err));
1510 ASSERT_EQ(
"subcommand failed", err);
1511 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1515 EXPECT_EQ(
"[%/s0/t0/r0/u0/f0]",
1516 status_.FormatProgressStatus(
"[%%/s%s/t%t/r%r/u%u/f%f]"));
1521 "build bad_deps.o: cat in1\n"
1523 " depfile = in1.d\n"));
1526 EXPECT_TRUE(builder_.AddTarget(
"bad_deps.o", &err));
1531 fs_.Create(
"in1.d",
"AAA BBB");
1533 EXPECT_FALSE(builder_.Build(&err));
1534 EXPECT_EQ(
"subcommand failed", err);
1564 const char* manifest =
1565 "build out: cat in1\n"
1567 " depfile = in1.d\n";
1570 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1571 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1575 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1578 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1580 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
1582 fs_.Create(
"in1.d",
"out: in2");
1583 EXPECT_TRUE(builder.
Build(&err));
1587 EXPECT_EQ(0, fs_.Stat(
"in1.d"));
1589 fs_.Create(
"in1.d",
"out: in2");
1596 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1597 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1601 fs_.Create(
"in2",
"");
1605 ASSERT_TRUE(deps_log.
Load(
"ninja_deps", &state, &err));
1606 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1608 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1609 builder.command_runner_.reset(&command_runner_);
1610 command_runner_.commands_ran_.clear();
1611 EXPECT_TRUE(builder.AddTarget(
"out", &err));
1613 EXPECT_TRUE(builder.Build(&err));
1618 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1620 builder.command_runner_.release();
1631 const char* manifest =
1632 "build out: cat in1\n"
1634 " depfile = in1.d\n";
1637 fs_.Create(
"in1",
"");
1638 fs_.Create(
"in1.d",
"out: ");
1641 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1642 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1646 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1649 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1651 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
1653 EXPECT_TRUE(builder.
Build(&err));
1663 fs_.Create(
"in1",
"");
1664 fs_.Create(
"out",
"");
1667 EXPECT_EQ(0, fs_.Stat(
"in1.d"));
1671 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1672 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1675 ASSERT_TRUE(deps_log.
Load(
"ninja_deps", &state, &err));
1676 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1678 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1679 builder.command_runner_.reset(&command_runner_);
1680 command_runner_.commands_ran_.clear();
1681 EXPECT_TRUE(builder.AddTarget(
"out", &err));
1685 fs_.Create(
"in1.d",
"out: ");
1687 EXPECT_TRUE(builder.Build(&err));
1692 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1694 builder.command_runner_.release();
1699 const char* manifest =
1700 "build out: cat in1\n"
1702 " depfile = in1.d\n";
1704 fs_.Create(
"out",
"");
1706 fs_.Create(
"in1",
"");
1709 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1710 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1713 config_.dry_run =
true;
1714 Builder builder(&state, config_, NULL, NULL, &fs_);
1716 command_runner_.commands_ran_.clear();
1719 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
1721 EXPECT_TRUE(builder.
Build(&err));
1722 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1733 "build header.h: true header.in\n"
1734 "build out: cat in1\n"
1735 " depfile = in1.d\n"));
1737 fs_.Create(
"header.h",
"");
1738 fs_.Create(
"in1.d",
"out: header.h");
1740 fs_.Create(
"header.in",
"");
1743 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1745 EXPECT_TRUE(builder_.Build(&err));
1754 const char* manifest =
1758 "build header.h: true header.in\n"
1759 "build out: cat in1\n"
1761 " depfile = in1.d\n";
1764 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1765 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1769 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1772 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1774 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
1776 fs_.Create(
"in1.d",
"out: header.h");
1777 EXPECT_TRUE(builder.
Build(&err));
1786 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1787 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1791 fs_.Create(
"header.in",
"");
1795 ASSERT_TRUE(deps_log.
Load(
"ninja_deps", &state, &err));
1796 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1798 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1799 builder.command_runner_.reset(&command_runner_);
1800 command_runner_.commands_ran_.clear();
1801 EXPECT_TRUE(builder.AddTarget(
"out", &err));
1803 EXPECT_TRUE(builder.Build(&err));
1808 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1810 builder.command_runner_.release();
1816 const char* manifest =
1817 "rule cc\n command = cc $in\n depfile = $out.d\n deps = gcc\n"
1818 "build fo$ o.o: cc foo.c\n";
1820 fs_.Create(
"foo.c",
"");
1824 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1828 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1831 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1833 EXPECT_TRUE(builder.
AddTarget(
"fo o.o", &err));
1835 fs_.Create(
"fo o.o.d",
"fo\\ o.o: blah.h bar.h\n");
1836 EXPECT_TRUE(builder.
Build(&err));
1845 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1848 ASSERT_TRUE(deps_log.
Load(
"ninja_deps", &state, &err));
1849 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1852 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1858 EXPECT_TRUE(builder.
AddTarget(
"fo o.o", &err));
1863 ASSERT_EQ(3u, state.
edges_.size());
1865 ASSERT_EQ(3u, edge->
inputs_.size());
1878 const char* manifest =
1882 "build header.h: true header.in\n"
1883 "build out: cat header.h\n"
1884 " depfile = out.d\n";
1886 fs_.Create(
"header.h",
"");
1888 fs_.Create(
"out",
"");
1889 fs_.Create(
"header.in",
"");
1895 RebuildTarget(
"out", manifest);
1896 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1903 const char* manifest =
1907 "build header.h: true header.in\n"
1908 "build out: cat header.h\n"
1910 " depfile = out.d\n";
1913 fs_.Create(
"header.in",
"");
1914 fs_.Create(
"out.d",
"out: header.h");
1915 fs_.Create(
"header.h",
"");
1917 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps");
1918 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1921 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps");
1922 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
1928 fs_.Create(
"header.in",
"");
1931 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps2");
1932 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1935 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps2");
1936 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
1941 fs_.Create(
"header.in",
"");
1942 fs_.Create(
"out",
"");
1943 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps2");
1944 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1947 RebuildTarget(
"out", manifest,
"build_log",
"ninja_deps2");
1948 ASSERT_EQ(0u, command_runner_.commands_ran_.size());
1954 " command = console\n"
1956 "build cons: console in.txt\n"));
1958 fs_.Create(
"in.txt",
"");
1961 EXPECT_TRUE(builder_.AddTarget(
"cons", &err));
1963 EXPECT_TRUE(builder_.Build(&err));
1965 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
FakeCommandRunner command_runner_
An implementation of DiskInterface that uses an in-memory representation of disk state.
CommandRunner is an interface that wraps running the build subcommands.
FakeCommandRunner(VirtualFileSystem *fs)
vector< Edge * > edges_
All the edges of the graph.
Node * GetNode(const string &path)
Short way to get a Node by its path from state_.
void TestPoolWithDepthOne(const char *test_case)
Plan stores the state of a build plan: what we intend to build, which steps we're ready to execute...
bool more_to_do() const
Returns true if there's more work to be done.
Node * GetNode(StringPiece path)
void * builder_
Shadow parent class builder_ so we don't accidentally use it.
The result of waiting for a command.
StringPiece represents a slice of a string whose memory is managed externally.
bool AddTarget(Node *node, string *err)
Add a target to our plan (including all its dependencies).
Information about a node in the dependency graph: the file, whether it's dirty, mtime, etc.
Fixture for tests involving Plan.
virtual vector< Edge * > GetActiveEdges()
void AssertParse(State *state, const char *input)
void Create(const string &path, const string &contents)
"Create" a file with contents.
An edge in the dependency graph; links between Nodes using Rules.
Store a log of every command ran for every build.
string EvaluateCommand(bool incl_rsp_file=false)
Expand all variables in a command and return it as a string.
bool AlreadyUpToDate() const
Returns true if the build targets are already up to date.
A base test fixture that includes a State object with a builtin "cat" rule.
void RebuildTarget(const string &target, const char *manifest, const char *log_path=NULL, const char *deps_path=NULL)
Rebuild target in the 'working tree' (fs_).
void EdgeFinished(Edge *edge)
Mark an edge as done building.
void AddCatRule(State *state)
Add a "cat" rule to state.
As build commands run they can output extra dependency information (e.g.
void FindWorkSorted(deque< Edge * > *ret, int count)
Because FindWork does not return Edges in any sort of predictable order,.
virtual bool IsPathDead(StringPiece s) const
Return if a given output no longer part of the build manifest.
bool OpenForWrite(const string &path, const BuildLogUser &user, string *err)
bool OpenForWrite(const string &path, string *err)
Tests of builds involving deps logs necessarily must span multiple builds.
virtual bool WaitForCommand(Result *result)
Wait for a command to complete, or return false if interrupted.
void MarkMissing()
Mark the Node as already-stat()ed and missing.
bool Load(const string &path, State *state, string *err)
Fake implementation of CommandRunner, useful for tests.
virtual bool CanRunMore()
auto_ptr< CommandRunner > command_runner_
void SetBuildLog(BuildLog *log)
Used for tests.
Builder wraps the build process: starting commands, updating status.
Tracks the status of a build: completion fraction, printing updates.
void Cleanup()
Clean up the temporary directory.
virtual bool StartCommand(Edge *edge)
void CreateAndEnter(const string &name)
Create a temporary directory and chdir into it.
Options (e.g. verbosity, parallelism) passed to a build.
Global state (file status, loaded rules) for a single run.
const string & name() const
void Dirty(const string &path)
bool Load(const string &path, string *err)
Load the on-disk log.
bool Build(string *err)
Run the build.
const Rule & rule() const
vector< string > commands_ran_
void AssertHash(const char *expected, uint64_t actual)
Node * AddTarget(const string &name, string *err)
Can answer questions about the manifest for the BuildLog.
vector< Node * > outputs_