Ninja
|
00001 // Copyright 2011 Google Inc. All Rights Reserved. 00002 // 00003 // Licensed under the Apache License, Version 2.0 (the "License"); 00004 // you may not use this file except in compliance with the License. 00005 // You may obtain a copy of the License at 00006 // 00007 // http://www.apache.org/licenses/LICENSE-2.0 00008 // 00009 // Unless required by applicable law or agreed to in writing, software 00010 // distributed under the License is distributed on an "AS IS" BASIS, 00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 // See the License for the specific language governing permissions and 00013 // limitations under the License. 00014 00015 #include "build.h" 00016 00017 #include "build_log.h" 00018 #include "deps_log.h" 00019 #include "graph.h" 00020 #include "test.h" 00021 00022 /// Fixture for tests involving Plan. 00023 // Though Plan doesn't use State, it's useful to have one around 00024 // to create Nodes and Edges. 00025 struct PlanTest : public StateTestWithBuiltinRules { 00026 Plan plan_; 00027 00028 /// Because FindWork does not return Edges in any sort of predictable order, 00029 // provide a means to get available Edges in order and in a format which is 00030 // easy to write tests around. 00031 void FindWorkSorted(deque<Edge*>* ret, int count) { 00032 struct CompareEdgesByOutput { 00033 static bool cmp(const Edge* a, const Edge* b) { 00034 return a->outputs_[0]->path() < b->outputs_[0]->path(); 00035 } 00036 }; 00037 00038 for (int i = 0; i < count; ++i) { 00039 ASSERT_TRUE(plan_.more_to_do()); 00040 Edge* edge = plan_.FindWork(); 00041 ASSERT_TRUE(edge); 00042 ret->push_back(edge); 00043 } 00044 ASSERT_FALSE(plan_.FindWork()); 00045 sort(ret->begin(), ret->end(), CompareEdgesByOutput::cmp); 00046 } 00047 }; 00048 00049 TEST_F(PlanTest, Basic) { 00050 AssertParse(&state_, 00051 "build out: cat mid\n" 00052 "build mid: cat in\n"); 00053 GetNode("mid")->MarkDirty(); 00054 GetNode("out")->MarkDirty(); 00055 string err; 00056 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err)); 00057 ASSERT_EQ("", err); 00058 ASSERT_TRUE(plan_.more_to_do()); 00059 00060 Edge* edge = plan_.FindWork(); 00061 ASSERT_TRUE(edge); 00062 ASSERT_EQ("in", edge->inputs_[0]->path()); 00063 ASSERT_EQ("mid", edge->outputs_[0]->path()); 00064 00065 ASSERT_FALSE(plan_.FindWork()); 00066 00067 plan_.EdgeFinished(edge); 00068 00069 edge = plan_.FindWork(); 00070 ASSERT_TRUE(edge); 00071 ASSERT_EQ("mid", edge->inputs_[0]->path()); 00072 ASSERT_EQ("out", edge->outputs_[0]->path()); 00073 00074 plan_.EdgeFinished(edge); 00075 00076 ASSERT_FALSE(plan_.more_to_do()); 00077 edge = plan_.FindWork(); 00078 ASSERT_EQ(0, edge); 00079 } 00080 00081 // Test that two outputs from one rule can be handled as inputs to the next. 00082 TEST_F(PlanTest, DoubleOutputDirect) { 00083 AssertParse(&state_, 00084 "build out: cat mid1 mid2\n" 00085 "build mid1 mid2: cat in\n"); 00086 GetNode("mid1")->MarkDirty(); 00087 GetNode("mid2")->MarkDirty(); 00088 GetNode("out")->MarkDirty(); 00089 00090 string err; 00091 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err)); 00092 ASSERT_EQ("", err); 00093 ASSERT_TRUE(plan_.more_to_do()); 00094 00095 Edge* edge; 00096 edge = plan_.FindWork(); 00097 ASSERT_TRUE(edge); // cat in 00098 plan_.EdgeFinished(edge); 00099 00100 edge = plan_.FindWork(); 00101 ASSERT_TRUE(edge); // cat mid1 mid2 00102 plan_.EdgeFinished(edge); 00103 00104 edge = plan_.FindWork(); 00105 ASSERT_FALSE(edge); // done 00106 } 00107 00108 // Test that two outputs from one rule can eventually be routed to another. 00109 TEST_F(PlanTest, DoubleOutputIndirect) { 00110 AssertParse(&state_, 00111 "build out: cat b1 b2\n" 00112 "build b1: cat a1\n" 00113 "build b2: cat a2\n" 00114 "build a1 a2: cat in\n"); 00115 GetNode("a1")->MarkDirty(); 00116 GetNode("a2")->MarkDirty(); 00117 GetNode("b1")->MarkDirty(); 00118 GetNode("b2")->MarkDirty(); 00119 GetNode("out")->MarkDirty(); 00120 string err; 00121 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err)); 00122 ASSERT_EQ("", err); 00123 ASSERT_TRUE(plan_.more_to_do()); 00124 00125 Edge* edge; 00126 edge = plan_.FindWork(); 00127 ASSERT_TRUE(edge); // cat in 00128 plan_.EdgeFinished(edge); 00129 00130 edge = plan_.FindWork(); 00131 ASSERT_TRUE(edge); // cat a1 00132 plan_.EdgeFinished(edge); 00133 00134 edge = plan_.FindWork(); 00135 ASSERT_TRUE(edge); // cat a2 00136 plan_.EdgeFinished(edge); 00137 00138 edge = plan_.FindWork(); 00139 ASSERT_TRUE(edge); // cat b1 b2 00140 plan_.EdgeFinished(edge); 00141 00142 edge = plan_.FindWork(); 00143 ASSERT_FALSE(edge); // done 00144 } 00145 00146 // Test that two edges from one output can both execute. 00147 TEST_F(PlanTest, DoubleDependent) { 00148 AssertParse(&state_, 00149 "build out: cat a1 a2\n" 00150 "build a1: cat mid\n" 00151 "build a2: cat mid\n" 00152 "build mid: cat in\n"); 00153 GetNode("mid")->MarkDirty(); 00154 GetNode("a1")->MarkDirty(); 00155 GetNode("a2")->MarkDirty(); 00156 GetNode("out")->MarkDirty(); 00157 00158 string err; 00159 EXPECT_TRUE(plan_.AddTarget(GetNode("out"), &err)); 00160 ASSERT_EQ("", err); 00161 ASSERT_TRUE(plan_.more_to_do()); 00162 00163 Edge* edge; 00164 edge = plan_.FindWork(); 00165 ASSERT_TRUE(edge); // cat in 00166 plan_.EdgeFinished(edge); 00167 00168 edge = plan_.FindWork(); 00169 ASSERT_TRUE(edge); // cat mid 00170 plan_.EdgeFinished(edge); 00171 00172 edge = plan_.FindWork(); 00173 ASSERT_TRUE(edge); // cat mid 00174 plan_.EdgeFinished(edge); 00175 00176 edge = plan_.FindWork(); 00177 ASSERT_TRUE(edge); // cat a1 a2 00178 plan_.EdgeFinished(edge); 00179 00180 edge = plan_.FindWork(); 00181 ASSERT_FALSE(edge); // done 00182 } 00183 00184 TEST_F(PlanTest, DependencyCycle) { 00185 AssertParse(&state_, 00186 "build out: cat mid\n" 00187 "build mid: cat in\n" 00188 "build in: cat pre\n" 00189 "build pre: cat out\n"); 00190 GetNode("out")->MarkDirty(); 00191 GetNode("mid")->MarkDirty(); 00192 GetNode("in")->MarkDirty(); 00193 GetNode("pre")->MarkDirty(); 00194 00195 string err; 00196 EXPECT_FALSE(plan_.AddTarget(GetNode("out"), &err)); 00197 ASSERT_EQ("dependency cycle: out -> mid -> in -> pre -> out", err); 00198 } 00199 00200 TEST_F(PlanTest, PoolWithDepthOne) { 00201 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00202 "pool foobar\n" 00203 " depth = 1\n" 00204 "rule poolcat\n" 00205 " command = cat $in > $out\n" 00206 " pool = foobar\n" 00207 "build out1: poolcat in\n" 00208 "build out2: poolcat in\n")); 00209 GetNode("out1")->MarkDirty(); 00210 GetNode("out2")->MarkDirty(); 00211 string err; 00212 EXPECT_TRUE(plan_.AddTarget(GetNode("out1"), &err)); 00213 ASSERT_EQ("", err); 00214 EXPECT_TRUE(plan_.AddTarget(GetNode("out2"), &err)); 00215 ASSERT_EQ("", err); 00216 ASSERT_TRUE(plan_.more_to_do()); 00217 00218 Edge* edge = plan_.FindWork(); 00219 ASSERT_TRUE(edge); 00220 ASSERT_EQ("in", edge->inputs_[0]->path()); 00221 ASSERT_EQ("out1", edge->outputs_[0]->path()); 00222 00223 // This will be false since poolcat is serialized 00224 ASSERT_FALSE(plan_.FindWork()); 00225 00226 plan_.EdgeFinished(edge); 00227 00228 edge = plan_.FindWork(); 00229 ASSERT_TRUE(edge); 00230 ASSERT_EQ("in", edge->inputs_[0]->path()); 00231 ASSERT_EQ("out2", edge->outputs_[0]->path()); 00232 00233 ASSERT_FALSE(plan_.FindWork()); 00234 00235 plan_.EdgeFinished(edge); 00236 00237 ASSERT_FALSE(plan_.more_to_do()); 00238 edge = plan_.FindWork(); 00239 ASSERT_EQ(0, edge); 00240 } 00241 00242 TEST_F(PlanTest, PoolsWithDepthTwo) { 00243 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00244 "pool foobar\n" 00245 " depth = 2\n" 00246 "pool bazbin\n" 00247 " depth = 2\n" 00248 "rule foocat\n" 00249 " command = cat $in > $out\n" 00250 " pool = foobar\n" 00251 "rule bazcat\n" 00252 " command = cat $in > $out\n" 00253 " pool = bazbin\n" 00254 "build out1: foocat in\n" 00255 "build out2: foocat in\n" 00256 "build out3: foocat in\n" 00257 "build outb1: bazcat in\n" 00258 "build outb2: bazcat in\n" 00259 "build outb3: bazcat in\n" 00260 " pool =\n" 00261 "build allTheThings: cat out1 out2 out3 outb1 outb2 outb3\n" 00262 )); 00263 // Mark all the out* nodes dirty 00264 for (int i = 0; i < 3; ++i) { 00265 GetNode("out" + string(1, '1' + static_cast<char>(i)))->MarkDirty(); 00266 GetNode("outb" + string(1, '1' + static_cast<char>(i)))->MarkDirty(); 00267 } 00268 GetNode("allTheThings")->MarkDirty(); 00269 00270 string err; 00271 EXPECT_TRUE(plan_.AddTarget(GetNode("allTheThings"), &err)); 00272 ASSERT_EQ("", err); 00273 00274 deque<Edge*> edges; 00275 FindWorkSorted(&edges, 5); 00276 00277 for (int i = 0; i < 4; ++i) { 00278 Edge *edge = edges[i]; 00279 ASSERT_EQ("in", edge->inputs_[0]->path()); 00280 string base_name(i < 2 ? "out" : "outb"); 00281 ASSERT_EQ(base_name + string(1, '1' + (i % 2)), edge->outputs_[0]->path()); 00282 } 00283 00284 // outb3 is exempt because it has an empty pool 00285 Edge* edge = edges[4]; 00286 ASSERT_TRUE(edge); 00287 ASSERT_EQ("in", edge->inputs_[0]->path()); 00288 ASSERT_EQ("outb3", edge->outputs_[0]->path()); 00289 00290 // finish out1 00291 plan_.EdgeFinished(edges.front()); 00292 edges.pop_front(); 00293 00294 // out3 should be available 00295 Edge* out3 = plan_.FindWork(); 00296 ASSERT_TRUE(out3); 00297 ASSERT_EQ("in", out3->inputs_[0]->path()); 00298 ASSERT_EQ("out3", out3->outputs_[0]->path()); 00299 00300 ASSERT_FALSE(plan_.FindWork()); 00301 00302 plan_.EdgeFinished(out3); 00303 00304 ASSERT_FALSE(plan_.FindWork()); 00305 00306 for (deque<Edge*>::iterator it = edges.begin(); it != edges.end(); ++it) { 00307 plan_.EdgeFinished(*it); 00308 } 00309 00310 Edge* last = plan_.FindWork(); 00311 ASSERT_TRUE(last); 00312 ASSERT_EQ("allTheThings", last->outputs_[0]->path()); 00313 00314 plan_.EdgeFinished(last); 00315 00316 ASSERT_FALSE(plan_.more_to_do()); 00317 ASSERT_FALSE(plan_.FindWork()); 00318 } 00319 00320 TEST_F(PlanTest, PoolWithRedundantEdges) { 00321 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00322 "pool compile\n" 00323 " depth = 1\n" 00324 "rule gen_foo\n" 00325 " command = touch foo.cpp\n" 00326 "rule gen_bar\n" 00327 " command = touch bar.cpp\n" 00328 "rule echo\n" 00329 " command = echo $out > $out\n" 00330 "build foo.cpp.obj: echo foo.cpp || foo.cpp\n" 00331 " pool = compile\n" 00332 "build bar.cpp.obj: echo bar.cpp || bar.cpp\n" 00333 " pool = compile\n" 00334 "build libfoo.a: echo foo.cpp.obj bar.cpp.obj\n" 00335 "build foo.cpp: gen_foo\n" 00336 "build bar.cpp: gen_bar\n" 00337 "build all: phony libfoo.a\n")); 00338 GetNode("foo.cpp")->MarkDirty(); 00339 GetNode("foo.cpp.obj")->MarkDirty(); 00340 GetNode("bar.cpp")->MarkDirty(); 00341 GetNode("bar.cpp.obj")->MarkDirty(); 00342 GetNode("libfoo.a")->MarkDirty(); 00343 GetNode("all")->MarkDirty(); 00344 string err; 00345 EXPECT_TRUE(plan_.AddTarget(GetNode("all"), &err)); 00346 ASSERT_EQ("", err); 00347 ASSERT_TRUE(plan_.more_to_do()); 00348 00349 Edge* edge = NULL; 00350 00351 deque<Edge*> initial_edges; 00352 FindWorkSorted(&initial_edges, 2); 00353 00354 edge = initial_edges[1]; // Foo first 00355 ASSERT_EQ("foo.cpp", edge->outputs_[0]->path()); 00356 plan_.EdgeFinished(edge); 00357 00358 edge = plan_.FindWork(); 00359 ASSERT_TRUE(edge); 00360 ASSERT_FALSE(plan_.FindWork()); 00361 ASSERT_EQ("foo.cpp", edge->inputs_[0]->path()); 00362 ASSERT_EQ("foo.cpp", edge->inputs_[1]->path()); 00363 ASSERT_EQ("foo.cpp.obj", edge->outputs_[0]->path()); 00364 plan_.EdgeFinished(edge); 00365 00366 edge = initial_edges[0]; // Now for bar 00367 ASSERT_EQ("bar.cpp", edge->outputs_[0]->path()); 00368 plan_.EdgeFinished(edge); 00369 00370 edge = plan_.FindWork(); 00371 ASSERT_TRUE(edge); 00372 ASSERT_FALSE(plan_.FindWork()); 00373 ASSERT_EQ("bar.cpp", edge->inputs_[0]->path()); 00374 ASSERT_EQ("bar.cpp", edge->inputs_[1]->path()); 00375 ASSERT_EQ("bar.cpp.obj", edge->outputs_[0]->path()); 00376 plan_.EdgeFinished(edge); 00377 00378 edge = plan_.FindWork(); 00379 ASSERT_TRUE(edge); 00380 ASSERT_FALSE(plan_.FindWork()); 00381 ASSERT_EQ("foo.cpp.obj", edge->inputs_[0]->path()); 00382 ASSERT_EQ("bar.cpp.obj", edge->inputs_[1]->path()); 00383 ASSERT_EQ("libfoo.a", edge->outputs_[0]->path()); 00384 plan_.EdgeFinished(edge); 00385 00386 edge = plan_.FindWork(); 00387 ASSERT_TRUE(edge); 00388 ASSERT_FALSE(plan_.FindWork()); 00389 ASSERT_EQ("libfoo.a", edge->inputs_[0]->path()); 00390 ASSERT_EQ("all", edge->outputs_[0]->path()); 00391 plan_.EdgeFinished(edge); 00392 00393 edge = plan_.FindWork(); 00394 ASSERT_FALSE(edge); 00395 ASSERT_FALSE(plan_.more_to_do()); 00396 } 00397 00398 /// Fake implementation of CommandRunner, useful for tests. 00399 struct FakeCommandRunner : public CommandRunner { 00400 explicit FakeCommandRunner(VirtualFileSystem* fs) : 00401 last_command_(NULL), fs_(fs) {} 00402 00403 // CommandRunner impl 00404 virtual bool CanRunMore(); 00405 virtual bool StartCommand(Edge* edge); 00406 virtual bool WaitForCommand(Result* result); 00407 virtual vector<Edge*> GetActiveEdges(); 00408 virtual void Abort(); 00409 00410 vector<string> commands_ran_; 00411 Edge* last_command_; 00412 VirtualFileSystem* fs_; 00413 }; 00414 00415 struct BuildTest : public StateTestWithBuiltinRules { 00416 BuildTest() : config_(MakeConfig()), command_runner_(&fs_), 00417 builder_(&state_, config_, NULL, NULL, &fs_), 00418 status_(config_) { 00419 } 00420 00421 virtual void SetUp() { 00422 StateTestWithBuiltinRules::SetUp(); 00423 00424 builder_.command_runner_.reset(&command_runner_); 00425 AssertParse(&state_, 00426 "build cat1: cat in1\n" 00427 "build cat2: cat in1 in2\n" 00428 "build cat12: cat cat1 cat2\n"); 00429 00430 fs_.Create("in1", ""); 00431 fs_.Create("in2", ""); 00432 } 00433 00434 ~BuildTest() { 00435 builder_.command_runner_.release(); 00436 } 00437 00438 // Mark a path dirty. 00439 void Dirty(const string& path); 00440 00441 BuildConfig MakeConfig() { 00442 BuildConfig config; 00443 config.verbosity = BuildConfig::QUIET; 00444 return config; 00445 } 00446 00447 BuildConfig config_; 00448 FakeCommandRunner command_runner_; 00449 VirtualFileSystem fs_; 00450 Builder builder_; 00451 00452 BuildStatus status_; 00453 }; 00454 00455 bool FakeCommandRunner::CanRunMore() { 00456 // Only run one at a time. 00457 return last_command_ == NULL; 00458 } 00459 00460 bool FakeCommandRunner::StartCommand(Edge* edge) { 00461 assert(!last_command_); 00462 commands_ran_.push_back(edge->EvaluateCommand()); 00463 if (edge->rule().name() == "cat" || 00464 edge->rule().name() == "cat_rsp" || 00465 edge->rule().name() == "cc" || 00466 edge->rule().name() == "touch" || 00467 edge->rule().name() == "touch-interrupt") { 00468 for (vector<Node*>::iterator out = edge->outputs_.begin(); 00469 out != edge->outputs_.end(); ++out) { 00470 fs_->Create((*out)->path(), ""); 00471 } 00472 } else if (edge->rule().name() == "true" || 00473 edge->rule().name() == "fail" || 00474 edge->rule().name() == "interrupt") { 00475 // Don't do anything. 00476 } else { 00477 printf("unknown command\n"); 00478 return false; 00479 } 00480 00481 last_command_ = edge; 00482 return true; 00483 } 00484 00485 bool FakeCommandRunner::WaitForCommand(Result* result) { 00486 if (!last_command_) 00487 return false; 00488 00489 Edge* edge = last_command_; 00490 result->edge = edge; 00491 00492 if (edge->rule().name() == "interrupt" || 00493 edge->rule().name() == "touch-interrupt") { 00494 result->status = ExitInterrupted; 00495 return true; 00496 } 00497 00498 if (edge->rule().name() == "fail") 00499 result->status = ExitFailure; 00500 else 00501 result->status = ExitSuccess; 00502 last_command_ = NULL; 00503 return true; 00504 } 00505 00506 vector<Edge*> FakeCommandRunner::GetActiveEdges() { 00507 vector<Edge*> edges; 00508 if (last_command_) 00509 edges.push_back(last_command_); 00510 return edges; 00511 } 00512 00513 void FakeCommandRunner::Abort() { 00514 last_command_ = NULL; 00515 } 00516 00517 void BuildTest::Dirty(const string& path) { 00518 Node* node = GetNode(path); 00519 node->MarkDirty(); 00520 00521 // If it's an input file, mark that we've already stat()ed it and 00522 // it's missing. 00523 if (!node->in_edge()) 00524 node->MarkMissing(); 00525 } 00526 00527 TEST_F(BuildTest, NoWork) { 00528 string err; 00529 EXPECT_TRUE(builder_.AlreadyUpToDate()); 00530 } 00531 00532 TEST_F(BuildTest, OneStep) { 00533 // Given a dirty target with one ready input, 00534 // we should rebuild the target. 00535 Dirty("cat1"); 00536 string err; 00537 EXPECT_TRUE(builder_.AddTarget("cat1", &err)); 00538 ASSERT_EQ("", err); 00539 EXPECT_TRUE(builder_.Build(&err)); 00540 ASSERT_EQ("", err); 00541 00542 ASSERT_EQ(1u, command_runner_.commands_ran_.size()); 00543 EXPECT_EQ("cat in1 > cat1", command_runner_.commands_ran_[0]); 00544 } 00545 00546 TEST_F(BuildTest, OneStep2) { 00547 // Given a target with one dirty input, 00548 // we should rebuild the target. 00549 Dirty("cat1"); 00550 string err; 00551 EXPECT_TRUE(builder_.AddTarget("cat1", &err)); 00552 ASSERT_EQ("", err); 00553 EXPECT_TRUE(builder_.Build(&err)); 00554 EXPECT_EQ("", err); 00555 00556 ASSERT_EQ(1u, command_runner_.commands_ran_.size()); 00557 EXPECT_EQ("cat in1 > cat1", command_runner_.commands_ran_[0]); 00558 } 00559 00560 TEST_F(BuildTest, TwoStep) { 00561 string err; 00562 EXPECT_TRUE(builder_.AddTarget("cat12", &err)); 00563 ASSERT_EQ("", err); 00564 EXPECT_TRUE(builder_.Build(&err)); 00565 EXPECT_EQ("", err); 00566 ASSERT_EQ(3u, command_runner_.commands_ran_.size()); 00567 // Depending on how the pointers work out, we could've ran 00568 // the first two commands in either order. 00569 EXPECT_TRUE((command_runner_.commands_ran_[0] == "cat in1 > cat1" && 00570 command_runner_.commands_ran_[1] == "cat in1 in2 > cat2") || 00571 (command_runner_.commands_ran_[1] == "cat in1 > cat1" && 00572 command_runner_.commands_ran_[0] == "cat in1 in2 > cat2")); 00573 00574 EXPECT_EQ("cat cat1 cat2 > cat12", command_runner_.commands_ran_[2]); 00575 00576 fs_.Tick(); 00577 00578 // Modifying in2 requires rebuilding one intermediate file 00579 // and the final file. 00580 fs_.Create("in2", ""); 00581 state_.Reset(); 00582 EXPECT_TRUE(builder_.AddTarget("cat12", &err)); 00583 ASSERT_EQ("", err); 00584 EXPECT_TRUE(builder_.Build(&err)); 00585 ASSERT_EQ("", err); 00586 ASSERT_EQ(5u, command_runner_.commands_ran_.size()); 00587 EXPECT_EQ("cat in1 in2 > cat2", command_runner_.commands_ran_[3]); 00588 EXPECT_EQ("cat cat1 cat2 > cat12", command_runner_.commands_ran_[4]); 00589 } 00590 00591 TEST_F(BuildTest, TwoOutputs) { 00592 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00593 "rule touch\n" 00594 " command = touch $out\n" 00595 "build out1 out2: touch in.txt\n")); 00596 00597 fs_.Create("in.txt", ""); 00598 00599 string err; 00600 EXPECT_TRUE(builder_.AddTarget("out1", &err)); 00601 ASSERT_EQ("", err); 00602 EXPECT_TRUE(builder_.Build(&err)); 00603 EXPECT_EQ("", err); 00604 ASSERT_EQ(1u, command_runner_.commands_ran_.size()); 00605 EXPECT_EQ("touch out1 out2", command_runner_.commands_ran_[0]); 00606 } 00607 00608 // Test case from 00609 // https://github.com/martine/ninja/issues/148 00610 TEST_F(BuildTest, MultiOutIn) { 00611 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00612 "rule touch\n" 00613 " command = touch $out\n" 00614 "build in1 otherfile: touch in\n" 00615 "build out: touch in | in1\n")); 00616 00617 fs_.Create("in", ""); 00618 fs_.Tick(); 00619 fs_.Create("in1", ""); 00620 00621 string err; 00622 EXPECT_TRUE(builder_.AddTarget("out", &err)); 00623 ASSERT_EQ("", err); 00624 EXPECT_TRUE(builder_.Build(&err)); 00625 EXPECT_EQ("", err); 00626 } 00627 00628 TEST_F(BuildTest, Chain) { 00629 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00630 "build c2: cat c1\n" 00631 "build c3: cat c2\n" 00632 "build c4: cat c3\n" 00633 "build c5: cat c4\n")); 00634 00635 fs_.Create("c1", ""); 00636 00637 string err; 00638 EXPECT_TRUE(builder_.AddTarget("c5", &err)); 00639 ASSERT_EQ("", err); 00640 EXPECT_TRUE(builder_.Build(&err)); 00641 EXPECT_EQ("", err); 00642 ASSERT_EQ(4u, command_runner_.commands_ran_.size()); 00643 00644 err.clear(); 00645 command_runner_.commands_ran_.clear(); 00646 state_.Reset(); 00647 EXPECT_TRUE(builder_.AddTarget("c5", &err)); 00648 ASSERT_EQ("", err); 00649 EXPECT_TRUE(builder_.AlreadyUpToDate()); 00650 00651 fs_.Tick(); 00652 00653 fs_.Create("c3", ""); 00654 err.clear(); 00655 command_runner_.commands_ran_.clear(); 00656 state_.Reset(); 00657 EXPECT_TRUE(builder_.AddTarget("c5", &err)); 00658 ASSERT_EQ("", err); 00659 EXPECT_FALSE(builder_.AlreadyUpToDate()); 00660 EXPECT_TRUE(builder_.Build(&err)); 00661 ASSERT_EQ(2u, command_runner_.commands_ran_.size()); // 3->4, 4->5 00662 } 00663 00664 TEST_F(BuildTest, MissingInput) { 00665 // Input is referenced by build file, but no rule for it. 00666 string err; 00667 Dirty("in1"); 00668 EXPECT_FALSE(builder_.AddTarget("cat1", &err)); 00669 EXPECT_EQ("'in1', needed by 'cat1', missing and no known rule to make it", 00670 err); 00671 } 00672 00673 TEST_F(BuildTest, MissingTarget) { 00674 // Target is not referenced by build file. 00675 string err; 00676 EXPECT_FALSE(builder_.AddTarget("meow", &err)); 00677 EXPECT_EQ("unknown target: 'meow'", err); 00678 } 00679 00680 TEST_F(BuildTest, MakeDirs) { 00681 string err; 00682 00683 #ifdef _WIN32 00684 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00685 "build subdir\\dir2\\file: cat in1\n")); 00686 EXPECT_TRUE(builder_.AddTarget("subdir\\dir2\\file", &err)); 00687 #else 00688 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00689 "build subdir/dir2/file: cat in1\n")); 00690 EXPECT_TRUE(builder_.AddTarget("subdir/dir2/file", &err)); 00691 #endif 00692 00693 EXPECT_EQ("", err); 00694 EXPECT_TRUE(builder_.Build(&err)); 00695 ASSERT_EQ("", err); 00696 ASSERT_EQ(2u, fs_.directories_made_.size()); 00697 EXPECT_EQ("subdir", fs_.directories_made_[0]); 00698 #ifdef _WIN32 00699 EXPECT_EQ("subdir\\dir2", fs_.directories_made_[1]); 00700 #else 00701 EXPECT_EQ("subdir/dir2", fs_.directories_made_[1]); 00702 #endif 00703 } 00704 00705 TEST_F(BuildTest, DepFileMissing) { 00706 string err; 00707 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00708 "rule cc\n command = cc $in\n depfile = $out.d\n" 00709 "build foo.o: cc foo.c\n")); 00710 fs_.Create("foo.c", ""); 00711 00712 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00713 ASSERT_EQ("", err); 00714 ASSERT_EQ(1u, fs_.files_read_.size()); 00715 EXPECT_EQ("foo.o.d", fs_.files_read_[0]); 00716 } 00717 00718 TEST_F(BuildTest, DepFileOK) { 00719 string err; 00720 int orig_edges = state_.edges_.size(); 00721 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00722 "rule cc\n command = cc $in\n depfile = $out.d\n" 00723 "build foo.o: cc foo.c\n")); 00724 Edge* edge = state_.edges_.back(); 00725 00726 fs_.Create("foo.c", ""); 00727 GetNode("bar.h")->MarkDirty(); // Mark bar.h as missing. 00728 fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n"); 00729 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00730 ASSERT_EQ("", err); 00731 ASSERT_EQ(1u, fs_.files_read_.size()); 00732 EXPECT_EQ("foo.o.d", fs_.files_read_[0]); 00733 00734 // Expect three new edges: one generating foo.o, and two more from 00735 // loading the depfile. 00736 ASSERT_EQ(orig_edges + 3, (int)state_.edges_.size()); 00737 // Expect our edge to now have three inputs: foo.c and two headers. 00738 ASSERT_EQ(3u, edge->inputs_.size()); 00739 00740 // Expect the command line we generate to only use the original input. 00741 ASSERT_EQ("cc foo.c", edge->EvaluateCommand()); 00742 } 00743 00744 TEST_F(BuildTest, DepFileParseError) { 00745 string err; 00746 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00747 "rule cc\n command = cc $in\n depfile = $out.d\n" 00748 "build foo.o: cc foo.c\n")); 00749 fs_.Create("foo.c", ""); 00750 fs_.Create("foo.o.d", "randomtext\n"); 00751 EXPECT_FALSE(builder_.AddTarget("foo.o", &err)); 00752 EXPECT_EQ("expected depfile 'foo.o.d' to mention 'foo.o', got 'randomtext'", 00753 err); 00754 } 00755 00756 TEST_F(BuildTest, OrderOnlyDeps) { 00757 string err; 00758 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00759 "rule cc\n command = cc $in\n depfile = $out.d\n" 00760 "build foo.o: cc foo.c || otherfile\n")); 00761 Edge* edge = state_.edges_.back(); 00762 00763 fs_.Create("foo.c", ""); 00764 fs_.Create("otherfile", ""); 00765 fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n"); 00766 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00767 ASSERT_EQ("", err); 00768 00769 // One explicit, two implicit, one order only. 00770 ASSERT_EQ(4u, edge->inputs_.size()); 00771 EXPECT_EQ(2, edge->implicit_deps_); 00772 EXPECT_EQ(1, edge->order_only_deps_); 00773 // Verify the inputs are in the order we expect 00774 // (explicit then implicit then orderonly). 00775 EXPECT_EQ("foo.c", edge->inputs_[0]->path()); 00776 EXPECT_EQ("blah.h", edge->inputs_[1]->path()); 00777 EXPECT_EQ("bar.h", edge->inputs_[2]->path()); 00778 EXPECT_EQ("otherfile", edge->inputs_[3]->path()); 00779 00780 // Expect the command line we generate to only use the original input. 00781 ASSERT_EQ("cc foo.c", edge->EvaluateCommand()); 00782 00783 // explicit dep dirty, expect a rebuild. 00784 EXPECT_TRUE(builder_.Build(&err)); 00785 ASSERT_EQ("", err); 00786 ASSERT_EQ(1u, command_runner_.commands_ran_.size()); 00787 00788 fs_.Tick(); 00789 00790 // Recreate the depfile, as it should have been deleted by the build. 00791 fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n"); 00792 00793 // implicit dep dirty, expect a rebuild. 00794 fs_.Create("blah.h", ""); 00795 fs_.Create("bar.h", ""); 00796 command_runner_.commands_ran_.clear(); 00797 state_.Reset(); 00798 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00799 EXPECT_TRUE(builder_.Build(&err)); 00800 ASSERT_EQ("", err); 00801 ASSERT_EQ(1u, command_runner_.commands_ran_.size()); 00802 00803 fs_.Tick(); 00804 00805 // Recreate the depfile, as it should have been deleted by the build. 00806 fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n"); 00807 00808 // order only dep dirty, no rebuild. 00809 fs_.Create("otherfile", ""); 00810 command_runner_.commands_ran_.clear(); 00811 state_.Reset(); 00812 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00813 EXPECT_EQ("", err); 00814 EXPECT_TRUE(builder_.AlreadyUpToDate()); 00815 00816 // implicit dep missing, expect rebuild. 00817 fs_.RemoveFile("bar.h"); 00818 command_runner_.commands_ran_.clear(); 00819 state_.Reset(); 00820 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00821 EXPECT_TRUE(builder_.Build(&err)); 00822 ASSERT_EQ("", err); 00823 ASSERT_EQ(1u, command_runner_.commands_ran_.size()); 00824 } 00825 00826 TEST_F(BuildTest, RebuildOrderOnlyDeps) { 00827 string err; 00828 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00829 "rule cc\n command = cc $in\n" 00830 "rule true\n command = true\n" 00831 "build oo.h: cc oo.h.in\n" 00832 "build foo.o: cc foo.c || oo.h\n")); 00833 00834 fs_.Create("foo.c", ""); 00835 fs_.Create("oo.h.in", ""); 00836 00837 // foo.o and order-only dep dirty, build both. 00838 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00839 EXPECT_TRUE(builder_.Build(&err)); 00840 ASSERT_EQ("", err); 00841 ASSERT_EQ(2u, command_runner_.commands_ran_.size()); 00842 00843 // all clean, no rebuild. 00844 command_runner_.commands_ran_.clear(); 00845 state_.Reset(); 00846 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00847 EXPECT_EQ("", err); 00848 EXPECT_TRUE(builder_.AlreadyUpToDate()); 00849 00850 // order-only dep missing, build it only. 00851 fs_.RemoveFile("oo.h"); 00852 command_runner_.commands_ran_.clear(); 00853 state_.Reset(); 00854 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00855 EXPECT_TRUE(builder_.Build(&err)); 00856 ASSERT_EQ("", err); 00857 ASSERT_EQ(1u, command_runner_.commands_ran_.size()); 00858 ASSERT_EQ("cc oo.h.in", command_runner_.commands_ran_[0]); 00859 00860 fs_.Tick(); 00861 00862 // order-only dep dirty, build it only. 00863 fs_.Create("oo.h.in", ""); 00864 command_runner_.commands_ran_.clear(); 00865 state_.Reset(); 00866 EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); 00867 EXPECT_TRUE(builder_.Build(&err)); 00868 ASSERT_EQ("", err); 00869 ASSERT_EQ(1u, command_runner_.commands_ran_.size()); 00870 ASSERT_EQ("cc oo.h.in", command_runner_.commands_ran_[0]); 00871 } 00872 00873 TEST_F(BuildTest, Phony) { 00874 string err; 00875 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00876 "build out: cat bar.cc\n" 00877 "build all: phony out\n")); 00878 fs_.Create("bar.cc", ""); 00879 00880 EXPECT_TRUE(builder_.AddTarget("all", &err)); 00881 ASSERT_EQ("", err); 00882 00883 // Only one command to run, because phony runs no command. 00884 EXPECT_FALSE(builder_.AlreadyUpToDate()); 00885 EXPECT_TRUE(builder_.Build(&err)); 00886 ASSERT_EQ("", err); 00887 ASSERT_EQ(1u, command_runner_.commands_ran_.size()); 00888 } 00889 00890 TEST_F(BuildTest, PhonyNoWork) { 00891 string err; 00892 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00893 "build out: cat bar.cc\n" 00894 "build all: phony out\n")); 00895 fs_.Create("bar.cc", ""); 00896 fs_.Create("out", ""); 00897 00898 EXPECT_TRUE(builder_.AddTarget("all", &err)); 00899 ASSERT_EQ("", err); 00900 EXPECT_TRUE(builder_.AlreadyUpToDate()); 00901 } 00902 00903 TEST_F(BuildTest, Fail) { 00904 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00905 "rule fail\n" 00906 " command = fail\n" 00907 "build out1: fail\n")); 00908 00909 string err; 00910 EXPECT_TRUE(builder_.AddTarget("out1", &err)); 00911 ASSERT_EQ("", err); 00912 00913 EXPECT_FALSE(builder_.Build(&err)); 00914 ASSERT_EQ(1u, command_runner_.commands_ran_.size()); 00915 ASSERT_EQ("subcommand failed", err); 00916 } 00917 00918 TEST_F(BuildTest, SwallowFailures) { 00919 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00920 "rule fail\n" 00921 " command = fail\n" 00922 "build out1: fail\n" 00923 "build out2: fail\n" 00924 "build out3: fail\n" 00925 "build all: phony out1 out2 out3\n")); 00926 00927 // Swallow two failures, die on the third. 00928 config_.failures_allowed = 3; 00929 00930 string err; 00931 EXPECT_TRUE(builder_.AddTarget("all", &err)); 00932 ASSERT_EQ("", err); 00933 00934 EXPECT_FALSE(builder_.Build(&err)); 00935 ASSERT_EQ(3u, command_runner_.commands_ran_.size()); 00936 ASSERT_EQ("subcommands failed", err); 00937 } 00938 00939 TEST_F(BuildTest, SwallowFailuresLimit) { 00940 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00941 "rule fail\n" 00942 " command = fail\n" 00943 "build out1: fail\n" 00944 "build out2: fail\n" 00945 "build out3: fail\n" 00946 "build final: cat out1 out2 out3\n")); 00947 00948 // Swallow ten failures; we should stop before building final. 00949 config_.failures_allowed = 11; 00950 00951 string err; 00952 EXPECT_TRUE(builder_.AddTarget("final", &err)); 00953 ASSERT_EQ("", err); 00954 00955 EXPECT_FALSE(builder_.Build(&err)); 00956 ASSERT_EQ(3u, command_runner_.commands_ran_.size()); 00957 ASSERT_EQ("cannot make progress due to previous errors", err); 00958 } 00959 00960 struct BuildWithLogTest : public BuildTest { 00961 BuildWithLogTest() { 00962 builder_.SetBuildLog(&build_log_); 00963 } 00964 00965 BuildLog build_log_; 00966 }; 00967 00968 TEST_F(BuildWithLogTest, NotInLogButOnDisk) { 00969 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00970 "rule cc\n" 00971 " command = cc\n" 00972 "build out1: cc in\n")); 00973 00974 // Create input/output that would be considered up to date when 00975 // not considering the command line hash. 00976 fs_.Create("in", ""); 00977 fs_.Create("out1", ""); 00978 string err; 00979 00980 // Because it's not in the log, it should not be up-to-date until 00981 // we build again. 00982 EXPECT_TRUE(builder_.AddTarget("out1", &err)); 00983 EXPECT_FALSE(builder_.AlreadyUpToDate()); 00984 00985 command_runner_.commands_ran_.clear(); 00986 state_.Reset(); 00987 00988 EXPECT_TRUE(builder_.AddTarget("out1", &err)); 00989 EXPECT_TRUE(builder_.Build(&err)); 00990 EXPECT_TRUE(builder_.AlreadyUpToDate()); 00991 } 00992 00993 TEST_F(BuildWithLogTest, RestatTest) { 00994 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 00995 "rule true\n" 00996 " command = true\n" 00997 " restat = 1\n" 00998 "rule cc\n" 00999 " command = cc\n" 01000 " restat = 1\n" 01001 "build out1: cc in\n" 01002 "build out2: true out1\n" 01003 "build out3: cat out2\n")); 01004 01005 fs_.Create("out1", ""); 01006 fs_.Create("out2", ""); 01007 fs_.Create("out3", ""); 01008 01009 fs_.Tick(); 01010 01011 fs_.Create("in", ""); 01012 01013 // Do a pre-build so that there's commands in the log for the outputs, 01014 // otherwise, the lack of an entry in the build log will cause out3 to rebuild 01015 // regardless of restat. 01016 string err; 01017 EXPECT_TRUE(builder_.AddTarget("out3", &err)); 01018 ASSERT_EQ("", err); 01019 EXPECT_TRUE(builder_.Build(&err)); 01020 ASSERT_EQ("", err); 01021 command_runner_.commands_ran_.clear(); 01022 state_.Reset(); 01023 01024 fs_.Tick(); 01025 01026 fs_.Create("in", ""); 01027 // "cc" touches out1, so we should build out2. But because "true" does not 01028 // touch out2, we should cancel the build of out3. 01029 EXPECT_TRUE(builder_.AddTarget("out3", &err)); 01030 ASSERT_EQ("", err); 01031 EXPECT_TRUE(builder_.Build(&err)); 01032 ASSERT_EQ(2u, command_runner_.commands_ran_.size()); 01033 01034 // If we run again, it should be a no-op, because the build log has recorded 01035 // that we've already built out2 with an input timestamp of 2 (from out1). 01036 command_runner_.commands_ran_.clear(); 01037 state_.Reset(); 01038 EXPECT_TRUE(builder_.AddTarget("out3", &err)); 01039 ASSERT_EQ("", err); 01040 EXPECT_TRUE(builder_.AlreadyUpToDate()); 01041 01042 fs_.Tick(); 01043 01044 fs_.Create("in", ""); 01045 01046 // The build log entry should not, however, prevent us from rebuilding out2 01047 // if out1 changes. 01048 command_runner_.commands_ran_.clear(); 01049 state_.Reset(); 01050 EXPECT_TRUE(builder_.AddTarget("out3", &err)); 01051 ASSERT_EQ("", err); 01052 EXPECT_TRUE(builder_.Build(&err)); 01053 ASSERT_EQ(2u, command_runner_.commands_ran_.size()); 01054 } 01055 01056 TEST_F(BuildWithLogTest, RestatMissingFile) { 01057 // If a restat rule doesn't create its output, and the output didn't 01058 // exist before the rule was run, consider that behavior equivalent 01059 // to a rule that doesn't modify its existent output file. 01060 01061 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 01062 "rule true\n" 01063 " command = true\n" 01064 " restat = 1\n" 01065 "rule cc\n" 01066 " command = cc\n" 01067 "build out1: true in\n" 01068 "build out2: cc out1\n")); 01069 01070 fs_.Create("in", ""); 01071 fs_.Create("out2", ""); 01072 01073 // Do a pre-build so that there's commands in the log for the outputs, 01074 // otherwise, the lack of an entry in the build log will cause out2 to rebuild 01075 // regardless of restat. 01076 string err; 01077 EXPECT_TRUE(builder_.AddTarget("out2", &err)); 01078 ASSERT_EQ("", err); 01079 EXPECT_TRUE(builder_.Build(&err)); 01080 ASSERT_EQ("", err); 01081 command_runner_.commands_ran_.clear(); 01082 state_.Reset(); 01083 01084 fs_.Tick(); 01085 fs_.Create("in", ""); 01086 fs_.Create("out2", ""); 01087 01088 // Run a build, expect only the first command to run. 01089 // It doesn't touch its output (due to being the "true" command), so 01090 // we shouldn't run the dependent build. 01091 EXPECT_TRUE(builder_.AddTarget("out2", &err)); 01092 ASSERT_EQ("", err); 01093 EXPECT_TRUE(builder_.Build(&err)); 01094 ASSERT_EQ(1u, command_runner_.commands_ran_.size()); 01095 } 01096 01097 // Test scenario, in which an input file is removed, but output isn't changed 01098 // https://github.com/martine/ninja/issues/295 01099 TEST_F(BuildWithLogTest, RestatMissingInput) { 01100 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 01101 "rule true\n" 01102 " command = true\n" 01103 " depfile = $out.d\n" 01104 " restat = 1\n" 01105 "rule cc\n" 01106 " command = cc\n" 01107 "build out1: true in\n" 01108 "build out2: cc out1\n")); 01109 01110 // Create all necessary files 01111 fs_.Create("in", ""); 01112 01113 // The implicit dependencies and the depfile itself 01114 // are newer than the output 01115 TimeStamp restat_mtime = fs_.Tick(); 01116 fs_.Create("out1.d", "out1: will.be.deleted restat.file\n"); 01117 fs_.Create("will.be.deleted", ""); 01118 fs_.Create("restat.file", ""); 01119 01120 // Run the build, out1 and out2 get built 01121 string err; 01122 EXPECT_TRUE(builder_.AddTarget("out2", &err)); 01123 ASSERT_EQ("", err); 01124 EXPECT_TRUE(builder_.Build(&err)); 01125 ASSERT_EQ(2u, command_runner_.commands_ran_.size()); 01126 01127 // See that an entry in the logfile is created, capturing 01128 // the right mtime 01129 BuildLog::LogEntry * log_entry = build_log_.LookupByOutput("out1"); 01130 ASSERT_TRUE(NULL != log_entry); 01131 ASSERT_EQ(restat_mtime, log_entry->restat_mtime); 01132 01133 // Now remove a file, referenced from depfile, so that target becomes 01134 // dirty, but the output does not change 01135 fs_.RemoveFile("will.be.deleted"); 01136 01137 // Trigger the build again - only out1 gets built 01138 command_runner_.commands_ran_.clear(); 01139 state_.Reset(); 01140 EXPECT_TRUE(builder_.AddTarget("out2", &err)); 01141 ASSERT_EQ("", err); 01142 EXPECT_TRUE(builder_.Build(&err)); 01143 ASSERT_EQ(1u, command_runner_.commands_ran_.size()); 01144 01145 // Check that the logfile entry remains correctly set 01146 log_entry = build_log_.LookupByOutput("out1"); 01147 ASSERT_TRUE(NULL != log_entry); 01148 ASSERT_EQ(restat_mtime, log_entry->restat_mtime); 01149 } 01150 01151 struct BuildDryRun : public BuildWithLogTest { 01152 BuildDryRun() { 01153 config_.dry_run = true; 01154 } 01155 }; 01156 01157 TEST_F(BuildDryRun, AllCommandsShown) { 01158 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 01159 "rule true\n" 01160 " command = true\n" 01161 " restat = 1\n" 01162 "rule cc\n" 01163 " command = cc\n" 01164 " restat = 1\n" 01165 "build out1: cc in\n" 01166 "build out2: true out1\n" 01167 "build out3: cat out2\n")); 01168 01169 fs_.Create("out1", ""); 01170 fs_.Create("out2", ""); 01171 fs_.Create("out3", ""); 01172 01173 fs_.Tick(); 01174 01175 fs_.Create("in", ""); 01176 01177 // "cc" touches out1, so we should build out2. But because "true" does not 01178 // touch out2, we should cancel the build of out3. 01179 string err; 01180 EXPECT_TRUE(builder_.AddTarget("out3", &err)); 01181 ASSERT_EQ("", err); 01182 EXPECT_TRUE(builder_.Build(&err)); 01183 ASSERT_EQ(3u, command_runner_.commands_ran_.size()); 01184 } 01185 01186 // Test that RSP files are created when & where appropriate and deleted after 01187 // successful execution. 01188 TEST_F(BuildTest, RspFileSuccess) 01189 { 01190 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 01191 "rule cat_rsp\n" 01192 " command = cat $rspfile > $out\n" 01193 " rspfile = $rspfile\n" 01194 " rspfile_content = $long_command\n" 01195 "build out1: cat in\n" 01196 "build out2: cat_rsp in\n" 01197 " rspfile = out2.rsp\n" 01198 " long_command = Some very long command\n")); 01199 01200 fs_.Create("out1", ""); 01201 fs_.Create("out2", ""); 01202 fs_.Create("out3", ""); 01203 01204 fs_.Tick(); 01205 01206 fs_.Create("in", ""); 01207 01208 string err; 01209 EXPECT_TRUE(builder_.AddTarget("out1", &err)); 01210 ASSERT_EQ("", err); 01211 EXPECT_TRUE(builder_.AddTarget("out2", &err)); 01212 ASSERT_EQ("", err); 01213 01214 size_t files_created = fs_.files_created_.size(); 01215 size_t files_removed = fs_.files_removed_.size(); 01216 01217 EXPECT_TRUE(builder_.Build(&err)); 01218 ASSERT_EQ(2u, command_runner_.commands_ran_.size()); // cat + cat_rsp 01219 01220 // The RSP file was created 01221 ASSERT_EQ(files_created + 1, fs_.files_created_.size()); 01222 ASSERT_EQ(1u, fs_.files_created_.count("out2.rsp")); 01223 01224 // The RSP file was removed 01225 ASSERT_EQ(files_removed + 1, fs_.files_removed_.size()); 01226 ASSERT_EQ(1u, fs_.files_removed_.count("out2.rsp")); 01227 } 01228 01229 // Test that RSP file is created but not removed for commands, which fail 01230 TEST_F(BuildTest, RspFileFailure) { 01231 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 01232 "rule fail\n" 01233 " command = fail\n" 01234 " rspfile = $rspfile\n" 01235 " rspfile_content = $long_command\n" 01236 "build out: fail in\n" 01237 " rspfile = out.rsp\n" 01238 " long_command = Another very long command\n")); 01239 01240 fs_.Create("out", ""); 01241 fs_.Tick(); 01242 fs_.Create("in", ""); 01243 01244 string err; 01245 EXPECT_TRUE(builder_.AddTarget("out", &err)); 01246 ASSERT_EQ("", err); 01247 01248 size_t files_created = fs_.files_created_.size(); 01249 size_t files_removed = fs_.files_removed_.size(); 01250 01251 EXPECT_FALSE(builder_.Build(&err)); 01252 ASSERT_EQ("subcommand failed", err); 01253 ASSERT_EQ(1u, command_runner_.commands_ran_.size()); 01254 01255 // The RSP file was created 01256 ASSERT_EQ(files_created + 1, fs_.files_created_.size()); 01257 ASSERT_EQ(1u, fs_.files_created_.count("out.rsp")); 01258 01259 // The RSP file was NOT removed 01260 ASSERT_EQ(files_removed, fs_.files_removed_.size()); 01261 ASSERT_EQ(0u, fs_.files_removed_.count("out.rsp")); 01262 01263 // The RSP file contains what it should 01264 ASSERT_EQ("Another very long command", fs_.files_["out.rsp"].contents); 01265 } 01266 01267 // Test that contens of the RSP file behaves like a regular part of 01268 // command line, i.e. triggers a rebuild if changed 01269 TEST_F(BuildWithLogTest, RspFileCmdLineChange) { 01270 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 01271 "rule cat_rsp\n" 01272 " command = cat $rspfile > $out\n" 01273 " rspfile = $rspfile\n" 01274 " rspfile_content = $long_command\n" 01275 "build out: cat_rsp in\n" 01276 " rspfile = out.rsp\n" 01277 " long_command = Original very long command\n")); 01278 01279 fs_.Create("out", ""); 01280 fs_.Tick(); 01281 fs_.Create("in", ""); 01282 01283 string err; 01284 EXPECT_TRUE(builder_.AddTarget("out", &err)); 01285 ASSERT_EQ("", err); 01286 01287 // 1. Build for the 1st time (-> populate log) 01288 EXPECT_TRUE(builder_.Build(&err)); 01289 ASSERT_EQ(1u, command_runner_.commands_ran_.size()); 01290 01291 // 2. Build again (no change) 01292 command_runner_.commands_ran_.clear(); 01293 state_.Reset(); 01294 EXPECT_TRUE(builder_.AddTarget("out", &err)); 01295 EXPECT_EQ("", err); 01296 ASSERT_TRUE(builder_.AlreadyUpToDate()); 01297 01298 // 3. Alter the entry in the logfile 01299 // (to simulate a change in the command line between 2 builds) 01300 BuildLog::LogEntry * log_entry = build_log_.LookupByOutput("out"); 01301 ASSERT_TRUE(NULL != log_entry); 01302 ASSERT_NO_FATAL_FAILURE(AssertHash( 01303 "cat out.rsp > out;rspfile=Original very long command", 01304 log_entry->command_hash)); 01305 log_entry->command_hash++; // Change the command hash to something else. 01306 // Now expect the target to be rebuilt 01307 command_runner_.commands_ran_.clear(); 01308 state_.Reset(); 01309 EXPECT_TRUE(builder_.AddTarget("out", &err)); 01310 EXPECT_EQ("", err); 01311 EXPECT_TRUE(builder_.Build(&err)); 01312 EXPECT_EQ(1u, command_runner_.commands_ran_.size()); 01313 } 01314 01315 TEST_F(BuildTest, InterruptCleanup) { 01316 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 01317 "rule interrupt\n" 01318 " command = interrupt\n" 01319 "rule touch-interrupt\n" 01320 " command = touch-interrupt\n" 01321 "build out1: interrupt in1\n" 01322 "build out2: touch-interrupt in2\n")); 01323 01324 fs_.Create("out1", ""); 01325 fs_.Create("out2", ""); 01326 fs_.Tick(); 01327 fs_.Create("in1", ""); 01328 fs_.Create("in2", ""); 01329 01330 // An untouched output of an interrupted command should be retained. 01331 string err; 01332 EXPECT_TRUE(builder_.AddTarget("out1", &err)); 01333 EXPECT_EQ("", err); 01334 EXPECT_FALSE(builder_.Build(&err)); 01335 EXPECT_EQ("interrupted by user", err); 01336 builder_.Cleanup(); 01337 EXPECT_GT(fs_.Stat("out1"), 0); 01338 err = ""; 01339 01340 // A touched output of an interrupted command should be deleted. 01341 EXPECT_TRUE(builder_.AddTarget("out2", &err)); 01342 EXPECT_EQ("", err); 01343 EXPECT_FALSE(builder_.Build(&err)); 01344 EXPECT_EQ("interrupted by user", err); 01345 builder_.Cleanup(); 01346 EXPECT_EQ(0, fs_.Stat("out2")); 01347 } 01348 01349 TEST_F(BuildTest, PhonyWithNoInputs) { 01350 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 01351 "build nonexistent: phony\n" 01352 "build out1: cat || nonexistent\n" 01353 "build out2: cat nonexistent\n")); 01354 fs_.Create("out1", ""); 01355 fs_.Create("out2", ""); 01356 01357 // out1 should be up to date even though its input is dirty, because its 01358 // order-only dependency has nothing to do. 01359 string err; 01360 EXPECT_TRUE(builder_.AddTarget("out1", &err)); 01361 ASSERT_EQ("", err); 01362 EXPECT_TRUE(builder_.AlreadyUpToDate()); 01363 01364 // out2 should still be out of date though, because its input is dirty. 01365 err.clear(); 01366 command_runner_.commands_ran_.clear(); 01367 state_.Reset(); 01368 EXPECT_TRUE(builder_.AddTarget("out2", &err)); 01369 ASSERT_EQ("", err); 01370 EXPECT_TRUE(builder_.Build(&err)); 01371 EXPECT_EQ("", err); 01372 ASSERT_EQ(1u, command_runner_.commands_ran_.size()); 01373 } 01374 01375 TEST_F(BuildTest, DepsGccWithEmptyDepfileErrorsOut) { 01376 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 01377 "rule cc\n" 01378 " command = cc\n" 01379 " deps = gcc\n" 01380 "build out: cc\n")); 01381 Dirty("out"); 01382 01383 string err; 01384 EXPECT_TRUE(builder_.AddTarget("out", &err)); 01385 ASSERT_EQ("", err); 01386 EXPECT_FALSE(builder_.AlreadyUpToDate()); 01387 01388 EXPECT_FALSE(builder_.Build(&err)); 01389 ASSERT_EQ("subcommand failed", err); 01390 ASSERT_EQ(1u, command_runner_.commands_ran_.size()); 01391 } 01392 01393 TEST_F(BuildTest, StatusFormatReplacePlaceholder) { 01394 EXPECT_EQ("[%/s0/t0/r0/u0/f0]", 01395 status_.FormatProgressStatus("[%%/s%s/t%t/r%r/u%u/f%f]")); 01396 } 01397 01398 TEST_F(BuildTest, FailedDepsParse) { 01399 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, 01400 "build bad_deps.o: cat in1\n" 01401 " deps = gcc\n" 01402 " depfile = in1.d\n")); 01403 01404 string err; 01405 EXPECT_TRUE(builder_.AddTarget("bad_deps.o", &err)); 01406 ASSERT_EQ("", err); 01407 01408 // These deps will fail to parse, as they should only have one 01409 // path to the left of the colon. 01410 fs_.Create("in1.d", "AAA BBB"); 01411 01412 EXPECT_FALSE(builder_.Build(&err)); 01413 EXPECT_EQ("subcommand failed", err); 01414 } 01415 01416 /// Tests of builds involving deps logs necessarily must span 01417 /// multiple builds. We reuse methods on BuildTest but not the 01418 /// builder_ it sets up, because we want pristine objects for 01419 /// each build. 01420 struct BuildWithDepsLogTest : public BuildTest { 01421 BuildWithDepsLogTest() {} 01422 01423 virtual void SetUp() { 01424 BuildTest::SetUp(); 01425 01426 temp_dir_.CreateAndEnter("BuildWithDepsLogTest"); 01427 } 01428 01429 virtual void TearDown() { 01430 temp_dir_.Cleanup(); 01431 } 01432 01433 ScopedTempDir temp_dir_; 01434 01435 /// Shadow parent class builder_ so we don't accidentally use it. 01436 void* builder_; 01437 }; 01438 01439 /// Run a straightforwad build where the deps log is used. 01440 TEST_F(BuildWithDepsLogTest, Straightforward) { 01441 string err; 01442 // Note: in1 was created by the superclass SetUp(). 01443 const char* manifest = 01444 "build out: cat in1\n" 01445 " deps = gcc\n" 01446 " depfile = in1.d\n"; 01447 { 01448 State state; 01449 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state)); 01450 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest)); 01451 01452 // Run the build once, everything should be ok. 01453 DepsLog deps_log; 01454 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err)); 01455 ASSERT_EQ("", err); 01456 01457 Builder builder(&state, config_, NULL, &deps_log, &fs_); 01458 builder.command_runner_.reset(&command_runner_); 01459 EXPECT_TRUE(builder.AddTarget("out", &err)); 01460 ASSERT_EQ("", err); 01461 fs_.Create("in1.d", "out: in2"); 01462 EXPECT_TRUE(builder.Build(&err)); 01463 EXPECT_EQ("", err); 01464 01465 // The deps file should have been removed. 01466 EXPECT_EQ(0, fs_.Stat("in1.d")); 01467 // Recreate it for the next step. 01468 fs_.Create("in1.d", "out: in2"); 01469 deps_log.Close(); 01470 builder.command_runner_.release(); 01471 } 01472 01473 { 01474 State state; 01475 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state)); 01476 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest)); 01477 01478 // Touch the file only mentioned in the deps. 01479 fs_.Tick(); 01480 fs_.Create("in2", ""); 01481 01482 // Run the build again. 01483 DepsLog deps_log; 01484 ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err)); 01485 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err)); 01486 01487 Builder builder(&state, config_, NULL, &deps_log, &fs_); 01488 builder.command_runner_.reset(&command_runner_); 01489 command_runner_.commands_ran_.clear(); 01490 EXPECT_TRUE(builder.AddTarget("out", &err)); 01491 ASSERT_EQ("", err); 01492 EXPECT_TRUE(builder.Build(&err)); 01493 EXPECT_EQ("", err); 01494 01495 // We should have rebuilt the output due to in2 being 01496 // out of date. 01497 EXPECT_EQ(1u, command_runner_.commands_ran_.size()); 01498 01499 builder.command_runner_.release(); 01500 } 01501 } 01502 01503 /// Verify that obsolete dependency info causes a rebuild. 01504 /// 1) Run a successful build where everything has time t, record deps. 01505 /// 2) Move input/output to time t+1 -- despite files in alignment, 01506 /// should still need to rebuild due to deps at older time. 01507 TEST_F(BuildWithDepsLogTest, ObsoleteDeps) { 01508 string err; 01509 // Note: in1 was created by the superclass SetUp(). 01510 const char* manifest = 01511 "build out: cat in1\n" 01512 " deps = gcc\n" 01513 " depfile = in1.d\n"; 01514 { 01515 // Run an ordinary build that gathers dependencies. 01516 fs_.Create("in1", ""); 01517 fs_.Create("in1.d", "out: "); 01518 01519 State state; 01520 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state)); 01521 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest)); 01522 01523 // Run the build once, everything should be ok. 01524 DepsLog deps_log; 01525 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err)); 01526 ASSERT_EQ("", err); 01527 01528 Builder builder(&state, config_, NULL, &deps_log, &fs_); 01529 builder.command_runner_.reset(&command_runner_); 01530 EXPECT_TRUE(builder.AddTarget("out", &err)); 01531 ASSERT_EQ("", err); 01532 EXPECT_TRUE(builder.Build(&err)); 01533 EXPECT_EQ("", err); 01534 01535 deps_log.Close(); 01536 builder.command_runner_.release(); 01537 } 01538 01539 // Push all files one tick forward so that only the deps are out 01540 // of date. 01541 fs_.Tick(); 01542 fs_.Create("in1", ""); 01543 fs_.Create("out", ""); 01544 01545 // The deps file should have been removed, so no need to timestamp it. 01546 EXPECT_EQ(0, fs_.Stat("in1.d")); 01547 01548 { 01549 State state; 01550 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state)); 01551 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest)); 01552 01553 DepsLog deps_log; 01554 ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err)); 01555 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err)); 01556 01557 Builder builder(&state, config_, NULL, &deps_log, &fs_); 01558 builder.command_runner_.reset(&command_runner_); 01559 command_runner_.commands_ran_.clear(); 01560 EXPECT_TRUE(builder.AddTarget("out", &err)); 01561 ASSERT_EQ("", err); 01562 01563 // Recreate the deps file here because the build expects them to exist. 01564 fs_.Create("in1.d", "out: "); 01565 01566 EXPECT_TRUE(builder.Build(&err)); 01567 EXPECT_EQ("", err); 01568 01569 // We should have rebuilt the output due to the deps being 01570 // out of date. 01571 EXPECT_EQ(1u, command_runner_.commands_ran_.size()); 01572 01573 builder.command_runner_.release(); 01574 } 01575 } 01576 01577 TEST_F(BuildWithDepsLogTest, DepsIgnoredInDryRun) { 01578 const char* manifest = 01579 "build out: cat in1\n" 01580 " deps = gcc\n" 01581 " depfile = in1.d\n"; 01582 01583 fs_.Create("out", ""); 01584 fs_.Tick(); 01585 fs_.Create("in1", ""); 01586 01587 State state; 01588 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state)); 01589 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest)); 01590 01591 // The deps log is NULL in dry runs. 01592 config_.dry_run = true; 01593 Builder builder(&state, config_, NULL, NULL, &fs_); 01594 builder.command_runner_.reset(&command_runner_); 01595 command_runner_.commands_ran_.clear(); 01596 01597 string err; 01598 EXPECT_TRUE(builder.AddTarget("out", &err)); 01599 ASSERT_EQ("", err); 01600 EXPECT_TRUE(builder.Build(&err)); 01601 ASSERT_EQ(1u, command_runner_.commands_ran_.size()); 01602 01603 builder.command_runner_.release(); 01604 } 01605 01606 /// Check that a restat rule generating a header cancels compilations correctly. 01607 TEST_F(BuildWithDepsLogTest, RestatDepfileDependency) { 01608 string err; 01609 // Note: in1 was created by the superclass SetUp(). 01610 const char* manifest = 01611 "rule true\n" 01612 " command = true\n" // Would be "write if out-of-date" in reality. 01613 " restat = 1\n" 01614 "build header.h: true header.in\n" 01615 "build out: cat in1\n" 01616 " deps = gcc\n" 01617 " depfile = in1.d\n"; 01618 { 01619 State state; 01620 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state)); 01621 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest)); 01622 01623 // Run the build once, everything should be ok. 01624 DepsLog deps_log; 01625 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err)); 01626 ASSERT_EQ("", err); 01627 01628 Builder builder(&state, config_, NULL, &deps_log, &fs_); 01629 builder.command_runner_.reset(&command_runner_); 01630 EXPECT_TRUE(builder.AddTarget("out", &err)); 01631 ASSERT_EQ("", err); 01632 fs_.Create("in1.d", "out: header.h"); 01633 EXPECT_TRUE(builder.Build(&err)); 01634 EXPECT_EQ("", err); 01635 01636 deps_log.Close(); 01637 builder.command_runner_.release(); 01638 } 01639 01640 { 01641 State state; 01642 ASSERT_NO_FATAL_FAILURE(AddCatRule(&state)); 01643 ASSERT_NO_FATAL_FAILURE(AssertParse(&state, manifest)); 01644 01645 // Touch the input of the restat rule. 01646 fs_.Tick(); 01647 fs_.Create("header.in", ""); 01648 01649 // Run the build again. 01650 DepsLog deps_log; 01651 ASSERT_TRUE(deps_log.Load("ninja_deps", &state, &err)); 01652 ASSERT_TRUE(deps_log.OpenForWrite("ninja_deps", &err)); 01653 01654 Builder builder(&state, config_, NULL, &deps_log, &fs_); 01655 builder.command_runner_.reset(&command_runner_); 01656 command_runner_.commands_ran_.clear(); 01657 EXPECT_TRUE(builder.AddTarget("out", &err)); 01658 ASSERT_EQ("", err); 01659 EXPECT_TRUE(builder.Build(&err)); 01660 EXPECT_EQ("", err); 01661 01662 // Rule "true" should have run again, but the build of "out" should have 01663 // been cancelled due to restat propagating through the depfile header. 01664 EXPECT_EQ(1u, command_runner_.commands_ran_.size()); 01665 01666 builder.command_runner_.release(); 01667 } 01668 }