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);
51 "build out: cat mid\n"
52 "build mid: cat in\n");
53 GetNode(
"mid")->MarkDirty();
54 GetNode(
"out")->MarkDirty();
56 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out"), &err));
58 ASSERT_TRUE(plan_.more_to_do());
60 Edge* edge = plan_.FindWork();
62 ASSERT_EQ(
"in", edge->inputs_[0]->path());
63 ASSERT_EQ(
"mid", edge->outputs_[0]->path());
65 ASSERT_FALSE(plan_.FindWork());
67 plan_.EdgeFinished(edge);
69 edge = plan_.FindWork();
71 ASSERT_EQ(
"mid", edge->inputs_[0]->path());
72 ASSERT_EQ(
"out", edge->outputs_[0]->path());
74 plan_.EdgeFinished(edge);
76 ASSERT_FALSE(plan_.more_to_do());
77 edge = plan_.FindWork();
84 "build out: cat mid1 mid2\n"
85 "build mid1 mid2: cat in\n");
86 GetNode(
"mid1")->MarkDirty();
87 GetNode(
"mid2")->MarkDirty();
88 GetNode(
"out")->MarkDirty();
91 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out"), &err));
93 ASSERT_TRUE(plan_.more_to_do());
96 edge = plan_.FindWork();
98 plan_.EdgeFinished(edge);
100 edge = plan_.FindWork();
102 plan_.EdgeFinished(edge);
104 edge = plan_.FindWork();
111 "build out: cat b1 b2\n"
114 "build a1 a2: cat in\n");
115 GetNode(
"a1")->MarkDirty();
116 GetNode(
"a2")->MarkDirty();
117 GetNode(
"b1")->MarkDirty();
118 GetNode(
"b2")->MarkDirty();
119 GetNode(
"out")->MarkDirty();
121 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out"), &err));
123 ASSERT_TRUE(plan_.more_to_do());
126 edge = plan_.FindWork();
128 plan_.EdgeFinished(edge);
130 edge = plan_.FindWork();
132 plan_.EdgeFinished(edge);
134 edge = plan_.FindWork();
136 plan_.EdgeFinished(edge);
138 edge = plan_.FindWork();
140 plan_.EdgeFinished(edge);
142 edge = plan_.FindWork();
149 "build out: cat a1 a2\n"
150 "build a1: cat mid\n"
151 "build a2: cat mid\n"
152 "build mid: cat in\n");
153 GetNode(
"mid")->MarkDirty();
154 GetNode(
"a1")->MarkDirty();
155 GetNode(
"a2")->MarkDirty();
156 GetNode(
"out")->MarkDirty();
159 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out"), &err));
161 ASSERT_TRUE(plan_.more_to_do());
164 edge = plan_.FindWork();
166 plan_.EdgeFinished(edge);
168 edge = plan_.FindWork();
170 plan_.EdgeFinished(edge);
172 edge = plan_.FindWork();
174 plan_.EdgeFinished(edge);
176 edge = plan_.FindWork();
178 plan_.EdgeFinished(edge);
180 edge = plan_.FindWork();
186 "build out: cat mid\n"
187 "build mid: cat in\n"
188 "build in: cat pre\n"
189 "build pre: cat out\n");
190 GetNode(
"out")->MarkDirty();
191 GetNode(
"mid")->MarkDirty();
192 GetNode(
"in")->MarkDirty();
193 GetNode(
"pre")->MarkDirty();
196 EXPECT_FALSE(plan_.AddTarget(GetNode(
"out"), &err));
197 ASSERT_EQ(
"dependency cycle: out -> mid -> in -> pre -> out", err);
205 " command = cat $in > $out\n"
207 "build out1: poolcat in\n"
208 "build out2: poolcat in\n"));
209 GetNode(
"out1")->MarkDirty();
210 GetNode(
"out2")->MarkDirty();
212 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out1"), &err));
214 EXPECT_TRUE(plan_.AddTarget(GetNode(
"out2"), &err));
216 ASSERT_TRUE(plan_.more_to_do());
218 Edge* edge = plan_.FindWork();
220 ASSERT_EQ(
"in", edge->inputs_[0]->path());
221 ASSERT_EQ(
"out1", edge->outputs_[0]->path());
224 ASSERT_FALSE(plan_.FindWork());
226 plan_.EdgeFinished(edge);
228 edge = plan_.FindWork();
230 ASSERT_EQ(
"in", edge->inputs_[0]->path());
231 ASSERT_EQ(
"out2", edge->outputs_[0]->path());
233 ASSERT_FALSE(plan_.FindWork());
235 plan_.EdgeFinished(edge);
237 ASSERT_FALSE(plan_.more_to_do());
238 edge = plan_.FindWork();
249 " command = cat $in > $out\n"
252 " command = cat $in > $out\n"
254 "build out1: foocat in\n"
255 "build out2: foocat in\n"
256 "build out3: foocat in\n"
257 "build outb1: bazcat in\n"
258 "build outb2: bazcat in\n"
259 "build outb3: bazcat in\n"
261 "build allTheThings: cat out1 out2 out3 outb1 outb2 outb3\n"
264 for (
int i = 0; i < 3; ++i) {
265 GetNode(
"out" +
string(1,
'1' + static_cast<char>(i)))->MarkDirty();
266 GetNode(
"outb" +
string(1,
'1' + static_cast<char>(i)))->MarkDirty();
268 GetNode(
"allTheThings")->MarkDirty();
271 EXPECT_TRUE(plan_.AddTarget(GetNode(
"allTheThings"), &err));
275 FindWorkSorted(&edges, 5);
277 for (
int i = 0; i < 4; ++i) {
278 Edge *edge = edges[i];
279 ASSERT_EQ(
"in", edge->
inputs_[0]->path());
280 string base_name(i < 2 ?
"out" :
"outb");
281 ASSERT_EQ(base_name +
string(1,
'1' + (i % 2)), edge->
outputs_[0]->path());
285 Edge* edge = edges[4];
287 ASSERT_EQ(
"in", edge->
inputs_[0]->path());
288 ASSERT_EQ(
"outb3", edge->
outputs_[0]->path());
291 plan_.EdgeFinished(edges.front());
295 Edge* out3 = plan_.FindWork();
297 ASSERT_EQ(
"in", out3->
inputs_[0]->path());
298 ASSERT_EQ(
"out3", out3->
outputs_[0]->path());
300 ASSERT_FALSE(plan_.FindWork());
302 plan_.EdgeFinished(out3);
304 ASSERT_FALSE(plan_.FindWork());
306 for (deque<Edge*>::iterator it = edges.begin(); it != edges.end(); ++it) {
307 plan_.EdgeFinished(*it);
310 Edge* last = plan_.FindWork();
312 ASSERT_EQ(
"allTheThings", last->
outputs_[0]->path());
314 plan_.EdgeFinished(last);
316 ASSERT_FALSE(plan_.more_to_do());
317 ASSERT_FALSE(plan_.FindWork());
325 " command = touch foo.cpp\n"
327 " command = touch bar.cpp\n"
329 " command = echo $out > $out\n"
330 "build foo.cpp.obj: echo foo.cpp || foo.cpp\n"
332 "build bar.cpp.obj: echo bar.cpp || bar.cpp\n"
334 "build libfoo.a: echo foo.cpp.obj bar.cpp.obj\n"
335 "build foo.cpp: gen_foo\n"
336 "build bar.cpp: gen_bar\n"
337 "build all: phony libfoo.a\n"));
338 GetNode(
"foo.cpp")->MarkDirty();
339 GetNode(
"foo.cpp.obj")->MarkDirty();
340 GetNode(
"bar.cpp")->MarkDirty();
341 GetNode(
"bar.cpp.obj")->MarkDirty();
342 GetNode(
"libfoo.a")->MarkDirty();
343 GetNode(
"all")->MarkDirty();
345 EXPECT_TRUE(plan_.AddTarget(GetNode(
"all"), &err));
347 ASSERT_TRUE(plan_.more_to_do());
351 deque<Edge*> initial_edges;
352 FindWorkSorted(&initial_edges, 2);
354 edge = initial_edges[1];
355 ASSERT_EQ(
"foo.cpp", edge->outputs_[0]->path());
356 plan_.EdgeFinished(edge);
358 edge = plan_.FindWork();
360 ASSERT_FALSE(plan_.FindWork());
361 ASSERT_EQ(
"foo.cpp", edge->inputs_[0]->path());
362 ASSERT_EQ(
"foo.cpp", edge->inputs_[1]->path());
363 ASSERT_EQ(
"foo.cpp.obj", edge->outputs_[0]->path());
364 plan_.EdgeFinished(edge);
366 edge = initial_edges[0];
367 ASSERT_EQ(
"bar.cpp", edge->outputs_[0]->path());
368 plan_.EdgeFinished(edge);
370 edge = plan_.FindWork();
372 ASSERT_FALSE(plan_.FindWork());
373 ASSERT_EQ(
"bar.cpp", edge->inputs_[0]->path());
374 ASSERT_EQ(
"bar.cpp", edge->inputs_[1]->path());
375 ASSERT_EQ(
"bar.cpp.obj", edge->outputs_[0]->path());
376 plan_.EdgeFinished(edge);
378 edge = plan_.FindWork();
380 ASSERT_FALSE(plan_.FindWork());
381 ASSERT_EQ(
"foo.cpp.obj", edge->inputs_[0]->path());
382 ASSERT_EQ(
"bar.cpp.obj", edge->inputs_[1]->path());
383 ASSERT_EQ(
"libfoo.a", edge->outputs_[0]->path());
384 plan_.EdgeFinished(edge);
386 edge = plan_.FindWork();
388 ASSERT_FALSE(plan_.FindWork());
389 ASSERT_EQ(
"libfoo.a", edge->inputs_[0]->path());
390 ASSERT_EQ(
"all", edge->outputs_[0]->path());
391 plan_.EdgeFinished(edge);
393 edge = plan_.FindWork();
395 ASSERT_FALSE(plan_.more_to_do());
408 virtual void Abort();
422 StateTestWithBuiltinRules::SetUp();
426 "build cat1: cat in1\n"
427 "build cat2: cat in1 in2\n"
428 "build cat12: cat cat1 cat2\n");
439 void Dirty(
const string& path);
467 edge->
rule().
name() ==
"touch-interrupt") {
468 for (vector<Node*>::iterator out = edge->
outputs_.begin();
469 out != edge->
outputs_.end(); ++out) {
472 }
else if (edge->
rule().
name() ==
"true" ||
474 edge->
rule().
name() ==
"interrupt") {
477 printf(
"unknown command\n");
492 if (edge->
rule().
name() ==
"interrupt" ||
493 edge->
rule().
name() ==
"touch-interrupt") {
529 EXPECT_TRUE(builder_.AlreadyUpToDate());
537 EXPECT_TRUE(builder_.AddTarget(
"cat1", &err));
539 EXPECT_TRUE(builder_.Build(&err));
542 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
543 EXPECT_EQ(
"cat in1 > cat1", command_runner_.commands_ran_[0]);
551 EXPECT_TRUE(builder_.AddTarget(
"cat1", &err));
553 EXPECT_TRUE(builder_.Build(&err));
556 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
557 EXPECT_EQ(
"cat in1 > cat1", command_runner_.commands_ran_[0]);
562 EXPECT_TRUE(builder_.AddTarget(
"cat12", &err));
564 EXPECT_TRUE(builder_.Build(&err));
566 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
569 EXPECT_TRUE((command_runner_.commands_ran_[0] ==
"cat in1 > cat1" &&
570 command_runner_.commands_ran_[1] ==
"cat in1 in2 > cat2") ||
571 (command_runner_.commands_ran_[1] ==
"cat in1 > cat1" &&
572 command_runner_.commands_ran_[0] ==
"cat in1 in2 > cat2"));
574 EXPECT_EQ(
"cat cat1 cat2 > cat12", command_runner_.commands_ran_[2]);
580 fs_.Create(
"in2",
"");
582 EXPECT_TRUE(builder_.AddTarget(
"cat12", &err));
584 EXPECT_TRUE(builder_.Build(&err));
586 ASSERT_EQ(5u, command_runner_.commands_ran_.size());
587 EXPECT_EQ(
"cat in1 in2 > cat2", command_runner_.commands_ran_[3]);
588 EXPECT_EQ(
"cat cat1 cat2 > cat12", command_runner_.commands_ran_[4]);
594 " command = touch $out\n"
595 "build out1 out2: touch in.txt\n"));
597 fs_.Create(
"in.txt",
"");
600 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
602 EXPECT_TRUE(builder_.Build(&err));
604 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
605 EXPECT_EQ(
"touch out1 out2", command_runner_.commands_ran_[0]);
613 " command = touch $out\n"
614 "build in1 otherfile: touch in\n"
615 "build out: touch in | in1\n"));
617 fs_.Create(
"in",
"");
619 fs_.Create(
"in1",
"");
622 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
624 EXPECT_TRUE(builder_.Build(&err));
633 "build c5: cat c4\n"));
635 fs_.Create(
"c1",
"");
638 EXPECT_TRUE(builder_.AddTarget(
"c5", &err));
640 EXPECT_TRUE(builder_.Build(&err));
642 ASSERT_EQ(4u, command_runner_.commands_ran_.size());
645 command_runner_.commands_ran_.clear();
647 EXPECT_TRUE(builder_.AddTarget(
"c5", &err));
649 EXPECT_TRUE(builder_.AlreadyUpToDate());
653 fs_.Create(
"c3",
"");
655 command_runner_.commands_ran_.clear();
657 EXPECT_TRUE(builder_.AddTarget(
"c5", &err));
659 EXPECT_FALSE(builder_.AlreadyUpToDate());
660 EXPECT_TRUE(builder_.Build(&err));
661 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
668 EXPECT_FALSE(builder_.AddTarget(
"cat1", &err));
669 EXPECT_EQ(
"'in1', needed by 'cat1', missing and no known rule to make it",
676 EXPECT_FALSE(builder_.AddTarget(
"meow", &err));
677 EXPECT_EQ(
"unknown target: 'meow'", err);
685 "build subdir\\dir2\\file: cat in1\n"));
686 EXPECT_TRUE(builder_.AddTarget(
"subdir\\dir2\\file", &err));
689 "build subdir/dir2/file: cat in1\n"));
690 EXPECT_TRUE(builder_.AddTarget(
"subdir/dir2/file", &err));
694 EXPECT_TRUE(builder_.Build(&err));
696 ASSERT_EQ(2u, fs_.directories_made_.size());
697 EXPECT_EQ(
"subdir", fs_.directories_made_[0]);
699 EXPECT_EQ(
"subdir\\dir2", fs_.directories_made_[1]);
701 EXPECT_EQ(
"subdir/dir2", fs_.directories_made_[1]);
708 "rule cc\n command = cc $in\n depfile = $out.d\n"
709 "build foo.o: cc foo.c\n"));
710 fs_.Create(
"foo.c",
"");
712 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
714 ASSERT_EQ(1u, fs_.files_read_.size());
715 EXPECT_EQ(
"foo.o.d", fs_.files_read_[0]);
720 int orig_edges = state_.edges_.size();
722 "rule cc\n command = cc $in\n depfile = $out.d\n"
723 "build foo.o: cc foo.c\n"));
724 Edge* edge = state_.edges_.back();
726 fs_.Create(
"foo.c",
"");
727 GetNode(
"bar.h")->MarkDirty();
728 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
729 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
731 ASSERT_EQ(1u, fs_.files_read_.size());
732 EXPECT_EQ(
"foo.o.d", fs_.files_read_[0]);
736 ASSERT_EQ(orig_edges + 3, (
int)state_.edges_.size());
738 ASSERT_EQ(3u, edge->
inputs_.size());
747 "rule cc\n command = cc $in\n depfile = $out.d\n"
748 "build foo.o: cc foo.c\n"));
749 fs_.Create(
"foo.c",
"");
750 fs_.Create(
"foo.o.d",
"randomtext\n");
751 EXPECT_FALSE(builder_.AddTarget(
"foo.o", &err));
752 EXPECT_EQ(
"expected depfile 'foo.o.d' to mention 'foo.o', got 'randomtext'",
759 "rule cc\n command = cc $in\n depfile = $out.d\n"
760 "build foo.o: cc foo.c || otherfile\n"));
761 Edge* edge = state_.edges_.back();
763 fs_.Create(
"foo.c",
"");
764 fs_.Create(
"otherfile",
"");
765 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
766 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
770 ASSERT_EQ(4u, edge->
inputs_.size());
775 EXPECT_EQ(
"foo.c", edge->
inputs_[0]->path());
776 EXPECT_EQ(
"blah.h", edge->
inputs_[1]->path());
777 EXPECT_EQ(
"bar.h", edge->
inputs_[2]->path());
778 EXPECT_EQ(
"otherfile", edge->
inputs_[3]->path());
784 EXPECT_TRUE(builder_.Build(&err));
786 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
791 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
794 fs_.Create(
"blah.h",
"");
795 fs_.Create(
"bar.h",
"");
796 command_runner_.commands_ran_.clear();
798 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
799 EXPECT_TRUE(builder_.Build(&err));
801 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
806 fs_.Create(
"foo.o.d",
"foo.o: blah.h bar.h\n");
809 fs_.Create(
"otherfile",
"");
810 command_runner_.commands_ran_.clear();
812 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
814 EXPECT_TRUE(builder_.AlreadyUpToDate());
817 fs_.RemoveFile(
"bar.h");
818 command_runner_.commands_ran_.clear();
820 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
821 EXPECT_TRUE(builder_.Build(&err));
823 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
829 "rule cc\n command = cc $in\n"
830 "rule true\n command = true\n"
831 "build oo.h: cc oo.h.in\n"
832 "build foo.o: cc foo.c || oo.h\n"));
834 fs_.Create(
"foo.c",
"");
835 fs_.Create(
"oo.h.in",
"");
838 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
839 EXPECT_TRUE(builder_.Build(&err));
841 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
844 command_runner_.commands_ran_.clear();
846 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
848 EXPECT_TRUE(builder_.AlreadyUpToDate());
851 fs_.RemoveFile(
"oo.h");
852 command_runner_.commands_ran_.clear();
854 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
855 EXPECT_TRUE(builder_.Build(&err));
857 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
858 ASSERT_EQ(
"cc oo.h.in", command_runner_.commands_ran_[0]);
863 fs_.Create(
"oo.h.in",
"");
864 command_runner_.commands_ran_.clear();
866 EXPECT_TRUE(builder_.AddTarget(
"foo.o", &err));
867 EXPECT_TRUE(builder_.Build(&err));
869 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
870 ASSERT_EQ(
"cc oo.h.in", command_runner_.commands_ran_[0]);
876 "build out: cat bar.cc\n"
877 "build all: phony out\n"));
878 fs_.Create(
"bar.cc",
"");
880 EXPECT_TRUE(builder_.AddTarget(
"all", &err));
884 EXPECT_FALSE(builder_.AlreadyUpToDate());
885 EXPECT_TRUE(builder_.Build(&err));
887 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
893 "build out: cat bar.cc\n"
894 "build all: phony out\n"));
895 fs_.Create(
"bar.cc",
"");
896 fs_.Create(
"out",
"");
898 EXPECT_TRUE(builder_.AddTarget(
"all", &err));
900 EXPECT_TRUE(builder_.AlreadyUpToDate());
907 "build out1: fail\n"));
910 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
913 EXPECT_FALSE(builder_.Build(&err));
914 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
915 ASSERT_EQ(
"subcommand failed", err);
925 "build all: phony out1 out2 out3\n"));
928 config_.failures_allowed = 3;
931 EXPECT_TRUE(builder_.AddTarget(
"all", &err));
934 EXPECT_FALSE(builder_.Build(&err));
935 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
936 ASSERT_EQ(
"subcommands failed", err);
946 "build final: cat out1 out2 out3\n"));
949 config_.failures_allowed = 11;
952 EXPECT_TRUE(builder_.AddTarget(
"final", &err));
955 EXPECT_FALSE(builder_.Build(&err));
956 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
957 ASSERT_EQ(
"cannot make progress due to previous errors", err);
972 "build out1: cc in\n"));
976 fs_.Create(
"in",
"");
977 fs_.Create(
"out1",
"");
982 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
983 EXPECT_FALSE(builder_.AlreadyUpToDate());
985 command_runner_.commands_ran_.clear();
988 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
989 EXPECT_TRUE(builder_.Build(&err));
990 EXPECT_TRUE(builder_.AlreadyUpToDate());
1001 "build out1: cc in\n"
1002 "build out2: true out1\n"
1003 "build out3: cat out2\n"));
1005 fs_.Create(
"out1",
"");
1006 fs_.Create(
"out2",
"");
1007 fs_.Create(
"out3",
"");
1011 fs_.Create(
"in",
"");
1017 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1019 EXPECT_TRUE(builder_.Build(&err));
1021 command_runner_.commands_ran_.clear();
1026 fs_.Create(
"in",
"");
1029 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1031 EXPECT_TRUE(builder_.Build(&err));
1032 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1036 command_runner_.commands_ran_.clear();
1038 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1040 EXPECT_TRUE(builder_.AlreadyUpToDate());
1044 fs_.Create(
"in",
"");
1048 command_runner_.commands_ran_.clear();
1050 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1052 EXPECT_TRUE(builder_.Build(&err));
1053 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1067 "build out1: true in\n"
1068 "build out2: cc out1\n"));
1070 fs_.Create(
"in",
"");
1071 fs_.Create(
"out2",
"");
1077 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1079 EXPECT_TRUE(builder_.Build(&err));
1081 command_runner_.commands_ran_.clear();
1085 fs_.Create(
"in",
"");
1086 fs_.Create(
"out2",
"");
1091 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1093 EXPECT_TRUE(builder_.Build(&err));
1094 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1103 " depfile = $out.d\n"
1107 "build out1: true in\n"
1108 "build out2: cc out1\n"));
1111 fs_.Create(
"in",
"");
1116 fs_.Create(
"out1.d",
"out1: will.be.deleted restat.file\n");
1117 fs_.Create(
"will.be.deleted",
"");
1118 fs_.Create(
"restat.file",
"");
1122 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1124 EXPECT_TRUE(builder_.Build(&err));
1125 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1130 ASSERT_TRUE(NULL != log_entry);
1131 ASSERT_EQ(restat_mtime, log_entry->restat_mtime);
1135 fs_.RemoveFile(
"will.be.deleted");
1138 command_runner_.commands_ran_.clear();
1140 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1142 EXPECT_TRUE(builder_.Build(&err));
1143 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1146 log_entry = build_log_.LookupByOutput(
"out1");
1147 ASSERT_TRUE(NULL != log_entry);
1148 ASSERT_EQ(restat_mtime, log_entry->restat_mtime);
1165 "build out1: cc in\n"
1166 "build out2: true out1\n"
1167 "build out3: cat out2\n"));
1169 fs_.Create(
"out1",
"");
1170 fs_.Create(
"out2",
"");
1171 fs_.Create(
"out3",
"");
1175 fs_.Create(
"in",
"");
1180 EXPECT_TRUE(builder_.AddTarget(
"out3", &err));
1182 EXPECT_TRUE(builder_.Build(&err));
1183 ASSERT_EQ(3u, command_runner_.commands_ran_.size());
1192 " command = cat $rspfile > $out\n"
1193 " rspfile = $rspfile\n"
1194 " rspfile_content = $long_command\n"
1195 "build out1: cat in\n"
1196 "build out2: cat_rsp in\n"
1197 " rspfile = out2.rsp\n"
1198 " long_command = Some very long command\n"));
1200 fs_.Create(
"out1",
"");
1201 fs_.Create(
"out2",
"");
1202 fs_.Create(
"out3",
"");
1206 fs_.Create(
"in",
"");
1209 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1211 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1214 size_t files_created = fs_.files_created_.size();
1215 size_t files_removed = fs_.files_removed_.size();
1217 EXPECT_TRUE(builder_.Build(&err));
1218 ASSERT_EQ(2u, command_runner_.commands_ran_.size());
1221 ASSERT_EQ(files_created + 1, fs_.files_created_.size());
1222 ASSERT_EQ(1u, fs_.files_created_.count(
"out2.rsp"));
1225 ASSERT_EQ(files_removed + 1, fs_.files_removed_.size());
1226 ASSERT_EQ(1u, fs_.files_removed_.count(
"out2.rsp"));
1234 " rspfile = $rspfile\n"
1235 " rspfile_content = $long_command\n"
1236 "build out: fail in\n"
1237 " rspfile = out.rsp\n"
1238 " long_command = Another very long command\n"));
1240 fs_.Create(
"out",
"");
1242 fs_.Create(
"in",
"");
1245 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1248 size_t files_created = fs_.files_created_.size();
1249 size_t files_removed = fs_.files_removed_.size();
1251 EXPECT_FALSE(builder_.Build(&err));
1252 ASSERT_EQ(
"subcommand failed", err);
1253 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1256 ASSERT_EQ(files_created + 1, fs_.files_created_.size());
1257 ASSERT_EQ(1u, fs_.files_created_.count(
"out.rsp"));
1260 ASSERT_EQ(files_removed, fs_.files_removed_.size());
1261 ASSERT_EQ(0u, fs_.files_removed_.count(
"out.rsp"));
1264 ASSERT_EQ(
"Another very long command", fs_.files_[
"out.rsp"].contents);
1272 " command = cat $rspfile > $out\n"
1273 " rspfile = $rspfile\n"
1274 " rspfile_content = $long_command\n"
1275 "build out: cat_rsp in\n"
1276 " rspfile = out.rsp\n"
1277 " long_command = Original very long command\n"));
1279 fs_.Create(
"out",
"");
1281 fs_.Create(
"in",
"");
1284 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1288 EXPECT_TRUE(builder_.Build(&err));
1289 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1292 command_runner_.commands_ran_.clear();
1294 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1296 ASSERT_TRUE(builder_.AlreadyUpToDate());
1301 ASSERT_TRUE(NULL != log_entry);
1303 "cat out.rsp > out;rspfile=Original very long command",
1304 log_entry->command_hash));
1305 log_entry->command_hash++;
1307 command_runner_.commands_ran_.clear();
1309 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1311 EXPECT_TRUE(builder_.Build(&err));
1312 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1318 " command = interrupt\n"
1319 "rule touch-interrupt\n"
1320 " command = touch-interrupt\n"
1321 "build out1: interrupt in1\n"
1322 "build out2: touch-interrupt in2\n"));
1324 fs_.Create(
"out1",
"");
1325 fs_.Create(
"out2",
"");
1327 fs_.Create(
"in1",
"");
1328 fs_.Create(
"in2",
"");
1332 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1334 EXPECT_FALSE(builder_.Build(&err));
1335 EXPECT_EQ(
"interrupted by user", err);
1337 EXPECT_GT(fs_.Stat(
"out1"), 0);
1341 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1343 EXPECT_FALSE(builder_.Build(&err));
1344 EXPECT_EQ(
"interrupted by user", err);
1346 EXPECT_EQ(0, fs_.Stat(
"out2"));
1351 "build nonexistent: phony\n"
1352 "build out1: cat || nonexistent\n"
1353 "build out2: cat nonexistent\n"));
1354 fs_.Create(
"out1",
"");
1355 fs_.Create(
"out2",
"");
1360 EXPECT_TRUE(builder_.AddTarget(
"out1", &err));
1362 EXPECT_TRUE(builder_.AlreadyUpToDate());
1366 command_runner_.commands_ran_.clear();
1368 EXPECT_TRUE(builder_.AddTarget(
"out2", &err));
1370 EXPECT_TRUE(builder_.Build(&err));
1372 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1380 "build out: cc\n"));
1384 EXPECT_TRUE(builder_.AddTarget(
"out", &err));
1386 EXPECT_FALSE(builder_.AlreadyUpToDate());
1388 EXPECT_FALSE(builder_.Build(&err));
1389 ASSERT_EQ(
"subcommand failed", err);
1390 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1394 EXPECT_EQ(
"[%/s0/t0/r0/u0/f0]",
1395 status_.FormatProgressStatus(
"[%%/s%s/t%t/r%r/u%u/f%f]"));
1400 "build bad_deps.o: cat in1\n"
1402 " depfile = in1.d\n"));
1405 EXPECT_TRUE(builder_.AddTarget(
"bad_deps.o", &err));
1410 fs_.Create(
"in1.d",
"AAA BBB");
1412 EXPECT_FALSE(builder_.Build(&err));
1413 EXPECT_EQ(
"subcommand failed", err);
1443 const char* manifest =
1444 "build out: cat in1\n"
1446 " depfile = in1.d\n";
1449 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1450 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1454 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1457 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1459 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
1461 fs_.Create(
"in1.d",
"out: in2");
1462 EXPECT_TRUE(builder.
Build(&err));
1466 EXPECT_EQ(0, fs_.Stat(
"in1.d"));
1468 fs_.Create(
"in1.d",
"out: in2");
1475 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1476 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1480 fs_.Create(
"in2",
"");
1484 ASSERT_TRUE(deps_log.
Load(
"ninja_deps", &state, &err));
1485 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1487 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1488 builder.command_runner_.reset(&command_runner_);
1489 command_runner_.commands_ran_.clear();
1490 EXPECT_TRUE(builder.AddTarget(
"out", &err));
1492 EXPECT_TRUE(builder.Build(&err));
1497 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1499 builder.command_runner_.release();
1510 const char* manifest =
1511 "build out: cat in1\n"
1513 " depfile = in1.d\n";
1516 fs_.Create(
"in1",
"");
1517 fs_.Create(
"in1.d",
"out: ");
1520 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1521 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1525 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1528 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1530 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
1532 EXPECT_TRUE(builder.
Build(&err));
1542 fs_.Create(
"in1",
"");
1543 fs_.Create(
"out",
"");
1546 EXPECT_EQ(0, fs_.Stat(
"in1.d"));
1550 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1551 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1554 ASSERT_TRUE(deps_log.
Load(
"ninja_deps", &state, &err));
1555 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1557 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1558 builder.command_runner_.reset(&command_runner_);
1559 command_runner_.commands_ran_.clear();
1560 EXPECT_TRUE(builder.AddTarget(
"out", &err));
1564 fs_.Create(
"in1.d",
"out: ");
1566 EXPECT_TRUE(builder.Build(&err));
1571 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1573 builder.command_runner_.release();
1578 const char* manifest =
1579 "build out: cat in1\n"
1581 " depfile = in1.d\n";
1583 fs_.Create(
"out",
"");
1585 fs_.Create(
"in1",
"");
1588 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1589 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1592 config_.dry_run =
true;
1593 Builder builder(&state, config_, NULL, NULL, &fs_);
1595 command_runner_.commands_ran_.clear();
1598 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
1600 EXPECT_TRUE(builder.
Build(&err));
1601 ASSERT_EQ(1u, command_runner_.commands_ran_.size());
1610 const char* manifest =
1614 "build header.h: true header.in\n"
1615 "build out: cat in1\n"
1617 " depfile = in1.d\n";
1620 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1621 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1625 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1628 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1630 EXPECT_TRUE(builder.
AddTarget(
"out", &err));
1632 fs_.Create(
"in1.d",
"out: header.h");
1633 EXPECT_TRUE(builder.
Build(&err));
1642 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state));
1643 ASSERT_NO_FATAL_FAILURE(
AssertParse(&state, manifest));
1647 fs_.Create(
"header.in",
"");
1651 ASSERT_TRUE(deps_log.
Load(
"ninja_deps", &state, &err));
1652 ASSERT_TRUE(deps_log.
OpenForWrite(
"ninja_deps", &err));
1654 Builder builder(&state, config_, NULL, &deps_log, &fs_);
1655 builder.command_runner_.reset(&command_runner_);
1656 command_runner_.commands_ran_.clear();
1657 EXPECT_TRUE(builder.AddTarget(
"out", &err));
1659 EXPECT_TRUE(builder.Build(&err));
1664 EXPECT_EQ(1u, command_runner_.commands_ran_.size());
1666 builder.command_runner_.release();
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)
Node * GetNode(const string &path)
Short way to get a Node by its path from state_.
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.
void * builder_
Shadow parent class builder_ so we don't accidentally use it.
The result of waiting for a command.
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.
A base test fixture that includes a State object with a builtin "cat" rule.
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,.
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 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)
vector< Node * > outputs_