summaryrefslogtreecommitdiffstats
path: root/src/graph.cc
diff options
context:
space:
mode:
authorScott Graham <scottmg@chromium.org>2012-04-13 23:55:37 (GMT)
committerScott Graham <scottmg@chromium.org>2012-04-13 23:55:37 (GMT)
commit1aae1bc765acf6a21b2fcb088f44bba8f3badec7 (patch)
tree1b6097fa397d37bb8d5725f203dcc4df9e31d866 /src/graph.cc
parent16cab01cccf0b3ccadb150cd54f760929b3cc07e (diff)
downloadNinja-1aae1bc765acf6a21b2fcb088f44bba8f3badec7.zip
Ninja-1aae1bc765acf6a21b2fcb088f44bba8f3badec7.tar.gz
Ninja-1aae1bc765acf6a21b2fcb088f44bba8f3badec7.tar.bz2
add support for -d explain to help debug why rules are running
Diffstat (limited to 'src/graph.cc')
-rw-r--r--src/graph.cc31
1 files changed, 25 insertions, 6 deletions
diff --git a/src/graph.cc b/src/graph.cc
index 9d45ce1..1d6d8c7 100644
--- a/src/graph.cc
+++ b/src/graph.cc
@@ -20,6 +20,7 @@
#include "build_log.h"
#include "depfile_parser.h"
#include "disk_interface.h"
+#include "explain.h"
#include "metrics.h"
#include "parsers.h"
#include "state.h"
@@ -43,6 +44,7 @@ bool Edge::RecomputeDirty(State* state, DiskInterface* disk_interface,
// Visit all inputs; we're dirty if any of the inputs are dirty.
TimeStamp most_recent_input = 1;
+ Node* most_recent_node = NULL;
for (vector<Node*>::iterator i = inputs_.begin(); i != inputs_.end(); ++i) {
if ((*i)->StatIfNecessary(disk_interface)) {
if (Edge* edge = (*i)->in_edge()) {
@@ -50,6 +52,8 @@ bool Edge::RecomputeDirty(State* state, DiskInterface* disk_interface,
return false;
} else {
// This input has no in-edge; it is dirty if it is missing.
+ if (!(*i)->exists())
+ EXPLAIN("%s has no in-edge and is missing", (*i)->path().c_str());
(*i)->set_dirty(!(*i)->exists());
}
}
@@ -64,10 +68,13 @@ bool Edge::RecomputeDirty(State* state, DiskInterface* disk_interface,
// If a regular input is dirty (or missing), we're dirty.
// Otherwise consider mtime.
if ((*i)->dirty()) {
+ EXPLAIN("%s is dirty", (*i)->path().c_str());
dirty = true;
} else {
- if ((*i)->mtime() > most_recent_input)
+ if ((*i)->mtime() > most_recent_input) {
most_recent_input = (*i)->mtime();
+ most_recent_node = *i;
+ }
}
}
}
@@ -81,7 +88,7 @@ bool Edge::RecomputeDirty(State* state, DiskInterface* disk_interface,
for (vector<Node*>::iterator i = outputs_.begin();
i != outputs_.end(); ++i) {
(*i)->StatIfNecessary(disk_interface);
- if (RecomputeOutputDirty(build_log, most_recent_input, command, *i)) {
+ if (RecomputeOutputDirty(build_log, most_recent_input, most_recent_node, command, *i)) {
dirty = true;
break;
}
@@ -107,7 +114,9 @@ bool Edge::RecomputeDirty(State* state, DiskInterface* disk_interface,
bool Edge::RecomputeOutputDirty(BuildLog* build_log,
TimeStamp most_recent_input,
- const string& command, Node* output) {
+ Node* most_recent_node,
+ const string& command,
+ Node* output) {
if (is_phony()) {
// Phony edges don't write any output. Outputs are only dirty if
// there are no inputs and we're missing the output.
@@ -117,8 +126,10 @@ bool Edge::RecomputeOutputDirty(BuildLog* build_log,
BuildLog::LogEntry* entry = 0;
// Dirty if we're missing the output.
- if (!output->exists())
+ if (!output->exists()) {
+ EXPLAIN("output %s doesn't exist", output->path().c_str());
return true;
+ }
// Dirty if the output is older than the input.
if (output->mtime() < most_recent_input) {
@@ -128,9 +139,15 @@ bool Edge::RecomputeOutputDirty(BuildLog* build_log,
// considered dirty if an input was modified since the previous run.
if (rule_->restat() && build_log &&
(entry = build_log->LookupByOutput(output->path()))) {
- if (entry->restat_mtime < most_recent_input)
+ if (entry->restat_mtime < most_recent_input) {
+ EXPLAIN("restat of output %s older than inputs", output->path().c_str());
return true;
+ }
} else {
+ EXPLAIN("output %s older than most recent input %s (%d vs %d)",
+ output->path().c_str(),
+ most_recent_node ? most_recent_node->path().c_str() : "",
+ output->mtime(), most_recent_input);
return true;
}
}
@@ -140,8 +157,10 @@ bool Edge::RecomputeOutputDirty(BuildLog* build_log,
// dirty.
if (!rule_->generator() && build_log &&
(entry || (entry = build_log->LookupByOutput(output->path())))) {
- if (command != entry->command)
+ if (command != entry->command) {
+ EXPLAIN("command line changed for %s", output->path().c_str());
return true;
+ }
}
return false;