From ec228f1e449c8e8cab4cc286b520a40c1e2431c4 Mon Sep 17 00:00:00 2001 From: wolfp Date: Tue, 22 May 2012 13:39:40 +0200 Subject: Do not reset restat_mtime if an input is missing (issue #295) --- src/build.cc | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/build.cc b/src/build.cc index 157442d..7eb3f24 100644 --- a/src/build.cc +++ b/src/build.cc @@ -749,19 +749,13 @@ void Builder::FinishEdge(Edge* edge, bool success, const string& output) { for (vector::iterator i = edge->inputs_.begin(); i != edge->inputs_.end() - edge->order_only_deps_; ++i) { TimeStamp input_mtime = disk_interface_->Stat((*i)->path()); - if (input_mtime == 0) { - restat_mtime = 0; - break; - } if (input_mtime > restat_mtime) restat_mtime = input_mtime; } if (restat_mtime != 0 && !edge->rule().depfile().empty()) { TimeStamp depfile_mtime = disk_interface_->Stat(edge->EvaluateDepFile()); - if (depfile_mtime == 0) - restat_mtime = 0; - else if (depfile_mtime > restat_mtime) + if (depfile_mtime > restat_mtime) restat_mtime = depfile_mtime; } -- cgit v0.12 From 4a083599bb654e894a1f6ce0dc1080b4e8df6f63 Mon Sep 17 00:00:00 2001 From: wolfp Date: Wed, 27 Jun 2012 10:29:17 +0200 Subject: Add a test for missing input files in restat rules --- src/build_test.cc | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/build_test.cc b/src/build_test.cc index c45f2b3..7a7c7bd 100644 --- a/src/build_test.cc +++ b/src/build_test.cc @@ -802,6 +802,60 @@ TEST_F(BuildWithLogTest, RestatMissingFile) { ASSERT_EQ(1u, commands_ran_.size()); } +// Test scenario, in which an input file is removed, but output isn't changed +// https://github.com/martine/ninja/issues/295 +TEST_F(BuildWithLogTest, RestatMissingInput) { + ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, + "rule true\n" + " command = true\n" + " depfile = $out.d\n" + " restat = 1\n" + "rule cc\n" + " command = cc\n" + "build out1: true in\n" + "build out2: cc out1\n")); + + // Create all necessary files + fs_.Create("in", now_, ""); + + // The implicit dependencies and the depfile itself + // are newer than the output + TimeStamp restat_mtime = ++now_; + fs_.Create("out1.d", now_, "out1: will.be.deleted restat.file\n"); + fs_.Create("will.be.deleted", now_, ""); + fs_.Create("restat.file", now_, ""); + + // Run the build, out1 and out2 get built + string err; + EXPECT_TRUE(builder_.AddTarget("out2", &err)); + ASSERT_EQ("", err); + EXPECT_TRUE(builder_.Build(&err)); + ASSERT_EQ(2u, commands_ran_.size()); + + // See that an entry in the logfile is created, capturing + // the right mtime + BuildLog::LogEntry * log_entry = build_log_.LookupByOutput("out1"); + ASSERT_TRUE(NULL != log_entry); + ASSERT_EQ(restat_mtime, log_entry->restat_mtime); + + // Now remove a file, referenced from depfile, so that target becomes + // dirty, but the output does not change + fs_.RemoveFile("will.be.deleted"); + + // Trigger the build again - only out1 gets built + commands_ran_.clear(); + state_.Reset(); + EXPECT_TRUE(builder_.AddTarget("out2", &err)); + ASSERT_EQ("", err); + EXPECT_TRUE(builder_.Build(&err)); + ASSERT_EQ(1u, commands_ran_.size()); + + // Check that the logfile entry remains correctly set + log_entry = build_log_.LookupByOutput("out1"); + ASSERT_TRUE(NULL != log_entry); + ASSERT_EQ(restat_mtime, log_entry->restat_mtime); +} + struct BuildDryRun : public BuildWithLogTest { BuildDryRun() { config_.dry_run = true; -- cgit v0.12