summaryrefslogtreecommitdiffstats
path: root/src/graph.cc
diff options
context:
space:
mode:
authorEvan Martin <martine@danga.com>2013-02-17 23:13:35 (GMT)
committerEvan Martin <martine@danga.com>2013-04-08 22:02:32 (GMT)
commit149e8d8d5d2b043fa53f9f8b74fff893ea1819df (patch)
tree93c41d13b33be468c61f586f1c25fe637341e29a /src/graph.cc
parent5031940a8fa5c0c7a76a4bb7fffdb4526713ce7c (diff)
downloadNinja-149e8d8d5d2b043fa53f9f8b74fff893ea1819df.zip
Ninja-149e8d8d5d2b043fa53f9f8b74fff893ea1819df.tar.gz
Ninja-149e8d8d5d2b043fa53f9f8b74fff893ea1819df.tar.bz2
use logged deps mtime in dirty calculation
The idea here is that it's possible for a build to complete (writing its output) but then for Ninja to get interrupted before writing out the updated dependency information. In that case the mtime stored in the deps log (if any) will match the previous output, and we'll know we need to rebuild the output just to get the deps updated.
Diffstat (limited to 'src/graph.cc')
-rw-r--r--src/graph.cc20
1 files changed, 15 insertions, 5 deletions
diff --git a/src/graph.cc b/src/graph.cc
index b11973f..5cc491b 100644
--- a/src/graph.cc
+++ b/src/graph.cc
@@ -61,7 +61,8 @@ bool DependencyScan::RecomputeDirty(Edge* edge, string* err) {
bool dirty = false;
edge->outputs_ready_ = true;
- if (!dep_loader_.LoadDeps(edge, err)) {
+ TimeStamp deps_mtime = 0;
+ if (!dep_loader_.LoadDeps(edge, &deps_mtime, err)) {
if (!err->empty())
return false;
// Failed to load dependency info: rebuild to regenerate it.
@@ -112,7 +113,8 @@ bool DependencyScan::RecomputeDirty(Edge* edge, string* err) {
for (vector<Node*>::iterator i = edge->outputs_.begin();
i != edge->outputs_.end(); ++i) {
(*i)->StatIfNecessary(disk_interface_);
- if (RecomputeOutputDirty(edge, most_recent_input, command, *i)) {
+ if (RecomputeOutputDirty(edge, most_recent_input, deps_mtime,
+ command, *i)) {
dirty = true;
break;
}
@@ -141,6 +143,7 @@ bool DependencyScan::RecomputeDirty(Edge* edge, string* err) {
bool DependencyScan::RecomputeOutputDirty(Edge* edge,
Node* most_recent_input,
+ TimeStamp deps_mtime,
const string& command,
Node* output) {
if (edge->is_phony()) {
@@ -182,6 +185,12 @@ bool DependencyScan::RecomputeOutputDirty(Edge* edge,
}
}
+ // Dirty if the output is newer than the deps.
+ if (deps_mtime && output->mtime() > deps_mtime) {
+ EXPLAIN("stored deps info out of date for for %s", output->path().c_str());
+ return true;
+ }
+
// May also be dirty due to the command changing since the last build.
// But if this is a generator rule, the command changing does not make us
// dirty.
@@ -322,10 +331,10 @@ void Node::Dump(const char* prefix) const {
}
}
-bool ImplicitDepLoader::LoadDeps(Edge* edge, string* err) {
+bool ImplicitDepLoader::LoadDeps(Edge* edge, TimeStamp* mtime, string* err) {
string deps_type = edge->GetBinding("deps");
if (!deps_type.empty()) {
- if (!LoadDepsFromLog(edge, err)) {
+ if (!LoadDepsFromLog(edge, mtime, err)) {
if (!err->empty())
return false;
EXPLAIN("deps for %s are missing", edge->outputs_[0]->path().c_str());
@@ -396,7 +405,8 @@ bool ImplicitDepLoader::LoadDepFile(Edge* edge, const string& path,
return true;
}
-bool ImplicitDepLoader::LoadDepsFromLog(Edge* edge, string* err) {
+bool ImplicitDepLoader::LoadDepsFromLog(Edge* edge, TimeStamp* deps_mtime,
+ string* err) {
DepsLog::Deps* deps = deps_log_->GetDeps(edge->outputs_[0]);
if (!deps)
return false;