diff options
author | Christopher Parsons <cparsons@google.com> | 2022-05-17 15:08:55 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2022-05-17 15:08:55 +0000 |
commit | 30041e4cd15ce5f55a7b2809e771c61a92b985d1 (patch) | |
tree | 29a992ca91f0568604657087120ce846f29df337 | |
parent | f5a64fd445303624881dc16eddbd104e1d08a592 (diff) | |
parent | b3dd6ea54b471469d46ad13d9ef0ee1de4bb7b7d (diff) | |
download | ninja-30041e4cd15ce5f55a7b2809e771c61a92b985d1.tar.gz |
Merge "Set output mtime of phony edges to latest inputs"
-rw-r--r-- | src/graph.cc | 12 | ||||
-rw-r--r-- | src/graph.h | 3 | ||||
-rw-r--r-- | src/graph_test.cc | 37 |
3 files changed, 52 insertions, 0 deletions
diff --git a/src/graph.cc b/src/graph.cc index b7a3c7c..682182e 100644 --- a/src/graph.cc +++ b/src/graph.cc @@ -49,6 +49,12 @@ bool Node::Stat(DiskInterface* disk_interface, string* err) { } } +void Node::UpdatePhonyMtime(TimeStamp mtime) { + if (!exists()) { + mtime_ = std::max(mtime_, mtime); + } +} + bool Node::LStat( DiskInterface* disk_interface, bool* is_dir, bool* is_symlink, string* err) { assert(in_edge() != nullptr); @@ -427,6 +433,12 @@ bool DependencyScan::RecomputeOutputsDirty(Edge* edge, Node* most_recent_input, return true; } } + + // Update the mtime with the newest input. Dependents can thus call mtime() + // on the fake node and get the latest mtime of the dependencies + if (most_recent_input) { + (*o)->UpdatePhonyMtime(most_recent_input->mtime()); + } continue; } if (RecomputeOutputDirty(edge, most_recent_input, command_hash, *o)) { diff --git a/src/graph.h b/src/graph.h index 3472c07..33a42fc 100644 --- a/src/graph.h +++ b/src/graph.h @@ -119,6 +119,9 @@ struct Node { /// Only use when lstat() is desired (output files) bool LStat(DiskInterface* disk_interface, bool* is_dir, bool* is_symlink, string* err); + /// If the file doesn't exist, set the mtime_ from its dependencies + void UpdatePhonyMtime(TimeStamp mtime); + /// Return false on error. bool StatIfNecessary(DiskInterface* disk_interface, string* err) { if (status_known()) diff --git a/src/graph_test.cc b/src/graph_test.cc index de39980..427334f 100644 --- a/src/graph_test.cc +++ b/src/graph_test.cc @@ -1189,3 +1189,40 @@ TEST_F(GraphTest, GetAllPathsInCycles) { std::vector<std::string> expected_path = {"f", "d", "c", "b", "a"}; ASSERT_TRUE(paths_f_to_a[0] == expected_path); } + +// Check that phony's dependencies' mtimes are propagated. +TEST_F(GraphTest, PhonyDepsMtimes) { + string err; + ASSERT_NO_FATAL_FAILURE(AssertParse(&state_, +"rule touch\n" +" command = touch $out\n" +"build in_ph: phony in1\n" +"build out1: touch in_ph\n" +)); + fs_.Create("in1", ""); + fs_.Create("out1", ""); + Node* out1 = GetNode("out1"); + Node* in1 = GetNode("in1"); + + EXPECT_TRUE(scan_.RecomputeDirty(GetNode("out1"), NULL, &err)); + EXPECT_TRUE(!out1->dirty()); + + // Get the mtime of out1 + ASSERT_TRUE(in1->Stat(&fs_, &err)); + ASSERT_TRUE(out1->Stat(&fs_, &err)); + TimeStamp out1Mtime1 = out1->mtime(); + TimeStamp in1Mtime1 = in1->mtime(); + + // Touch in1. This should cause out1 to be dirty + state_.Reset(); + fs_.Tick(); + fs_.Create("in1", ""); + + ASSERT_TRUE(in1->Stat(&fs_, &err)); + EXPECT_GT(in1->mtime(), in1Mtime1); + + EXPECT_TRUE(scan_.RecomputeDirty(GetNode("out1"), NULL, &err)); + EXPECT_GT(in1->mtime(), in1Mtime1); + EXPECT_EQ(out1->mtime(), out1Mtime1); + EXPECT_TRUE(out1->dirty()); +} |