Allow selection of autoninja for XCode building.

Bug: crbug.com/1052038
Change-Id: I2c9f33d9633bd48166f459fa4c5fbfdd31c9851d
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/7440
Reviewed-by: Brett Wilson <brettw@chromium.org>
Commit-Queue: Brett Wilson <brettw@chromium.org>
diff --git a/src/gn/command_gen.cc b/src/gn/command_gen.cc
index 57828ad..0059689 100644
--- a/src/gn/command_gen.cc
+++ b/src/gn/command_gen.cc
@@ -42,6 +42,7 @@
 const char kSwitchIdeValueWinSdk[] = "winsdk";
 const char kSwitchIdeValueXcode[] = "xcode";
 const char kSwitchIdeValueJson[] = "json";
+const char kSwitchNinjaExecutable[] = "ninja-executable";
 const char kSwitchNinjaExtraArgs[] = "ninja-extra-args";
 const char kSwitchNoDeps[] = "no-deps";
 const char kSwitchRootTarget[] = "root-target";
@@ -237,6 +238,7 @@
     bool res = XcodeWriter::RunAndWriteFiles(
         command_line->GetSwitchValueASCII(kSwitchWorkspace),
         command_line->GetSwitchValueASCII(kSwitchRootTarget),
+        command_line->GetSwitchValueASCII(kSwitchNinjaExecutable),
         command_line->GetSwitchValueASCII(kSwitchNinjaExtraArgs),
         command_line->GetSwitchValueASCII(kSwitchFilters), build_settings,
         builder, err);
@@ -375,6 +377,9 @@
       Override defaut workspace file name ("all"). The workspace file is
       written to the root build directory.
 
+  --ninja-executable=<string>
+      Can be used to specify the ninja executable to use when building.
+
   --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".
diff --git a/src/gn/xcode_writer.cc b/src/gn/xcode_writer.cc
index 8281a2c..6ffcc58 100644
--- a/src/gn/xcode_writer.cc
+++ b/src/gn/xcode_writer.cc
@@ -71,7 +71,12 @@
   return XcodeWriter::WRITER_TARGET_OS_MACOS;
 }
 
+std::string GetNinjaExecutable(const std::string& ninja_executable) {
+  return ninja_executable.empty() ? "ninja" : ninja_executable;
+}
+
 std::string GetBuildScript(const std::string& target_name,
+                           const std::string& ninja_executable,
                            const std::string& ninja_extra_args,
                            base::Environment* environment) {
   std::stringstream script;
@@ -96,7 +101,7 @@
     script << "\" ";
   }
 
-  script << "ninja -C .";
+  script << GetNinjaExecutable(ninja_executable) << " -C .";
   if (!ninja_extra_args.empty())
     script << " " << ninja_extra_args;
   if (!target_name.empty())
@@ -358,6 +363,7 @@
 // static
 bool XcodeWriter::RunAndWriteFiles(const std::string& workspace_name,
                                    const std::string& root_target_name,
+                                   const std::string& ninja_executable,
                                    const std::string& ninja_extra_args,
                                    const std::string& dir_filters_string,
                                    const BuildSettings* build_settings,
@@ -401,7 +407,8 @@
   XcodeWriter workspace(workspace_name);
   workspace.CreateProductsProject(targets, all_targets, attributes, source_path,
                                   config_name, root_target_name,
-                                  ninja_extra_args, build_settings, target_os);
+                                  ninja_executable, ninja_extra_args,
+                                  build_settings, target_os);
 
   return workspace.WriteFiles(build_settings, err);
 }
@@ -474,6 +481,7 @@
     const std::string& source_path,
     const std::string& config_name,
     const std::string& root_target,
+    const std::string& ninja_executable,
     const std::string& ninja_extra_args,
     const BuildSettings* build_settings,
     TargetOsType target_os) {
@@ -489,7 +497,8 @@
   AddSourceFilesToProjectForIndexing(all_targets, main_project.get(),
                                      source_dir, build_settings);
   main_project->AddAggregateTarget(
-      "All", GetBuildScript(root_target, ninja_extra_args, env.get()));
+      "All", GetBuildScript(root_target, ninja_executable, ninja_extra_args,
+                            env.get()));
 
   // Needs to search for xctest files under the application targets, and this
   // variable is used to store the results of visited targets, thus making the
@@ -507,8 +516,8 @@
             target->output_name().empty() ? target->label().name()
                                           : target->output_name(),
             "com.apple.product-type.tool",
-            GetBuildScript(target->label().name(), ninja_extra_args,
-                           env.get()));
+            GetBuildScript(target->label().name(), ninja_executable,
+                           ninja_extra_args, env.get()));
         break;
 
       case Target::CREATE_BUNDLE: {
@@ -538,7 +547,8 @@
         PBXNativeTarget* native_target = main_project->AddNativeTarget(
             pbxtarget_name, std::string(), target_output_name,
             target->bundle_data().product_type(),
-            GetBuildScript(pbxtarget_name, ninja_extra_args, env.get()),
+            GetBuildScript(pbxtarget_name, ninja_executable, ninja_extra_args,
+              env.get()),
             xcode_extra_attributes);
 
         bundle_targets.push_back(target);
diff --git a/src/gn/xcode_writer.h b/src/gn/xcode_writer.h
index 24953dc..e391c56 100644
--- a/src/gn/xcode_writer.h
+++ b/src/gn/xcode_writer.h
@@ -33,6 +33,8 @@
   // |workspace_name| is the optional name of the workspace file name ("all"
   // is used if not specified). |root_target_name| is the name of the main
   // target corresponding to building "All" (for example "gn_all" in Chromium).
+  // |ninja_executable| can be used to control which ninja executable will be
+  // run. When empty, regular ninja will be used.
   // |ninja_extra_args| are additional arguments to pass to ninja invocation
   // (can be used to increase limit of concurrent processes when using goma).
   // |dir_filters_string| is optional semicolon-separated list of label patterns
@@ -40,6 +42,7 @@
   // included to the workspace. On failure will populate |err| and return false.
   static bool RunAndWriteFiles(const std::string& workspace_name,
                                const std::string& root_target_name,
+                               const std::string& ninja_executable,
                                const std::string& ninja_extra_args,
                                const std::string& dir_filters_string,
                                const BuildSettings* build_settings,
@@ -68,6 +71,7 @@
                              const std::string& source_path,
                              const std::string& config_name,
                              const std::string& root_target,
+                             const std::string& ninja_executable,
                              const std::string& ninja_extra_args,
                              const BuildSettings* build_settings,
                              TargetOsType target_os);