Add support for customizing GN's args text.

It would be nice if, when you ran `gn args out/foo`, you could get
some sample text that was actually customized to the build that
you have, rather than referencing dummy arguments like 'enable_doom_melon'.

This CL adds support for that. If you set `arg_file_template_path` in
your dotfile, then GN will use the contents of that file as the sample
text that it passes to the editor.

R=brettw@chromium.org
BUG=

Review-Url: https://codereview.chromium.org/2514333005
Cr-Original-Commit-Position: refs/heads/master@{#454750}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: eacf0f430d80615f07da8bc4094bb981771a155c
diff --git a/tools/gn/build_settings.cc b/tools/gn/build_settings.cc
index 3fac976..c60002d 100644
--- a/tools/gn/build_settings.cc
+++ b/tools/gn/build_settings.cc
@@ -18,9 +18,9 @@
       secondary_source_path_(other.secondary_source_path_),
       python_path_(other.python_path_),
       build_config_file_(other.build_config_file_),
+      arg_file_template_path_(other.arg_file_template_path_),
       build_dir_(other.build_dir_),
-      build_args_(other.build_args_) {
-}
+      build_args_(other.build_args_) {}
 
 BuildSettings::~BuildSettings() {
 }
diff --git a/tools/gn/build_settings.h b/tools/gn/build_settings.h
index 0b986cd..3f9f45b 100644
--- a/tools/gn/build_settings.h
+++ b/tools/gn/build_settings.h
@@ -52,6 +52,14 @@
   const SourceFile& build_config_file() const { return build_config_file_; }
   void set_build_config_file(const SourceFile& f) { build_config_file_ = f; }
 
+  // Path to a file containing the default text to use when running `gn args`.
+  const SourceFile& arg_file_template_path() const {
+    return arg_file_template_path_;
+  }
+  void set_arg_file_template_path(const SourceFile& f) {
+    arg_file_template_path_ = f;
+  }
+
   // The build directory is the root of all output files. The default toolchain
   // files go into here, and non-default toolchains will have separate
   // toolchain-specific root directories inside this.
@@ -102,6 +110,7 @@
   base::FilePath python_path_;
 
   SourceFile build_config_file_;
+  SourceFile arg_file_template_path_;
   SourceDir build_dir_;
   Args build_args_;
 
diff --git a/tools/gn/command_args.cc b/tools/gn/command_args.cc
index 98283f2..2772fc2 100644
--- a/tools/gn/command_args.cc
+++ b/tools/gn/command_args.cc
@@ -268,16 +268,32 @@
     // Ensure the file exists. Need to normalize path separators since on
     // Windows they can come out as forward slashes here, and that confuses some
     // of the commands.
+    BuildSettings build_settings = setup.build_settings();
     base::FilePath arg_file =
-        setup.build_settings().GetFullPath(setup.GetBuildArgFile())
-        .NormalizePathSeparators();
+        build_settings.GetFullPath(setup.GetBuildArgFile())
+            .NormalizePathSeparators();
     if (!base::PathExists(arg_file)) {
       std::string argfile_default_contents =
-          "# Build arguments go here. Examples:\n"
-          "#   is_component_build = true\n"
-          "#   is_debug = false\n"
+          "# Build arguments go here.\n"
           "# See \"gn args <out_dir> --list\" for available build "
           "arguments.\n";
+
+      SourceFile template_path = build_settings.arg_file_template_path();
+      if (!template_path.is_null()) {
+        base::FilePath full_path =
+            build_settings.GetFullPath(template_path).NormalizePathSeparators();
+        if (!base::PathExists(full_path)) {
+          Err err =
+              Err(Location(), std::string("Can't load arg_file_template:\n  ") +
+                                  template_path.value());
+          err.PrintToStdout();
+          return 1;
+        }
+
+        // Ignore the return code; if the read fails (unlikely), we'll just
+        // use the default contents.
+        base::ReadFileToString(full_path, &argfile_default_contents);
+      }
 #if defined(OS_WIN)
       // Use Windows lineendings for this file since it will often open in
       // Notepad which can't handle Unix ones.
diff --git a/tools/gn/docs/reference.md b/tools/gn/docs/reference.md
index 97a2c86..db5c341 100644
--- a/tools/gn/docs/reference.md
+++ b/tools/gn/docs/reference.md
@@ -3893,7 +3893,7 @@
 
   This should be set to the most specific value possible. So, "android" or
   "chromeos" should be used instead of "linux" where applicable, even though
-  Android and Chrome OS are both Linux variants. This can mean that one needs to
+  Android and ChromeOS are both Linux variants. This can mean that one needs to
   write
 
       if (target_os == "android" || target_os == "linux") {
@@ -5307,12 +5307,28 @@
   config applying to this target specifies this value. In addition, the tool
   corresponding to the source files must also specify precompiled headers (see
   "gn help tool"). The tool will also specify what type of precompiled headers
-  to use.
+  to use, by setting precompiled_header_type to either "gcc" or "msvc".
 
   The precompiled header/source variables can be specified on a target or a
   config, but must be the same for all configs applying to a given target since
   a target can only have one precompiled header.
 
+  If you use both C and C++ sources, the precompiled header and source file
+  will be compiled once per language. You will want to make sure to wrap C++
+  includes in __cplusplus #ifdefs so the file will compile in C mode.
+
+```
+
+### **GCC precompiled headers**
+
+```
+  When using GCC-style precompiled headers, "precompiled_source" contains the
+  path of a .h file that is precompiled and then included by all source files
+  in targets that set "precompiled_source".
+
+  The value of "precompiled_header" is not used with GCC-style precompiled
+  headers.
+
 ```
 
 ### **MSVC precompiled headers**
@@ -5320,8 +5336,8 @@
 ```
   When using MSVC-style precompiled headers, the "precompiled_header" value is
   a string corresponding to the header. This is NOT a path to a file that GN
-  recognises, but rather the exact string that appears in quotes after an
-  #include line in source code. The compiler will match this string against
+  recognises, but rather the exact string that appears in quotes after
+  an #include line in source code. The compiler will match this string against
   includes or forced includes (/FI).
 
   MSVC also requires a source file to compile the header with. This must be
@@ -5329,10 +5345,6 @@
   this IS a GN-style file name, and tells GN which source file to compile to
   make the .pch file used for subsequent compiles.
 
-  If you use both C and C++ sources, the precompiled header and source file
-  will be compiled using both tools. You will want to make sure to wrap C++
-  includes in __cplusplus #ifdefs so the file will compile in C mode.
-
   For example, if the toolchain specifies MSVC headers:
 
     toolchain("vc_x64") {
@@ -5360,6 +5372,13 @@
 
 
 ```
+## **precompiled_header_type**: [string] "gcc" or "msvc".
+
+```
+  See "gn help precompiled_header".
+
+
+```
 ## **precompiled_source**: [file name] Source file to precompile.
 
 ```
@@ -5796,8 +5815,12 @@
 ### **Variables**
 
 ```
+  arg_file_template [optional]
+      Path to a file containing the text that should be used as the default
+      args.gn content when you run `gn args`.
+
   buildconfig [required]
-      Label of the build config file. This file will be used to set up the
+      Path to the build config file. This file will be used to set up the
       build file execution environment for each toolchain.
 
   check_targets [optional]
diff --git a/tools/gn/setup.cc b/tools/gn/setup.cc
index 5c4e984..2c2ba38 100644
--- a/tools/gn/setup.cc
+++ b/tools/gn/setup.cc
@@ -58,8 +58,12 @@
 
 Variables
 
+  arg_file_template [optional]
+      Path to a file containing the text that should be used as the default
+      args.gn content when you run `gn args`.
+
   buildconfig [required]
-      Label of the build config file. This file will be used to set up the
+      Path to the build config file. This file will be used to set up the
       build file execution environment for each toolchain.
 
   check_targets [optional]
@@ -790,5 +794,16 @@
     default_args_ = default_args_value->scope_value();
   }
 
+  const Value* arg_file_template_value =
+      dotfile_scope_.GetValue("arg_file_template", true);
+  if (arg_file_template_value) {
+    if (!arg_file_template_value->VerifyTypeIs(Value::STRING, &err)) {
+      err.PrintToStdout();
+      return false;
+    }
+    SourceFile path(arg_file_template_value->string_value());
+    build_settings_.set_arg_file_template_path(path);
+  }
+
   return true;
 }