// Copyright 2016 The Tulsi Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import Foundation

/// Provides a set of project paths to stub Info.plist files to be used by generated targets.
struct StubInfoPlistPaths {
  let resourcesDirectory: String
  let defaultStub: String
  let watchOSStub: String
  let watchOSAppExStub: String

  func stubPlist(_ entry: RuleEntry) -> String {

    switch entry.pbxTargetType! {
    case .Watch1App, .Watch2App:
      return watchOSStub

    case .Watch1Extension, .Watch2Extension:
      return watchOSAppExStub

    case .MessagesExtension:
      fallthrough
    case .MessagesStickerPackExtension:
      fallthrough
    case .AppExtension:
      return stubProjectPath(forRuleEntry: entry)

    default:
      return defaultStub
    }
  }

  func plistFilename(forRuleEntry ruleEntry: RuleEntry) -> String {
    return "Stub_\(ruleEntry.label.asFullPBXTargetName!).plist"
  }

  func stubProjectPath(forRuleEntry ruleEntry: RuleEntry) -> String {
    let fileName = plistFilename(forRuleEntry: ruleEntry)
    return "\(resourcesDirectory)/\(fileName)"
  }
}

/// Defines an object that can populate a PBXProject based on RuleEntry's.
protocol PBXTargetGeneratorProtocol: class {
  static func getRunTestTargetBuildConfigPrefix() -> String

  static func workingDirectoryForPBXGroup(_ group: PBXGroup) -> String

  /// Returns a new PBXGroup instance appropriate for use as a top level project group.
  static func mainGroupForOutputFolder(_ outputFolderURL: URL, workspaceRootURL: URL) -> PBXGroup

  init(bazelPath: String,
       bazelBinPath: String,
       project: PBXProject,
       buildScriptPath: String,
       stubInfoPlistPaths: StubInfoPlistPaths,
       tulsiVersion: String,
       options: TulsiOptionSet,
       localizedMessageLogger: LocalizedMessageLogger,
       workspaceRootURL: URL,
       suppressCompilerDefines: Bool,
       redactWorkspaceSymlink: Bool)

  /// Generates file references for the given file paths in the associated project without adding
  /// them to an indexer target. The paths must be relative to the workspace root. If pathFilters is
  /// non-nil, paths that do not match an entry in the pathFilters set will be omitted.
  func generateFileReferencesForFilePaths(_ paths: [String], pathFilters: Set<String>?)

  /// Registers the given Bazel rule and its transitive dependencies for inclusion by the Xcode
  /// indexer, adding source files whose directories are present in pathFilters. The rule will
  /// only be processed if it hasn't already (and therefore isn't in processedEntries).
  /// - processedEntries: Map of RuleEntry to cumulative preprocessor framework search paths.
  func registerRuleEntryForIndexer(_ ruleEntry: RuleEntry,
                                   ruleEntryMap: RuleEntryMap,
                                   pathFilters: Set<String>,
                                   processedEntries: inout [RuleEntry: (NSOrderedSet)])

  /// Generates indexer targets for rules that were previously registered through
  /// registerRuleEntryForIndexer. This method may only be called once, after all rule entries have
  /// been registered.
  /// Returns a map of indexer targets, keyed by the name of the indexer.
  func generateIndexerTargets() -> [String: PBXTarget]

  /// Generates a legacy target that is added as a dependency of all build targets and invokes
  /// the given script. The build action may be accessed by the script via the ACTION environment
  /// variable.
  func generateBazelCleanTarget(_ scriptPath: String, workingDirectory: String,
                                startupOptions: [String])

  /// Generates project-level build configurations.
  func generateTopLevelBuildConfigurations(_ buildSettingOverrides: [String: String])

  /// Generates Xcode build targets that invoke Bazel for the given targets. For test-type rules,
  /// non-compiling source file linkages are created to facilitate indexing of XCTests.
  ///
  /// Returns a mapping from build label to generated PBXNativeTarget.
  /// Throws if one of the RuleEntry instances is for an unsupported Bazel target type.
  func generateBuildTargetsForRuleEntries(
    _ entries: Set<RuleEntry>,
    ruleEntryMap: RuleEntryMap
  ) throws -> [BuildLabel: PBXNativeTarget]
}

extension PBXTargetGeneratorProtocol {
  func generateFileReferencesForFilePaths(_ paths: [String]) {
    generateFileReferencesForFilePaths(paths, pathFilters: nil)
  }
}


/// Concrete PBXProject target generator.
final class PBXTargetGenerator: PBXTargetGeneratorProtocol {

  enum ProjectSerializationError: Error {
    case buildFileIsNotContainedByProjectRoot
    case generalFailure(String)
    case unsupportedTargetType(String, String)
  }

  /// Names of Xcode build configurations to generate.
  // NOTE: Must be kept in sync with the CONFIGURATION environment variable use in the build script.
  static let buildConfigNames = ["Debug", "Release"]

  /// Tuples consisting of a test runner config name and the base config name (from
  /// buildConfigNames) that it inherits from.
  static let testRunnerEnabledBuildConfigNames = ["Debug", "Release"].map({
    (runTestTargetBuildConfigPrefix + $0, $0)
  })

  /// Prefix for special configs used when running XCTests that prevent compilation and linking of
  /// any source files. This allows XCTest bundles to have associated test sources indexed by Xcode
  /// but not compiled when testing (as they're compiled by Bazel and the generated project may be
  /// missing information necessary to compile them anyway). Configs are generated for Debug and
  /// Release builds.
  // NOTE: This value needs to be kept in sync with the bazel_build script.
  static let runTestTargetBuildConfigPrefix = "__TulsiTestRunner_"
  static func getRunTestTargetBuildConfigPrefix() -> String {
    return runTestTargetBuildConfigPrefix
  }

  /// Name of the static library target that will be used to accumulate all source file dependencies
  /// in order to make their symbols available to the Xcode indexer.
  static let IndexerTargetPrefix = "_idx_"

  /// Rough sanity limit on indexer name length. Names may be slightly longer than this limit.
  /// Empirically, 255 characters is the observed threshold for problems with file systems.
  static let MaxIndexerNameLength = 180

  // Name prefix for auto-generated nop-app extension targets necessary to get Xcode to debug watch
  // Apps.
  private static let watchAppExtensionTargetPrefix = "_tulsi_appex_"

  /// Name of the legacy target that will be used to communicate with Bazel during Xcode clean
  /// actions.
  static let BazelCleanTarget = "_bazel_clean_"

  /// Xcode variable name used to refer to the workspace root.
  static let WorkspaceRootVarName = "TULSI_WR"

  /// Symlink to the Bazel workspace
  static let TulsiWorkspacePath = "tulsi-workspace"

  /// Xcode variable name used to refer to the symlink generated by Bazel that contains all
  /// workspace content.
  static let BazelWorkspaceSymlinkVarName = "TULSI_BWRS"

  /// Path to the Bazel executable.
  let bazelPath: String

  /// Location of the bazel bin symlink, relative to the workspace root.
  let bazelBinPath: String
  private(set) lazy var bazelGenfilesPath: String = { [unowned self] in
    return self.bazelBinPath.replacingOccurrences(of: "-bin", with: "-genfiles")
  }()

  /// Previous path to the Tulsi generated outputs root. We remap any paths of this form to the
  /// new `tulsiIncludesPath` form automatically for convenience.
  static let legacyTulsiIncludesPath = "_tulsi-includes/x/x"

  /// The path to the Tulsi generated outputs root. For more information see tulsi_aspects.bzl
  static let tulsiIncludesPath = "bazel-tulsi-includes/x/x"

  let project: PBXProject
  let buildScriptPath: String
  let stubInfoPlistPaths: StubInfoPlistPaths
  let tulsiVersion: String
  let options: TulsiOptionSet
  let localizedMessageLogger: LocalizedMessageLogger
  let workspaceRootURL: URL
  let suppressCompilerDefines: Bool
  let redactWorkspaceSymlink: Bool

  var bazelCleanScriptTarget: PBXLegacyTarget? = nil

  /// Stores data about a given RuleEntry to be used in order to generate Xcode indexer targets.
  private struct IndexerData {
    /// Provides information about the RuleEntry instances supported by an IndexerData.
    /// Specifically, NameInfoToken tuples provide the targetName, full target label hash, and
    /// potentially the target configuration in order to differentiate between rules with the
    /// same name but different paths and configurations.
    struct NameInfoToken {
      let targetName: String
      let labelHash: Int

      init(ruleEntry: RuleEntry) {
        self.init(label: ruleEntry.label)
      }

      init(label: BuildLabel) {
        targetName = label.targetName!
        labelHash = label.hashValue
      }
    }

    let indexerNameInfo: [NameInfoToken]
    let dependencies: Set<BuildLabel>
    let resolvedDependencies: Set<RuleEntry>
    let preprocessorDefines: Set<String>
    let otherCFlags: [String]
    let otherSwiftFlags: [String]
    let includes: [String]
    let frameworkSearchPaths: [String]
    let swiftIncludePaths: [String]
    let deploymentTarget: DeploymentTarget
    let buildPhase: PBXSourcesBuildPhase
    let pchFile: BazelFileInfo?
    let bridgingHeader: BazelFileInfo?
    let enableModules: Bool

    /// Returns the deploymentTarget as a string for an indexerName.
    static func deploymentTargetLabel(_ deploymentTarget: DeploymentTarget) -> String {
      return String(format: "%@_min%@",
                    deploymentTarget.platform.rawValue,
                    deploymentTarget.osVersion)
    }

    /// Returns the deploymentTarget as a string for the indexerName.
    var deploymentTargetLabel: String {
      return IndexerData.deploymentTargetLabel(deploymentTarget)
    }

    /// Returns the full name that should be used when generating a target for this indexer.
    var indexerName: String {
      var fullName = ""
      var fullHash = 0

      for token in indexerNameInfo {
        if fullName.isEmpty {
          fullName = token.targetName
        } else {
          fullName += "_\(token.targetName)"
        }
        fullHash = fullHash &+ token.labelHash
      }
      return PBXTargetGenerator.indexerNameForTargetName(fullName,
                                                         hash: fullHash,
                                                         suffix: deploymentTargetLabel)
    }

    /// Returns an array of aliases for this indexer data. Each element is the full indexerName of
    /// an IndexerData instance that has been merged into this IndexerData.
    var supportedIndexingTargets: [String] {
      var supportedTargets = [indexerName]
      if indexerNameInfo.count > 1 {
        for token in indexerNameInfo {
          supportedTargets.append(PBXTargetGenerator.indexerNameForTargetName(token.targetName,
                                                                              hash: token.labelHash,
                                                                              suffix: deploymentTargetLabel))
        }
      }
      return supportedTargets
    }

    /// Returns an array of indexing target names that this indexer depends on.
    var indexerNamesForResolvedDependencies: [String] {
      let parentDeploymentTargetLabel = self.deploymentTargetLabel
      return resolvedDependencies.map() { entry in
        let deploymentTargetLabel: String
        if let deploymentTarget = entry.deploymentTarget {
          deploymentTargetLabel = IndexerData.deploymentTargetLabel(deploymentTarget)
        } else {
          deploymentTargetLabel = parentDeploymentTargetLabel
        }
        return PBXTargetGenerator.indexerNameForTargetName(entry.label.targetName!,
                                                           hash: entry.label.hashValue,
                                                           suffix: deploymentTargetLabel)
      }
    }

    /// Indicates whether or not this indexer may be merged with the given indexer.
    func canMergeWith(_ other: IndexerData) -> Bool {
      if self.pchFile != other.pchFile || self.bridgingHeader != other.bridgingHeader {
        return false
      }

      if !(preprocessorDefines == other.preprocessorDefines &&
          enableModules == other.enableModules &&
          otherCFlags == other.otherCFlags &&
          otherSwiftFlags == other.otherSwiftFlags &&
          frameworkSearchPaths == other.frameworkSearchPaths &&
          includes == other.includes &&
          swiftIncludePaths == other.swiftIncludePaths &&
          deploymentTarget == other.deploymentTarget) {
        return false
      }

      return true
    }

    /// Returns a new IndexerData instance that is the result of merging this indexer with another.
    func merging(_ other: IndexerData) -> IndexerData {
      let newDependencies = dependencies.union(other.dependencies)
      let newResolvedDependencies = resolvedDependencies.union(other.resolvedDependencies)
      let newName = indexerNameInfo + other.indexerNameInfo
      let newBuildPhase = PBXSourcesBuildPhase()
      newBuildPhase.files = buildPhase.files + other.buildPhase.files

      return IndexerData(indexerNameInfo: newName,
                         dependencies: newDependencies,
                         resolvedDependencies: newResolvedDependencies,
                         preprocessorDefines: preprocessorDefines,
                         otherCFlags: otherCFlags,
                         otherSwiftFlags: otherSwiftFlags,
                         includes: includes,
                         frameworkSearchPaths: frameworkSearchPaths,
                         swiftIncludePaths: swiftIncludePaths,
                         deploymentTarget: deploymentTarget,
                         buildPhase: newBuildPhase,
                         pchFile: pchFile,
                         bridgingHeader: bridgingHeader,
                         enableModules: enableModules)
    }
  }

  /// Registered indexers that will be modeled as static libraries.
  private var staticIndexers = [String: IndexerData]()
  /// Registered indexers that will be modeled as dynamic frameworks.
  private var frameworkIndexers = [String: IndexerData]()

  /// Maps the names of indexer targets to the generated target instance in the project. Values are
  /// not guaranteed to be unique, as several targets may be merged into a single target during
  /// optimization.
  private var indexerTargetByName = [String: PBXTarget]()

  static func workingDirectoryForPBXGroup(_ group: PBXGroup) -> String {
    switch group.sourceTree {
      case .SourceRoot:
        if let relativePath = group.path, !relativePath.isEmpty {
          return "${SRCROOT}/\(relativePath)"
        }
        return ""

      case .Absolute:
        return group.path!

      default:
        assertionFailure("Group has an unexpected sourceTree type \(group.sourceTree)")
        return ""
    }
  }

  static func mainGroupForOutputFolder(_ outputFolderURL: URL, workspaceRootURL: URL) -> PBXGroup {
    let outputFolder = outputFolderURL.path
    let workspaceRoot = workspaceRootURL.path

    let slashTerminatedOutputFolder = outputFolder + (outputFolder.hasSuffix("/") ? "" : "/")
    let slashTerminatedWorkspaceRoot = workspaceRoot + (workspaceRoot.hasSuffix("/") ? "" : "/")

    // If workspaceRoot == outputFolder, return a relative group with no path.
    if slashTerminatedOutputFolder == slashTerminatedWorkspaceRoot {
      return PBXGroup(name: "mainGroup", path: nil, sourceTree: .SourceRoot, parent: nil)
    }

    // If outputFolder contains workspaceRoot, return a relative group with the path from
    // outputFolder to workspaceRoot
    if workspaceRoot.hasPrefix(slashTerminatedOutputFolder) {
      let index = workspaceRoot.index(workspaceRoot.startIndex, offsetBy: slashTerminatedOutputFolder.count)
      let relativePath = String(workspaceRoot[index...])
      return PBXGroup(name: "mainGroup",
                      path: relativePath,
                      sourceTree: .SourceRoot,
                      parent: nil)
    }

    // If workspaceRoot contains outputFolder, return a relative group using .. to walk up to
    // workspaceRoot from outputFolder.
    if outputFolder.hasPrefix(slashTerminatedWorkspaceRoot) {
      let index = outputFolder.index(outputFolder.startIndex, offsetBy: slashTerminatedWorkspaceRoot.count + 1)
      let pathToWalkBackUp = String(outputFolder[index...]) as NSString
      let numberOfDirectoriesToWalk = pathToWalkBackUp.pathComponents.count
      let relativePath = [String](repeating: "..", count: numberOfDirectoriesToWalk).joined(separator: "/")
      return PBXGroup(name: "mainGroup",
                      path: relativePath,
                      sourceTree: .SourceRoot,
                      parent: nil)
    }

    return PBXGroup(name: "mainGroup",
                    path: workspaceRootURL.path,
                    sourceTree: .Absolute,
                    parent: nil)
  }

  /// Returns a project-relative path for the given BazelFileInfo.
  private static func projectRefForBazelFileInfo(_ info: BazelFileInfo) -> String {
    switch info.targetType {
      case .generatedFile:
        return "$(\(WorkspaceRootVarName))/\(info.fullPath)"
      case .sourceFile:
        return "$(\(BazelWorkspaceSymlinkVarName))/\(info.fullPath)"
    }
  }

  /// Returns the default Deployment Target (iOS 9). This is just a sensible default
  /// in the odd case that we didn't get a Deployment Target from the Aspect.
  private static func defaultDeploymentTarget() -> DeploymentTarget {
    return DeploymentTarget(platform: .ios, osVersion: "9.0")
  }

  /// Computed property to determine if USER_HEADER_SEARCH_PATHS should be set for Objective-C
  /// targets.
  var improvedImportAutocompletionFix: Bool {
    return options[.ImprovedImportAutocompletionFix].commonValueAsBool ?? true
  }

  init(bazelPath: String,
       bazelBinPath: String,
       project: PBXProject,
       buildScriptPath: String,
       stubInfoPlistPaths: StubInfoPlistPaths,
       tulsiVersion: String,
       options: TulsiOptionSet,
       localizedMessageLogger: LocalizedMessageLogger,
       workspaceRootURL: URL,
       suppressCompilerDefines: Bool = false,
       redactWorkspaceSymlink: Bool = false) {
    self.bazelPath = bazelPath
    self.bazelBinPath = bazelBinPath
    self.project = project
    self.buildScriptPath = buildScriptPath
    self.stubInfoPlistPaths = stubInfoPlistPaths
    self.tulsiVersion = tulsiVersion
    self.options = options
    self.localizedMessageLogger = localizedMessageLogger
    self.workspaceRootURL = workspaceRootURL
    self.suppressCompilerDefines = suppressCompilerDefines
    self.redactWorkspaceSymlink = redactWorkspaceSymlink
  }

  func generateFileReferencesForFilePaths(_ paths: [String], pathFilters: Set<String>?) {
    if let pathFilters = pathFilters {
      let filteredPaths = paths.filter(pathFilterFunc(pathFilters))
      project.getOrCreateGroupsAndFileReferencesForPaths(filteredPaths)
    } else {
      project.getOrCreateGroupsAndFileReferencesForPaths(paths)
    }
  }

  /// Registers the given Bazel rule and its transitive dependencies for inclusion by the Xcode
  /// indexer, adding source files whose directories are present in pathFilters. The rule will
  /// only be processed if it hasn't already (and therefore isn't in processedEntries).
  /// - processedEntries: Map of RuleEntry to cumulative preprocessor framework search paths.
  func registerRuleEntryForIndexer(_ ruleEntry: RuleEntry,
                                   ruleEntryMap: RuleEntryMap,
                                   pathFilters: Set<String>,
                                   processedEntries: inout [RuleEntry: (NSOrderedSet)]) {
    let includePathInProject = pathFilterFunc(pathFilters)
    func includeFileInProject(_ info: BazelFileInfo) -> Bool {
      return includePathInProject(info.fullPath)
    }

    func addFileReference(_ info: BazelFileInfo) {
      let (_, fileReferences) = project.getOrCreateGroupsAndFileReferencesForPaths([info.fullPath])
      fileReferences.first!.isInputFile = info.targetType == .sourceFile
    }

    func addBuildFileForRule(_ ruleEntry: RuleEntry) {
      guard let buildFilePath = ruleEntry.buildFilePath, includePathInProject(buildFilePath) else {
        return
      }
      project.getOrCreateGroupsAndFileReferencesForPaths([buildFilePath])
    }

    // Recursively find all targets that are direct dependencies of test targets, and skip adding
    // indexers for them, because their sources will be added directly to the test target.
    var ruleEntryLabelsToSkipForIndexing = Set<BuildLabel>()
    func addTestDepsToSkipList(_ ruleEntry: RuleEntry) {
      if ruleEntry.pbxTargetType?.isTest ?? false {
        for dep in ruleEntry.dependencies {
          ruleEntryLabelsToSkipForIndexing.insert(dep)
          guard let depEntry = ruleEntryMap.ruleEntry(buildLabel: dep, depender: ruleEntry) else {
            localizedMessageLogger.warning("UnknownTargetRule",
                                           comment: "Failure to look up a Bazel target that was expected to be present. The target label is %1$@",
                                           values: dep.value)
            continue
          }
          addTestDepsToSkipList(depEntry)
        }
      }
    }
    addTestDepsToSkipList(ruleEntry)

    // TODO(b/63628175): Clean this nested method to also retrieve framework_dir and framework_file
    // from the ObjcProvider, for both static and dynamic frameworks.
    @discardableResult
    func generateIndexerTargetGraphForRuleEntry(_ ruleEntry: RuleEntry) -> (NSOrderedSet) {
      if let data = processedEntries[ruleEntry] {
        return data
      }
      var frameworkSearchPaths = NSMutableOrderedSet()

      defer {
        processedEntries[ruleEntry] = (frameworkSearchPaths)
      }

      var resolvedDependecies = [RuleEntry]()
      for dep in ruleEntry.dependencies {
        guard let depEntry = ruleEntryMap.ruleEntry(buildLabel: dep, depender: ruleEntry) else {
          localizedMessageLogger.warning("UnknownTargetRule",
                                         comment: "Failure to look up a Bazel target that was expected to be present. The target label is %1$@",
                                         values: dep.value)
          continue
        }

        resolvedDependecies.append(depEntry)
        let inheritedFrameworkSearchPaths = generateIndexerTargetGraphForRuleEntry(depEntry)
        frameworkSearchPaths.union(inheritedFrameworkSearchPaths)
      }
      var defines = Set<String>()
      if let ruleDefines = ruleEntry.objcDefines {
        defines.formUnion(ruleDefines)
      }

      if !suppressCompilerDefines,
         let ruleDefines = ruleEntry.attributes[.compiler_defines] as? [String], !ruleDefines.isEmpty {
        defines.formUnion(ruleDefines)
      }

      let includes = NSMutableOrderedSet()
      addIncludes(ruleEntry, toSet: includes)

      // Search path entries are added for all framework imports, regardless of whether the
      // framework bundles are allowed by the include filters. The search path excludes the bundle
      // itself.
      ruleEntry.frameworkImports.forEach() {
        let fullPath = $0.fullPath as NSString
        let rootedPath = "$(\(PBXTargetGenerator.BazelWorkspaceSymlinkVarName))/\(fullPath.deletingLastPathComponent)"
        frameworkSearchPaths.add(rootedPath)
      }
      let sourceFileInfos = ruleEntry.sourceFiles.filter(includeFileInProject)
      let nonARCSourceFileInfos = ruleEntry.nonARCSourceFiles.filter(includeFileInProject)
      let frameworkFileInfos = ruleEntry.frameworkImports.filter(includeFileInProject)
      let nonSourceVersionedFileInfos = ruleEntry.versionedNonSourceArtifacts.filter(includeFileInProject)

      for target in ruleEntry.normalNonSourceArtifacts.filter(includeFileInProject) {
        let path = target.fullPath
        let (_, ref) = project.createGroupsAndFileReferenceForPath(path, underGroup: project.mainGroup)
        ref.isInputFile = target.targetType == .sourceFile
      }

      // Indexer targets aren't needed:
      // - if the target is a filegroup (we generate an indexer for what references the filegroup).
      // - if the target has no source files (there's nothing to index!)
      // - if the target is a test bundle (we generate proper targets for these).
      // - if the target is a direct dependency of a test target (these sources are added directly to the test target).
      if (sourceFileInfos.isEmpty &&
          nonARCSourceFileInfos.isEmpty &&
          frameworkFileInfos.isEmpty &&
          nonSourceVersionedFileInfos.isEmpty)
        || ruleEntry.pbxTargetType?.isTest ?? false
        || ruleEntry.type == "filegroup"
        || ruleEntryLabelsToSkipForIndexing.contains(ruleEntry.label) {
        addBuildFileForRule(ruleEntry)
        return (frameworkSearchPaths)
      }

      var localPreprocessorDefines = defines
      let localIncludes = includes.mutableCopy() as! NSMutableOrderedSet
      let otherCFlags = NSMutableArray()
      let swiftIncludePaths = NSMutableOrderedSet()
      let otherSwiftFlags = NSMutableArray()
      addLocalSettings(ruleEntry, localDefines: &localPreprocessorDefines, localIncludes: localIncludes,
                       otherCFlags: otherCFlags, swiftIncludePaths: swiftIncludePaths, otherSwiftFlags: otherSwiftFlags)

      addOtherSwiftFlags(ruleEntry, toArray: otherSwiftFlags)
      addSwiftIncludes(ruleEntry, toSet: swiftIncludePaths)

      let pchFile = BazelFileInfo(info: ruleEntry.attributes[.pch])
      if let pchFile = pchFile, includeFileInProject(pchFile) {
        addFileReference(pchFile)
      }

      let bridgingHeader = BazelFileInfo(info: ruleEntry.attributes[.bridging_header])
      if let bridgingHeader = bridgingHeader, includeFileInProject(bridgingHeader) {
        addFileReference(bridgingHeader)
      }
      let enableModules = (ruleEntry.attributes[.enable_modules] as? Bool) == true

      addBuildFileForRule(ruleEntry)

      let (nonARCFiles, nonARCSettings) = generateFileReferencesAndSettingsForNonARCFileInfos(nonARCSourceFileInfos)
      var fileReferences = generateFileReferencesForFileInfos(sourceFileInfos)
      fileReferences.append(contentsOf: generateFileReferencesForFileInfos(frameworkFileInfos))
      fileReferences.append(contentsOf: nonARCFiles)

      var buildPhaseReferences: [PBXReference]
      if nonSourceVersionedFileInfos.isEmpty {
        buildPhaseReferences = [PBXReference]()
      } else {
        let versionedFileReferences = createReferencesForVersionedFileTargets(nonSourceVersionedFileInfos)
        buildPhaseReferences = versionedFileReferences as [PBXReference]
      }
      buildPhaseReferences.append(contentsOf: fileReferences as [PBXReference])

      let buildPhase = createBuildPhaseForReferences(buildPhaseReferences,
                                                     withPerFileSettings: nonARCSettings)

      if !buildPhase.files.isEmpty {
        let resolvedIncludes = localIncludes.array as! [String]

        let deploymentTarget: DeploymentTarget
        if let ruleDeploymentTarget = ruleEntry.deploymentTarget {
          deploymentTarget = ruleDeploymentTarget
        } else {
          deploymentTarget = PBXTargetGenerator.defaultDeploymentTarget()
          localizedMessageLogger.warning("NoDeploymentTarget",
                                         comment: "Rule Entry for %1$@ has no DeploymentTarget set. Defaulting to iOS 9.",
                                         values: ruleEntry.label.value)
        }

        let indexerData = IndexerData(indexerNameInfo: [IndexerData.NameInfoToken(ruleEntry: ruleEntry)],
                                      dependencies: ruleEntry.dependencies,
                                      resolvedDependencies: Set(resolvedDependecies),
                                      preprocessorDefines: localPreprocessorDefines,
                                      otherCFlags: otherCFlags as! [String],
                                      otherSwiftFlags: otherSwiftFlags as! [String],
                                      includes: resolvedIncludes,
                                      frameworkSearchPaths: frameworkSearchPaths.array as! [String],
                                      swiftIncludePaths: swiftIncludePaths.array as! [String],
                                      deploymentTarget: deploymentTarget,
                                      buildPhase: buildPhase,
                                      pchFile: pchFile,
                                      bridgingHeader: bridgingHeader,
                                      enableModules: enableModules)
        let isSwiftRule = ruleEntry.attributes[.has_swift_info] as? Bool ?? false
        if (isSwiftRule) {
          frameworkIndexers[indexerData.indexerName] = indexerData
        } else {
          staticIndexers[indexerData.indexerName] = indexerData
        }
      }

      return (frameworkSearchPaths)
    }

    generateIndexerTargetGraphForRuleEntry(ruleEntry)
  }

  @discardableResult
  func generateIndexerTargets() -> [String: PBXTarget] {
    mergeRegisteredIndexers()

    func generateIndexer(_ name: String,
                         indexerType: PBXTarget.ProductType,
                         data: IndexerData) {
      let indexingTarget = project.createNativeTarget(name,
                                                      deploymentTarget: nil,
                                                      targetType: indexerType,
                                                      isIndexerTarget: true)
      indexingTarget.buildPhases.append(data.buildPhase)
      addConfigsForIndexingTarget(indexingTarget, data: data)

      for name in data.supportedIndexingTargets {
        indexerTargetByName[name] = indexingTarget
      }
    }

    for (name, data) in staticIndexers {
      generateIndexer(name, indexerType: PBXTarget.ProductType.StaticLibrary, data: data)
    }

    for (name, data) in frameworkIndexers {
      generateIndexer(name, indexerType: PBXTarget.ProductType.Framework, data: data)
    }

    func linkDependencies(_ dataMap: [String: IndexerData]) {
      for (name, data) in dataMap {
        guard let indexerTarget = indexerTargetByName[name] else {
          localizedMessageLogger.infoMessage("Unexpectedly failed to resolve indexer \(name)")
          continue
        }

        for depName in data.indexerNamesForResolvedDependencies {
          guard let indexerDependency = indexerTargetByName[depName], indexerDependency !== indexerTarget else {
            continue
          }

          indexerTarget.createDependencyOn(indexerDependency,
                                           proxyType: PBXContainerItemProxy.ProxyType.targetReference,
                                           inProject: project)
        }
      }
    }

    linkDependencies(staticIndexers)
    linkDependencies(frameworkIndexers)

    return indexerTargetByName
  }

  func generateBazelCleanTarget(_ scriptPath: String, workingDirectory: String = "",
                                startupOptions: [String] = []) {
    assert(bazelCleanScriptTarget == nil, "generateBazelCleanTarget may only be called once")

    let allArgs = [bazelPath, bazelBinPath] + startupOptions
    let buildArgs = allArgs.map { "\"\($0)\""}.joined(separator: " ")

    bazelCleanScriptTarget = project.createLegacyTarget(PBXTargetGenerator.BazelCleanTarget,
                                                        deploymentTarget: nil,
                                                        buildToolPath: "\(scriptPath)",
                                                        buildArguments: buildArgs,
                                                        buildWorkingDirectory: workingDirectory)

    for target: PBXTarget in project.allTargets {
      if target === bazelCleanScriptTarget {
        continue
      }

      target.createDependencyOn(bazelCleanScriptTarget!,
                                proxyType: PBXContainerItemProxy.ProxyType.targetReference,
                                inProject: project,
                                first: true)
    }
  }

  func generateTopLevelBuildConfigurations(_ buildSettingOverrides: [String: String] = [:]) {
    var buildSettings = options.commonBuildSettings()

    for (key, value) in buildSettingOverrides {
      buildSettings[key] = value
    }

    buildSettings["ONLY_ACTIVE_ARCH"] = "YES"
    // Fixes an Xcode "Upgrade to recommended settings" warning. Technically the warning only
    // requires this to be added to the Debug build configuration but as code is never compiled
    // anyway it doesn't hurt anything to set it on all configs.
    buildSettings["ENABLE_TESTABILITY"] = "YES"

    // Bazel sources are more or less ARC by default (the user has to use the special non_arc_srcs
    // attribute for non-ARC) so the project is set to reflect that and per-file flags are used to
    // override the default.
    buildSettings["CLANG_ENABLE_OBJC_ARC"] = "YES"

    // Bazel takes care of signing the generated applications, so Xcode's signing must be disabled.
    buildSettings["CODE_SIGNING_REQUIRED"] = "NO"
    buildSettings["CODE_SIGN_IDENTITY"] = ""

    // Explicitly setting the FRAMEWORK_SEARCH_PATHS will allow Xcode to resolve references to the
    // XCTest framework when performing Live issues analysis.
    buildSettings["FRAMEWORK_SEARCH_PATHS"] = "$(PLATFORM_DIR)/Developer/Library/Frameworks";

    // Prevent Xcode from replacing the Swift StdLib dylibs that Bazel already packaged.
    buildSettings["DONT_RUN_SWIFT_STDLIB_TOOL"] = "YES"

    var sourceDirectory = PBXTargetGenerator.workingDirectoryForPBXGroup(project.mainGroup)
    if sourceDirectory.isEmpty {
      sourceDirectory = "$(SRCROOT)"
    }

    // A variable pointing to the true root is provided for scripts that may need it.
    buildSettings["\(PBXTargetGenerator.WorkspaceRootVarName)"] = sourceDirectory

    // Bazel generates a symlink to a directory that collects all of the data needed for this
    // workspace. While this is often identical to the workspace, it sometimes collects other paths
    // and is the better option for most Xcode project path references.
    // This directory is symlinked to `tulsi-workspace` during builds.
    // The symlink is located inside of the project package as opposed to relative to the workspace
    // so that it is using the same local file system as the project to maximize performance.
    // In some cases where the workspace was on a remote volume, jumping through the symlink on the
    // remote volume that pointed back to local disk was causing performance issues.
    buildSettings["\(PBXTargetGenerator.BazelWorkspaceSymlinkVarName)"] =
        "$(PROJECT_FILE_PATH)/.tulsi/\(PBXTargetGenerator.TulsiWorkspacePath)"

    buildSettings["TULSI_VERSION"] = tulsiVersion

    // Set default Python STDOUT encoding of scripts run by Xcode (such as bazel_build.py) to UTF-8.
    // Otherwise, this would be the Python 2 default of ASCII, causing various encoding errors when
    // handling UTF-8 output from Bazel BEP in bazel_build.py.
    buildSettings["PYTHONIOENCODING"] = "utf8"

    let searchPaths = ["$(\(PBXTargetGenerator.BazelWorkspaceSymlinkVarName))",
                       "$(\(PBXTargetGenerator.WorkspaceRootVarName))/\(bazelBinPath)",
                       "$(\(PBXTargetGenerator.WorkspaceRootVarName))/\(bazelGenfilesPath)",
                       "$(\(PBXTargetGenerator.BazelWorkspaceSymlinkVarName))/\(PBXTargetGenerator.tulsiIncludesPath)"
    ]
    // Ideally this would use USER_HEADER_SEARCH_PATHS but some code generation tools (e.g.,
    // protocol buffers) make use of system-style includes.
    buildSettings["HEADER_SEARCH_PATHS"] = searchPaths.joined(separator: " ")

    createBuildConfigurationsForList(project.buildConfigurationList, buildSettings: buildSettings)
    addTestRunnerBuildConfigurationToBuildConfigurationList(project.buildConfigurationList)
  }

  /// Generates build targets for the given rule entries.
  func generateBuildTargetsForRuleEntries(
    _ ruleEntries: Set<RuleEntry>,
    ruleEntryMap: RuleEntryMap
  ) throws -> [BuildLabel: PBXNativeTarget] {
    let namedRuleEntries = generateUniqueNamesForRuleEntries(ruleEntries)

    let progressNotifier = ProgressNotifier(name: GeneratingBuildTargets,
                                            maxValue: namedRuleEntries.count)

    var testTargetLinkages = [(PBXNativeTarget, BuildLabel?, RuleEntry)]()
    var watchAppTargets = [String: (PBXNativeTarget, RuleEntry)]()
    var watchExtensionsByEntry = [RuleEntry: PBXNativeTarget]()
    var targetsByLabel = [BuildLabel: PBXNativeTarget]()

    for (name, entry) in namedRuleEntries {
      progressNotifier.incrementValue()
      let target = try createBuildTargetForRuleEntry(entry,
                                                     named: name,
                                                     ruleEntryMap: ruleEntryMap)
      targetsByLabel[entry.label] = target

      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))
      } else if entry.pbxTargetType == .UnitTest {
        // If there is no host and it's a unit test, assume it doesn't need one, i.e. it's a
        // library based test.
        testTargetLinkages.append((target, nil, entry))
      }

      switch entry.pbxTargetType {
      case .Watch2App?:
        watchAppTargets[name] = (target, entry)
      case .Watch2Extension?:
        watchExtensionsByEntry[entry] = target
      default:
        break
      }
    }

    // The watch app target must have an explicit dependency on the watch extension target.
    for (_, (watchAppTarget, watchRuleEntry)) in watchAppTargets {
      for ext in watchRuleEntry.extensions {
        if let extEntry = ruleEntryMap.ruleEntry(buildLabel: ext, depender: watchRuleEntry),
            extEntry.pbxTargetType == .Watch2Extension {
          if let watchExtensionTarget = watchExtensionsByEntry[extEntry] {
            watchAppTarget.createDependencyOn(watchExtensionTarget, proxyType: .targetReference, inProject: project)
          } else {
            localizedMessageLogger.warning("FindingWatchExtensionFailed",
                                           comment: "Message to show when the watchOS app extension %1$@ could not be found and the resulting project will not be able to launch the watch app.",
                                           values: extEntry.label.value)
          }
        }
      }
    }

    for (testTarget, testHostLabel, entry) in testTargetLinkages {
      let testHostTarget: PBXNativeTarget?
      if let hostTargetLabel = testHostLabel {
        testHostTarget = targetsByLabel[hostTargetLabel]
        if testHostTarget == nil {
          // If the user did not choose to include the host target it won't be available so the
          // linkage can be skipped. We will still force the generation of this test host target to
          // avoid issues when running tests as bundle targets in Xcode.
          localizedMessageLogger.warning("MissingTestHost",
                                         comment: "Warning to show when a user has selected an XCTest but not its host application.",
                                         values: entry.label.value, hostTargetLabel.value)
          continue
        }
      } else {
        testHostTarget = nil
      }
      updateTestTarget(testTarget,
                       withLinkageToHostTarget: testHostTarget,
                       ruleEntry: entry,
                       ruleEntryMap: ruleEntryMap)
    }
    return targetsByLabel
  }

  // MARK: - Private methods

  /// Generates a filter function that may be used to verify that a path string is allowed by the
  /// given set of pathFilters.
  private func pathFilterFunc(_ pathFilters: Set<String>) -> (String) -> Bool {
    let recursiveFilters = Set<String>(pathFilters.filter({ $0.hasSuffix("/...") }).map() {
      let index = $0.index($0.endIndex, offsetBy: -3)
      return String($0[..<index])
    })

    func includePath(_ path: String) -> Bool {
      let dir = (path as NSString).deletingLastPathComponent
      if pathFilters.contains(dir) { return true }
      let terminatedDir = dir + "/"
      for filter in recursiveFilters {
        if terminatedDir.hasPrefix(filter) { return true }
      }
      return false
    }

    return includePath
  }

  /// Attempts to reduce the number of indexers by merging any that have identical settings.
  private func mergeRegisteredIndexers() {

    func mergeIndexers<T : Sequence>(_ indexers: T) -> [String: IndexerData] where T.Iterator.Element == IndexerData {
      var mergedIndexers = [String: IndexerData]()
      var indexers = Array(indexers).sorted { $0.indexerName < $1.indexerName }

      while !indexers.isEmpty {
        var remaining = [IndexerData]()
        var d1 = indexers.popLast()!
        for d2 in indexers {
          if d1.canMergeWith(d2) {
            d1 = d1.merging(d2)
          } else {
            remaining.append(d2)
          }
        }

        mergedIndexers[d1.indexerName] = d1
        indexers = remaining
      }

      return mergedIndexers
    }

    staticIndexers = mergeIndexers(staticIndexers.values)
    frameworkIndexers = mergeIndexers(frameworkIndexers.values)
  }

  private func generateFileReferencesForFileInfos(_ infos: [BazelFileInfo]) -> [PBXFileReference] {
    guard !infos.isEmpty else { return [] }
    var generatedFilePaths = [String]()
    var sourceFilePaths = [String]()
    for info in infos {
      switch info.targetType {
        case .generatedFile:
          generatedFilePaths.append(info.fullPath)
        case .sourceFile:
          sourceFilePaths.append(info.fullPath)
      }
    }

    // Add the source paths directly and the generated paths with explicitFileType set.
    var (_, fileReferences) = project.getOrCreateGroupsAndFileReferencesForPaths(sourceFilePaths)
    let (_, generatedFileReferences) = project.getOrCreateGroupsAndFileReferencesForPaths(generatedFilePaths)
    generatedFileReferences.forEach() { $0.isInputFile = false }

    fileReferences.append(contentsOf: generatedFileReferences)
    return fileReferences
  }

  /// Generates file references for the given infos, and returns a settings dictionary to be passed
  /// to createBuildPhaseForReferences:withPerFileSettings:.
  private func generateFileReferencesAndSettingsForNonARCFileInfos(_ infos: [BazelFileInfo]) -> ([PBXFileReference], [PBXFileReference: [String: String]]) {
    let nonARCFileReferences = generateFileReferencesForFileInfos(infos)
    var settings = [PBXFileReference: [String: String]]()
    let disableARCSetting = ["COMPILER_FLAGS": "-fno-objc-arc"]
    nonARCFileReferences.forEach() {
      settings[$0] = disableARCSetting
    }
    return (nonARCFileReferences, settings)
  }

  /// Find the longest common non-empty strict prefix for the given strings if there is one.
  private func longestCommonPrefix(_ strings: Set<String>, separator: Character) -> String {
    // Longest common prefix for 0 or 1 string(s) doesn't make sense.
    guard strings.count >= 2, var shortestString = strings.first else { return "" }
    for str in strings {
      guard str.count < shortestString.count else { continue }
      shortestString = str
    }

    guard !shortestString.isEmpty else { return "" }

    // Drop the last so we can only get a strict prefix.
    var components = shortestString.split(separator: separator).dropLast()
    var potentialPrefix = "\(components.joined(separator: "\(separator)"))\(separator)"

    for str in strings {
      while !components.isEmpty && !str.hasPrefix(potentialPrefix) {
        components = components.dropLast()
        potentialPrefix = "\(components.joined(separator: "\(separator)"))\(separator)"
      }
    }
    return potentialPrefix
  }

  /// Name the given `ruleEntries` using the `namer` function.
  ///
  /// `ruleEntries` must be mutually exclusive with the values in `named`. Intended use case:
  /// call this first with an initial set and `namer`, and then subsequent calls should use the
  /// results of the previous call (unnamed entries) with a different `namer`.
  ///
  /// Only unique names will be inserted into the `named` dictionary. If when naming a
  /// `RuleEntry`, the name is already in the `named` dictionary, the previously named
  /// `RuleEntry` will still be valid.
  ///
  /// Returns a `Set<RuleEntry>` representing the entries which still need to be named.
  private func uniqueNames(for ruleEntries: Set<RuleEntry>,
                           named: inout [String: RuleEntry],
                           namer: (_ ruleEntry: RuleEntry) -> String?
  ) -> Set<RuleEntry> {
    var unnamed = Set<RuleEntry>()

    // Group the entries by name.
    var ruleEntriesByName = [String: [RuleEntry]]()
    for entry in ruleEntries {
      guard let name = namer(entry) else {
        unnamed.insert(entry)
        continue
      }
      ruleEntriesByName[name, default: []].append(entry)
    }

    for (name, entries) in ruleEntriesByName {
      // Name already used or not unique.
      guard entries.count == 1 && named.index(forKey: name) == nil else {
        unnamed.formUnion(entries)
        continue
      }
      named[name] = entries.first!
    }
    return unnamed
  }

  /// Generate unique names for the given rule entries, using the bundle name when it is
  /// unique. Otherwise, falls back to a name based on the target label.
  private func generateUniqueNamesForRuleEntries(_ ruleEntries: Set<RuleEntry>) -> [String: RuleEntry] {
    var named = [String: RuleEntry]()
    // Try to name using the bundle names first, then the target name.
    var unnamed = self.uniqueNames(for: ruleEntries, named: &named) { $0.bundleName }
    unnamed = self.uniqueNames(for: unnamed, named: &named) {
      $0.label.targetName
    }

    // Continue only if we need to de-duplicate.
    guard !unnamed.isEmpty else {
      return named
    }

    // Special handling for the remaining unnamed entries - use their full target label.
    let conflictingFullNames = Set(unnamed.map {
      $0.label.asFullPBXTargetName!
    })

    // Try to strip out a common prefix if we can find one.
    let commonPrefix = self.longestCommonPrefix(conflictingFullNames, separator: "-")

    guard !commonPrefix.isEmpty else {
      for entry in unnamed {
        let fullName = entry.label.asFullPBXTargetName!
        named[fullName] = entry
      }
      return named
    }

    // Found a common prefix, we can strip it as long as we don't cause a new duplicate.
    let charsToDrop = commonPrefix.count
    for entry in unnamed {
      let fullName = entry.label.asFullPBXTargetName!
      let shortenedFullName = String(fullName.dropFirst(charsToDrop))
      guard !shortenedFullName.isEmpty && named.index(forKey: shortenedFullName) == nil else {
        named[fullName] = entry
        continue
      }
      named[shortenedFullName] = entry
    }

    return named
  }

  /// Adds the given file targets to a versioned group.
  private func createReferencesForVersionedFileTargets(_ fileInfos: [BazelFileInfo]) -> [XCVersionGroup] {
    var groups = [String: XCVersionGroup]()

    for info in fileInfos {
      let path = info.fullPath as NSString
      let versionedGroupPath = path.deletingLastPathComponent
      let type = info.subPath.pbPathUTI ?? ""
      let versionedGroup = project.getOrCreateVersionGroupForPath(versionedGroupPath,
                                                                  versionGroupType: type)
      if groups[versionedGroupPath] == nil {
        groups[versionedGroupPath] = versionedGroup
      }
      let ref = versionedGroup.getOrCreateFileReferenceBySourceTree(.Group,
                                                                    path: path as String)
      ref.isInputFile = info.targetType == .sourceFile
    }

    for (sourcePath, group) in groups {
      setCurrentVersionForXCVersionGroup(group, atPath: sourcePath)
    }
    return Array(groups.values)
  }

  // Attempt to read the .xccurrentversion plists in the xcdatamodeld's and sync up the
  // currentVersion in the XCVersionGroup instances. Failure to specify the currentVersion will
  // result in Xcode picking an arbitrary version.
  private func setCurrentVersionForXCVersionGroup(_ group: XCVersionGroup,
                                                  atPath sourcePath: String) {

    let versionedBundleURL = workspaceRootURL.appendingPathComponent(sourcePath,
                                                                     isDirectory: true)
    let currentVersionPlistURL = versionedBundleURL.appendingPathComponent(".xccurrentversion",
                                                                           isDirectory: false)
    let path = currentVersionPlistURL.path
    guard let data = FileManager.default.contents(atPath: path) else {
      self.localizedMessageLogger.warning("LoadingXCCurrentVersionFailed",
                                          comment: "Message to show when loading a .xccurrentversion file fails.",
                                          values: group.name, "Version file at '\(path)' could not be read")
      return
    }

    do {
      let plist = try PropertyListSerialization.propertyList(from: data,
                                                                       options: PropertyListSerialization.MutabilityOptions(),
                                                                       format: nil) as! [String: AnyObject]
      if let currentVersion = plist["_XCCurrentVersionName"] as? String {
        if !group.setCurrentVersionByName(currentVersion) {
          self.localizedMessageLogger.warning("LoadingXCCurrentVersionFailed",
                                              comment: "Message to show when loading a .xccurrentversion file fails.",
                                              values: group.name, "Version '\(currentVersion)' specified by file at '\(path)' was not found")
        }
      }
    } catch let e as NSError {
      self.localizedMessageLogger.warning("LoadingXCCurrentVersionFailed",
                                          comment: "Message to show when loading a .xccurrentversion file fails.",
                                          values: group.name, "Version file at '\(path)' is invalid: \(e)")
    } catch {
      self.localizedMessageLogger.warning("LoadingXCCurrentVersionFailed",
                                          comment: "Message to show when loading a .xccurrentversion file fails.",
                                          values: group.name, "Version file at '\(path)' is invalid.")
    }
  }

  // Adds XCBuildConfigurations to the given indexer PBXTarget.
  // Note that preprocessorDefines may or may not contain values with spaces. If it does contain
  // spaces, the key will be escaped (e.g. -Dfoo bar becomes -D"foo bar").
  private func addConfigsForIndexingTarget(_ target: PBXTarget, data: IndexerData) {

    var buildSettings = options.buildSettingsForTarget(target.name)
    buildSettings["PRODUCT_NAME"] = target.productName!

    if let pchFile = data.pchFile {
      buildSettings["GCC_PREFIX_HEADER"] = PBXTargetGenerator.projectRefForBazelFileInfo(pchFile)
    }

    var allOtherCFlags = data.otherCFlags.filter { !$0.hasPrefix("-W") }
    // Escape the spaces in the defines by transforming -Dfoo bar into -D"foo bar".
    if !data.preprocessorDefines.isEmpty {
      allOtherCFlags.append(contentsOf: data.preprocessorDefines.sorted().map { define in
        // Need to quote all defines with spaces that are not yet quoted.
        if define.rangeOfCharacter(from: .whitespaces) != nil &&
            !((define.hasPrefix("\"") && define.hasSuffix("\"")) ||
              (define.hasPrefix("'") && define.hasSuffix("'"))) {
          return "-D\"\(define)\""
        }
        return "-D\(define)"
      })
    }

    if !allOtherCFlags.isEmpty {
      buildSettings["OTHER_CFLAGS"] = allOtherCFlags.joined(separator: " ")
    }

    if let bridgingHeader = data.bridgingHeader {
      buildSettings["SWIFT_OBJC_BRIDGING_HEADER"] = PBXTargetGenerator.projectRefForBazelFileInfo(bridgingHeader)
    }

    if data.enableModules {
      buildSettings["CLANG_ENABLE_MODULES"] = "YES"
    }

    if !data.includes.isEmpty {
      let includes = data.includes.joined(separator: " ")
      buildSettings["HEADER_SEARCH_PATHS"] = "$(inherited) \(includes) "
    }

    if !data.frameworkSearchPaths.isEmpty {
      buildSettings["FRAMEWORK_SEARCH_PATHS"] = "$(inherited) " + data.frameworkSearchPaths.joined(separator: " ")
    }

    if !data.swiftIncludePaths.isEmpty {
      let paths = data.swiftIncludePaths.joined(separator: " ")
      buildSettings["SWIFT_INCLUDE_PATHS"] = "$(inherited) \(paths)"
    }

    if !data.otherSwiftFlags.isEmpty {
      buildSettings["OTHER_SWIFT_FLAGS"] = "$(inherited) " + data.otherSwiftFlags.joined(separator: " ")
    }

    // Set USER_HEADER_SEARCH_PATHS for non-Swift (meaning static library) indexer targets if the
    // improved include/import setting is enabled.
    if self.improvedImportAutocompletionFix, let nativeTarget = target as? PBXNativeTarget,
       nativeTarget.productType == .StaticLibrary {
      buildSettings["USER_HEADER_SEARCH_PATHS"] = "$(\(PBXTargetGenerator.WorkspaceRootVarName))"
    }

    // Default the SDKROOT to the proper device SDK.
    // Previously, we would force the indexer targets to the x86_64 simulator. This caused indexing
    // to fail when building Swift for device, as the arm Swift modules would be discovered via
    // tulsi-includes but Xcode would only index for x86_64. Note that just setting this is not
    // enough; research has shown that Xcode needs a scheme for these indexer targets in order to
    // use the proper ARCH for indexing, so we also generate an `_idx_Scheme` containing all
    // indexer targets as build targets.
    let deploymentTarget = data.deploymentTarget
    let platform = deploymentTarget.platform
    buildSettings["SDKROOT"] = platform.deviceSDK
    buildSettings[platform.buildSettingsDeploymentTarget] = deploymentTarget.osVersion

    createBuildConfigurationsForList(target.buildConfigurationList,
                                     buildSettings: buildSettings,
                                     indexerSettingsOnly: true)
  }

  /// Updates the build settings and optionally adds a "Compile sources" phase for the given test
  /// bundle target.
  private func updateTestTarget(_ target: PBXNativeTarget,
                                withLinkageToHostTarget hostTarget: PBXNativeTarget?,
                                ruleEntry: RuleEntry,
                                ruleEntryMap: RuleEntryMap) {
    // If the test target has a test host, check that it was included in the Tulsi configuration.
    if let hostTarget = hostTarget {
      project.linkTestTarget(target, toHostTarget: hostTarget)
    }
    updateTestTargetIndexer(target, ruleEntry: ruleEntry, hostTarget: hostTarget, ruleEntryMap: ruleEntryMap)
    updateTestTargetBuildPhases(target, ruleEntry: ruleEntry, ruleEntryMap: ruleEntryMap)
  }

  /// Updates the test target indexer with test specific values.
  private func updateTestTargetIndexer(_ target: PBXNativeTarget,
                                       ruleEntry: RuleEntry,
                                       hostTarget: PBXNativeTarget?,
                                       ruleEntryMap: RuleEntryMap) {
    let testSettings = targetTestSettings(target, hostTarget: hostTarget, ruleEntry: ruleEntry, ruleEntryMap: ruleEntryMap)

    // Inherit the resolved values from the indexer.
    let deploymentTarget = ruleEntry.deploymentTarget ?? PBXTargetGenerator.defaultDeploymentTarget()
    let deploymentTargetLabel = IndexerData.deploymentTargetLabel(deploymentTarget)
    let indexerName = PBXTargetGenerator.indexerNameForTargetName(ruleEntry.label.targetName!,
                                                                  hash: ruleEntry.label.hashValue,
                                                                  suffix: deploymentTargetLabel)
    let indexerTarget = indexerTargetByName[indexerName]
    updateMissingBuildConfigurationsForList(target.buildConfigurationList,
                                            withBuildSettings: testSettings,
                                            inheritingFromConfigurationList: indexerTarget?.buildConfigurationList,
                                            suppressingBuildSettings: ["ARCHS", "VALID_ARCHS"])
  }

  private func updateTestTargetBuildPhases(_ target: PBXNativeTarget,
                                           ruleEntry: RuleEntry,
                                           ruleEntryMap: RuleEntryMap) {
    let testSourceFileInfos = ruleEntry.sourceFiles
    let testNonArcSourceFileInfos = ruleEntry.nonARCSourceFiles
    let containsSwift = ruleEntry.attributes[.has_swift_dependency] as? Bool ?? false

    // For the Swift dummy files phase to work, it has to be placed before the Compile Sources build
    // phase.
    if containsSwift {
      let testBuildPhase = createGenerateSwiftDummyFilesTestBuildPhase()
      target.buildPhases.append(testBuildPhase)
    }
    if !testSourceFileInfos.isEmpty || !testNonArcSourceFileInfos.isEmpty {
      // Create dummy dependency files for non-Swift code as Xcode expects Clang to generate them.
      let allSources = testSourceFileInfos + testNonArcSourceFileInfos
      let nonSwiftSources = allSources.filter { !$0.subPath.hasSuffix(".swift") }
      if !nonSwiftSources.isEmpty {
        let testBuildPhase = createGenerateDummyDependencyFilesTestBuildPhase(nonSwiftSources)
        target.buildPhases.append(testBuildPhase)
      }
      var fileReferences = generateFileReferencesForFileInfos(testSourceFileInfos)
      let (nonARCFiles, nonARCSettings) =
          generateFileReferencesAndSettingsForNonARCFileInfos(testNonArcSourceFileInfos)
      fileReferences.append(contentsOf: nonARCFiles)
      let buildPhase = createBuildPhaseForReferences(fileReferences,
                                                     withPerFileSettings: nonARCSettings)
      target.buildPhases.append(buildPhase)
    }
  }

  /// Adds includes paths from the RuleEntry to the given NSSet.
  private func addIncludes(_ ruleEntry: RuleEntry,
                           toSet includes: NSMutableOrderedSet) {
    if let includePaths = ruleEntry.includePaths {
      let rootedPaths: [String] = includePaths.map() { (path, recursive) in
        // Any paths of the tulsi-includes form will only be in the bazel workspace symlink since
        // they refer to generated files from a build.
        // Otherwise we assume the file exists in the workspace.
        let prefixVar = path.hasPrefix(PBXTargetGenerator.tulsiIncludesPath)
            ? PBXTargetGenerator.BazelWorkspaceSymlinkVarName
            : PBXTargetGenerator.WorkspaceRootVarName
        let rootedPath = "$(\(prefixVar))/\(path)"
        if recursive {
          return "\(rootedPath)/**"
        }
        return rootedPath
      }
      includes.addObjects(from: rootedPaths)
    }

    // TODO(rdar://36107040): Once Xcode supports indexing with multiple -fmodule-map-file
    // arguments, remove this in favor of "-Xcc -fmodule-map-file=<>" below.
    //
    // Include the ObjC modules in HEADER_SEARCH_PATHS in order to fix issues regarding
    // explicitly passing them via -fmodule-map-file: Xcode 8 seems to ignore the
    // -fmodule-map-file flag when using SourceKit for CMD+click and Xcode 9 seems to only
    // pass in the last -fmodule-map-file flag given.
    for moduleMap in ruleEntry.objCModuleMaps {
      let fullPath = (moduleMap.fullPath as NSString).deletingLastPathComponent
      includes.add("$(\(PBXTargetGenerator.BazelWorkspaceSymlinkVarName))/\(fullPath)")
    }
  }

  /// Adds swift include paths from the RuleEntry to the given NSSet.
  private func addSwiftIncludes(_ ruleEntry: RuleEntry,
                                toSet swiftIncludes: NSMutableOrderedSet) {
    for module in ruleEntry.swiftTransitiveModules {
      let fullPath = module.fullPath as NSString
      let includePath = fullPath.deletingLastPathComponent
      swiftIncludes.add("$(\(PBXTargetGenerator.BazelWorkspaceSymlinkVarName))/\(includePath)")
    }
  }

  /// Returns other swift compiler flags for the given target based on the RuleEntry.
  private func addOtherSwiftFlags(_ ruleEntry: RuleEntry, toArray swiftFlags: NSMutableArray) {
    // Load module maps explicitly instead of letting Clang discover them on search paths. This
    // is needed to avoid a case where Clang may load the same header both in modular and
    // non-modular contexts, leading to duplicate definitions in the same file.
    // See llvm.org/bugs/show_bug.cgi?id=19501
    swiftFlags.addObjects(from: ruleEntry.objCModuleMaps.map() {
      "-Xcc -fmodule-map-file=$(\(PBXTargetGenerator.BazelWorkspaceSymlinkVarName))/\($0.fullPath)"
    })

    if let swiftDefines = ruleEntry.swiftDefines {
      for flag in swiftDefines {
        swiftFlags.add("-D\(flag)")
      }
    }
  }

  /// Reads the RuleEntry's copts and puts the arguments into the correct set.
  private func addLocalSettings(_ ruleEntry: RuleEntry,
                                localDefines: inout Set<String>,
                                localIncludes: NSMutableOrderedSet,
                                otherCFlags: NSMutableArray,
                                swiftIncludePaths: NSMutableOrderedSet,
                                otherSwiftFlags: NSMutableArray) {
    if let swiftc_opts = ruleEntry.attributes[.swiftc_opts] as? [String], !swiftc_opts.isEmpty {
      for opt in swiftc_opts {
        if opt.hasPrefix("-I") {
          let index = opt.index(opt.startIndex, offsetBy: 2)
          var path = String(opt[index...])
          if !path.hasPrefix("/") {
            path = "$(\(PBXTargetGenerator.BazelWorkspaceSymlinkVarName))/\(path)"
          }
          swiftIncludePaths.add(path)
        } else {
          otherSwiftFlags.add(opt)
        }
      }
    }
    guard let copts = ruleEntry.attributes[.copts] as? [String], !copts.isEmpty else {
      return
    }
    for opt in copts {
      if opt.hasPrefix("-D") {
        let index = opt.index(opt.startIndex, offsetBy: 2)
        localDefines.insert(String(opt[index...]))
      } else if opt.hasPrefix("-I") {
        let index = opt.index(opt.startIndex, offsetBy: 2)
        var path = String(opt[index...])
        if !path.hasPrefix("/") {
          path = "$(\(PBXTargetGenerator.BazelWorkspaceSymlinkVarName))/\(path)"
        }
        localIncludes.add(path)
      } else {
        otherCFlags.add(opt)
      }
    }
  }

  /// Returns test specific settings for test targets.
  private func targetTestSettings(_ target: PBXNativeTarget,
                                  hostTarget: PBXNativeTarget?,
                                  ruleEntry: RuleEntry,
                                  ruleEntryMap: RuleEntryMap) -> [String: String] {
    var testSettings = ["TULSI_TEST_RUNNER_ONLY": "YES"]
    // Attempt to update the build configs for the target to include BUNDLE_LOADER and TEST_HOST
    // values, linking the test target to its host.
    if let hostTargetPath = hostTarget?.productReference?.path,
      let hostTargetProductName = hostTarget?.productName,
      let deploymentTarget = target.deploymentTarget {

      if target.productType == .UIUnitTest {
        testSettings["TEST_TARGET_NAME"] = hostTargetProductName
      } else if let testHostPath = deploymentTarget.platform.testHostPath(hostTargetPath: hostTargetPath,
                                                                          hostTargetProductName: hostTargetProductName) {
        testSettings["BUNDLE_LOADER"] = "$(TEST_HOST)"
        testSettings["TEST_HOST"] = testHostPath
      }
    }

    let includes = NSMutableOrderedSet()

    // We don't use the defines at the moment but the function will add them anyway. We could try
    // to use the defines but we'd have to do so on a per-file basis as this Test target can contain
    // files from multiple targets.
    var defines = Set<String>()
    let swiftIncludePaths = NSMutableOrderedSet()
    let otherSwiftFlags = NSMutableArray()

    addIncludes(ruleEntry, toSet: includes)
    addLocalSettings(ruleEntry, localDefines: &defines, localIncludes: includes,
                     otherCFlags: NSMutableArray(), swiftIncludePaths: NSMutableOrderedSet(),
                     otherSwiftFlags: NSMutableArray())
    addSwiftIncludes(ruleEntry, toSet: swiftIncludePaths)
    addOtherSwiftFlags(ruleEntry, toArray: otherSwiftFlags)

    let includesArr = includes.array as! [String]
    if !includesArr.isEmpty {
      testSettings["HEADER_SEARCH_PATHS"] = "$(inherited) " + includesArr.joined(separator: " ")
    }

    if let swiftIncludes = swiftIncludePaths.array as? [String], !swiftIncludes.isEmpty {
      testSettings["SWIFT_INCLUDE_PATHS"] = "$(inherited) " + swiftIncludes.joined(separator: " ")
    }

    if let otherSwiftFlagsArr = otherSwiftFlags as? [String], !otherSwiftFlagsArr.isEmpty {
      testSettings["OTHER_SWIFT_FLAGS"] = "$(inherited) " + otherSwiftFlagsArr.joined(separator: " ")
    }

    if let moduleName = ruleEntry.moduleName {
      testSettings["PRODUCT_MODULE_NAME"] = moduleName
    }

    return testSettings
  }

  // Adds a dummy build configuration to the given list based off of the Debug config that is
  // used to effectively disable compilation when running XCTests by converting each compile call
  // into a "clang --version" invocation.
  private func addTestRunnerBuildConfigurationToBuildConfigurationList(_ list: XCConfigurationList) {

    func createTestConfigNamed(_ testConfigName: String,
                               forBaseConfigNamed configurationName: String) {
      let baseConfig = list.getOrCreateBuildConfiguration(configurationName)
      let config = list.getOrCreateBuildConfiguration(testConfigName)

      var runTestTargetBuildSettings = baseConfig.buildSettings
      // Prevent compilation invocations from actually compiling ObjC, C and Swift files.
      runTestTargetBuildSettings["OTHER_CFLAGS"] = "--version"
      runTestTargetBuildSettings["OTHER_SWIFT_FLAGS"] = "--version"
      // Prevents linker invocations from attempting to use the .o files which were never generated
      // due to compilation being turned into nop's.
      runTestTargetBuildSettings["OTHER_LDFLAGS"] = "--version"

      // Force the output of the -emit-objc-header flag to a known value. This should be kept in
      // sync with the RunScript build phase created in createGenerateSwiftDummyFilesTestBuildPhase.
      runTestTargetBuildSettings["SWIFT_OBJC_INTERFACE_HEADER_NAME"] = "$(PRODUCT_NAME).h"

      // Disable the generation of ObjC header files from Swift for test targets.
      runTestTargetBuildSettings["SWIFT_INSTALL_OBJC_HEADER"] = "NO"

      // Prevent Xcode from attempting to create a fat binary with lipo from artifacts that were
      // never generated by the linker nop's.
      runTestTargetBuildSettings["ONLY_ACTIVE_ARCH"] = "YES"

      // Wipe out settings that are not useful for test runners
      // These do nothing and can cause issues due to exceeding environment limits:
      runTestTargetBuildSettings["FRAMEWORK_SEARCH_PATHS"] = ""
      runTestTargetBuildSettings["HEADER_SEARCH_PATHS"] = ""

      config.buildSettings = runTestTargetBuildSettings
    }

    for (testConfigName, configName) in PBXTargetGenerator.testRunnerEnabledBuildConfigNames {
      createTestConfigNamed(testConfigName, forBaseConfigNamed: configName)
    }
  }

  private func createBuildConfigurationsForList(_ buildConfigurationList: XCConfigurationList,
                                                buildSettings: Dictionary<String, String>,
                                                indexerSettingsOnly: Bool = false) {
    func addPreprocessorDefine(_ define: String, toConfig config: XCBuildConfiguration) {
      if let existingDefinitions = config.buildSettings["GCC_PREPROCESSOR_DEFINITIONS"] {
        // NOTE(abaire): Technically this should probably check first to see if "define" has been
        //               set but in the foreseeable usage it's unlikely that this if condition would
        //               ever trigger at all.
        config.buildSettings["GCC_PREPROCESSOR_DEFINITIONS"] = existingDefinitions + " \(define)"
      } else {
        config.buildSettings["GCC_PREPROCESSOR_DEFINITIONS"] = define
      }
    }

    for configName in PBXTargetGenerator.buildConfigNames {
      let config = buildConfigurationList.getOrCreateBuildConfiguration(configName)
      config.buildSettings = buildSettings

      // Insert any defines that are injected by Bazel's ObjcConfiguration.
      if configName == "Debug" {
        addPreprocessorDefine("DEBUG=1", toConfig: config)
      } else if configName == "Release" {
        addPreprocessorDefine("NDEBUG=1", toConfig: config)
      }
    }
  }

  private func updateMissingBuildConfigurationsForList(_ buildConfigurationList: XCConfigurationList,
                                                       withBuildSettings newSettings: Dictionary<String, String>,
                                                       inheritingFromConfigurationList baseConfigurationList: XCConfigurationList? = nil,
                                                       suppressingBuildSettings suppressedKeys: Set<String> = []) {
    func mergeDictionary(_ old: inout [String: String],
                         withContentsOfDictionary new: [String: String]) {
      for (key, value) in new {
        if let _ = old[key] { continue }
        if suppressedKeys.contains(key) { continue }
        old.updateValue(value, forKey: key)
      }
    }

    for configName in PBXTargetGenerator.buildConfigNames {
      let config = buildConfigurationList.getOrCreateBuildConfiguration(configName)
      mergeDictionary(&config.buildSettings, withContentsOfDictionary: newSettings)

      if let baseSettings = baseConfigurationList?.getBuildConfiguration(configName)?.buildSettings {
        mergeDictionary(&config.buildSettings, withContentsOfDictionary: baseSettings)
      }
    }

    for (testRunnerConfigName, configName) in PBXTargetGenerator.testRunnerEnabledBuildConfigNames {
      let config = buildConfigurationList.getOrCreateBuildConfiguration(testRunnerConfigName)
      mergeDictionary(&config.buildSettings, withContentsOfDictionary: newSettings)

      if let baseSettings = baseConfigurationList?.getBuildConfiguration(testRunnerConfigName)?.buildSettings {
        mergeDictionary(&config.buildSettings, withContentsOfDictionary: baseSettings)
      } else if let baseSettings = baseConfigurationList?.getBuildConfiguration(configName)?.buildSettings {
        // Fall back to the base config name if the base configuration list doesn't support a given
        // test runner.
        mergeDictionary(&config.buildSettings, withContentsOfDictionary: baseSettings)
      }
    }
  }

  static func indexerNameForTargetName(_ targetName: String, hash: Int, suffix: String?) -> String {
    let normalizedTargetName: String
    if targetName.count > MaxIndexerNameLength {
      let endIndex = targetName.index(targetName.startIndex, offsetBy: MaxIndexerNameLength - 4)
      normalizedTargetName = String(targetName[..<endIndex]) + "_etc"
    } else {
      normalizedTargetName = targetName
    }
    if let suffix = suffix {
      return String(format: "\(IndexerTargetPrefix)\(normalizedTargetName)_%08X_%@", hash, suffix)
    }
    return String(format: "\(IndexerTargetPrefix)\(normalizedTargetName)_%08X", hash)
  }

  // Creates a PBXSourcesBuildPhase with the given references, optionally applying the given
  // per-file settings to each.
  private func createBuildPhaseForReferences(_ refs: [PBXReference],
                                             withPerFileSettings settings: [PBXFileReference: [String: String]]? = nil) -> PBXSourcesBuildPhase {
    let buildPhase = PBXSourcesBuildPhase()

    for ref in refs {
      if let ref = ref as? PBXFileReference {
        // Do not add header files to the build phase.
        guard let fileUTI = ref.uti, fileUTI.hasPrefix("sourcecode.") && !fileUTI.hasSuffix(".h") else {
          continue
        }
        buildPhase.files.append(PBXBuildFile(fileRef: ref, settings: settings?[ref]))
      } else {
        buildPhase.files.append(PBXBuildFile(fileRef: ref))
      }

    }
    return buildPhase
  }

  /// Creates a PBXNativeTarget for the given rule entry, returning it.
  private func createBuildTargetForRuleEntry(_ entry: RuleEntry,
                                             named name: String,
                                             ruleEntryMap: RuleEntryMap)
      throws -> (PBXNativeTarget) {
    guard let pbxTargetType = entry.pbxTargetType else {
      throw ProjectSerializationError.unsupportedTargetType(entry.type, entry.label.value)
    }
    let target = project.createNativeTarget(name,
                                            deploymentTarget: entry.deploymentTarget,
                                            targetType: pbxTargetType)

    for f in entry.secondaryArtifacts {
      project.createProductReference(f.fullPath)
    }

    var buildSettings = options.buildSettingsForTarget(name)
    buildSettings["TULSI_BUILD_PATH"] = entry.label.packageName!


    buildSettings["PRODUCT_NAME"] = name
    if let bundleID = entry.bundleID {
      buildSettings["PRODUCT_BUNDLE_IDENTIFIER"] = bundleID
    }
    if let sdkRoot = entry.XcodeSDKRoot {
      buildSettings["SDKROOT"] = sdkRoot
    }

    // An invalid launch image is set in order to suppress Xcode's warning about missing default
    // launch images.
    buildSettings["ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME"] = "Stub Launch Image"
    buildSettings["INFOPLIST_FILE"] = stubInfoPlistPaths.stubPlist(entry)

    if let deploymentTarget = entry.deploymentTarget {
      buildSettings[deploymentTarget.platform.buildSettingsDeploymentTarget] = deploymentTarget.osVersion
    }

    // watchOS1 apps require TARGETED_DEVICE_FAMILY to be overridden as they are a specialization of
    // an iOS target rather than a true standalone (like watchOS2 and later).
    if pbxTargetType == .Watch1App {
      buildSettings["TARGETED_DEVICE_FAMILY"] = "4"
      buildSettings["TARGETED_DEVICE_FAMILY[sdk=iphonesimulator*]"] = "1,4"
    }

    // bazel_build.py uses this to determine if it needs to pass the --xcode_version flag, as the
    // flag can have implications for caching even if the user's active Xcode version is the same
    // as the flag.
    if let xcodeVersion = entry.xcodeVersion {
      buildSettings["TULSI_XCODE_VERSION"] = xcodeVersion
    }

    // Disable Xcode's attempts at generating dSYM bundles as it conflicts with the operation of the
    // special test runner build configurations (which have associated sources but don't actually
    // compile anything).
    buildSettings["DEBUG_INFORMATION_FORMAT"] = "dwarf"

    // The following settings are simply passed through the environment for use by build scripts.
    buildSettings["BAZEL_TARGET"] = entry.label.value

    createBuildConfigurationsForList(target.buildConfigurationList, buildSettings: buildSettings)
    addTestRunnerBuildConfigurationToBuildConfigurationList(target.buildConfigurationList)

    if let buildPhase = createBuildPhaseForRuleEntry(entry) {
      target.buildPhases.append(buildPhase)
    }

    if let legacyTarget = bazelCleanScriptTarget {
      target.createDependencyOn(legacyTarget,
                                proxyType: PBXContainerItemProxy.ProxyType.targetReference,
                                inProject: project,
                                first: true)
    }

    return target
  }

  private func createGenerateSwiftDummyFilesTestBuildPhase() -> PBXShellScriptBuildPhase {
    let shellScript =
        "# Script to generate specific Swift files Xcode expects when running tests.\n" +
        "set -eu\n" +
        "ARCH_ARRAY=($ARCHS)\n" +
        "SUFFIXES=(swiftdoc swiftmodule)\n" +
        "for ARCH in \"${ARCH_ARRAY[@]}\"\n" +
        "do\n" +
        "  mkdir -p \"$OBJECT_FILE_DIR_normal/$ARCH/\"\n" +
        "  touch \"$OBJECT_FILE_DIR_normal/$ARCH/$SWIFT_OBJC_INTERFACE_HEADER_NAME\"\n" +
        "  for SUFFIX in \"${SUFFIXES[@]}\"\n" +
        "  do\n" +
        "    touch \"$OBJECT_FILE_DIR_normal/$ARCH/$PRODUCT_MODULE_NAME.$SUFFIX\"\n" +
        "  done\n" +
        "done\n"

    let buildPhase = PBXShellScriptBuildPhase(shellScript: shellScript, shellPath: "/bin/bash")
    buildPhase.showEnvVarsInLog = true
    buildPhase.mnemonic = "SwiftDummy"
    return buildPhase
  }

  private func createGenerateDummyDependencyFilesTestBuildPhase(_ sources: [BazelFileInfo]) -> PBXShellScriptBuildPhase {
    let files = sources.map { ($0.subPath as NSString).deletingPathExtension.pbPathLastComponent }
    let shellScript = """
# Script to generate dependency files Xcode expects when running tests.
set -eu
ARCH_ARRAY=($ARCHS)
FILES=(\(files.map { $0.escapingForShell }.joined(separator: " ")))
for ARCH in "${ARCH_ARRAY[@]}"
do
  mkdir -p "$OBJECT_FILE_DIR_normal/$ARCH/"
  rm -f "$OBJECT_FILE_DIR_normal/$ARCH/${PRODUCT_NAME}_dependency_info.dat"
  printf '\\x00\\x31\\x00' >"$OBJECT_FILE_DIR_normal/$ARCH/${PRODUCT_NAME}_dependency_info.dat"
  for FILE in "${FILES[@]}"
  do
    touch "$OBJECT_FILE_DIR_normal/$ARCH/$FILE.d"
  done
done
"""
    let buildPhase = PBXShellScriptBuildPhase(shellScript: shellScript, shellPath: "/bin/bash")
    buildPhase.showEnvVarsInLog = true
    buildPhase.mnemonic = "ObjcDummy"
    return buildPhase
  }

  private func createBuildPhaseForRuleEntry(_ entry: RuleEntry)
      -> PBXShellScriptBuildPhase? {
    let buildLabel = entry.label.value
    let commandLine = buildScriptCommandlineForBuildLabels(buildLabel)
    let workingDirectory = PBXTargetGenerator.workingDirectoryForPBXGroup(project.mainGroup)
    let changeDirectoryAction: String
    if workingDirectory.isEmpty {
      changeDirectoryAction = ""
    } else {
      changeDirectoryAction = "cd \"\(workingDirectory)\""
    }
    let shellScript = "set -e\n" +
        "\(changeDirectoryAction)\n" +
        "exec \(commandLine)"

    // Using the Info.plist as an input forces Xcode to run this after processing the Info.plist,
    // allowing our script to safely overwrite the Info.plist after Xcode does its processing.
    let inputPaths = ["$(TARGET_BUILD_DIR)/$(INFOPLIST_PATH)"]
    let buildPhase = PBXShellScriptBuildPhase(
      shellScript: shellScript,
      shellPath: "/bin/bash",
      inputPaths: inputPaths
    )
    buildPhase.showEnvVarsInLog = true
    buildPhase.mnemonic = "BazelBuild"
    return buildPhase
  }

  /// Constructs a commandline string that will invoke the bazel build script to generate the given
  /// buildLabels (a space-separated set of Bazel target labels).
  private func buildScriptCommandlineForBuildLabels(_ buildLabels: String) -> String {
    return "\"\(buildScriptPath)\" " +
        "\(buildLabels) " +
        "--bazel \"\(bazelPath)\" " +
        "--bazel_bin_path \"\(bazelBinPath)\" " +
        "--verbose "
  }
}
