From 54741dc29e33214c69a06af6ef8717893960a7bf Mon Sep 17 00:00:00 2001 From: Evan Martin Date: Wed, 20 Oct 2010 20:40:58 -0700 Subject: [PATCH] sketch out how recursive stats should work --- ninja.h | 67 ++++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/ninja.h b/ninja.h index 74b9405..def68d9 100644 --- a/ninja.h +++ b/ninja.h @@ -42,6 +42,23 @@ struct FileStat { // Return true if the file exists (mtime_ got a value). bool Stat(StatHelper* stat_helper); + // Return true if we needed to stat. + bool StatIfNecessary(StatHelper* stat_helper) { + if (status_known()) + return false; + Stat(stat_helper); + return true; + } + + bool exists() const { + assert(status_known()); + return mtime_ != 0; + } + + bool status_known() const { + return mtime_ == -1; + } + string path_; // Possible values of mtime_: // -1: file hasn't been examined @@ -77,7 +94,7 @@ struct Edge { Edge() : rule_(NULL), env_(NULL) {} void MarkDirty(Node* node); - void RecomputeDirty(); + void RecomputeDirty(StatHelper* stat_helper); string EvaluateCommand(); // XXX move to env, take env ptr Rule* rule_; @@ -88,6 +105,7 @@ struct Edge { }; void FileStat::Touch(int mtime) { + mtime_ = mtime; if (node_) node_->MarkDirty(); } @@ -107,18 +125,26 @@ void Node::MarkDirty() { (*i)->MarkDirty(this); } -void Edge::RecomputeDirty() { - assert(!outputs_.empty()); +void Edge::RecomputeDirty(StatHelper* stat_helper) { + bool missing_input = false; - time_t min_mtime = outputs_[0]->file_->mtime_; - for (vector::iterator i = outputs_.begin(); i != outputs_.end(); ++i) { - min_mtime = min(min_mtime, (*i)->file_->mtime_); + time_t most_recent_input = 1; + for (vector::iterator i = inputs_.begin(); i != inputs_.end(); ++i) { + if ((*i)->file_->StatIfNecessary(stat_helper)) { + if (Edge* edge = (*i)->in_edge_) + edge->RecomputeDirty(stat_helper); + } + if (!(*i)->file_->exists()) + missing_input = true; + else if ((*i)->file_->mtime_ > most_recent_input) + most_recent_input = (*i)->file_->mtime_; } - for (vector::iterator i = inputs_.begin(); i != inputs_.end(); ++i) { - if ((*i)->file_->mtime_ > min_mtime) { - MarkDirty(*i); - break; + assert(!outputs_.empty()); + for (vector::iterator i = outputs_.begin(); i != outputs_.end(); ++i) { + assert((*i)->file_->status_known()); + if (missing_input || (*i)->file_->mtime_ < most_recent_input) { + (*i)->dirty_ = true; } } } @@ -183,26 +209,6 @@ void StatCache::Dump() { } } -void StatCache::Reload() { - StatHelper stat_helper; - set leaf_edges; - for (Paths::iterator i = paths_.begin(); i != paths_.end(); ++i) { - bool exists = i->second->Stat(&stat_helper); - Node* node = i->second->node_; - node->dirty_ = !exists; - if (!node->in_edge_) { - for (vector::iterator j = node->out_edges_.begin(); - j != node->out_edges_.end(); ++j) { - leaf_edges.insert(*j); - } - } - } - - for (set::iterator i = leaf_edges.begin(); i != leaf_edges.end(); ++i) { - (*i)->RecomputeDirty(); - } -} - struct State : public EvalString::Env { StatCache stat_cache_; map rules_; @@ -297,6 +303,7 @@ void Plan::AddTarget(const string& path) { bool Plan::AddTarget(Node* node) { if (!node->dirty()) return false; + Edge* edge = node->in_edge_; assert(edge); // Only nodes with in-edges can be dirty. -- 2.7.4