summaryrefslogtreecommitdiffstats
path: root/ninja.h
diff options
context:
space:
mode:
authorEvan Martin <martine@danga.com>2010-10-21 03:40:58 (GMT)
committerEvan Martin <martine@danga.com>2010-10-21 03:40:58 (GMT)
commit54741dc29e33214c69a06af6ef8717893960a7bf (patch)
tree213b9d16a2d1517eed39e37e4a9249abdd520f01 /ninja.h
parent1998243378fa61c0a24417d5d0751a8be1a90d7e (diff)
downloadNinja-54741dc29e33214c69a06af6ef8717893960a7bf.zip
Ninja-54741dc29e33214c69a06af6ef8717893960a7bf.tar.gz
Ninja-54741dc29e33214c69a06af6ef8717893960a7bf.tar.bz2
sketch out how recursive stats should work
Diffstat (limited to 'ninja.h')
-rw-r--r--ninja.h67
1 files 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<Node*>::iterator i = outputs_.begin(); i != outputs_.end(); ++i) {
- min_mtime = min(min_mtime, (*i)->file_->mtime_);
+ time_t most_recent_input = 1;
+ for (vector<Node*>::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<Node*>::iterator i = inputs_.begin(); i != inputs_.end(); ++i) {
- if ((*i)->file_->mtime_ > min_mtime) {
- MarkDirty(*i);
- break;
+ assert(!outputs_.empty());
+ for (vector<Node*>::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<Edge*> 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<Edge*>::iterator j = node->out_edges_.begin();
- j != node->out_edges_.end(); ++j) {
- leaf_edges.insert(*j);
- }
- }
- }
-
- for (set<Edge*>::iterator i = leaf_edges.begin(); i != leaf_edges.end(); ++i) {
- (*i)->RecomputeDirty();
- }
-}
-
struct State : public EvalString::Env {
StatCache stat_cache_;
map<string, Rule*> 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.