Allow overriding script executable in .gn file

This eliminates the need for using gn executable wrapper in cases
where a custom script interpreter is always being used.

Review-Url: https://codereview.chromium.org/2936773006
Cr-Original-Commit-Position: refs/heads/master@{#481105}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: a104997ecbfd50c1d6a3399a49c9ad52c198259c
diff --git a/tools/gn/docs/reference.md b/tools/gn/docs/reference.md
index 2e6aa6f..af2224a 100644
--- a/tools/gn/docs/reference.md
+++ b/tools/gn/docs/reference.md
@@ -598,7 +598,7 @@
 ### <a name="gen:"></a>**gn gen**: Generate ninja files.
 
 ```
-  gn gen [<ide options>] <out_dir>
+  gn gen [--check] [<ide options>] <out_dir>
 
   Generates ninja files from the current tree and puts them in the given output
   directory.
@@ -608,6 +608,9 @@
   Or it can be a directory relative to the current directory such as:
       out/foo
 
+  "gn gen --check" is the same as running "gn check". See "gn help check"
+  for documentation on that mode.
+
   See "gn help switches" for the common command-line switches.
 ```
 
@@ -645,6 +648,11 @@
   --no-deps
       Don't include targets dependencies to the solution. Changes the way how
       --filters option works. Only directly matching targets are included.
+
+  --winsdk=<sdk_version>
+      Use the specified Windows 10 SDK version to generate project files.
+      As an example, "10.0.15063.0" can be specified to use Creators Update SDK
+      instead of the default one.
 ```
 
 #### **Xcode Flags**
@@ -688,9 +696,10 @@
 #### **Generic JSON Output**
 
 ```
-  Dumps target information to JSON file and optionally invokes python script on
-  generated file. See comments at the beginning of json_project_writer.cc and
-  desc_builder.cc for overview of JSON file format.
+  Dumps target information to a JSON file and optionally invokes a
+  python script on the generated file. See the comments at the beginning
+  of json_project_writer.cc and desc_builder.cc for an overview of the JSON
+  file format.
 
   --json-file-name=<json_file_name>
       Overrides default file name (project.json) of generated JSON file.
@@ -1932,7 +1941,7 @@
   get_label_info(":foo", "name")
   # Returns string "foo".
 
-  get_label_info("//foo/bar:baz", "gen_dir")
+  get_label_info("//foo/bar:baz", "target_gen_dir")
   # Returns string "//out/Debug/gen/foo/bar".
 ```
 ### <a name="get_path_info"></a>**get_path_info**: Extract parts of a file or directory name.
@@ -5358,6 +5367,11 @@
       build file containing this target name. This defaults to "//:" which will
       cause the file //BUILD.gn to be loaded.
 
+  script_executable [optional]
+      Path to specific Python executable or potentially a different language
+      interpreter that is used to execute scripts in action targets and
+      exec_script calls.
+
   secondary_source [optional]
       Label of an alternate directory tree to find input files. When searching
       for a BUILD.gn file (or the build config file discussed above), the file
diff --git a/tools/gn/setup.cc b/tools/gn/setup.cc
index 192230d..7fc4a2e 100644
--- a/tools/gn/setup.cc
+++ b/tools/gn/setup.cc
@@ -98,6 +98,11 @@
       build file containing this target name. This defaults to "//:" which will
       cause the file //BUILD.gn to be loaded.
 
+  script_executable [optional]
+      Path to specific Python executable or potentially a different language
+      interpreter that is used to execute scripts in action targets and
+      exec_script calls.
+
   secondary_source [optional]
       Label of an alternate directory tree to find input files. When searching
       for a BUILD.gn file (or the build config file discussed above), the file
@@ -314,13 +319,6 @@
   if (!FillBuildDir(build_dir, !force_create))
     return false;
 
-  // Check for unused variables in the .gn file.
-  Err err;
-  if (!dotfile_scope_.CheckForUnusedVars(&err)) {
-    err.PrintToStdout();
-    return false;
-  }
-
   // Apply project-specific default (if specified).
   // Must happen before FillArguments().
   if (default_args_) {
@@ -333,7 +331,15 @@
     if (!FillArguments(*cmdline))
       return false;
   }
-  FillPythonPath(*cmdline);
+  if (!FillPythonPath(*cmdline))
+    return false;
+
+  // Check for unused variables in the .gn file.
+  Err err;
+  if (!dotfile_scope_.CheckForUnusedVars(&err)) {
+    err.PrintToStdout();
+    return false;
+  }
 
   return true;
 }
@@ -626,12 +632,21 @@
   return true;
 }
 
-void Setup::FillPythonPath(const base::CommandLine& cmdline) {
+bool Setup::FillPythonPath(const base::CommandLine& cmdline) {
   // Trace this since it tends to be a bit slow on Windows.
   ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Fill Python Path");
+  const Value* value = dotfile_scope_.GetValue("script_executable", true);
   if (cmdline.HasSwitch(switches::kScriptExecutable)) {
     build_settings_.set_python_path(
         cmdline.GetSwitchValuePath(switches::kScriptExecutable));
+  } else if (value) {
+    Err err;
+    if (!value->VerifyTypeIs(Value::STRING, &err)) {
+      err.PrintToStdout();
+      return false;
+    }
+    build_settings_.set_python_path(
+        base::FilePath(UTF8ToFilePath(value->string_value())));
   } else {
 #if defined(OS_WIN)
     base::FilePath python_path = FindWindowsPython();
@@ -645,6 +660,7 @@
     build_settings_.set_python_path(base::FilePath("python"));
 #endif
   }
+  return true;
 }
 
 bool Setup::RunConfigFile() {
diff --git a/tools/gn/setup.h b/tools/gn/setup.h
index d9a77d0..68a8f0b 100644
--- a/tools/gn/setup.h
+++ b/tools/gn/setup.h
@@ -119,7 +119,7 @@
 
   // Fills the python path portion of the command line. On failure, sets
   // it to just "python".
-  void FillPythonPath(const base::CommandLine& cmdline);
+  bool FillPythonPath(const base::CommandLine& cmdline);
 
   // Run config file.
   bool RunConfigFile();