diff options
-rw-r--r-- | src/build.cc | 15 | ||||
-rw-r--r-- | src/build_test.cc | 27 |
2 files changed, 34 insertions, 8 deletions
diff --git a/src/build.cc b/src/build.cc index cd1618c..ebf63b2 100644 --- a/src/build.cc +++ b/src/build.cc @@ -577,14 +577,13 @@ void Builder::FinishEdge(Edge* edge, bool success, const string& output) { for (vector<Node*>::iterator i = edge->outputs_.begin(); i != edge->outputs_.end(); ++i) { - if ((*i)->exists()) { - TimeStamp new_mtime = disk_interface_->Stat((*i)->path()); - if ((*i)->mtime() == new_mtime) { - // The rule command did not change the output. Propagate the clean - // state through the build graph. - plan_.CleanNode(log_, *i); - node_cleaned = true; - } + TimeStamp new_mtime = disk_interface_->Stat((*i)->path()); + if ((*i)->mtime() == new_mtime) { + // The rule command did not change the output. Propagate the clean + // state through the build graph. + // Note that this also applies to nonexistent outputs (mtime == 0). + plan_.CleanNode(log_, *i); + node_cleaned = true; } } diff --git a/src/build_test.cc b/src/build_test.cc index 40d116f..7f977a6 100644 --- a/src/build_test.cc +++ b/src/build_test.cc @@ -745,3 +745,30 @@ TEST_F(BuildWithLogTest, RestatTest) { EXPECT_TRUE(builder_.Build(&err)); ASSERT_EQ(2u, commands_ran_.size()); } + +TEST_F(BuildWithLogTest, RestatMissingFile) { + // If a restat rule doesn't create its output, and the output didn't + // exist before the rule was run, consider that behavior equivalent + // to a rule that doesn't modify its existent output file. + + ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, +"rule true\n" +" command = true\n" +" restat = 1\n" +"rule cc\n" +" command = cc\n" +"build out1: true in\n" +"build out2: cc out1\n")); + + fs_.Create("in", now_, ""); + fs_.Create("out2", now_, ""); + + // Run a build, expect only the first command to run. + // It doesn't touch its output (due to being the "true" command), so + // we shouldn't run the dependent build. + string err; + EXPECT_TRUE(builder_.AddTarget("out2", &err)); + ASSERT_EQ("", err); + EXPECT_TRUE(builder_.Build(&err)); + ASSERT_EQ(1u, commands_ran_.size()); +} |