Add output reference to gen written files.

By adding the outputs written at gn gen time to the build.ninja representation the build tool (ninja) can know how to recreate them if and when necessary.

For example, if one or more of the <blah>.tmp files is removed, even as part of an entire hierarchy/subtree currently the build fails because ninja does not know how to re-make it.

BUG=469621
TEST=Build time only. See https://code.google.com/p/chromium/issues/detail?id=469621#c3

Review URL: https://codereview.chromium.org/1220223002

Cr-Original-Commit-Position: refs/heads/master@{#338929}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 517ac52f86903beb206b19e6ddeedbc709b253a1
diff --git a/tools/gn/function_write_file.cc b/tools/gn/function_write_file.cc
index d24abc1..45387a3 100644
--- a/tools/gn/function_write_file.cc
+++ b/tools/gn/function_write_file.cc
@@ -115,14 +115,6 @@
     return Value();
   g_scheduler->AddWrittenFile(source_file);  // Track that we wrote this file.
 
-  // Track how to recreate this file, since we write it a gen time.
-  // Note this is a hack since the correct output is not a dependency proper,
-  // but an addition of this file to the output of the gn rule that writes it.
-  // This dependency will, however, cause the gen step to be re-run and the
-  // build restarted if the file is missing.
-  g_scheduler->AddGenDependency(
-      scope->settings()->build_settings()->GetFullPath(source_file));
-
   // Compute output.
   std::ostringstream contents;
   if (args[1].type() == Value::LIST) {
diff --git a/tools/gn/ninja_build_writer.cc b/tools/gn/ninja_build_writer.cc
index 591947d..701179f 100644
--- a/tools/gn/ninja_build_writer.cc
+++ b/tools/gn/ninja_build_writer.cc
@@ -143,10 +143,19 @@
 void NinjaBuildWriter::WriteNinjaRules() {
   out_ << "rule gn\n";
   out_ << "  command = " << GetSelfInvocationCommand(build_settings_) << "\n";
-  out_ << "  description = Regenerating ninja files\n\n";
+  out_ << "  description = Regenerating ninja files\n";
+  out_ << "  restat = 1\n\n";
 
-  // This rule will regenerate the ninja files when any input file has changed.
-  out_ << "build build.ninja: gn\n"
+  // This rule will regenerate the ninja files when any input file has changed,
+  // or is missing.
+  out_ << "build build.ninja";
+
+  // Other files read by the build.
+  std::vector<SourceFile> written_files = g_scheduler->GetWrittenFiles();
+  for (const auto& written_file : written_files)
+    out_ << " " << FilePathToUTF8(build_settings_->GetFullPath(written_file));
+
+  out_ << ": gn\n"
        << "  generator = 1\n"
        << "  depfile = build.ninja.d\n";
 
diff --git a/tools/gn/scheduler.cc b/tools/gn/scheduler.cc
index 622019e..db0929d 100644
--- a/tools/gn/scheduler.cc
+++ b/tools/gn/scheduler.cc
@@ -113,6 +113,11 @@
   written_files_.push_back(file);
 }
 
+std::vector<SourceFile> Scheduler::GetWrittenFiles() const {
+  base::AutoLock lock(lock_);
+  return written_files_;
+}
+
 void Scheduler::AddUnknownGeneratedInput(const Target* target,
                                          const SourceFile& file) {
   base::AutoLock lock(lock_);
diff --git a/tools/gn/scheduler.h b/tools/gn/scheduler.h
index 4375f63..9b3ccb3 100644
--- a/tools/gn/scheduler.h
+++ b/tools/gn/scheduler.h
@@ -56,6 +56,7 @@
   // Tracks calls to write_file for resolving with the unknown generated
   // inputs (see AddUnknownGeneratedInput below).
   void AddWrittenFile(const SourceFile& file);
+  std::vector<SourceFile> GetWrittenFiles() const;
 
   // Unknown generated inputs are files that a target declares as an input
   // in the output directory, but which aren't generated by any dependency.