summaryrefslogtreecommitdiffstats
path: root/src/build.cc
diff options
context:
space:
mode:
authorChris Hopman <cjhopman@gmail.com>2013-07-03 21:26:25 (GMT)
committerNico Weber <nicolasweber@gmx.de>2013-07-20 19:11:18 (GMT)
commit9635dae5558b2bb04f021699ed66b1f6f7634acd (patch)
treefd2c350b376b948063ea85d68a20cbb7fa07f9a6 /src/build.cc
parent3f605a8504cfc5fc5cd2bfae50d45f9d3d34d824 (diff)
downloadNinja-9635dae5558b2bb04f021699ed66b1f6f7634acd.zip
Ninja-9635dae5558b2bb04f021699ed66b1f6f7634acd.tar.gz
Ninja-9635dae5558b2bb04f021699ed66b1f6f7634acd.tar.bz2
Fix restat dirty check logic for edges with multiple outputs
In a normal dependency scan (see DependencyScan::RecomputeDirty) we mark all outputs of an Edge as dirty if any of the outputs is dirty. This is the correct behavior because if any output is dirty, we will run the command for that Edge and that can touch any of the outputs of the Edge and so all the outputs should be marked dirty. When updating the dirty state of Node's for a restat check, we were not applying this logic, instead only those outputs that were actually "dirty" were marked dirty. Before this patch, restat edges with multiple outputs caused not all dependent edges to run.
Diffstat (limited to 'src/build.cc')
-rw-r--r--src/build.cc23
1 files changed, 11 insertions, 12 deletions
diff --git a/src/build.cc b/src/build.cc
index 2fbfdec..143aeb2 100644
--- a/src/build.cc
+++ b/src/build.cc
@@ -422,23 +422,22 @@ void Plan::CleanNode(DependencyScan* scan, Node* node) {
}
string command = (*ei)->EvaluateCommand(true);
- // Now, recompute the dirty state of each output.
- bool all_outputs_clean = true;
+ // Now, this edge is dirty if any of the outputs are dirty.
+ bool dirty = false;
for (vector<Node*>::iterator ni = (*ei)->outputs_.begin();
- ni != (*ei)->outputs_.end(); ++ni) {
- if (!(*ni)->dirty())
- continue;
+ !dirty && ni != (*ei)->outputs_.end(); ++ni) {
+ dirty = scan->RecomputeOutputDirty(*ei, most_recent_input, 0,
+ command, *ni);
+ }
- if (scan->RecomputeOutputDirty(*ei, most_recent_input, 0,
- command, *ni)) {
- all_outputs_clean = false;
- } else {
+ // If the edge isn't dirty, clean the outputs and mark the edge as not
+ // wanted.
+ if (!dirty) {
+ for (vector<Node*>::iterator ni = (*ei)->outputs_.begin();
+ ni != (*ei)->outputs_.end(); ++ni) {
CleanNode(scan, *ni);
}
- }
- // If we cleaned all outputs, mark the edge as not wanted.
- if (all_outputs_clean) {
want_i->second = false;
--wanted_edges_;
if (!(*ei)->is_phony())