summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/build.cc2
-rw-r--r--src/graph.cc20
-rw-r--r--src/graph.h8
3 files changed, 21 insertions, 9 deletions
diff --git a/src/build.cc b/src/build.cc
index df208af..ecde4df 100644
--- a/src/build.cc
+++ b/src/build.cc
@@ -516,7 +516,7 @@ void Plan::CleanNode(DependencyScan* scan, Node* node) {
if (!(*ni)->dirty())
continue;
- if (scan->RecomputeOutputDirty(*ei, most_recent_input,
+ if (scan->RecomputeOutputDirty(*ei, most_recent_input, 0,
command, *ni)) {
(*ni)->MarkDirty();
all_outputs_clean = false;
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;
diff --git a/src/graph.h b/src/graph.h
index 650a83e..428ba01 100644
--- a/src/graph.h
+++ b/src/graph.h
@@ -192,9 +192,10 @@ struct ImplicitDepLoader {
DiskInterface* disk_interface)
: state_(state), disk_interface_(disk_interface), deps_log_(deps_log) {}
- /// Load implicit dependencies for \a edge.
+ /// Load implicit dependencies for \a edge. May fill in \a mtime with
+ /// the timestamp of the loaded information.
/// @return false on error (without filling \a err if info is just missing).
- bool LoadDeps(Edge* edge, string* err);
+ bool LoadDeps(Edge* edge, TimeStamp* mtime, string* err);
DepsLog* deps_log() const {
return deps_log_;
@@ -207,7 +208,7 @@ struct ImplicitDepLoader {
/// Load implicit dependencies for \a edge from the DepsLog.
/// @return false on error (without filling \a err if info is just missing).
- bool LoadDepsFromLog(Edge* edge, string* err);
+ bool LoadDepsFromLog(Edge* edge, TimeStamp* mtime, string* err);
/// Preallocate \a count spaces in the input array on \a edge, returning
/// an iterator pointing at the first new space.
@@ -242,6 +243,7 @@ struct DependencyScan {
/// Recompute whether a given single output should be marked dirty.
/// Returns true if so.
bool RecomputeOutputDirty(Edge* edge, Node* most_recent_input,
+ TimeStamp deps_mtime,
const string& command, Node* output);
BuildLog* build_log() const {