summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/build.cc15
-rw-r--r--src/build_test.cc27
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());
+}