Restore missing dep from depfile support
The restriction about not having phony rules that were dirty because of
a missing input was causing incremental build breaks because phony edges
are automatically created for each file listed in a depfile.
Restore the original behavior for these edges, while keeping the error
for phony rules defined in the ninja file.
Test: run ninja_tests (through build-prebuilts.sh)
Change-Id: Id41b7ecd329844a97db4d3cb9c585f26ac2774bd
diff --git a/src/build_test.cc b/src/build_test.cc
index 406b291..2400f18 100644
--- a/src/build_test.cc
+++ b/src/build_test.cc
@@ -914,6 +914,29 @@
ASSERT_EQ("cc foo.c", edge->EvaluateCommand());
}
+TEST_F(BuildTest, DepFileOKWithPhonyOutputs) {
+ string err;
+ ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
+"rule cc\n command = cc $in\n depfile = $out.d\n"
+"build foo.o: cc foo.c\n"));
+
+ BuildConfig config(config_);
+ config.uses_phony_outputs = true;
+ Builder builder(&state_, config, nullptr, nullptr, &fs_, &status_, 0);
+ builder.command_runner_.reset(&command_runner_);
+ command_runner_.commands_ran_.clear();
+
+ fs_.Create("foo.c", "");
+ GetNode("bar.h")->MarkDirty(); // Mark bar.h as missing.
+ fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
+ EXPECT_TRUE(builder.AddTarget("foo.o", &err));
+ ASSERT_EQ("", err);
+
+ ASSERT_TRUE(GetNode("bar.h")->in_edge()->phony_from_depfile_);
+
+ builder.command_runner_.release();
+}
+
TEST_F(BuildTest, DepFileParseError) {
string err;
ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
diff --git a/src/graph.cc b/src/graph.cc
index b1cdf77..e93a2e1 100644
--- a/src/graph.cc
+++ b/src/graph.cc
@@ -345,7 +345,9 @@
// Phony edges don't write any output. Outputs are only dirty if
// there are no inputs and we're missing the output.
if (edge->inputs_.empty() && !(*o)->exists()) {
- if (missing_phony_is_err_) {
+ // For phony targets defined in the ninja file, error when using dirty phony edges.
+ // The phony edges automatically created from depfiles still need the old behavior.
+ if (missing_phony_is_err_ && !edge->phony_from_depfile_) {
*err = "output " + (*o)->path() + " of phony edge doesn't exist. Missing 'phony_output = true'?";
return false;
} else {
@@ -875,4 +877,6 @@
// to avoid a potential stuck build. If we do call RecomputeDirty for
// this node, it will simply set outputs_ready_ to the correct value.
phony_edge->outputs_ready_ = true;
+
+ phony_edge->phony_from_depfile_ = true;
}
diff --git a/src/graph.h b/src/graph.h
index 07bd377..4559027 100644
--- a/src/graph.h
+++ b/src/graph.h
@@ -378,6 +378,7 @@
size_t id_ = 0;
bool outputs_ready_ = false;
bool deps_missing_ = false;
+ bool phony_from_depfile_ = false;
DepScanInfo dep_scan_info_;
DeclIndex dfs_location() const { return pos_.dfs_location(); }