Support --ninja-extra-args with --ide=vs

Bug: 776727
Change-Id: I401f31efa5a25033999e1cf5275275c7955fa41c
Reviewed-on: https://chromium-review.googlesource.com/731323
Reviewed-by: Dirk Pranke <dpranke@chromium.org>
Commit-Queue: Brian Osman <brianosman@google.com>
Cr-Original-Commit-Position: refs/heads/master@{#512592}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 0738f52d11987091a239d61ab965e58f492516d7
diff --git a/tools/gn/command_gen.cc b/tools/gn/command_gen.cc
index 9c08a84..5775f78 100644
--- a/tools/gn/command_gen.cc
+++ b/tools/gn/command_gen.cc
@@ -211,10 +211,14 @@
     std::string win_kit;
     if (command_line->HasSwitch(kSwitchIdeValueWinSdk))
       win_kit = command_line->GetSwitchValueASCII(kSwitchIdeValueWinSdk);
+    std::string ninja_extra_args;
+    if (command_line->HasSwitch(kSwitchNinjaExtraArgs))
+      ninja_extra_args =
+          command_line->GetSwitchValueASCII(kSwitchNinjaExtraArgs);
     bool no_deps = command_line->HasSwitch(kSwitchNoDeps);
-    bool res = VisualStudioWriter::RunAndWriteFiles(build_settings, builder,
-                                                    version, sln_name, filters,
-                                                    win_kit, no_deps, err);
+    bool res = VisualStudioWriter::RunAndWriteFiles(
+        build_settings, builder, version, sln_name, filters, win_kit,
+        ninja_extra_args, no_deps, err);
     if (res && !quiet) {
       OutputString("Generating Visual Studio projects took " +
                    base::Int64ToString(timer.Elapsed().InMilliseconds()) +
@@ -329,6 +333,10 @@
       As an example, "10.0.15063.0" can be specified to use Creators Update SDK
       instead of the default one.
 
+  --ninja-extra-args=<string>
+      This string is passed without any quoting to the ninja invocation
+      command-line. Can be used to configure ninja flags, like "-j".
+
 Xcode Flags
 
   --workspace=<file_name>
@@ -337,8 +345,7 @@
 
   --ninja-extra-args=<string>
       This string is passed without any quoting to the ninja invocation
-      command-line. Can be used to configure ninja flags, like "-j" if using
-      goma for example.
+      command-line. Can be used to configure ninja flags, like "-j".
 
   --root-target=<target_name>
       Name of the target corresponding to "All" target in Xcode. If unset,
diff --git a/tools/gn/docs/reference.md b/tools/gn/docs/reference.md
index d5fe229..733588a 100644
--- a/tools/gn/docs/reference.md
+++ b/tools/gn/docs/reference.md
@@ -663,6 +663,10 @@
       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.
+
+  --ninja-extra-args=<string>
+      This string is passed without any quoting to the ninja invocation
+      command-line. Can be used to configure ninja flags, like "-j".
 ```
 
 #### **Xcode Flags**
@@ -674,8 +678,7 @@
 
   --ninja-extra-args=<string>
       This string is passed without any quoting to the ninja invocation
-      command-line. Can be used to configure ninja flags, like "-j" if using
-      goma for example.
+      command-line. Can be used to configure ninja flags, like "-j".
 
   --root-target=<target_name>
       Name of the target corresponding to "All" target in Xcode. If unset,
diff --git a/tools/gn/visual_studio_writer.cc b/tools/gn/visual_studio_writer.cc
index ad821a7..bbb99c6 100644
--- a/tools/gn/visual_studio_writer.cc
+++ b/tools/gn/visual_studio_writer.cc
@@ -316,6 +316,7 @@
                                           const std::string& sln_name,
                                           const std::string& filters,
                                           const std::string& win_sdk,
+                                          const std::string& ninja_extra_args,
                                           bool no_deps,
                                           Err* err) {
   std::vector<const Target*> targets;
@@ -351,7 +352,7 @@
       continue;
     }
 
-    if (!writer.WriteProjectFiles(target, err))
+    if (!writer.WriteProjectFiles(target, ninja_extra_args, err))
       return false;
   }
 
@@ -372,7 +373,9 @@
   return writer.WriteSolutionFile(sln_name, err);
 }
 
-bool VisualStudioWriter::WriteProjectFiles(const Target* target, Err* err) {
+bool VisualStudioWriter::WriteProjectFiles(const Target* target,
+                                           const std::string& ninja_extra_args,
+                                           Err* err) {
   std::string project_name = target->label().name();
   const char* project_config_platform = config_platform_;
   if (!target->settings()->is_default()) {
@@ -403,7 +406,7 @@
   std::stringstream vcxproj_string_out;
   SourceFileCompileTypePairs source_types;
   if (!WriteProjectFileContents(vcxproj_string_out, *projects_.back(), target,
-                                &source_types, err)) {
+                                ninja_extra_args, &source_types, err)) {
     projects_.pop_back();
     return false;
   }
@@ -424,6 +427,7 @@
     std::ostream& out,
     const SolutionProject& solution_project,
     const Target* target,
+    const std::string& ninja_extra_args,
     SourceFileCompileTypePairs* source_types,
     Err* err) {
   PathOutput path_output(
@@ -611,6 +615,7 @@
         std::unique_ptr<XmlElementWriter> build = group->SubElement(
             compile_type, "Include", SourceFileWriter(path_output, file));
         build->SubElement("Command")->Text("call ninja.exe -C $(OutDir) " +
+                                           ninja_extra_args + " " +
                                            tool_outputs[0].value());
         build->SubElement("Outputs")->Text("$(OutDir)" +
                                            tool_outputs[0].value());
@@ -638,8 +643,9 @@
     std::unique_ptr<XmlElementWriter> build =
         project.SubElement("Target", XmlAttributes("Name", "Build"));
     build->SubElement(
-        "Exec", XmlAttributes("Command",
-                              "call ninja.exe -C $(OutDir) " + ninja_target));
+        "Exec",
+        XmlAttributes("Command", "call ninja.exe -C $(OutDir) " +
+                                     ninja_extra_args + " " + ninja_target));
   }
 
   {
diff --git a/tools/gn/visual_studio_writer.h b/tools/gn/visual_studio_writer.h
index db2f3ea..d9bb883 100644
--- a/tools/gn/visual_studio_writer.h
+++ b/tools/gn/visual_studio_writer.h
@@ -45,6 +45,7 @@
                                const std::string& sln_name,
                                const std::string& filters,
                                const std::string& win_sdk,
+                               const std::string& ninja_extra_args,
                                bool no_deps,
                                Err* err);
 
@@ -104,10 +105,13 @@
                      const std::string& win_kit);
   ~VisualStudioWriter();
 
-  bool WriteProjectFiles(const Target* target, Err* err);
+  bool WriteProjectFiles(const Target* target,
+                         const std::string& ninja_extra_args,
+                         Err* err);
   bool WriteProjectFileContents(std::ostream& out,
                                 const SolutionProject& solution_project,
                                 const Target* target,
+                                const std::string& ninja_extra_args,
                                 SourceFileCompileTypePairs* source_types,
                                 Err* err);
   void WriteFiltersFileContents(std::ostream& out,