Add a tulsi options that allows users to set build phase run scripts that run before or after the main bazel build script.

PiperOrigin-RevId: 211496119
diff --git a/src/TulsiGenerator/PBXTargetGenerator.swift b/src/TulsiGenerator/PBXTargetGenerator.swift
index f96bb21..46ffcd6 100644
--- a/src/TulsiGenerator/PBXTargetGenerator.swift
+++ b/src/TulsiGenerator/PBXTargetGenerator.swift
@@ -794,6 +794,18 @@
                                                      named: name,
                                                      ruleEntryMap: ruleEntryMap)
 
+      if let script = options[.PreBuildPhaseRunScript, entry.label.value] {
+        let runScript = PBXShellScriptBuildPhase(shellScript: script, shellPath: "/bin/bash")
+        runScript.showEnvVarsInLog = true
+        target.buildPhases.insert(runScript, at: 0)
+      }
+
+      if let script = options[.PostBuildPhaseRunScript, entry.label.value] {
+        let runScript = PBXShellScriptBuildPhase(shellScript: script, shellPath: "/bin/bash")
+        runScript.showEnvVarsInLog = true
+        target.buildPhases.append(runScript)
+      }
+
       if let hostLabelString = entry.attributes[.test_host] as? String {
         let hostLabel = BuildLabel(hostLabelString)
         testTargetLinkages.append((target, hostLabel, entry))
diff --git a/src/TulsiGenerator/TulsiOptionSet.swift b/src/TulsiGenerator/TulsiOptionSet.swift
index cecf691..68b4012 100644
--- a/src/TulsiGenerator/TulsiOptionSet.swift
+++ b/src/TulsiGenerator/TulsiOptionSet.swift
@@ -60,7 +60,13 @@
       GenerateRunfiles,
 
       // Used by Tulsi to improve Bazel-caching of build flags.
-      ProjectPrioritizesSwift
+      ProjectPrioritizesSwift,
+
+      // Custom build phase run script that runs before bazel build.
+      PreBuildPhaseRunScript,
+
+      // Custom build phase run script that runs after bazel build.
+      PostBuildPhaseRunScript
 
   // Options for build invocations.
   case BazelBuildOptionsDebug,
@@ -318,6 +324,8 @@
     let cppLanguageStandards = ["compiler-default", "c++98", "gnu++98", "c++0x", "gnu++0x", "c++14", "gnu++14", "c++17", "gnu++17"]
     addStringEnumOption(.CLANG_CXX_LANGUAGE_STANDARD, .BuildSetting, "compiler-default",  cppLanguageStandards)
 
+    addStringOption(.PreBuildPhaseRunScript, [.TargetSpecializable])
+    addStringOption(.PostBuildPhaseRunScript, [.TargetSpecializable])
     addStringOption(.BuildActionPreActionScript, [.TargetSpecializable, .SupportsInheritKeyword])
     addStringOption(.LaunchActionPreActionScript, [.TargetSpecializable, .SupportsInheritKeyword])
     addStringOption(.TestActionPreActionScript, [.TargetSpecializable, .SupportsInheritKeyword])
diff --git a/src/TulsiGenerator/XcodeProjectGenerator.swift b/src/TulsiGenerator/XcodeProjectGenerator.swift
index da09fa5..f5c8323 100644
--- a/src/TulsiGenerator/XcodeProjectGenerator.swift
+++ b/src/TulsiGenerator/XcodeProjectGenerator.swift
@@ -695,20 +695,21 @@
     }
 
     func preActionScripts(for ruleEntry: RuleEntry) -> [XcodeActionType: String] {
-        var preActionScripts: [XcodeActionType: String] = [:]
-        preActionScripts[.BuildAction] = config.options[.BuildActionPreActionScript, ruleEntry.label.value] ?? nil
-        preActionScripts[.LaunchAction] = config.options[.LaunchActionPreActionScript, ruleEntry.label.value] ?? nil
-        preActionScripts[.TestAction] = config.options[.TestActionPreActionScript, ruleEntry.label.value] ?? nil
-        return preActionScripts
+      var preActionScripts: [XcodeActionType: String] = [:]
+      preActionScripts[.BuildAction] = config.options[.BuildActionPreActionScript, ruleEntry.label.value] ?? nil
+      preActionScripts[.LaunchAction] = config.options[.LaunchActionPreActionScript, ruleEntry.label.value] ?? nil
+      preActionScripts[.TestAction] = config.options[.TestActionPreActionScript, ruleEntry.label.value] ?? nil
+      return preActionScripts
     }
 
     func postActionScripts(for ruleEntry: RuleEntry) -> [XcodeActionType: String] {
-        var postActionScripts: [XcodeActionType: String] = [:]
-        postActionScripts[.BuildAction] = config.options[.BuildActionPostActionScript, ruleEntry.label.value] ?? nil
-        postActionScripts[.LaunchAction] = config.options[.LaunchActionPostActionScript, ruleEntry.label.value] ?? nil
-        postActionScripts[.TestAction] = config.options[.TestActionPostActionScript, ruleEntry.label.value] ?? nil
-        return postActionScripts
+      var postActionScripts: [XcodeActionType: String] = [:]
+      postActionScripts[.BuildAction] = config.options[.BuildActionPostActionScript, ruleEntry.label.value] ?? nil
+      postActionScripts[.LaunchAction] = config.options[.LaunchActionPostActionScript, ruleEntry.label.value] ?? nil
+      postActionScripts[.TestAction] = config.options[.TestActionPostActionScript, ruleEntry.label.value] ?? nil
+      return postActionScripts
     }
+
     // Build a map of extension targets to hosts so the hosts may be referenced as additional build
     // requirements. This is necessary for watchOS2 targets (Xcode will spawn an error when
     // attempting to run the app without the scheme linkage, even though Bazel will create the
diff --git a/src/TulsiGenerator/en.lproj/Options.strings b/src/TulsiGenerator/en.lproj/Options.strings
index e55a23f..022475f 100644
--- a/src/TulsiGenerator/en.lproj/Options.strings
+++ b/src/TulsiGenerator/en.lproj/Options.strings
@@ -49,6 +49,11 @@
 "TestActionPreActionScript" = "Test";
 "TestActionPostActionScript" = "Test";
 
+"PreBuildPhaseRunScript" = "Build phase run script (pre bazel build)";
+"PreBuildPhaseRunScript_DESC" = "Build phase run script that runs before the bazel_build.py script (i.e. `exec ${PATH_TO_SCRIPT}')";
+"PostBuildPhaseRunScript" = "Build phase run script (post bazel build)";
+"PostBuildPhaseRunScript_DESC" = "Build phase run script that runs after the bazel_build.py script (i.e. `exec ${PATH_TO_SCRIPT}')";
+
 "SuppressSwiftUpdateCheck" = "Suppress Xcode Swift update check";
 "SuppressSwiftUpdateCheck_DESC" = "Suppresses Xcode's update notification for projects containing Swift code. This asserts that the Swift code is at least version 2.1.";