summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2015-06-18 13:41:35 -0400
committerBrad King <brad.king@kitware.com>2019-04-18 08:21:44 -0400
commite50299c5004e1890d5335f4d51e8e576fa6836d5 (patch)
treebf2e3ba2be1b0b885c37c1796f1d90662ef414e8
parent54520575cd11250ecf5d115b74fce5b8acd3e1aa (diff)
downloadninja-e50299c5004e1890d5335f4d51e8e576fa6836d5.tar.gz
Allow EdgeFinished and NodeFinished to fail with errors
Add an 'err' string argument and return a boolean for success. Update call sites to pass an 'err' string argument and check the return value. This will be useful later for adding logic to these methods that may fail.
-rw-r--r--src/build.cc26
-rw-r--r--src/build.h8
-rw-r--r--src/build_test.cc78
3 files changed, 75 insertions, 37 deletions
diff --git a/src/build.cc b/src/build.cc
index 90e910f..d76d7f2 100644
--- a/src/build.cc
+++ b/src/build.cc
@@ -377,7 +377,7 @@ void Plan::ScheduleWork(map<Edge*, Want>::iterator want_e) {
}
}
-void Plan::EdgeFinished(Edge* edge, EdgeResult result) {
+bool Plan::EdgeFinished(Edge* edge, EdgeResult result, string* err) {
map<Edge*, Want>::iterator e = want_.find(edge);
assert(e != want_.end());
bool directly_wanted = e->second != kWantNothing;
@@ -389,7 +389,7 @@ void Plan::EdgeFinished(Edge* edge, EdgeResult result) {
// The rest of this function only applies to successful commands.
if (result != kEdgeSucceeded)
- return;
+ return true;
if (directly_wanted)
--wanted_edges_;
@@ -399,11 +399,13 @@ void Plan::EdgeFinished(Edge* edge, EdgeResult result) {
// Check off any nodes we were waiting for with this edge.
for (vector<Node*>::iterator o = edge->outputs_.begin();
o != edge->outputs_.end(); ++o) {
- NodeFinished(*o);
+ if (!NodeFinished(*o, err))
+ return false;
}
+ return true;
}
-void Plan::NodeFinished(Node* node) {
+bool Plan::NodeFinished(Node* node, string* err) {
// See if we we want any edges from this node.
for (vector<Edge*>::const_iterator oe = node->out_edges().begin();
oe != node->out_edges().end(); ++oe) {
@@ -418,10 +420,12 @@ void Plan::NodeFinished(Node* node) {
} else {
// We do not need to build this edge, but we might need to build one of
// its dependents.
- EdgeFinished(*oe, kEdgeSucceeded);
+ if (!EdgeFinished(*oe, kEdgeSucceeded, err))
+ return false;
}
}
}
+ return true;
}
bool Plan::CleanNode(DependencyScan* scan, Node* node, string* err) {
@@ -661,7 +665,11 @@ bool Builder::Build(string* err) {
}
if (edge->is_phony()) {
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ if (!plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, err)) {
+ Cleanup();
+ status_->BuildFinished();
+ return false;
+ }
} else {
++pending_commands;
}
@@ -781,8 +789,7 @@ bool Builder::FinishCommand(CommandRunner::Result* result, string* err) {
// The rest of this function only applies to successful commands.
if (!result->success()) {
- plan_.EdgeFinished(edge, Plan::kEdgeFailed);
- return true;
+ return plan_.EdgeFinished(edge, Plan::kEdgeFailed, err);
}
// Restat the edge outputs
@@ -838,7 +845,8 @@ bool Builder::FinishCommand(CommandRunner::Result* result, string* err) {
}
}
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ if (!plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, err))
+ return false;
// Delete any left over response file.
string rspfile = edge->GetUnescapedRspfile();
diff --git a/src/build.h b/src/build.h
index a42b8d4..fdd9891 100644
--- a/src/build.h
+++ b/src/build.h
@@ -63,7 +63,8 @@ struct Plan {
};
/// Mark an edge as done building (whether it succeeded or failed).
- void EdgeFinished(Edge* edge, EdgeResult result);
+ /// Returns 'true'.
+ bool EdgeFinished(Edge* edge, EdgeResult result, string* err);
/// Clean the given node during the build.
/// Return false on error.
@@ -77,7 +78,10 @@ struct Plan {
private:
bool AddSubTarget(Node* node, Node* dependent, string* err);
- void NodeFinished(Node* node);
+
+ /// Update plan with knowledge that the given node is up to date.
+ /// Returns 'true'.
+ bool NodeFinished(Node* node, string* err);
/// Enumerate possible steps we want for an edge.
enum Want
diff --git a/src/build_test.cc b/src/build_test.cc
index 46ab33e..b50b66f 100644
--- a/src/build_test.cc
+++ b/src/build_test.cc
@@ -68,14 +68,16 @@ TEST_F(PlanTest, Basic) {
ASSERT_FALSE(plan_.FindWork());
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edge = plan_.FindWork();
ASSERT_TRUE(edge);
ASSERT_EQ("mid", edge->inputs_[0]->path());
ASSERT_EQ("out", edge->outputs_[0]->path());
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
ASSERT_FALSE(plan_.more_to_do());
edge = plan_.FindWork();
@@ -99,11 +101,13 @@ TEST_F(PlanTest, DoubleOutputDirect) {
Edge* edge;
edge = plan_.FindWork();
ASSERT_TRUE(edge); // cat in
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edge = plan_.FindWork();
ASSERT_TRUE(edge); // cat mid1 mid2
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edge = plan_.FindWork();
ASSERT_FALSE(edge); // done
@@ -129,19 +133,23 @@ TEST_F(PlanTest, DoubleOutputIndirect) {
Edge* edge;
edge = plan_.FindWork();
ASSERT_TRUE(edge); // cat in
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edge = plan_.FindWork();
ASSERT_TRUE(edge); // cat a1
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edge = plan_.FindWork();
ASSERT_TRUE(edge); // cat a2
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edge = plan_.FindWork();
ASSERT_TRUE(edge); // cat b1 b2
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edge = plan_.FindWork();
ASSERT_FALSE(edge); // done
@@ -167,19 +175,23 @@ TEST_F(PlanTest, DoubleDependent) {
Edge* edge;
edge = plan_.FindWork();
ASSERT_TRUE(edge); // cat in
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edge = plan_.FindWork();
ASSERT_TRUE(edge); // cat mid
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edge = plan_.FindWork();
ASSERT_TRUE(edge); // cat mid
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edge = plan_.FindWork();
ASSERT_TRUE(edge); // cat a1 a2
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edge = plan_.FindWork();
ASSERT_FALSE(edge); // done
@@ -204,7 +216,8 @@ void PlanTest::TestPoolWithDepthOne(const char* test_case) {
// This will be false since poolcat is serialized
ASSERT_FALSE(plan_.FindWork());
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edge = plan_.FindWork();
ASSERT_TRUE(edge);
@@ -213,7 +226,8 @@ void PlanTest::TestPoolWithDepthOne(const char* test_case) {
ASSERT_FALSE(plan_.FindWork());
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
ASSERT_FALSE(plan_.more_to_do());
edge = plan_.FindWork();
@@ -289,7 +303,8 @@ TEST_F(PlanTest, PoolsWithDepthTwo) {
ASSERT_EQ("outb3", edge->outputs_[0]->path());
// finish out1
- plan_.EdgeFinished(edges.front(), Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edges.front(), Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edges.pop_front();
// out3 should be available
@@ -300,19 +315,22 @@ TEST_F(PlanTest, PoolsWithDepthTwo) {
ASSERT_FALSE(plan_.FindWork());
- plan_.EdgeFinished(out3, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(out3, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
ASSERT_FALSE(plan_.FindWork());
for (deque<Edge*>::iterator it = edges.begin(); it != edges.end(); ++it) {
- plan_.EdgeFinished(*it, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(*it, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
}
Edge* last = plan_.FindWork();
ASSERT_TRUE(last);
ASSERT_EQ("allTheThings", last->outputs_[0]->path());
- plan_.EdgeFinished(last, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(last, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
ASSERT_FALSE(plan_.more_to_do());
ASSERT_FALSE(plan_.FindWork());
@@ -354,7 +372,8 @@ TEST_F(PlanTest, PoolWithRedundantEdges) {
edge = initial_edges[1]; // Foo first
ASSERT_EQ("foo.cpp", edge->outputs_[0]->path());
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edge = plan_.FindWork();
ASSERT_TRUE(edge);
@@ -362,11 +381,13 @@ TEST_F(PlanTest, PoolWithRedundantEdges) {
ASSERT_EQ("foo.cpp", edge->inputs_[0]->path());
ASSERT_EQ("foo.cpp", edge->inputs_[1]->path());
ASSERT_EQ("foo.cpp.obj", edge->outputs_[0]->path());
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edge = initial_edges[0]; // Now for bar
ASSERT_EQ("bar.cpp", edge->outputs_[0]->path());
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edge = plan_.FindWork();
ASSERT_TRUE(edge);
@@ -374,7 +395,8 @@ TEST_F(PlanTest, PoolWithRedundantEdges) {
ASSERT_EQ("bar.cpp", edge->inputs_[0]->path());
ASSERT_EQ("bar.cpp", edge->inputs_[1]->path());
ASSERT_EQ("bar.cpp.obj", edge->outputs_[0]->path());
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edge = plan_.FindWork();
ASSERT_TRUE(edge);
@@ -382,14 +404,16 @@ TEST_F(PlanTest, PoolWithRedundantEdges) {
ASSERT_EQ("foo.cpp.obj", edge->inputs_[0]->path());
ASSERT_EQ("bar.cpp.obj", edge->inputs_[1]->path());
ASSERT_EQ("libfoo.a", edge->outputs_[0]->path());
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edge = plan_.FindWork();
ASSERT_TRUE(edge);
ASSERT_FALSE(plan_.FindWork());
ASSERT_EQ("libfoo.a", edge->inputs_[0]->path());
ASSERT_EQ("all", edge->outputs_[0]->path());
- plan_.EdgeFinished(edge, Plan::kEdgeSucceeded);
+ plan_.EdgeFinished(edge, Plan::kEdgeSucceeded, &err);
+ ASSERT_EQ("", err);
edge = plan_.FindWork();
ASSERT_FALSE(edge);
@@ -422,7 +446,8 @@ TEST_F(PlanTest, PoolWithFailingEdge) {
// This will be false since poolcat is serialized
ASSERT_FALSE(plan_.FindWork());
- plan_.EdgeFinished(edge, Plan::kEdgeFailed);
+ plan_.EdgeFinished(edge, Plan::kEdgeFailed, &err);
+ ASSERT_EQ("", err);
edge = plan_.FindWork();
ASSERT_TRUE(edge);
@@ -431,7 +456,8 @@ TEST_F(PlanTest, PoolWithFailingEdge) {
ASSERT_FALSE(plan_.FindWork());
- plan_.EdgeFinished(edge, Plan::kEdgeFailed);
+ plan_.EdgeFinished(edge, Plan::kEdgeFailed, &err);
+ ASSERT_EQ("", err);
ASSERT_TRUE(plan_.more_to_do()); // Jobs have failed
edge = plan_.FindWork();