diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2011-09-19 01:56:15 (GMT) |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2011-10-24 00:16:38 (GMT) |
commit | 0efbbbf67a94452919084765e87106e7748274cb (patch) | |
tree | 21c8c5a13b70d7f287b2f569a35f6a03a7f1c19d /src/build_log.cc | |
parent | 386cbf6c7e49c88b87f54619b06670ea9f66c8a5 (diff) | |
download | Ninja-0efbbbf67a94452919084765e87106e7748274cb.zip Ninja-0efbbbf67a94452919084765e87106e7748274cb.tar.gz Ninja-0efbbbf67a94452919084765e87106e7748274cb.tar.bz2 |
Implement restat rules
A restat rule is a rule which is capable of pruning the build tree
depending on the timestamps of its outputs before and after a build.
After a restat rule is rebuilt, Ninja will re-stat each output file
to obtain its current timestamp. If the timestamp is unchanged from
when Ninja initially stat'ed the file before starting the build,
Ninja will mark that output file as clean, and recursively for each
reverse dependency of the output file, recompute its dirty status.
Ninja then stores the most recent timestamp of any input file in the
build log entry associated with the output file. This timestamp
will be treated by future invocations of Ninja as the output file's
modification time instead of the output file's actual modification
time for the purpose of deciding whether it is dirty (but not whether
its reverse dependencies are dirty).
Diffstat (limited to 'src/build_log.cc')
-rw-r--r-- | src/build_log.cc | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/src/build_log.cc b/src/build_log.cc index 98ce872..28cb6f8 100644 --- a/src/build_log.cc +++ b/src/build_log.cc @@ -32,8 +32,8 @@ namespace { -const char kFileSignature[] = "# ninja log v2\n"; -const int kCurrentVersion = 2; +const char kFileSignature[] = "# ninja log v%d\n"; +const int kCurrentVersion = 3; void SetCloseOnExec(FILE* file) { #ifndef _WIN32 @@ -74,7 +74,7 @@ bool BuildLog::OpenForWrite(const string& path, string* err) { SetCloseOnExec(log_file_); if (ftell(log_file_) == 0) { - if (fwrite(kFileSignature, sizeof(kFileSignature) - 1, 1, log_file_) < 1) { + if (fprintf(log_file_, kFileSignature, kCurrentVersion) < 0) { *err = strerror(errno); return false; } @@ -83,7 +83,8 @@ bool BuildLog::OpenForWrite(const string& path, string* err) { return true; } -void BuildLog::RecordCommand(Edge* edge, int start_time, int end_time) { +void BuildLog::RecordCommand(Edge* edge, int start_time, int end_time, + time_t restat_mtime) { const string command = edge->EvaluateCommand(); for (vector<Node*>::iterator out = edge->outputs_.begin(); out != edge->outputs_.end(); ++out) { @@ -100,6 +101,7 @@ void BuildLog::RecordCommand(Edge* edge, int start_time, int end_time) { log_entry->command = command; log_entry->start_time = start_time; log_entry->end_time = end_time; + log_entry->restat_mtime = restat_mtime; if (log_file_) WriteEntry(log_file_, *log_entry); @@ -129,10 +131,8 @@ bool BuildLog::Load(const string& path, string* err) { while (fgets(buf, sizeof(buf), file)) { if (!log_version) { log_version = 1; // Assume by default. - if (strcmp(buf, kFileSignature) == 0) { - log_version = 2; + if (sscanf(buf, kFileSignature, &log_version) > 0) continue; - } } char* start = buf; char* end = strchr(start, ' '); @@ -141,6 +141,8 @@ bool BuildLog::Load(const string& path, string* err) { *end = 0; int start_time = 0, end_time = 0; + time_t restat_mtime = 0; + if (log_version == 1) { // In v1 we logged how long the command took; we don't use this info. // int time_ms = atoi(start); @@ -157,6 +159,16 @@ bool BuildLog::Load(const string& path, string* err) { end_time = atoi(start); start = end + 1; } + + if (log_version >= 3) { + // In v3 we log the restat mtime. + char* end = strchr(start, ' '); + if (!end) + continue; + *end = 0; + restat_mtime = atol(start); + start = end + 1; + } end = strchr(start, ' '); if (!end) @@ -182,6 +194,7 @@ bool BuildLog::Load(const string& path, string* err) { entry->start_time = start_time; entry->end_time = end_time; + entry->restat_mtime = restat_mtime; entry->command = string(start, end - start); } @@ -210,8 +223,8 @@ BuildLog::LogEntry* BuildLog::LookupByOutput(const string& path) { } void BuildLog::WriteEntry(FILE* f, const LogEntry& entry) { - fprintf(f, "%d %d %s %s\n", - entry.start_time, entry.end_time, + fprintf(f, "%d %d %ld %s %s\n", + entry.start_time, entry.end_time, (long) entry.restat_mtime, entry.output.c_str(), entry.command.c_str()); } @@ -225,7 +238,7 @@ bool BuildLog::Recompact(const string& path, string* err) { return false; } - if (fwrite(kFileSignature, sizeof(kFileSignature) - 1, 1, f) < 1) { + if (fprintf(f, kFileSignature, kCurrentVersion) < 0) { *err = strerror(errno); return false; } |