diff options
-rw-r--r-- | src/build.cc | 11 | ||||
-rw-r--r-- | src/build.h | 9 | ||||
-rw-r--r-- | src/build_test.cc | 24 | ||||
-rw-r--r-- | src/ninja.cc | 17 |
4 files changed, 41 insertions, 20 deletions
diff --git a/src/build.cc b/src/build.cc index 3b7d5b8..e0118ef 100644 --- a/src/build.cc +++ b/src/build.cc @@ -387,7 +387,7 @@ bool Builder::AddTarget(Node* node, string* err) { return false; } if (!node->dirty_) - return false; // Intentionally no error. + return true; // Nothing to do. if (!plan_.AddTarget(node, err)) return false; @@ -395,11 +395,12 @@ bool Builder::AddTarget(Node* node, string* err) { return true; } +bool Builder::AlreadyUpToDate() const { + return !plan_.more_to_do(); +} + bool Builder::Build(string* err) { - if (!plan_.more_to_do()) { - *err = "no work to do"; - return true; - } + assert(!AlreadyUpToDate()); status_->PlanHasTotalEdges(plan_.command_edge_count()); int pending_commands = 0; diff --git a/src/build.h b/src/build.h index 5969441..0f7303e 100644 --- a/src/build.h +++ b/src/build.h @@ -97,7 +97,16 @@ struct Builder { Builder(State* state, const BuildConfig& config); Node* AddTarget(const string& name, string* err); + + /// Add a target to the build, scanning dependencies. + /// @return false on error. bool AddTarget(Node* target, string* err); + + /// Returns true if the build targets are already up to date. + bool AlreadyUpToDate() const; + + /// Run the build. Returns false on error. + /// It is an error to call this function when AlreadyUpToDate() is true. bool Build(string* err); bool StartEdge(Edge* edge, string* err); diff --git a/src/build_test.cc b/src/build_test.cc index 282e4b7..db69628 100644 --- a/src/build_test.cc +++ b/src/build_test.cc @@ -278,9 +278,7 @@ Edge* BuildTest::WaitForCommand(bool* success, string* output) { TEST_F(BuildTest, NoWork) { string err; - EXPECT_TRUE(builder_.Build(&err)); - EXPECT_EQ("no work to do", err); - EXPECT_EQ(0u, commands_ran_.size()); + EXPECT_TRUE(builder_.AlreadyUpToDate()); } TEST_F(BuildTest, OneStep) { @@ -375,10 +373,9 @@ TEST_F(BuildTest, Chain) { err.clear(); commands_ran_.clear(); - EXPECT_FALSE(builder_.AddTarget("c5", &err)); + EXPECT_TRUE(builder_.AddTarget("c5", &err)); ASSERT_EQ("", err); - EXPECT_TRUE(builder_.Build(&err)); - ASSERT_EQ(0u, commands_ran_.size()); + EXPECT_TRUE(builder_.AlreadyUpToDate()); GetNode("c4")->dirty_ = true; GetNode("c5")->dirty_ = true; @@ -386,6 +383,7 @@ TEST_F(BuildTest, Chain) { commands_ran_.clear(); EXPECT_TRUE(builder_.AddTarget("c5", &err)); ASSERT_EQ("", err); + EXPECT_FALSE(builder_.AlreadyUpToDate()); EXPECT_TRUE(builder_.Build(&err)); ASSERT_EQ(2u, commands_ran_.size()); // 3->4, 4->5 } @@ -523,10 +521,9 @@ TEST_F(BuildTest, OrderOnlyDeps) { // order only dep dirty, no rebuild. commands_ran_.clear(); GetNode("otherfile")->dirty_ = true; - // We should fail to even add the depenency on foo.o, because - // there's nothing to do. - EXPECT_FALSE(builder_.AddTarget("foo.o", &err)); + EXPECT_TRUE(builder_.AddTarget("foo.o", &err)); EXPECT_EQ("", err); + EXPECT_TRUE(builder_.AlreadyUpToDate()); } TEST_F(BuildTest, Phony) { @@ -540,12 +537,17 @@ TEST_F(BuildTest, Phony) { ASSERT_EQ("", err); // Only one command to run, because phony runs no command. + EXPECT_FALSE(builder_.AlreadyUpToDate()); EXPECT_TRUE(builder_.Build(&err)); ASSERT_EQ("", err); ASSERT_EQ(1u, commands_ran_.size()); - EXPECT_TRUE(builder_.Build(&err)); - ASSERT_NE("", err); + // XXX need a test that asserts we do nothing when we only + // have pending phony rules. + // fs_.Create("out", now_, ""); + // EXPECT_TRUE(builder_.AddTarget("all", &err)); + // ASSERT_EQ("", err); + // EXPECT_TRUE(builder_.AlreadyUpToDate()); } TEST_F(BuildTest, Fail) { diff --git a/src/ninja.cc b/src/ninja.cc index cdaab3a..e892f9d 100644 --- a/src/ninja.cc +++ b/src/ninja.cc @@ -109,6 +109,8 @@ struct RealFileReader : public ManifestParser::FileReader { } }; +/// Rebuild the build manifest, if necessary. +/// Returns true if the manifest was rebuilt. bool RebuildManifest(State* state, const BuildConfig& config, const char* input_file, string* err) { string path = input_file; @@ -121,6 +123,8 @@ bool RebuildManifest(State* state, const BuildConfig& config, if (!manifest_builder.AddTarget(node, err)) return false; + if (manifest_builder.AlreadyUpToDate()) + return false; // Not an error, but we didn't rebuild. return manifest_builder.Build(err); } @@ -498,10 +502,15 @@ reload: } } - bool success = builder.Build(&err); - if (!err.empty()) { - printf("build stopped: %s.\n", err.c_str()); + if (builder.AlreadyUpToDate()) { + printf("ninja: no work to do.\n"); + return 0; } - return success ? 0 : 1; + if (!builder.Build(&err)) { + printf("ninja: build stopped: %s.\n", err.c_str()); + return 1; + } + + return 0; } |