Adding support for macOS tests.

Added support for macos_unit_test and macos_ui_tests.
macos_unit_test in Tulsi only supports targets that have
a test_host configured.

--
PiperOrigin-RevId: 168458500
MOS_MIGRATED_REVID=168458500
diff --git a/src/Tulsi.xcodeproj/project.pbxproj b/src/Tulsi.xcodeproj/project.pbxproj
index 8e42109..1f694f2 100644
--- a/src/Tulsi.xcodeproj/project.pbxproj
+++ b/src/Tulsi.xcodeproj/project.pbxproj
@@ -7,7 +7,10 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
-		2D9DB34A1E5DECA40021EAF4 /* XCTRunner.entitlements in Resources */ = {isa = PBXBuildFile; fileRef = 2D9DB3491E5DEC680021EAF4 /* XCTRunner.entitlements */; };
+		2D7A8EB51F67220400392DA3 /* macOSXCTRunner.entitlements in Resources */ = {isa = PBXBuildFile; fileRef = 2D7A8EB41F6720EB00392DA3 /* macOSXCTRunner.entitlements */; };
+		2D9DB34A1E5DECA40021EAF4 /* iOSXCTRunner.entitlements in Resources */ = {isa = PBXBuildFile; fileRef = 2D9DB3491E5DEC680021EAF4 /* iOSXCTRunner.entitlements */; };
+		2DD7C6C21F6886D400163B92 /* TulsiError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D387BB71C761B8800544AE0 /* TulsiError.swift */; };
+		2DD7C6C41F6887DB00163B92 /* DeploymentTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DD7C6C31F6887DB00163B92 /* DeploymentTarget.swift */; };
 		3D029B581C6421B400779E8E /* ProcessRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D029B571C6421B400779E8E /* ProcessRunner.swift */; };
 		3D029C7E1C650DD100779E8E /* ProjectEditorPackageManagerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D029C7C1C650DD100779E8E /* ProjectEditorPackageManagerViewController.swift */; };
 		3D062FA31DA6C77500E79AD4 /* Swift.BUILD in Resources */ = {isa = PBXBuildFile; fileRef = 3D062FA11DA6C76900E79AD4 /* Swift.BUILD */; };
@@ -26,7 +29,6 @@
 		3D387BAD1C7500B500544AE0 /* NewGeneratorConfigViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3D387BAF1C7500B500544AE0 /* NewGeneratorConfigViewController.xib */; };
 		3D387BB21C75352E00544AE0 /* XcodeProjectGenerationProgressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D387BB01C75352E00544AE0 /* XcodeProjectGenerationProgressViewController.swift */; };
 		3D387BB41C75354C00544AE0 /* XcodeProjectGenerationProgressViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3D387BB61C75354C00544AE0 /* XcodeProjectGenerationProgressViewController.xib */; };
-		3D387BB81C761B8800544AE0 /* TulsiError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D387BB71C761B8800544AE0 /* TulsiError.swift */; };
 		3D3DDD141CCA7BCF00E21FA4 /* ErrorAlertDetailView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3D3DDD161CCA7BCF00E21FA4 /* ErrorAlertDetailView.xib */; };
 		3D47D6BA1D13190E005B5BF3 /* NSJSONSerializationExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D47D6B91D13190E005B5BF3 /* NSJSONSerializationExtensions.swift */; };
 		3D4E5A421D07123900DAB0B4 /* HeadlessXcodeProjectGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D4E5A411D07123900DAB0B4 /* HeadlessXcodeProjectGenerator.swift */; };
@@ -136,8 +138,8 @@
 		AB18CC4A7B1A308E23A1CE6F /* HeadlessTulsiProjectCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB18CFC29644CD1B3B860056 /* HeadlessTulsiProjectCreator.swift */; };
 		D33C204F1EC108CC00867450 /* tulsi_logging.py in Resources */ = {isa = PBXBuildFile; fileRef = D33C204E1EC108CC00867450 /* tulsi_logging.py */; };
 		D3F78C681F391E9700AE0571 /* bazel_options.py in Resources */ = {isa = PBXBuildFile; fileRef = D3F78C671F391E9700AE0571 /* bazel_options.py */; };
-        E1D27C2A1F57782D000B9B13 /* SimpleBad.BUILD in Resources */ = {isa = PBXBuildFile; fileRef = E1D27C281F57781A000B9B13 /* SimpleBad.BUILD */; };
 		E19C1C571F5886A000D6E38A /* QueuedLogging.swift in Sources */ = {isa = PBXBuildFile; fileRef = E19C1C561F5886A000D6E38A /* QueuedLogging.swift */; };
+		E1D27C2A1F57782D000B9B13 /* SimpleBad.BUILD in Resources */ = {isa = PBXBuildFile; fileRef = E1D27C281F57781A000B9B13 /* SimpleBad.BUILD */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -204,7 +206,9 @@
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
-		2D9DB3491E5DEC680021EAF4 /* XCTRunner.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = XCTRunner.entitlements; sourceTree = "<group>"; };
+		2D7A8EB41F6720EB00392DA3 /* macOSXCTRunner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = macOSXCTRunner.entitlements; sourceTree = "<group>"; };
+		2D9DB3491E5DEC680021EAF4 /* iOSXCTRunner.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = iOSXCTRunner.entitlements; sourceTree = "<group>"; };
+		2DD7C6C31F6887DB00163B92 /* DeploymentTarget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeploymentTarget.swift; sourceTree = "<group>"; };
 		3D029B571C6421B400779E8E /* ProcessRunner.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProcessRunner.swift; sourceTree = "<group>"; };
 		3D029C7C1C650DD100779E8E /* ProjectEditorPackageManagerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProjectEditorPackageManagerViewController.swift; sourceTree = "<group>"; };
 		3D062FA11DA6C76900E79AD4 /* Swift.BUILD */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Swift.BUILD; path = Resources/Swift.BUILD; sourceTree = "<group>"; };
@@ -339,8 +343,8 @@
 		AB18CFC29644CD1B3B860056 /* HeadlessTulsiProjectCreator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeadlessTulsiProjectCreator.swift; sourceTree = "<group>"; };
 		D33C204E1EC108CC00867450 /* tulsi_logging.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = tulsi_logging.py; sourceTree = "<group>"; };
 		D3F78C671F391E9700AE0571 /* bazel_options.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = bazel_options.py; sourceTree = "<group>"; };
-        E1D27C281F57781A000B9B13 /* SimpleBad.BUILD */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = SimpleBad.BUILD; path = Resources/SimpleBad.BUILD; sourceTree = "<group>"; };
 		E19C1C561F5886A000D6E38A /* QueuedLogging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueuedLogging.swift; sourceTree = "<group>"; };
+		E1D27C281F57781A000B9B13 /* SimpleBad.BUILD */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = SimpleBad.BUILD; path = Resources/SimpleBad.BUILD; sourceTree = "<group>"; };
 		F4469ECE1C5BCA5900BCFAA1 /* TulsiVersion.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = TulsiVersion.xcconfig; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
@@ -394,7 +398,8 @@
 				3DAFE8AD1DF1F23D0055AF56 /* StubIOSAppExtensionInfoPlist.plist */,
 				3DCD08101D779576006ABE5B /* StubWatchOS2AppExtensionInfoPlist.plist */,
 				3D903A791D775AE800B034E9 /* StubWatchOS2InfoPlist.plist */,
-				2D9DB3491E5DEC680021EAF4 /* XCTRunner.entitlements */,
+				2D9DB3491E5DEC680021EAF4 /* iOSXCTRunner.entitlements */,
+				2D7A8EB41F6720EB00392DA3 /* macOSXCTRunner.entitlements */,
 			);
 			name = GeneratedProjectResources;
 			sourceTree = "<group>";
@@ -458,6 +463,7 @@
 				3DD0DE461C654E79008B0CDF /* TulsiProject.swift */,
 				3D250B7E1C5DCE120091C7A5 /* XcodeScheme.swift */,
 				54BDD0171F4E0FD000AAC99A /* TulsiParameter.swift */,
+				2DD7C6C31F6887DB00163B92 /* DeploymentTarget.swift */,
 			);
 			name = Models;
 			sourceTree = "<group>";
@@ -819,7 +825,8 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				2D9DB34A1E5DECA40021EAF4 /* XCTRunner.entitlements in Resources */,
+				2D7A8EB51F67220400392DA3 /* macOSXCTRunner.entitlements in Resources */,
+				2D9DB34A1E5DECA40021EAF4 /* iOSXCTRunner.entitlements in Resources */,
 				3D329D0E1C4831EF00DFBD0F /* bazel_build.py in Resources */,
 				D33C204F1EC108CC00867450 /* tulsi_logging.py in Resources */,
 				54EF320A1F3E0804009E9C7F /* bazel_build_events.py in Resources */,
@@ -917,6 +924,7 @@
 				3D029B581C6421B400779E8E /* ProcessRunner.swift in Sources */,
 				5429EA8B1F38C4DB00A78405 /* BazelPBXReferencePatcher.swift in Sources */,
 				3D99268F1C29F1100094E098 /* PBXProjSerializer.swift in Sources */,
+				2DD7C6C41F6887DB00163B92 /* DeploymentTarget.swift in Sources */,
 				3D99268C1C29F1100094E098 /* PBXUniformTypeIdentifiers.swift in Sources */,
 				3D1F2E261CF760420008CE83 /* BazelLocator.swift in Sources */,
 				3DAEE45E1C85128600BA1C67 /* BazelWorkspacePathInfoFetcher.swift in Sources */,
@@ -983,9 +991,9 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				3D387BB81C761B8800544AE0 /* TulsiError.swift in Sources */,
 				3DB1FC2B1C32DCBC0080198C /* MessageViewController.swift in Sources */,
 				3D4E5A421D07123900DAB0B4 /* HeadlessXcodeProjectGenerator.swift in Sources */,
+				2DD7C6C21F6886D400163B92 /* TulsiError.swift in Sources */,
 				3D0849F11C739D75005F5ABA /* TulsiGeneratorConfigDocument.swift in Sources */,
 				3DDA83921C7BB1F100CA7BB5 /* BazelSelectionPanel.swift in Sources */,
 				3D7CED5B1CC171CD0073204D /* SplashScreenWindowController.swift in Sources */,
diff --git a/src/TulsiGenerator/DeploymentTarget.swift b/src/TulsiGenerator/DeploymentTarget.swift
new file mode 100644
index 0000000..77c10fa
--- /dev/null
+++ b/src/TulsiGenerator/DeploymentTarget.swift
@@ -0,0 +1,72 @@
+// Copyright 2017 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
+
+
+/// Valid Apple Platform Types.
+/// See https://docs.bazel.build/versions/master/skylark/lib/apple_common.html#platform_type
+public enum PlatformType: String {
+  case ios
+  case macos
+  case tvos
+  case watchos
+
+  var buildSettingsDeploymentTarget: String {
+    switch self {
+    case .ios: return "IPHONEOS_DEPLOYMENT_TARGET"
+    case .macos: return "MACOSX_DEPLOYMENT_TARGET"
+    case .tvos: return "TVOS_DEPLOYMENT_TARGET"
+    case .watchos: return "WATCHOS_DEPLOYMENT_TARGET"
+    }
+  }
+
+  var simulatorSDK: String {
+    switch self {
+    case .ios: return "iphonesimulator"
+    case .macos: return "macosx"
+    case .tvos: return "appletvsimulator"
+    case .watchos: return "watchsimulator"
+    }
+  }
+
+  var deviceSDK: String {
+    switch self {
+    case .ios: return "iphoneos"
+    case .macos: return "macosx"
+    case .tvos: return "appletvos"
+    case .watchos: return "watchos"
+    }
+  }
+
+  /// Path of where the test host is expected to be built for each available platform.
+  func testHostPath(hostTargetPath: String, hostTargetProductName: String) -> String? {
+    switch self {
+    case .ios: return "$(BUILT_PRODUCTS_DIR)/\(hostTargetPath)/\(hostTargetProductName)"
+    case .macos: return "$(BUILT_PRODUCTS_DIR)/\(hostTargetPath)/Contents/MacOS/\(hostTargetProductName)"
+    case .tvos: return "$(BUILT_PRODUCTS_DIR)/\(hostTargetPath)/\(hostTargetProductName)"
+    case .watchos: return nil
+    }
+  }
+}
+
+/// Target platform and os version to be used when generating the project.
+public struct DeploymentTarget : Equatable {
+  let platform: PlatformType
+  let osVersion: String
+
+  public static func ==(lhs: DeploymentTarget, rhs: DeploymentTarget) -> Bool {
+    return lhs.platform == rhs.platform && lhs.osVersion == rhs.osVersion
+  }
+}
diff --git a/src/TulsiGenerator/PBXObjects.swift b/src/TulsiGenerator/PBXObjects.swift
index ffa05e3..cf9edd8 100644
--- a/src/TulsiGenerator/PBXObjects.swift
+++ b/src/TulsiGenerator/PBXObjects.swift
@@ -46,7 +46,6 @@
   case DeveloperDir = "DEVELOPER_DIR"
 }
 
-
 // Models a path within an Xcode project file.
 struct SourceTreePath: Hashable {
   /// Indicates the type of "path".
@@ -829,6 +828,8 @@
   var buildActionDependencies = Set<PBXTarget>()
   /// The build phases to be executed to generate this target.
   var buildPhases = [PBXBuildPhase]()
+  /// Deployment target for this target, if available.
+  let deploymentTarget: DeploymentTarget?
 
   var isa: String {
     assertionFailure("PBXTarget must be subclassed")
@@ -843,8 +844,9 @@
     return name
   }
 
-  init(name: String) {
+  init(name: String, deploymentTarget: DeploymentTarget?) {
     self.name = name
+    self.deploymentTarget = deploymentTarget
   }
 
   /// Creates a dependency on the given target.
@@ -902,9 +904,9 @@
     return "PBXNativeTarget"
   }
 
-  init(name: String, productType: ProductType) {
+  init(name: String, deploymentTarget: DeploymentTarget?, productType: ProductType) {
     self.productType = productType
-    super.init(name: name)
+    super.init(name: name, deploymentTarget: deploymentTarget)
   }
 
   override func serializeInto(_ serializer: PBXProjFieldSerializer) throws {
@@ -928,11 +930,15 @@
     return "PBXLegacyTarget"
   }
 
-  init(name: String, buildToolPath: String, buildArguments: String, buildWorkingDirectory: String) {
+  init(name: String,
+       deploymentTarget: DeploymentTarget?,
+       buildToolPath: String,
+       buildArguments: String,
+       buildWorkingDirectory: String) {
     self.buildToolPath = buildToolPath
     self.buildArgumentsString = buildArguments
     self.buildWorkingDirectory = buildWorkingDirectory
-    super.init(name: name)
+    super.init(name: name, deploymentTarget: deploymentTarget)
   }
 
   override func serializeInto(_ serializer: PBXProjFieldSerializer) throws {
@@ -1095,8 +1101,12 @@
     self.name = name
   }
 
-  func createNativeTarget(_ name: String, targetType: PBXTarget.ProductType) -> PBXNativeTarget {
-    let value = PBXNativeTarget(name: name, productType: targetType)
+  func createNativeTarget(_ name: String,
+                          deploymentTarget: DeploymentTarget?,
+                          targetType: PBXTarget.ProductType) -> PBXNativeTarget {
+    let value = PBXNativeTarget(name: name,
+                                deploymentTarget: deploymentTarget,
+                                productType: targetType)
     targetByName[name] = value
 
     let productsGroup = mainGroup.getOrCreateChildGroupByName(PBXProject.ProductsGroupName,
@@ -1112,10 +1122,12 @@
   }
 
   func createLegacyTarget(_ name: String,
+                          deploymentTarget: DeploymentTarget?,
                           buildToolPath: String,
                           buildArguments: String,
                           buildWorkingDirectory: String) -> PBXLegacyTarget {
     let value = PBXLegacyTarget(name: name,
+                                deploymentTarget: deploymentTarget,
                                 buildToolPath: buildToolPath,
                                 buildArguments: buildArguments,
                                 buildWorkingDirectory: buildWorkingDirectory)
diff --git a/src/TulsiGenerator/PBXTargetGenerator.swift b/src/TulsiGenerator/PBXTargetGenerator.swift
index c671c47..c986971 100644
--- a/src/TulsiGenerator/PBXTargetGenerator.swift
+++ b/src/TulsiGenerator/PBXTargetGenerator.swift
@@ -217,7 +217,7 @@
     let includes: [String]
     let frameworkSearchPaths: [String]
     let swiftIncludePaths: [String]
-    let deploymentTarget: RuleEntry.DeploymentTarget
+    let deploymentTarget: DeploymentTarget
     let buildPhase: PBXSourcesBuildPhase
     let pchFile: BazelFileInfo?
     let bridgingHeader: BazelFileInfo?
@@ -597,11 +597,11 @@
            "-Xcc -fmodule-map-file=$(\(PBXTargetGenerator.BazelWorkspaceSymlinkVarName))/\($0.fullPath)"
         }
 
-        let deploymentTarget: RuleEntry.DeploymentTarget
+        let deploymentTarget: DeploymentTarget
         if let ruleDeploymentTarget = ruleEntry.deploymentTarget {
           deploymentTarget = ruleDeploymentTarget
         } else {
-          deploymentTarget = RuleEntry.DeploymentTarget(platform: .ios, osVersion: "9.0")
+          deploymentTarget = DeploymentTarget(platform: .ios, osVersion: "9.0")
           localizedMessageLogger.warning("NoDeploymentTarget",
                                          comment: "Rule Entry for %1$@ has no DeploymentTarget set. Defaulting to iOS 9.",
                                          values: ruleEntry.label.value)
@@ -641,7 +641,7 @@
     func generateIndexer(_ name: String,
                          indexerType: PBXTarget.ProductType,
                          data: IndexerData) {
-      let indexingTarget = project.createNativeTarget(name, targetType: indexerType)
+      let indexingTarget = project.createNativeTarget(name, deploymentTarget: nil, targetType: indexerType)
       indexingTarget.buildPhases.append(data.buildPhase)
       addConfigsForIndexingTarget(indexingTarget, data: data)
 
@@ -688,6 +688,7 @@
 
     let bazelPath = bazelURL.path
     bazelCleanScriptTarget = project.createLegacyTarget(PBXTargetGenerator.BazelCleanTarget,
+                                                        deploymentTarget: nil,
                                                         buildToolPath: "\(scriptPath)",
                                                         buildArguments: "\"\(bazelPath)\" \"\(bazelBinPath)\"",
                                                         buildWorkingDirectory: workingDirectory)
@@ -1087,20 +1088,24 @@
 
     // 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 hostProduct = hostTarget.productReference?.path,
-           let hostProductName = hostTarget.productName {
+    if let hostTargetPath = hostTarget.productReference?.path,
+       let hostTargetProductName = hostTarget.productName,
+       let deploymentTarget = target.deploymentTarget {
       let testSettings: [String: String]
       if ruleEntry.pbxTargetType == .UIUnitTest {
         testSettings = [
-          "TEST_TARGET_NAME": hostProductName,
+          "TEST_TARGET_NAME": hostTargetProductName,
+          "TULSI_TEST_RUNNER_ONLY": "YES",
+        ]
+      } else if let testHostPath = deploymentTarget.platform.testHostPath(hostTargetPath: hostTargetPath,
+                                                                          hostTargetProductName: hostTargetProductName) {
+        testSettings = [
+          "BUNDLE_LOADER": "$(TEST_HOST)",
+          "TEST_HOST": testHostPath,
           "TULSI_TEST_RUNNER_ONLY": "YES",
         ]
       } else {
-        testSettings = [
-          "BUNDLE_LOADER": "$(TEST_HOST)",
-          "TEST_HOST": "$(BUILT_PRODUCTS_DIR)/\(hostProduct)/\(hostProductName)",
-          "TULSI_TEST_RUNNER_ONLY": "YES",
-        ]
+        testSettings = [:]
       }
 
       // Inherit the resolved values from the indexer.
@@ -1333,7 +1338,9 @@
     guard let pbxTargetType = entry.pbxTargetType else {
       throw ProjectSerializationError.unsupportedTargetType(entry.type)
     }
-    let target = project.createNativeTarget(name, targetType: pbxTargetType)
+    let target = project.createNativeTarget(name,
+                                            deploymentTarget: entry.deploymentTarget,
+                                            targetType: pbxTargetType)
 
     for f in entry.secondaryArtifacts {
       project.createProductReference(f.fullPath)
diff --git a/src/TulsiGenerator/RuleEntry.swift b/src/TulsiGenerator/RuleEntry.swift
index 0900eef..91feeae 100644
--- a/src/TulsiGenerator/RuleEntry.swift
+++ b/src/TulsiGenerator/RuleEntry.swift
@@ -150,50 +150,6 @@
       "_test_host_": PBXTarget.ProductType.Application,
   ]
 
-  /// Valid Apple Platform Types.
-  /// See https://docs.bazel.build/versions/master/skylark/lib/apple_common.html#platform_type
-  public enum PlatformType: String {
-    case ios
-    case macos
-    case tvos
-    case watchos
-
-    var buildSettingsDeploymentTarget: String {
-      switch self {
-        case .ios: return "IPHONEOS_DEPLOYMENT_TARGET"
-        case .macos: return "MACOSX_DEPLOYMENT_TARGET"
-        case .tvos: return "TVOS_DEPLOYMENT_TARGET"
-        case .watchos: return "WATCHOS_DEPLOYMENT_TARGET"
-      }
-    }
-    var simulatorSDK: String {
-      switch self {
-        case .ios: return "iphonesimulator"
-        case .macos: return "macosx"
-        case .tvos: return "appletvsimulator"
-        case .watchos: return "watchsimulator"
-      }
-    }
-    var deviceSDK: String {
-      switch self {
-        case .ios: return "iphoneos"
-        case .macos: return "macosx"
-        case .tvos: return "appletvos"
-        case .watchos: return "watchos"
-      }
-    }
-  }
-
-  /// Target platform and os version to be used when generating the project.
-  public struct DeploymentTarget : Equatable {
-    let platform: PlatformType
-    let osVersion: String
-
-    public static func ==(lhs: RuleEntry.DeploymentTarget, rhs: RuleEntry.DeploymentTarget) -> Bool {
-      return lhs.platform == rhs.platform && lhs.osVersion == rhs.osVersion
-    }
-  }
-
   /// Keys for a RuleEntry's attributes map. Definitions may be found in the Bazel Build
   /// Encyclopedia (see http://bazel.build/docs/be/overview.html).
   // Note: This set of must be kept in sync with the tulsi_aspects aspect.
diff --git a/src/TulsiGenerator/Scripts/bazel_build.py b/src/TulsiGenerator/Scripts/bazel_build.py
index b9120cf..a33cbfb 100755
--- a/src/TulsiGenerator/Scripts/bazel_build.py
+++ b/src/TulsiGenerator/Scripts/bazel_build.py
@@ -503,28 +503,18 @@
 
     # Path where Xcode expects the artifacts to be written to. This is not the
     # codesigning_path as device vs simulator builds have different signing
-    # requirements, so Xcode expects different things to be signed. This is
+    # requirements, so Xcode expects different paths to be signed. This is
     # mostly apparent on XCUITests where simulator builds set the codesigning
     # path to be the .xctest bundle, but for device builds it is actually the
     # UI runner app (since it needs to be codesigned to run on the device.) The
-    # contents folder path is a stable path on where to put the expected
+    # FULL_PRODUCT_NAME variable is a stable path on where to put the expected
     # artifacts. For static libraries (objc_library, swift_library),
-    # CONTENTS_FOLDER_PATH does not exist, but the location where Xcode expects
-    # the archive coincides with the TARGET_BUILD_DIR, so using an empty
-    # default for CONTENTS_FOLDER_PATH supports both bundle and single artifact
-    # outputs.
+    # FULL_PRODUCT_NAME corresponds to the .a file name, which coincides with
+    # the expected location for a single artifact output.
     # TODO(b/35811023): Check these paths are still valid.
-    self.content_folder_path = os.path.join(
+    self.artifact_output_path = os.path.join(
         os.environ['TARGET_BUILD_DIR'],
-        os.environ.get('CONTENTS_FOLDER_PATH', ''))
-
-    # For macOS applications and extensions, Xcode includes the Contents/ at
-    # the end, which we don't want.
-    if (self.bazel_target_type == 'macos_application'
-        or self.bazel_target_type == 'macos_extension'):
-      head, tail = os.path.split(self.content_folder_path)
-      if tail == 'Contents':
-        self.content_folder_path = head
+        os.environ['FULL_PRODUCT_NAME'])
 
     # Path to where Xcode expects the binary to be placed.
     self.binary_path = os.path.join(
@@ -548,10 +538,14 @@
                                               'Utils',
                                               'post_processor')
     if self.codesigning_allowed:
+      platform_prefix = 'iOS'
+      if self.platform_name.startswith('macos'):
+        platform_prefix = 'macOS'
+      entitlements_filename = '%sXCTRunner.entitlements' % platform_prefix
       self.runner_entitlements_template = os.path.join(self.project_file_path,
                                                        '.tulsi',
                                                        'Resources',
-                                                       'XCTRunner.entitlements')
+                                                       entitlements_filename)
 
     self.main_group_path = os.getcwd()
 
@@ -891,7 +885,7 @@
 
   def _InstallArtifact(self, outputs):
     """Installs Bazel-generated artifacts into the Xcode output directory."""
-    xcode_artifact_path = self.content_folder_path
+    xcode_artifact_path = self.artifact_output_path
 
     if os.path.isdir(xcode_artifact_path):
       try:
@@ -1055,6 +1049,14 @@
         expected_ipa_subpath = os.path.join('PlugIns', expected_bundle_name)
       elif self.product_type == 'com.apple.product-type.application.watchapp2':
         expected_ipa_subpath = os.path.join('Watch', expected_bundle_name)
+      elif self.platform_name.startswith('macos'):
+        # The test rules for now need to output .ipa files instead of .zip
+        # files. For this reason, macOS xctest bundles are detected as IPA
+        # files. So, if we're building for macOS and it's and IPA, just use
+        # the expected_bundle_name.
+        # TODO(b/34774324): Clean this so macOS bundles always fall outside of
+        # the is_ipa if branch.
+        expected_ipa_subpath = expected_bundle_name
       else:
         expected_ipa_subpath = os.path.join('Payload', expected_bundle_name)
     else:
@@ -1089,8 +1091,9 @@
         dir_components = self._SplitPathComponents(filename)
 
         # Get the file's path, ignoring the payload components if the archive
-        # is an IPA.
-        if is_ipa:
+        # is an IPA and it's not a macOS bundle.
+        # TODO(b/34774324): Clean this.
+        if is_ipa and not self.platform_name.startswith('macos'):
           subpath = os.path.join(*dir_components[2:])
         else:
           subpath = os.path.join(*dir_components[1:])
@@ -1258,7 +1261,7 @@
       return 0
     # Extract the signing identity from the bundle at the expected output path
     # since that's where the signed bundle from bazel was placed.
-    signing_identity = self._ExtractSigningIdentity(self.content_folder_path)
+    signing_identity = self._ExtractSigningIdentity(self.artifact_output_path)
     if not signing_identity:
       return 800
 
@@ -1331,10 +1334,10 @@
       contents = template.read()
       contents = contents.replace(
           '$(TeamIdentifier)',
-          self._ExtractSigningTeamIdentifier(self.content_folder_path))
+          self._ExtractSigningTeamIdentifier(self.artifact_output_path))
       contents = contents.replace(
           '$(BundleIdentifier)',
-          self._ExtractSigningBundleIdentifier(self.content_folder_path))
+          self._ExtractSigningBundleIdentifier(self.artifact_output_path))
       with open(output_file, 'w') as output:
         output.write(contents)
     return output_file
diff --git a/src/TulsiGenerator/TulsiXcodeProjectGenerator.swift b/src/TulsiGenerator/TulsiXcodeProjectGenerator.swift
index 30b8eb3..aad6d67 100644
--- a/src/TulsiGenerator/TulsiXcodeProjectGenerator.swift
+++ b/src/TulsiGenerator/TulsiXcodeProjectGenerator.swift
@@ -55,7 +55,8 @@
         postProcessor: bundle.url(forResource: "post_processor",
                                              withExtension: "",
                                              subdirectory: "Utilities")!,
-        uiRunnerEntitlements: bundle.url(forResource: "XCTRunner", withExtension: "entitlements")!,
+        iOSUIRunnerEntitlements: bundle.url(forResource: "iOSXCTRunner", withExtension: "entitlements")!,
+        macOSUIRunnerEntitlements: bundle.url(forResource: "macOSXCTRunner", withExtension: "entitlements")!,
         stubInfoPlist: bundle.url(forResource: "StubInfoPlist", withExtension: "plist")!,
         stubIOSAppExInfoPlistTemplate: bundle.url(forResource: "StubIOSAppExtensionInfoPlist", withExtension: "plist")!,
         stubWatchOS2InfoPlist: bundle.url(forResource: "StubWatchOS2InfoPlist", withExtension: "plist")!,
diff --git a/src/TulsiGenerator/XcodeProjectGenerator.swift b/src/TulsiGenerator/XcodeProjectGenerator.swift
index a27ee8a..fdf0198 100644
--- a/src/TulsiGenerator/XcodeProjectGenerator.swift
+++ b/src/TulsiGenerator/XcodeProjectGenerator.swift
@@ -35,7 +35,8 @@
     let cleanScript: URL  // The script to run on "clean" actions.
     let extraBuildScripts: [URL] // Any additional scripts to install into the project bundle.
     let postProcessor: URL  // Binary post processor utility.
-    let uiRunnerEntitlements: URL  // Entitlements file template for UI Test runner apps.
+    let iOSUIRunnerEntitlements: URL  // Entitlements file template for iOS UI Test runner apps.
+    let macOSUIRunnerEntitlements: URL  // Entitlements file template for macOS UI Test runner apps.
     let stubInfoPlist: URL  // Stub Info.plist (needed for Xcode 8).
     let stubIOSAppExInfoPlistTemplate: URL  // Stub Info.plist (needed for app extension targets).
     let stubWatchOS2InfoPlist: URL  // Stub Info.plist (needed for watchOS2 app targets).
@@ -67,7 +68,8 @@
   private static let CleanScript = "bazel_clean.sh"
   private static let WorkspaceFile = "WORKSPACE"
   private static let PostProcessorUtil = "post_processor"
-  private static let UIRunnerEntitlements = "XCTRunner.entitlements"
+  private static let IOSUIRunnerEntitlements = "iOSXCTRunner.entitlements"
+  private static let MacOSUIRunnerEntitlements = "macOSXCTRunner.entitlements"
   private static let StubInfoPlistFilename = "StubInfoPlist.plist"
   private static let StubWatchOS2InfoPlistFilename = "StubWatchOS2InfoPlist.plist"
   private static let StubWatchOS2AppExInfoPlistFilename = "StubWatchOS2AppExInfoPlist.plist"
@@ -813,7 +815,8 @@
                                                                context: config.projectName)
     localizedMessageLogger.infoMessage("Installing project resources")
 
-    installFiles([(resourceURLs.uiRunnerEntitlements, XcodeProjectGenerator.UIRunnerEntitlements),
+    installFiles([(resourceURLs.iOSUIRunnerEntitlements, XcodeProjectGenerator.IOSUIRunnerEntitlements),
+                  (resourceURLs.macOSUIRunnerEntitlements, XcodeProjectGenerator.MacOSUIRunnerEntitlements),
                   (resourceURLs.stubInfoPlist, XcodeProjectGenerator.StubInfoPlistFilename),
                   (resourceURLs.stubWatchOS2InfoPlist, XcodeProjectGenerator.StubWatchOS2InfoPlistFilename),
                   (resourceURLs.stubWatchOS2AppExInfoPlist, XcodeProjectGenerator.StubWatchOS2AppExInfoPlistFilename),
diff --git a/src/TulsiGenerator/XCTRunner.entitlements b/src/TulsiGenerator/iOSXCTRunner.entitlements
similarity index 100%
rename from src/TulsiGenerator/XCTRunner.entitlements
rename to src/TulsiGenerator/iOSXCTRunner.entitlements
diff --git a/src/TulsiGenerator/macOSXCTRunner.entitlements b/src/TulsiGenerator/macOSXCTRunner.entitlements
new file mode 100644
index 0000000..226c940
--- /dev/null
+++ b/src/TulsiGenerator/macOSXCTRunner.entitlements
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>com.apple.application-identifier</key>
+	<string>$(BundleIdentifier)</string>
+	<key>com.apple.security.app-sandbox</key>
+	<true/>
+	<key>com.apple.security.network.client</key>
+	<true/>
+	<key>com.apple.security.temporary-exception.files.absolute-path.read-only</key>
+	<array>
+		<string>/</string>
+		<string>/</string>
+	</array>
+	<key>com.apple.security.temporary-exception.mach-lookup.global-name</key>
+	<array>
+		<string>com.apple.coresymbolicationd</string>
+		<string>com.apple.testmanagerd</string>
+	</array>
+	<key>com.apple.security.temporary-exception.mach-lookup.local-name</key>
+	<array>
+		<string>com.apple.axserver</string>
+	</array>
+	<key>com.apple.security.temporary-exception.sbpl</key>
+	<array>
+		<string>(allow network-outbound (subpath "/private/tmp"))</string>
+		<string>(allow hid-control)</string>
+		<string>(allow signal)</string>
+		<string>(allow network-outbound (subpath "/private/tmp"))</string>
+	</array>
+</dict>
+</plist>
diff --git a/src/TulsiGeneratorIntegrationTests/EndToEndGenerationTests.swift b/src/TulsiGeneratorIntegrationTests/EndToEndGenerationTests.swift
index 534a29f..9183ef1 100644
--- a/src/TulsiGeneratorIntegrationTests/EndToEndGenerationTests.swift
+++ b/src/TulsiGeneratorIntegrationTests/EndToEndGenerationTests.swift
@@ -201,6 +201,38 @@
     validateDiff(diffLines)
   }
 
+  func test_macTestsProject() {
+    let testDir = "tulsi_e2e_mac"
+    installBUILDFile("Mac", intoSubdirectory: testDir)
+
+    let appLabel = BuildLabel("//\(testDir):MyMacOSApp")
+    let unitTestsLabel = BuildLabel("//\(testDir):UnitTests")
+    let uiTestsLabel = BuildLabel("//\(testDir):UITests")
+    let hostLabels = Set<BuildLabel>([appLabel])
+    let buildTargets = [RuleInfo(label: unitTestsLabel,
+                                 type: "apple_unit_test",
+                                 linkedTargetLabels: hostLabels),
+                        RuleInfo(label: uiTestsLabel,
+                                 type: "apple_ui_test",
+                                 linkedTargetLabels: hostLabels)]
+    let additionalFilePaths = ["\(testDir)/BUILD"]
+
+    let projectName = "MacOSTestsProject"
+    guard let projectURL = generateProjectNamed(projectName,
+                                                buildTargets: buildTargets,
+                                                pathFilters: ["\(testDir)/...",
+                                                  "blaze-bin/...",
+                                                  "blaze-genfiles/..."],
+                                                additionalFilePaths: additionalFilePaths,
+                                                outputDir: "tulsi_e2e_output/") else {
+                                                  // The test has already been marked as failed.
+                                                  return
+    }
+
+    let diffLines = diffProjectAt(projectURL, againstGoldenProject: projectName)
+    validateDiff(diffLines)
+  }
+
   func test_simpleCCProject() {
     let testDir = "tulsi_e2e_ccsimple"
     let appLabel = BuildLabel("//\(testDir):ccBinary")
diff --git a/src/TulsiGeneratorIntegrationTests/Resources/GoldenProjects/MacOSTestsProject.xcodeproj/project.pbxproj b/src/TulsiGeneratorIntegrationTests/Resources/GoldenProjects/MacOSTestsProject.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..7b9b3cf
--- /dev/null
+++ b/src/TulsiGeneratorIntegrationTests/Resources/GoldenProjects/MacOSTestsProject.xcodeproj/project.pbxproj
@@ -0,0 +1,929 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		E6AF49472511224F00000000 /* TodayViewController.m in ExtSources */ = {isa = PBXBuildFile; fileRef = 43D68C282511224F00000000 /* TodayViewController.m */; };
+		E6AF49473C553F8E00000000 /* main.m in src */ = {isa = PBXBuildFile; fileRef = 43D68C283C553F8E00000000 /* main.m */; };
+		E6AF494759FC82CA00000000 /* AppDelegate.m in src */ = {isa = PBXBuildFile; fileRef = 43D68C2859FC82CA00000000 /* AppDelegate.m */; };
+		E6AF494767EA07A300000000 /* UITests.m in test */ = {isa = PBXBuildFile; fileRef = 43D68C2867EA07A300000000 /* UITests.m */; };
+		E6AF494767EA07A300000001 /* UITests.m in test */ = {isa = PBXBuildFile; fileRef = 43D68C2867EA07A300000000 /* UITests.m */; };
+		E6AF4947C47949AB00000000 /* UnitTests.m in test */ = {isa = PBXBuildFile; fileRef = 43D68C28C47949AB00000000 /* UnitTests.m */; };
+		E6AF4947C47949AB00000001 /* UnitTests.m in test */ = {isa = PBXBuildFile; fileRef = 43D68C28C47949AB00000000 /* UnitTests.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		819366726921D83500000000 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 7E7BD0EA26475A8F00000000 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = ECCC95946921D83400000000;
+		};
+		81936672F53E4F0B00000000 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 7E7BD0EA26475A8F00000000 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 3D31C5E6F53E4F0A00000000;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+		43D68C2810C8DA6C00000000 /* MyMacOSApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; name = MyMacOSApp.app; path = MyMacOSApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		43D68C282511224F00000000 /* TodayViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = TodayViewController.m; path = "tulsi-workspace/tulsi_e2e_mac/src/extensions/today/ExtSources/TodayViewController.m"; sourceTree = "<group>"; };
+		43D68C2834A5AC2900000000 /* TodayViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = TodayViewController.xib; path = "tulsi-workspace/tulsi_e2e_mac/Resources/extensions/today/TodayViewController.xib"; sourceTree = "<group>"; };
+		43D68C283646FFE900000000 /* MyTodayExtension-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; name = "MyTodayExtension-Info.plist"; path = "tulsi-workspace/tulsi_e2e_mac/MyTodayExtension-Info.plist"; sourceTree = "<group>"; };
+		43D68C283C553F8E00000000 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = main.m; path = "tulsi-workspace/tulsi_e2e_mac/src/main.m"; sourceTree = "<group>"; };
+		43D68C283E3D735200000000 /* UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; name = UITests.xctest; path = UITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+		43D68C2859BF633C00000000 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = "tulsi-workspace/tulsi_e2e_mac/src/AppDelegate.h"; sourceTree = "<group>"; };
+		43D68C2859FC82CA00000000 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = "tulsi-workspace/tulsi_e2e_mac/src/AppDelegate.m"; sourceTree = "<group>"; };
+		43D68C2867EA07A300000000 /* UITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = UITests.m; path = "tulsi-workspace/tulsi_e2e_mac/test/UITests.m"; sourceTree = "<group>"; };
+		43D68C286BE5C4F400000000 /* TodayViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TodayViewController.h; path = "tulsi-workspace/tulsi_e2e_mac/src/extensions/today/TodayViewController.h"; sourceTree = "<group>"; };
+		43D68C2870F6EB5A00000000 /* UnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; name = UnitTests.xctest; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+		43D68C2876BC0BC700000000 /* MyTodayExtension-Entitlements.entitlements */ = {isa = PBXFileReference; lastKnownFileType = "com.apple.xcode.entitlements-property-list"; name = "MyTodayExtension-Entitlements.entitlements"; path = "tulsi-workspace/tulsi_e2e_mac/MyTodayExtension-Entitlements.entitlements"; sourceTree = "<group>"; };
+		43D68C289199386500000000 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; name = Info.plist; path = "tulsi-workspace/tulsi_e2e_mac/Info.plist"; sourceTree = "<group>"; };
+		43D68C289D2139D400000000 /* lib_idx_MyTodayExtensionSources_MyMacAppSources_60F77E70.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; name = lib_idx_MyTodayExtensionSources_MyMacAppSources_60F77E70.a; path = lib_idx_MyTodayExtensionSources_MyMacAppSources_60F77E70.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		43D68C28C47949AB00000000 /* UnitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = UnitTests.m; path = "tulsi-workspace/tulsi_e2e_mac/test/UnitTests.m"; sourceTree = "<group>"; };
+		43D68C28CBE52D2300000000 /* BUILD */ = {isa = PBXFileReference; lastKnownFileType = text; name = BUILD; path = tulsi_e2e_mac/BUILD; sourceTree = "<group>"; };
+		43D68C28DE68C70F00000000 /* Main.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Main.storyboard; path = "tulsi-workspace/tulsi_e2e_mac/Resources/Main.storyboard"; sourceTree = "<group>"; };
+		43D68C28DF4AEE6A00000000 /* lib_idx_UnitTestsLib_UITestsLib_F31E7B72.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; name = lib_idx_UnitTestsLib_UITestsLib_F31E7B72.a; path = lib_idx_UnitTestsLib_UITestsLib_F31E7B72.a; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXGroup section */
+		966FB6DE05FFEC7B00000000 /* extensions */ = {
+			isa = PBXGroup;
+			children = (
+				966FB6DEA15649C700000000 /* today */,
+			);
+			name = extensions;
+			sourceTree = "<group>";
+		};
+		966FB6DE05FFEC7B00000001 /* extensions */ = {
+			isa = PBXGroup;
+			children = (
+				966FB6DEA15649C700000001 /* today */,
+			);
+			name = extensions;
+			sourceTree = "<group>";
+		};
+		966FB6DE200CADE500000000 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				43D68C28DE68C70F00000000 /* Main.storyboard */,
+				966FB6DE05FFEC7B00000000 /* extensions */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		966FB6DE2BD1037D00000000 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				43D68C2810C8DA6C00000000 /* MyMacOSApp.app */,
+				43D68C283E3D735200000000 /* UITests.xctest */,
+				43D68C2870F6EB5A00000000 /* UnitTests.xctest */,
+				43D68C289D2139D400000000 /* lib_idx_MyTodayExtensionSources_MyMacAppSources_60F77E70.a */,
+				43D68C28DF4AEE6A00000000 /* lib_idx_UnitTestsLib_UITestsLib_F31E7B72.a */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		966FB6DE6B4B9B2500000000 /* test */ = {
+			isa = PBXGroup;
+			children = (
+				43D68C2867EA07A300000000 /* UITests.m */,
+				43D68C28C47949AB00000000 /* UnitTests.m */,
+			);
+			name = test;
+			sourceTree = "<group>";
+		};
+		966FB6DE97B5B88200000000 /* src */ = {
+			isa = PBXGroup;
+			children = (
+				43D68C2859BF633C00000000 /* AppDelegate.h */,
+				43D68C2859FC82CA00000000 /* AppDelegate.m */,
+				966FB6DE05FFEC7B00000001 /* extensions */,
+				43D68C283C553F8E00000000 /* main.m */,
+			);
+			name = src;
+			sourceTree = "<group>";
+		};
+		966FB6DE987F633E00000000 /* ExtSources */ = {
+			isa = PBXGroup;
+			children = (
+				43D68C282511224F00000000 /* TodayViewController.m */,
+			);
+			name = ExtSources;
+			sourceTree = "<group>";
+		};
+		966FB6DEA121610800000000 /* tulsi_e2e_mac */ = {
+			isa = PBXGroup;
+			children = (
+				43D68C28CBE52D2300000000 /* BUILD */,
+				43D68C289199386500000000 /* Info.plist */,
+				43D68C2876BC0BC700000000 /* MyTodayExtension-Entitlements.entitlements */,
+				43D68C283646FFE900000000 /* MyTodayExtension-Info.plist */,
+				966FB6DE200CADE500000000 /* Resources */,
+				966FB6DE97B5B88200000000 /* src */,
+				966FB6DE6B4B9B2500000000 /* test */,
+			);
+			name = tulsi_e2e_mac;
+			sourceTree = "<group>";
+		};
+		966FB6DEA15649C700000000 /* today */ = {
+			isa = PBXGroup;
+			children = (
+				43D68C2834A5AC2900000000 /* TodayViewController.xib */,
+			);
+			name = today;
+			sourceTree = "<group>";
+		};
+		966FB6DEA15649C700000001 /* today */ = {
+			isa = PBXGroup;
+			children = (
+				966FB6DE987F633E00000000 /* ExtSources */,
+				43D68C286BE5C4F400000000 /* TodayViewController.h */,
+			);
+			name = today;
+			sourceTree = "<group>";
+		};
+		966FB6DEB6031FE700000000 /* mainGroup */ = {
+			isa = PBXGroup;
+			children = (
+				966FB6DE2BD1037D00000000 /* Products */,
+				966FB6DEA121610800000000 /* tulsi_e2e_mac */,
+			);
+			name = mainGroup;
+			path = ../..;
+			sourceTree = SOURCE_ROOT;
+		};
+/* End PBXGroup section */
+
+/* Begin PBXLegacyTarget section */
+		ECCC95946921D83400000000 /* _bazel_clean_ */ = {
+			isa = PBXLegacyTarget;
+			buildArgumentsString = "\"/fake/tulsi_test_bazel\" \"blaze-bin\"";
+			buildConfigurationList = DE475583CA83BF7E00000000 /* Build configuration list for PBXLegacyTarget "_bazel_clean_" */;
+			buildPhases = (
+			);
+			buildToolPath = "${PROJECT_FILE_PATH}/.tulsi/Scripts/bazel_clean.sh";
+			buildWorkingDirectory = "${SRCROOT}/../..";
+			dependencies = (
+			);
+			name = _bazel_clean_;
+			passBuildSettingsInEnvironment = 1;
+			productName = _bazel_clean_;
+		};
+/* End PBXLegacyTarget section */
+
+/* Begin PBXNativeTarget section */
+		3D31C5E619998B3A00000000 /* UnitTests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = DE47558302B841D300000000 /* Build configuration list for PBXNativeTarget "UnitTests" */;
+			buildPhases = (
+				84B422719AEB146200000000 /* ShellScript */,
+				605793E20000000000000000 /* Sources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				4DAD0B426921D83500000000 /* PBXTargetDependency */,
+				4DAD0B42F53E4F0B00000000 /* PBXTargetDependency */,
+			);
+			name = UnitTests;
+			productName = UnitTests;
+			productReference = 43D68C2870F6EB5A00000000 /* UnitTests.xctest */;
+			productType = "com.apple.product-type.bundle.unit-test";
+		};
+		3D31C5E63E63044200000000 /* _idx_MyTodayExtensionSources_MyMacAppSources_60F77E70 */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = DE475583CD23F30700000000 /* Build configuration list for PBXNativeTarget "_idx_MyTodayExtensionSources_MyMacAppSources_60F77E70" */;
+			buildPhases = (
+				605793E20000000000000002 /* Sources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				4DAD0B426921D83500000000 /* PBXTargetDependency */,
+			);
+			name = _idx_MyTodayExtensionSources_MyMacAppSources_60F77E70;
+			productName = _idx_MyTodayExtensionSources_MyMacAppSources_60F77E70;
+			productReference = 43D68C289D2139D400000000 /* lib_idx_MyTodayExtensionSources_MyMacAppSources_60F77E70.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		3D31C5E660313F3200000000 /* UITests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = DE475583737127CF00000000 /* Build configuration list for PBXNativeTarget "UITests" */;
+			buildPhases = (
+				84B4227183F1866200000000 /* ShellScript */,
+				605793E20000000000000001 /* Sources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				4DAD0B426921D83500000000 /* PBXTargetDependency */,
+				4DAD0B42F53E4F0B00000000 /* PBXTargetDependency */,
+			);
+			name = UITests;
+			productName = UITests;
+			productReference = 43D68C283E3D735200000000 /* UITests.xctest */;
+			productType = "com.apple.product-type.bundle.ui-testing";
+		};
+		3D31C5E6CE26869000000000 /* _idx_UnitTestsLib_UITestsLib_F31E7B72 */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = DE475583C1784B5E00000000 /* Build configuration list for PBXNativeTarget "_idx_UnitTestsLib_UITestsLib_F31E7B72" */;
+			buildPhases = (
+				605793E20000000000000003 /* Sources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				4DAD0B426921D83500000000 /* PBXTargetDependency */,
+			);
+			name = _idx_UnitTestsLib_UITestsLib_F31E7B72;
+			productName = _idx_UnitTestsLib_UITestsLib_F31E7B72;
+			productReference = 43D68C28DF4AEE6A00000000 /* lib_idx_UnitTestsLib_UITestsLib_F31E7B72.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		3D31C5E6F53E4F0A00000000 /* MyMacOSApp */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = DE47558336864DFB00000000 /* Build configuration list for PBXNativeTarget "MyMacOSApp" */;
+			buildPhases = (
+				84B42271DD6C746100000000 /* ShellScript */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				4DAD0B426921D83500000000 /* PBXTargetDependency */,
+			);
+			name = MyMacOSApp;
+			productName = MyMacOSApp;
+			productReference = 43D68C2810C8DA6C00000000 /* MyMacOSApp.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		7E7BD0EA26475A8F00000000 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastSwiftUpdateCheck = 0710;
+				LastUpgradeCheck = 0830;
+				TargetAttributes = {
+					3D31C5E619998B3A00000000 = {
+						TestTargetID = 3D31C5E6F53E4F0A00000000;
+					};
+					3D31C5E660313F3200000000 = {
+						TestTargetID = 3D31C5E6F53E4F0A00000000;
+					};
+				};
+			};
+			buildConfigurationList = DE47558382AEE2C900000000 /* Build configuration list for PBXProject "MacOSTestsProject" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+			);
+			mainGroup = 966FB6DEB6031FE700000000 /* mainGroup */;
+			targets = (
+				3D31C5E6F53E4F0A00000000 /* MyMacOSApp */,
+				3D31C5E660313F3200000000 /* UITests */,
+				3D31C5E619998B3A00000000 /* UnitTests */,
+				ECCC95946921D83400000000 /* _bazel_clean_ */,
+				3D31C5E63E63044200000000 /* _idx_MyTodayExtensionSources_MyMacAppSources_60F77E70 */,
+				3D31C5E6CE26869000000000 /* _idx_UnitTestsLib_UITestsLib_F31E7B72 */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		84B4227183F1866200000000 /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 0;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/bash;
+			shellScript = "set -e\ncd \"${SRCROOT}/../..\"\nexec \"${PROJECT_FILE_PATH}/.tulsi/Scripts/bazel_build.py\" //tulsi_e2e_mac:UITests --bazel \"/fake/tulsi_test_bazel\" --bazel_bin_path \"blaze-bin\" --verbose --bazel_options[Release] --define=TULSI_TEST=rel --ios_minimum_os=7.0 --macos_minimum_os=10.10 --tvos_minimum_os=10.0 --watchos_minimum_os=3.0 -- --bazel_options[Debug] --define=TULSI_TEST=dbg --ios_minimum_os=7.0 --macos_minimum_os=10.10 --tvos_minimum_os=10.0 --watchos_minimum_os=3.0 -- --bazel_startup_options[Debug] --blazerc=/dev/null --  --install_generated_artifacts";
+			showEnvVarsInLog = 1;
+		};
+		84B422719AEB146200000000 /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 0;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/bash;
+			shellScript = "set -e\ncd \"${SRCROOT}/../..\"\nexec \"${PROJECT_FILE_PATH}/.tulsi/Scripts/bazel_build.py\" //tulsi_e2e_mac:UnitTests --bazel \"/fake/tulsi_test_bazel\" --bazel_bin_path \"blaze-bin\" --verbose --bazel_options[Release] --define=TULSI_TEST=rel --ios_minimum_os=7.0 --macos_minimum_os=10.10 --tvos_minimum_os=10.0 --watchos_minimum_os=3.0 -- --bazel_options[Debug] --define=TULSI_TEST=dbg --ios_minimum_os=7.0 --macos_minimum_os=10.10 --tvos_minimum_os=10.0 --watchos_minimum_os=3.0 -- --bazel_startup_options[Debug] --blazerc=/dev/null --  --install_generated_artifacts";
+			showEnvVarsInLog = 1;
+		};
+		84B42271DD6C746100000000 /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 0;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/bash;
+			shellScript = "set -e\ncd \"${SRCROOT}/../..\"\nexec \"${PROJECT_FILE_PATH}/.tulsi/Scripts/bazel_build.py\" //tulsi_e2e_mac:MyMacOSApp --bazel \"/fake/tulsi_test_bazel\" --bazel_bin_path \"blaze-bin\" --verbose --bazel_options[Release] --define=TULSI_TEST=rel --ios_minimum_os=7.0 --macos_minimum_os=10.10 --tvos_minimum_os=10.0 --watchos_minimum_os=3.0 -- --bazel_options[Debug] --define=TULSI_TEST=dbg --ios_minimum_os=7.0 --macos_minimum_os=10.10 --tvos_minimum_os=10.0 --watchos_minimum_os=3.0 -- --bazel_startup_options[Debug] --blazerc=/dev/null --  --install_generated_artifacts";
+			showEnvVarsInLog = 1;
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		605793E20000000000000000 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 0;
+			files = (
+				E6AF4947C47949AB00000000 /* UnitTests.m in test */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		605793E20000000000000001 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 0;
+			files = (
+				E6AF494767EA07A300000000 /* UITests.m in test */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		605793E20000000000000002 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 0;
+			files = (
+				E6AF49472511224F00000000 /* TodayViewController.m in ExtSources */,
+				E6AF494759FC82CA00000000 /* AppDelegate.m in src */,
+				E6AF49473C553F8E00000000 /* main.m in src */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		605793E20000000000000003 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 0;
+			files = (
+				E6AF4947C47949AB00000001 /* UnitTests.m in test */,
+				E6AF494767EA07A300000001 /* UITests.m in test */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		4DAD0B426921D83500000000 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			targetProxy = 819366726921D83500000000 /* PBXContainerItemProxy */;
+		};
+		4DAD0B42F53E4F0B00000000 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			targetProxy = 81936672F53E4F0B00000000 /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+		44936BD67EED3C4D00000000 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Stub Launch Image";
+				BAZEL_TARGET = "//tulsi_e2e_mac:UnitTests";
+				BAZEL_TARGET_TYPE = apple_unit_test;
+				BUNDLE_LOADER = "$(TEST_HOST)";
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
+				INFOPLIST_FILE = "${PROJECT_FILE_PATH}/.tulsi/Resources/StubInfoPlist.plist";
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				PRODUCT_NAME = UnitTests;
+				SDKROOT = macosx;
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MyMacOSApp.app/Contents/MacOS/MyMacOSApp";
+				TULSI_BUILD_PATH = tulsi_e2e_mac;
+				TULSI_TEST_RUNNER_ONLY = YES;
+				TULSI_USE_DSYM = NO;
+			};
+			name = Debug;
+		};
+		44936BD67EED3C4D00000001 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Stub Launch Image";
+				BAZEL_TARGET = "//tulsi_e2e_mac:MyMacOSApp";
+				BAZEL_TARGET_TYPE = _test_host_;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
+				INFOPLIST_FILE = "${PROJECT_FILE_PATH}/.tulsi/Resources/StubInfoPlist.plist";
+				PRODUCT_NAME = MyMacOSApp;
+				SDKROOT = iphoneos;
+				TULSI_BUILD_PATH = tulsi_e2e_mac;
+				TULSI_USE_DSYM = NO;
+			};
+			name = Debug;
+		};
+		44936BD67EED3C4D00000002 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Stub Launch Image";
+				BAZEL_TARGET = "//tulsi_e2e_mac:UITests";
+				BAZEL_TARGET_TYPE = apple_ui_test;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
+				INFOPLIST_FILE = "${PROJECT_FILE_PATH}/.tulsi/Resources/StubInfoPlist.plist";
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				PRODUCT_NAME = UITests;
+				SDKROOT = macosx;
+				TEST_TARGET_NAME = MyMacOSApp;
+				TULSI_BUILD_PATH = tulsi_e2e_mac;
+				TULSI_TEST_RUNNER_ONLY = YES;
+				TULSI_USE_DSYM = NO;
+			};
+			name = Debug;
+		};
+		44936BD67EED3C4D00000003 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGNING_REQUIRED = NO;
+				CODE_SIGN_IDENTITY = "";
+				ENABLE_TESTABILITY = YES;
+				FRAMEWORK_SEARCH_PATHS = "$(PLATFORM_DIR)/Developer/Library/Frameworks";
+				GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = "$(TULSI_BWRS) $(TULSI_WR)/blaze-bin $(TULSI_WR)/blaze-genfiles $(TULSI_BWRS)/tulsi-includes/x/x";
+				ONLY_ACTIVE_ARCH = YES;
+				TULSI_BWRS = "${TULSI_WR}/tulsi-workspace";
+				TULSI_PROJECT = MacOSTestsProject;
+				TULSI_USE_BEP = YES;
+				TULSI_VERSION = 9.99.999.9999;
+				TULSI_WR = "${SRCROOT}/../..";
+			};
+			name = Debug;
+		};
+		44936BD67EED3C4D00000004 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = x86_64;
+				GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
+				HEADER_SEARCH_PATHS = "$(inherited) $(TULSI_BWRS)/tools/cpp/gcc3 ";
+				MACOSX_DEPLOYMENT_TARGET = 10.12;
+				PRODUCT_NAME = _idx_MyTodayExtensionSources_MyMacAppSources_60F77E70;
+				SDKROOT = macosx;
+				VALID_ARCHS = x86_64;
+			};
+			name = Debug;
+		};
+		44936BD67EED3C4D00000005 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = x86_64;
+				GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
+				HEADER_SEARCH_PATHS = "$(inherited) $(TULSI_BWRS)/tools/cpp/gcc3 ";
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				PRODUCT_NAME = _idx_UnitTestsLib_UITestsLib_F31E7B72;
+				SDKROOT = macosx;
+				VALID_ARCHS = x86_64;
+			};
+			name = Debug;
+		};
+		44936BD6A3D45CE900000000 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Stub Launch Image";
+				BAZEL_TARGET = "//tulsi_e2e_mac:UnitTests";
+				BAZEL_TARGET_TYPE = apple_unit_test;
+				BUNDLE_LOADER = "$(TEST_HOST)";
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1";
+				INFOPLIST_FILE = "${PROJECT_FILE_PATH}/.tulsi/Resources/StubInfoPlist.plist";
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				PRODUCT_NAME = UnitTests;
+				SDKROOT = macosx;
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MyMacOSApp.app/Contents/MacOS/MyMacOSApp";
+				TULSI_BUILD_PATH = tulsi_e2e_mac;
+				TULSI_TEST_RUNNER_ONLY = YES;
+				TULSI_USE_DSYM = YES;
+			};
+			name = Release;
+		};
+		44936BD6A3D45CE900000001 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Stub Launch Image";
+				BAZEL_TARGET = "//tulsi_e2e_mac:MyMacOSApp";
+				BAZEL_TARGET_TYPE = _test_host_;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1";
+				INFOPLIST_FILE = "${PROJECT_FILE_PATH}/.tulsi/Resources/StubInfoPlist.plist";
+				PRODUCT_NAME = MyMacOSApp;
+				SDKROOT = iphoneos;
+				TULSI_BUILD_PATH = tulsi_e2e_mac;
+				TULSI_USE_DSYM = YES;
+			};
+			name = Release;
+		};
+		44936BD6A3D45CE900000002 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Stub Launch Image";
+				BAZEL_TARGET = "//tulsi_e2e_mac:UITests";
+				BAZEL_TARGET_TYPE = apple_ui_test;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1";
+				INFOPLIST_FILE = "${PROJECT_FILE_PATH}/.tulsi/Resources/StubInfoPlist.plist";
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				PRODUCT_NAME = UITests;
+				SDKROOT = macosx;
+				TEST_TARGET_NAME = MyMacOSApp;
+				TULSI_BUILD_PATH = tulsi_e2e_mac;
+				TULSI_TEST_RUNNER_ONLY = YES;
+				TULSI_USE_DSYM = YES;
+			};
+			name = Release;
+		};
+		44936BD6A3D45CE900000003 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGNING_REQUIRED = NO;
+				CODE_SIGN_IDENTITY = "";
+				ENABLE_TESTABILITY = YES;
+				FRAMEWORK_SEARCH_PATHS = "$(PLATFORM_DIR)/Developer/Library/Frameworks";
+				GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1";
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = "$(TULSI_BWRS) $(TULSI_WR)/blaze-bin $(TULSI_WR)/blaze-genfiles $(TULSI_BWRS)/tulsi-includes/x/x";
+				ONLY_ACTIVE_ARCH = YES;
+				TULSI_BWRS = "${TULSI_WR}/tulsi-workspace";
+				TULSI_PROJECT = MacOSTestsProject;
+				TULSI_USE_BEP = YES;
+				TULSI_USE_DSYM = YES;
+				TULSI_VERSION = 9.99.999.9999;
+				TULSI_WR = "${SRCROOT}/../..";
+			};
+			name = Release;
+		};
+		44936BD6A3D45CE900000004 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = x86_64;
+				GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1";
+				HEADER_SEARCH_PATHS = "$(inherited) $(TULSI_BWRS)/tools/cpp/gcc3 ";
+				MACOSX_DEPLOYMENT_TARGET = 10.12;
+				PRODUCT_NAME = _idx_MyTodayExtensionSources_MyMacAppSources_60F77E70;
+				SDKROOT = macosx;
+				VALID_ARCHS = x86_64;
+			};
+			name = Release;
+		};
+		44936BD6A3D45CE900000005 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = x86_64;
+				GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1";
+				HEADER_SEARCH_PATHS = "$(inherited) $(TULSI_BWRS)/tools/cpp/gcc3 ";
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				PRODUCT_NAME = _idx_UnitTestsLib_UITestsLib_F31E7B72;
+				SDKROOT = macosx;
+				VALID_ARCHS = x86_64;
+			};
+			name = Release;
+		};
+		44936BD6C928366700000000 /* __TulsiTestRunner_Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Stub Launch Image";
+				BAZEL_TARGET = "//tulsi_e2e_mac:UnitTests";
+				BAZEL_TARGET_TYPE = apple_unit_test;
+				BUNDLE_LOADER = "$(TEST_HOST)";
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				FRAMEWORK_SEARCH_PATHS = "";
+				GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
+				HEADER_SEARCH_PATHS = "";
+				INFOPLIST_FILE = "${PROJECT_FILE_PATH}/.tulsi/Resources/StubInfoPlist.plist";
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_CFLAGS = "-help";
+				OTHER_LDFLAGS = "-help";
+				OTHER_SWIFT_FLAGS = "-help";
+				PRODUCT_NAME = UnitTests;
+				SDKROOT = macosx;
+				SWIFT_INSTALL_OBJC_HEADER = NO;
+				SWIFT_OBJC_INTERFACE_HEADER_NAME = "$(PRODUCT_NAME).h";
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MyMacOSApp.app/Contents/MacOS/MyMacOSApp";
+				TULSI_BUILD_PATH = tulsi_e2e_mac;
+				TULSI_TEST_RUNNER_ONLY = YES;
+				TULSI_USE_DSYM = NO;
+			};
+			name = __TulsiTestRunner_Debug;
+		};
+		44936BD6C928366700000001 /* __TulsiTestRunner_Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Stub Launch Image";
+				BAZEL_TARGET = "//tulsi_e2e_mac:MyMacOSApp";
+				BAZEL_TARGET_TYPE = _test_host_;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				FRAMEWORK_SEARCH_PATHS = "";
+				GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
+				HEADER_SEARCH_PATHS = "";
+				INFOPLIST_FILE = "${PROJECT_FILE_PATH}/.tulsi/Resources/StubInfoPlist.plist";
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_CFLAGS = "-help";
+				OTHER_LDFLAGS = "-help";
+				OTHER_SWIFT_FLAGS = "-help";
+				PRODUCT_NAME = MyMacOSApp;
+				SDKROOT = iphoneos;
+				SWIFT_INSTALL_OBJC_HEADER = NO;
+				SWIFT_OBJC_INTERFACE_HEADER_NAME = "$(PRODUCT_NAME).h";
+				TULSI_BUILD_PATH = tulsi_e2e_mac;
+				TULSI_USE_DSYM = NO;
+			};
+			name = __TulsiTestRunner_Debug;
+		};
+		44936BD6C928366700000002 /* __TulsiTestRunner_Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Stub Launch Image";
+				BAZEL_TARGET = "//tulsi_e2e_mac:UITests";
+				BAZEL_TARGET_TYPE = apple_ui_test;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				FRAMEWORK_SEARCH_PATHS = "";
+				GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
+				HEADER_SEARCH_PATHS = "";
+				INFOPLIST_FILE = "${PROJECT_FILE_PATH}/.tulsi/Resources/StubInfoPlist.plist";
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_CFLAGS = "-help";
+				OTHER_LDFLAGS = "-help";
+				OTHER_SWIFT_FLAGS = "-help";
+				PRODUCT_NAME = UITests;
+				SDKROOT = macosx;
+				SWIFT_INSTALL_OBJC_HEADER = NO;
+				SWIFT_OBJC_INTERFACE_HEADER_NAME = "$(PRODUCT_NAME).h";
+				TEST_TARGET_NAME = MyMacOSApp;
+				TULSI_BUILD_PATH = tulsi_e2e_mac;
+				TULSI_TEST_RUNNER_ONLY = YES;
+				TULSI_USE_DSYM = NO;
+			};
+			name = __TulsiTestRunner_Debug;
+		};
+		44936BD6C928366700000003 /* __TulsiTestRunner_Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGNING_REQUIRED = NO;
+				CODE_SIGN_IDENTITY = "";
+				ENABLE_TESTABILITY = YES;
+				FRAMEWORK_SEARCH_PATHS = "";
+				GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = "";
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_CFLAGS = "-help";
+				OTHER_LDFLAGS = "-help";
+				OTHER_SWIFT_FLAGS = "-help";
+				SWIFT_INSTALL_OBJC_HEADER = NO;
+				SWIFT_OBJC_INTERFACE_HEADER_NAME = "$(PRODUCT_NAME).h";
+				TULSI_BWRS = "${TULSI_WR}/tulsi-workspace";
+				TULSI_PROJECT = MacOSTestsProject;
+				TULSI_USE_BEP = YES;
+				TULSI_VERSION = 9.99.999.9999;
+				TULSI_WR = "${SRCROOT}/../..";
+			};
+			name = __TulsiTestRunner_Debug;
+		};
+		44936BD6FCBCA00300000000 /* __TulsiTestRunner_Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Stub Launch Image";
+				BAZEL_TARGET = "//tulsi_e2e_mac:UnitTests";
+				BAZEL_TARGET_TYPE = apple_unit_test;
+				BUNDLE_LOADER = "$(TEST_HOST)";
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				FRAMEWORK_SEARCH_PATHS = "";
+				GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1";
+				HEADER_SEARCH_PATHS = "";
+				INFOPLIST_FILE = "${PROJECT_FILE_PATH}/.tulsi/Resources/StubInfoPlist.plist";
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_CFLAGS = "-help";
+				OTHER_LDFLAGS = "-help";
+				OTHER_SWIFT_FLAGS = "-help";
+				PRODUCT_NAME = UnitTests;
+				SDKROOT = macosx;
+				SWIFT_INSTALL_OBJC_HEADER = NO;
+				SWIFT_OBJC_INTERFACE_HEADER_NAME = "$(PRODUCT_NAME).h";
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MyMacOSApp.app/Contents/MacOS/MyMacOSApp";
+				TULSI_BUILD_PATH = tulsi_e2e_mac;
+				TULSI_TEST_RUNNER_ONLY = YES;
+				TULSI_USE_DSYM = YES;
+			};
+			name = __TulsiTestRunner_Release;
+		};
+		44936BD6FCBCA00300000001 /* __TulsiTestRunner_Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Stub Launch Image";
+				BAZEL_TARGET = "//tulsi_e2e_mac:MyMacOSApp";
+				BAZEL_TARGET_TYPE = _test_host_;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				FRAMEWORK_SEARCH_PATHS = "";
+				GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1";
+				HEADER_SEARCH_PATHS = "";
+				INFOPLIST_FILE = "${PROJECT_FILE_PATH}/.tulsi/Resources/StubInfoPlist.plist";
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_CFLAGS = "-help";
+				OTHER_LDFLAGS = "-help";
+				OTHER_SWIFT_FLAGS = "-help";
+				PRODUCT_NAME = MyMacOSApp;
+				SDKROOT = iphoneos;
+				SWIFT_INSTALL_OBJC_HEADER = NO;
+				SWIFT_OBJC_INTERFACE_HEADER_NAME = "$(PRODUCT_NAME).h";
+				TULSI_BUILD_PATH = tulsi_e2e_mac;
+				TULSI_USE_DSYM = YES;
+			};
+			name = __TulsiTestRunner_Release;
+		};
+		44936BD6FCBCA00300000002 /* __TulsiTestRunner_Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Stub Launch Image";
+				BAZEL_TARGET = "//tulsi_e2e_mac:UITests";
+				BAZEL_TARGET_TYPE = apple_ui_test;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				FRAMEWORK_SEARCH_PATHS = "";
+				GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1";
+				HEADER_SEARCH_PATHS = "";
+				INFOPLIST_FILE = "${PROJECT_FILE_PATH}/.tulsi/Resources/StubInfoPlist.plist";
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_CFLAGS = "-help";
+				OTHER_LDFLAGS = "-help";
+				OTHER_SWIFT_FLAGS = "-help";
+				PRODUCT_NAME = UITests;
+				SDKROOT = macosx;
+				SWIFT_INSTALL_OBJC_HEADER = NO;
+				SWIFT_OBJC_INTERFACE_HEADER_NAME = "$(PRODUCT_NAME).h";
+				TEST_TARGET_NAME = MyMacOSApp;
+				TULSI_BUILD_PATH = tulsi_e2e_mac;
+				TULSI_TEST_RUNNER_ONLY = YES;
+				TULSI_USE_DSYM = YES;
+			};
+			name = __TulsiTestRunner_Release;
+		};
+		44936BD6FCBCA00300000003 /* __TulsiTestRunner_Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGNING_REQUIRED = NO;
+				CODE_SIGN_IDENTITY = "";
+				ENABLE_TESTABILITY = YES;
+				FRAMEWORK_SEARCH_PATHS = "";
+				GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1";
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = "";
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_CFLAGS = "-help";
+				OTHER_LDFLAGS = "-help";
+				OTHER_SWIFT_FLAGS = "-help";
+				SWIFT_INSTALL_OBJC_HEADER = NO;
+				SWIFT_OBJC_INTERFACE_HEADER_NAME = "$(PRODUCT_NAME).h";
+				TULSI_BWRS = "${TULSI_WR}/tulsi-workspace";
+				TULSI_PROJECT = MacOSTestsProject;
+				TULSI_USE_BEP = YES;
+				TULSI_USE_DSYM = YES;
+				TULSI_VERSION = 9.99.999.9999;
+				TULSI_WR = "${SRCROOT}/../..";
+			};
+			name = __TulsiTestRunner_Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		DE47558302B841D300000000 /* Build configuration list for PBXNativeTarget "UnitTests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				44936BD67EED3C4D00000000 /* Debug */,
+				44936BD6A3D45CE900000000 /* Release */,
+				44936BD6C928366700000000 /* __TulsiTestRunner_Debug */,
+				44936BD6FCBCA00300000000 /* __TulsiTestRunner_Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+		};
+		DE47558336864DFB00000000 /* Build configuration list for PBXNativeTarget "MyMacOSApp" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				44936BD67EED3C4D00000001 /* Debug */,
+				44936BD6A3D45CE900000001 /* Release */,
+				44936BD6C928366700000001 /* __TulsiTestRunner_Debug */,
+				44936BD6FCBCA00300000001 /* __TulsiTestRunner_Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+		};
+		DE475583737127CF00000000 /* Build configuration list for PBXNativeTarget "UITests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				44936BD67EED3C4D00000002 /* Debug */,
+				44936BD6A3D45CE900000002 /* Release */,
+				44936BD6C928366700000002 /* __TulsiTestRunner_Debug */,
+				44936BD6FCBCA00300000002 /* __TulsiTestRunner_Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+		};
+		DE47558382AEE2C900000000 /* Build configuration list for PBXProject "MacOSTestsProject" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				44936BD67EED3C4D00000003 /* Debug */,
+				44936BD6A3D45CE900000003 /* Release */,
+				44936BD6C928366700000003 /* __TulsiTestRunner_Debug */,
+				44936BD6FCBCA00300000003 /* __TulsiTestRunner_Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+		};
+		DE475583C1784B5E00000000 /* Build configuration list for PBXNativeTarget "_idx_UnitTestsLib_UITestsLib_F31E7B72" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				44936BD67EED3C4D00000005 /* Debug */,
+				44936BD6A3D45CE900000005 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+		};
+		DE475583CA83BF7E00000000 /* Build configuration list for PBXLegacyTarget "_bazel_clean_" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+			);
+			defaultConfigurationIsVisible = 0;
+		};
+		DE475583CD23F30700000000 /* Build configuration list for PBXNativeTarget "_idx_MyTodayExtensionSources_MyMacAppSources_60F77E70" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				44936BD67EED3C4D00000004 /* Debug */,
+				44936BD6A3D45CE900000004 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 7E7BD0EA26475A8F00000000 /* Project object */;
+}
\ No newline at end of file
diff --git a/src/TulsiGeneratorIntegrationTests/Resources/GoldenProjects/MacOSTestsProject.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/src/TulsiGeneratorIntegrationTests/Resources/GoldenProjects/MacOSTestsProject.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 0000000..08de0be
--- /dev/null
+++ b/src/TulsiGeneratorIntegrationTests/Resources/GoldenProjects/MacOSTestsProject.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
+	<false/>
+</dict>
+</plist>
diff --git a/src/TulsiGeneratorIntegrationTests/Resources/GoldenProjects/MacOSTestsProject.xcodeproj/project.xcworkspace/xcuserdata/_TEST_USER_.xcuserdatad/WorkspaceSettings.xcsettings b/src/TulsiGeneratorIntegrationTests/Resources/GoldenProjects/MacOSTestsProject.xcodeproj/project.xcworkspace/xcuserdata/_TEST_USER_.xcuserdatad/WorkspaceSettings.xcsettings
new file mode 100644
index 0000000..8ab079c
--- /dev/null
+++ b/src/TulsiGeneratorIntegrationTests/Resources/GoldenProjects/MacOSTestsProject.xcodeproj/project.xcworkspace/xcuserdata/_TEST_USER_.xcuserdatad/WorkspaceSettings.xcsettings
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IssueFilterStyle</key>
+	<string>ShowAll</string>
+	<key>LiveSourceIssuesEnabled</key>
+	<true/>
+</dict>
+</plist>
diff --git a/src/TulsiGeneratorIntegrationTests/Resources/GoldenProjects/MacOSTestsProject.xcodeproj/xcshareddata/xcschemes/MyMacOSApp.xcscheme b/src/TulsiGeneratorIntegrationTests/Resources/GoldenProjects/MacOSTestsProject.xcodeproj/xcshareddata/xcschemes/MyMacOSApp.xcscheme
new file mode 100644
index 0000000..a53515b
--- /dev/null
+++ b/src/TulsiGeneratorIntegrationTests/Resources/GoldenProjects/MacOSTestsProject.xcodeproj/xcshareddata/xcschemes/MyMacOSApp.xcscheme
@@ -0,0 +1,36 @@
+
+<Scheme LastUpgradeVersion="0830" version="1.3">
+    <BuildAction parallelizeBuildables="YES" buildImplicitDependencies="YES">
+        <BuildActionEntries>
+            <BuildActionEntry buildForArchiving="YES" buildForTesting="YES" buildForRunning="YES" buildForAnalyzing="YES" buildForProfiling="YES">
+                <BuildableReference BlueprintIdentifier="3D31C5E6F53E4F0A00000000" ReferencedContainer="container:MacOSTestsProject.xcodeproj" BuildableName="MyMacOSApp.app" BlueprintName="MyMacOSApp" BuildableIdentifier="primary"></BuildableReference>
+            </BuildActionEntry>
+        </BuildActionEntries>
+    </BuildAction>
+    <TestAction selectedDebuggerIdentifier="Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier="Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv="YES" buildConfiguration="__TulsiTestRunner_Debug">
+        <Testables>
+            <TestableReference skipped="NO">
+                <BuildableReference BlueprintIdentifier="3D31C5E619998B3A00000000" ReferencedContainer="container:MacOSTestsProject.xcodeproj" BuildableName="UnitTests.xctest" BlueprintName="UnitTests" BuildableIdentifier="primary"></BuildableReference>
+            </TestableReference>
+            <TestableReference skipped="NO">
+                <BuildableReference BlueprintIdentifier="3D31C5E660313F3200000000" ReferencedContainer="container:MacOSTestsProject.xcodeproj" BuildableName="UITests.xctest" BlueprintName="UITests" BuildableIdentifier="primary"></BuildableReference>
+            </TestableReference>
+        </Testables>
+        <BuildableProductRunnable runnableDebuggingMode="0">
+            <BuildableReference BlueprintIdentifier="3D31C5E6F53E4F0A00000000" ReferencedContainer="container:MacOSTestsProject.xcodeproj" BuildableName="MyMacOSApp.app" BlueprintName="MyMacOSApp" BuildableIdentifier="primary"></BuildableReference>
+        </BuildableProductRunnable>
+    </TestAction>
+    <LaunchAction selectedDebuggerIdentifier="Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier="Xcode.DebuggerFoundation.Launcher.LLDB" launchStyle="0" buildConfiguration="Debug" debugServiceExtension="internal" ignoresPersistentStateOnLaunch="NO" useCustomWorkingDirectory="NO" allowLocationSimulation="YES" debugDocumentVersioning="YES">
+        <EnvironmentVariables></EnvironmentVariables>
+        <BuildableProductRunnable runnableDebuggingMode="0">
+            <BuildableReference BlueprintIdentifier="3D31C5E6F53E4F0A00000000" ReferencedContainer="container:MacOSTestsProject.xcodeproj" BuildableName="MyMacOSApp.app" BlueprintName="MyMacOSApp" BuildableIdentifier="primary"></BuildableReference>
+        </BuildableProductRunnable>
+    </LaunchAction>
+    <ProfileAction useCustomWorkingDirectory="NO" shouldUseLaunchSchemeArgsEnv="YES" buildConfiguration="__TulsiTestRunner_Release" debugDocumentVersioning="YES">
+        <BuildableProductRunnable runnableDebuggingMode="0">
+            <BuildableReference BlueprintIdentifier="3D31C5E6F53E4F0A00000000" ReferencedContainer="container:MacOSTestsProject.xcodeproj" BuildableName="MyMacOSApp.app" BlueprintName="MyMacOSApp" BuildableIdentifier="primary"></BuildableReference>
+        </BuildableProductRunnable>
+    </ProfileAction>
+    <AnalyzeAction buildConfiguration="Debug"></AnalyzeAction>
+    <ArchiveAction buildConfiguration="Release" revealArchiveInOrganizer="YES"></ArchiveAction>
+</Scheme>
\ No newline at end of file
diff --git a/src/TulsiGeneratorIntegrationTests/Resources/GoldenProjects/MacOSTestsProject.xcodeproj/xcshareddata/xcschemes/UITests.xcscheme b/src/TulsiGeneratorIntegrationTests/Resources/GoldenProjects/MacOSTestsProject.xcodeproj/xcshareddata/xcschemes/UITests.xcscheme
new file mode 100644
index 0000000..32fdf13
--- /dev/null
+++ b/src/TulsiGeneratorIntegrationTests/Resources/GoldenProjects/MacOSTestsProject.xcodeproj/xcshareddata/xcschemes/UITests.xcscheme
@@ -0,0 +1,33 @@
+
+<Scheme LastUpgradeVersion="0830" version="1.3">
+    <BuildAction parallelizeBuildables="YES" buildImplicitDependencies="YES">
+        <BuildActionEntries>
+            <BuildActionEntry buildForArchiving="YES" buildForTesting="YES" buildForRunning="YES" buildForAnalyzing="YES" buildForProfiling="YES">
+                <BuildableReference BlueprintIdentifier="3D31C5E660313F3200000000" ReferencedContainer="container:MacOSTestsProject.xcodeproj" BuildableName="UITests.xctest" BlueprintName="UITests" BuildableIdentifier="primary"></BuildableReference>
+            </BuildActionEntry>
+        </BuildActionEntries>
+    </BuildAction>
+    <TestAction selectedDebuggerIdentifier="Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier="Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv="YES" buildConfiguration="__TulsiTestRunner_Debug">
+        <Testables>
+            <TestableReference skipped="NO">
+                <BuildableReference BlueprintIdentifier="3D31C5E660313F3200000000" ReferencedContainer="container:MacOSTestsProject.xcodeproj" BuildableName="UITests.xctest" BlueprintName="UITests" BuildableIdentifier="primary"></BuildableReference>
+            </TestableReference>
+        </Testables>
+        <BuildableProductRunnable runnableDebuggingMode="0">
+            <BuildableReference BlueprintIdentifier="3D31C5E660313F3200000000" ReferencedContainer="container:MacOSTestsProject.xcodeproj" BuildableName="UITests.xctest" BlueprintName="UITests" BuildableIdentifier="primary"></BuildableReference>
+        </BuildableProductRunnable>
+    </TestAction>
+    <LaunchAction selectedDebuggerIdentifier="Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier="Xcode.DebuggerFoundation.Launcher.LLDB" launchStyle="0" buildConfiguration="Debug" debugServiceExtension="internal" ignoresPersistentStateOnLaunch="NO" useCustomWorkingDirectory="NO" allowLocationSimulation="YES" debugDocumentVersioning="YES">
+        <EnvironmentVariables></EnvironmentVariables>
+        <BuildableProductRunnable runnableDebuggingMode="0">
+            <BuildableReference BlueprintIdentifier="3D31C5E660313F3200000000" ReferencedContainer="container:MacOSTestsProject.xcodeproj" BuildableName="UITests.xctest" BlueprintName="UITests" BuildableIdentifier="primary"></BuildableReference>
+        </BuildableProductRunnable>
+    </LaunchAction>
+    <ProfileAction useCustomWorkingDirectory="NO" shouldUseLaunchSchemeArgsEnv="YES" buildConfiguration="__TulsiTestRunner_Release" debugDocumentVersioning="YES">
+        <BuildableProductRunnable runnableDebuggingMode="0">
+            <BuildableReference BlueprintIdentifier="3D31C5E660313F3200000000" ReferencedContainer="container:MacOSTestsProject.xcodeproj" BuildableName="UITests.xctest" BlueprintName="UITests" BuildableIdentifier="primary"></BuildableReference>
+        </BuildableProductRunnable>
+    </ProfileAction>
+    <AnalyzeAction buildConfiguration="Debug"></AnalyzeAction>
+    <ArchiveAction buildConfiguration="Release" revealArchiveInOrganizer="YES"></ArchiveAction>
+</Scheme>
\ No newline at end of file
diff --git a/src/TulsiGeneratorIntegrationTests/Resources/GoldenProjects/MacOSTestsProject.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme b/src/TulsiGeneratorIntegrationTests/Resources/GoldenProjects/MacOSTestsProject.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme
new file mode 100644
index 0000000..e4df1ff
--- /dev/null
+++ b/src/TulsiGeneratorIntegrationTests/Resources/GoldenProjects/MacOSTestsProject.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme
@@ -0,0 +1,33 @@
+
+<Scheme LastUpgradeVersion="0830" version="1.3">
+    <BuildAction parallelizeBuildables="YES" buildImplicitDependencies="YES">
+        <BuildActionEntries>
+            <BuildActionEntry buildForArchiving="YES" buildForTesting="YES" buildForRunning="YES" buildForAnalyzing="YES" buildForProfiling="YES">
+                <BuildableReference BlueprintIdentifier="3D31C5E619998B3A00000000" ReferencedContainer="container:MacOSTestsProject.xcodeproj" BuildableName="UnitTests.xctest" BlueprintName="UnitTests" BuildableIdentifier="primary"></BuildableReference>
+            </BuildActionEntry>
+        </BuildActionEntries>
+    </BuildAction>
+    <TestAction selectedDebuggerIdentifier="Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier="Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv="YES" buildConfiguration="__TulsiTestRunner_Debug">
+        <Testables>
+            <TestableReference skipped="NO">
+                <BuildableReference BlueprintIdentifier="3D31C5E619998B3A00000000" ReferencedContainer="container:MacOSTestsProject.xcodeproj" BuildableName="UnitTests.xctest" BlueprintName="UnitTests" BuildableIdentifier="primary"></BuildableReference>
+            </TestableReference>
+        </Testables>
+        <BuildableProductRunnable runnableDebuggingMode="0">
+            <BuildableReference BlueprintIdentifier="3D31C5E619998B3A00000000" ReferencedContainer="container:MacOSTestsProject.xcodeproj" BuildableName="UnitTests.xctest" BlueprintName="UnitTests" BuildableIdentifier="primary"></BuildableReference>
+        </BuildableProductRunnable>
+    </TestAction>
+    <LaunchAction selectedDebuggerIdentifier="Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier="Xcode.DebuggerFoundation.Launcher.LLDB" launchStyle="0" buildConfiguration="Debug" debugServiceExtension="internal" ignoresPersistentStateOnLaunch="NO" useCustomWorkingDirectory="NO" allowLocationSimulation="YES" debugDocumentVersioning="YES">
+        <EnvironmentVariables></EnvironmentVariables>
+        <BuildableProductRunnable runnableDebuggingMode="0">
+            <BuildableReference BlueprintIdentifier="3D31C5E619998B3A00000000" ReferencedContainer="container:MacOSTestsProject.xcodeproj" BuildableName="UnitTests.xctest" BlueprintName="UnitTests" BuildableIdentifier="primary"></BuildableReference>
+        </BuildableProductRunnable>
+    </LaunchAction>
+    <ProfileAction useCustomWorkingDirectory="NO" shouldUseLaunchSchemeArgsEnv="YES" buildConfiguration="__TulsiTestRunner_Release" debugDocumentVersioning="YES">
+        <BuildableProductRunnable runnableDebuggingMode="0">
+            <BuildableReference BlueprintIdentifier="3D31C5E619998B3A00000000" ReferencedContainer="container:MacOSTestsProject.xcodeproj" BuildableName="UnitTests.xctest" BlueprintName="UnitTests" BuildableIdentifier="primary"></BuildableReference>
+        </BuildableProductRunnable>
+    </ProfileAction>
+    <AnalyzeAction buildConfiguration="Debug"></AnalyzeAction>
+    <ArchiveAction buildConfiguration="Release" revealArchiveInOrganizer="YES"></ArchiveAction>
+</Scheme>
\ No newline at end of file
diff --git a/src/TulsiGeneratorIntegrationTests/Resources/Mac.BUILD b/src/TulsiGeneratorIntegrationTests/Resources/Mac.BUILD
index 173b2e6..1ad213c 100644
--- a/src/TulsiGeneratorIntegrationTests/Resources/Mac.BUILD
+++ b/src/TulsiGeneratorIntegrationTests/Resources/Mac.BUILD
@@ -20,6 +20,8 @@
     "macos_application",
     "macos_command_line_application",
     "macos_extension",
+    "macos_unit_test",
+    "macos_ui_test",
 )
 load(
     "//tools/build_defs/apple:versioning.bzl",
@@ -112,3 +114,27 @@
     name = "CommandLineVersion",
     build_version = "1.0",
 )
+
+# Test targets
+
+objc_library(
+    name = "UnitTestsLib",
+    srcs = ["test/UnitTests.m"],
+)
+
+objc_library(
+    name = "UITestsLib",
+    srcs = ["test/UITests.m"],
+)
+
+macos_unit_test(
+    name = "UnitTests",
+    test_host = ":MyMacOSApp",
+    deps = [":UnitTestsLib"],
+)
+
+macos_ui_test(
+    name = "UITests",
+    test_host = ":MyMacOSApp",
+    deps = [":UITestsLib"],
+)
diff --git a/src/TulsiGeneratorTests/PBXProjSerializerTests.swift b/src/TulsiGeneratorTests/PBXProjSerializerTests.swift
index f40ce6d..9cb034e 100644
--- a/src/TulsiGeneratorTests/PBXProjSerializerTests.swift
+++ b/src/TulsiGeneratorTests/PBXProjSerializerTests.swift
@@ -303,10 +303,13 @@
       let config = targetProject.buildConfigurationList.getOrCreateBuildConfiguration(projectLevelBuildConfigName)
       config.buildSettings = projectLevelBuildConfigSettings
     }
-    let nativePBXTarget = targetProject.createNativeTarget(nativeTarget.name, targetType: nativeTarget.targetType)
+    let nativePBXTarget = targetProject.createNativeTarget(nativeTarget.name,
+                                                           deploymentTarget: nil,
+                                                           targetType: nativeTarget.targetType)
     let config = nativePBXTarget.buildConfigurationList.getOrCreateBuildConfiguration(nativeTarget.config)
     config.buildSettings = nativeTarget.settings
     let legacyPBXTarget = targetProject.createLegacyTarget(legacyTarget.name,
+                                                           deploymentTarget: nil,
                                                            buildToolPath: legacyTarget.buildToolPath,
                                                            buildArguments: legacyTarget.buildArguments,
                                                            buildWorkingDirectory: legacyTarget.buildWorkingDirectory)
diff --git a/src/TulsiGeneratorTests/PBXTargetGeneratorTests.swift b/src/TulsiGeneratorTests/PBXTargetGeneratorTests.swift
index 1ed539a..72c378b 100644
--- a/src/TulsiGeneratorTests/PBXTargetGeneratorTests.swift
+++ b/src/TulsiGeneratorTests/PBXTargetGeneratorTests.swift
@@ -425,7 +425,9 @@
       makeTestRuleEntry(rule1BuildTarget, type: "ios_application"),
       makeTestRuleEntry(rule2BuildTarget,
                         type: testRuleType,
-                        attributes: rule2Attributes as [String: AnyObject]),
+                        attributes: rule2Attributes as [String: AnyObject],
+                        platformType: "ios",
+                        osDeploymentTarget: "8.0"),
     ])
 
     do {
@@ -487,6 +489,7 @@
           "BUNDLE_LOADER": "$(TEST_HOST)",
           "DEBUG_INFORMATION_FORMAT": "dwarf",
           "INFOPLIST_FILE": stubPlistPaths.defaultStub,
+          "IPHONEOS_DEPLOYMENT_TARGET": "8.0",
           "PRODUCT_NAME": rule2TargetName,
           "SDKROOT": "iphoneos",
           "TEST_HOST": "$(BUILT_PRODUCTS_DIR)/\(rule1TargetName).app/\(rule1TargetName)",
@@ -536,7 +539,9 @@
       makeTestRuleEntry(rule1BuildTarget, type: "ios_application"),
       makeTestRuleEntry(rule2BuildTarget,
                         type: testRuleType,
-                        attributes: rule2Attributes as [String: AnyObject]),
+                        attributes: rule2Attributes as [String: AnyObject],
+                        platformType: "ios",
+                        osDeploymentTarget: "8.0"),
       ])
 
     do {
@@ -597,6 +602,7 @@
         "BAZEL_TARGET_TYPE": testRuleType,
         "DEBUG_INFORMATION_FORMAT": "dwarf",
         "INFOPLIST_FILE": stubPlistPaths.defaultStub,
+        "IPHONEOS_DEPLOYMENT_TARGET": "8.0",
         "PRODUCT_NAME": rule2TargetName,
         "SDKROOT": "iphoneos",
         "TEST_TARGET_NAME": rule1TargetName,
@@ -632,6 +638,241 @@
     }
   }
 
+  func testGenerateTargetsForLinkedRuleEntriesWithNoSourcesMacOSUnitTests() {
+    let testRuleType = "apple_unit_test"
+    let testHostAttributeName = "test_host"
+    let rule1BuildPath = "test/app"
+    let rule1TargetName = "TestApplication"
+    let rule1BuildTarget = "\(rule1BuildPath):\(rule1TargetName)"
+    let rule2BuildPath = "test/testbundle"
+    let rule2TargetName = "TestBundle"
+    let rule2BuildTarget = "\(rule2BuildPath):\(rule2TargetName)"
+    let rule2Attributes = [testHostAttributeName: rule1BuildTarget]
+    let rules = Set([
+      makeTestRuleEntry(rule1BuildTarget,
+                        type: "macos_application",
+                        platformType: "macos",
+                        osDeploymentTarget: "10.11"),
+      makeTestRuleEntry(rule2BuildTarget,
+                        type: testRuleType,
+                        attributes: rule2Attributes as [String: AnyObject],
+                        platformType: "macos",
+                        osDeploymentTarget: "10.11"),
+      ])
+
+    do {
+      try targetGenerator.generateBuildTargetsForRuleEntries(rules, ruleEntryMap: [:])
+    } catch let e as NSError {
+      XCTFail("Failed to generate build targets with error \(e.localizedDescription)")
+    }
+    XCTAssert(!messageLogger.warningMessageKeys.contains("MissingTestHost"))
+
+    let topLevelConfigs = project.buildConfigurationList.buildConfigurations
+    XCTAssertEqual(topLevelConfigs.count, 0)
+
+    let targets = project.targetByName
+    XCTAssertEqual(targets.count, 2)
+
+    do {
+      let expectedBuildSettings = [
+        "ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME": "Stub Launch Image",
+        "BAZEL_TARGET": "test/app:TestApplication",
+        "BAZEL_TARGET_TYPE": "macos_application",
+        "DEBUG_INFORMATION_FORMAT": "dwarf",
+        "INFOPLIST_FILE": stubPlistPaths.defaultStub,
+        "MACOSX_DEPLOYMENT_TARGET": "10.11",
+        "PRODUCT_NAME": rule1TargetName,
+        "SDKROOT": "macosx",
+        "TULSI_BUILD_PATH": rule1BuildPath,
+        "TULSI_USE_DSYM": "NO",
+        ]
+      let expectedTarget = TargetDefinition(
+        name: rule1TargetName,
+        buildConfigurations: [
+          BuildConfigurationDefinition(
+            name: "Debug",
+            expectedBuildSettings: debugBuildSettingsFromSettings(expectedBuildSettings)
+          ),
+          BuildConfigurationDefinition(
+            name: "Release",
+            expectedBuildSettings: releaseBuildSettingsFromSettings(expectedBuildSettings)
+          ),
+          BuildConfigurationDefinition(
+            name: "__TulsiTestRunner_Debug",
+            expectedBuildSettings: debugTestRunnerBuildSettingsFromSettings(expectedBuildSettings)
+          ),
+          BuildConfigurationDefinition(
+            name: "__TulsiTestRunner_Release",
+            expectedBuildSettings: releaseTestRunnerBuildSettingsFromSettings(expectedBuildSettings)
+          ),
+          ],
+        expectedBuildPhases: [
+          BazelShellScriptBuildPhaseDefinition(bazelURL: bazelURL, buildTarget: rule1BuildTarget)
+        ]
+      )
+      assertTarget(expectedTarget, inTargets: targets)
+    }
+    do {
+      let expectedBuildSettings = [
+        "ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME": "Stub Launch Image",
+        "BAZEL_TARGET": "test/testbundle:TestBundle",
+        "BAZEL_TARGET_TYPE": testRuleType,
+        "BUNDLE_LOADER": "$(TEST_HOST)",
+        "DEBUG_INFORMATION_FORMAT": "dwarf",
+        "INFOPLIST_FILE": stubPlistPaths.defaultStub,
+        "MACOSX_DEPLOYMENT_TARGET": "10.11",
+        "PRODUCT_NAME": rule2TargetName,
+        "SDKROOT": "macosx",
+        "TEST_HOST": "$(BUILT_PRODUCTS_DIR)/\(rule1TargetName).app/Contents/MacOS/\(rule1TargetName)",
+        "TULSI_BUILD_PATH": rule2BuildPath,
+        "TULSI_TEST_RUNNER_ONLY": "YES",
+        "TULSI_USE_DSYM": "NO",
+        ]
+      let expectedTarget = TargetDefinition(
+        name: rule2TargetName,
+        buildConfigurations: [
+          BuildConfigurationDefinition(
+            name: "Debug",
+            expectedBuildSettings: debugBuildSettingsFromSettings(expectedBuildSettings)
+          ),
+          BuildConfigurationDefinition(
+            name: "Release",
+            expectedBuildSettings: releaseBuildSettingsFromSettings(expectedBuildSettings)
+          ),
+          BuildConfigurationDefinition(
+            name: "__TulsiTestRunner_Debug",
+            expectedBuildSettings: debugTestRunnerBuildSettingsFromSettings(expectedBuildSettings)
+          ),
+          BuildConfigurationDefinition(
+            name: "__TulsiTestRunner_Release",
+            expectedBuildSettings: releaseTestRunnerBuildSettingsFromSettings(expectedBuildSettings)
+          ),
+          ],
+        expectedBuildPhases: [
+          BazelShellScriptBuildPhaseDefinition(bazelURL: bazelURL, buildTarget: rule2BuildTarget)
+        ]
+      )
+      assertTarget(expectedTarget, inTargets: targets)
+    }
+  }
+
+  func testGenerateTargetsForLinkedRuleEntriesWithNoSourcesMacOSUITests() {
+    let testRuleType = "apple_ui_test"
+    let testHostAttributeName = "test_host"
+    let rule1BuildPath = "test/app"
+    let rule1TargetName = "TestApplication"
+    let rule1BuildTarget = "\(rule1BuildPath):\(rule1TargetName)"
+    let rule2BuildPath = "test/testbundle"
+    let rule2TargetName = "TestBundle"
+    let rule2BuildTarget = "\(rule2BuildPath):\(rule2TargetName)"
+    let rule2Attributes = [testHostAttributeName: rule1BuildTarget]
+    let rules = Set([
+      makeTestRuleEntry(rule1BuildTarget,
+                        type: "macos_application",
+                        platformType: "macos",
+                        osDeploymentTarget: "10.11"),
+      makeTestRuleEntry(rule2BuildTarget,
+                        type: testRuleType,
+                        attributes: rule2Attributes as [String: AnyObject],
+                        platformType: "macos",
+                        osDeploymentTarget: "10.11"),
+      ])
+
+    do {
+      try targetGenerator.generateBuildTargetsForRuleEntries(rules, ruleEntryMap: [:])
+    } catch let e as NSError {
+      XCTFail("Failed to generate build targets with error \(e.localizedDescription)")
+    }
+    XCTAssert(!messageLogger.warningMessageKeys.contains("MissingTestHost"))
+
+    let topLevelConfigs = project.buildConfigurationList.buildConfigurations
+    XCTAssertEqual(topLevelConfigs.count, 0)
+
+    let targets = project.targetByName
+    XCTAssertEqual(targets.count, 2)
+
+    do {
+      let expectedBuildSettings = [
+        "ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME": "Stub Launch Image",
+        "BAZEL_TARGET": "test/app:TestApplication",
+        "BAZEL_TARGET_TYPE": "macos_application",
+        "DEBUG_INFORMATION_FORMAT": "dwarf",
+        "INFOPLIST_FILE": stubPlistPaths.defaultStub,
+        "MACOSX_DEPLOYMENT_TARGET": "10.11",
+        "PRODUCT_NAME": rule1TargetName,
+        "SDKROOT": "macosx",
+        "TULSI_BUILD_PATH": rule1BuildPath,
+        "TULSI_USE_DSYM": "NO",
+        ]
+      let expectedTarget = TargetDefinition(
+        name: rule1TargetName,
+        buildConfigurations: [
+          BuildConfigurationDefinition(
+            name: "Debug",
+            expectedBuildSettings: debugBuildSettingsFromSettings(expectedBuildSettings)
+          ),
+          BuildConfigurationDefinition(
+            name: "Release",
+            expectedBuildSettings: releaseBuildSettingsFromSettings(expectedBuildSettings)
+          ),
+          BuildConfigurationDefinition(
+            name: "__TulsiTestRunner_Debug",
+            expectedBuildSettings: debugTestRunnerBuildSettingsFromSettings(expectedBuildSettings)
+          ),
+          BuildConfigurationDefinition(
+            name: "__TulsiTestRunner_Release",
+            expectedBuildSettings: releaseTestRunnerBuildSettingsFromSettings(expectedBuildSettings)
+          ),
+          ],
+        expectedBuildPhases: [
+          BazelShellScriptBuildPhaseDefinition(bazelURL: bazelURL, buildTarget: rule1BuildTarget)
+        ]
+      )
+      assertTarget(expectedTarget, inTargets: targets)
+    }
+    do {
+      let expectedBuildSettings = [
+        "ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME": "Stub Launch Image",
+        "BAZEL_TARGET": "test/testbundle:TestBundle",
+        "BAZEL_TARGET_TYPE": testRuleType,
+        "DEBUG_INFORMATION_FORMAT": "dwarf",
+        "INFOPLIST_FILE": stubPlistPaths.defaultStub,
+        "MACOSX_DEPLOYMENT_TARGET": "10.11",
+        "PRODUCT_NAME": rule2TargetName,
+        "SDKROOT": "macosx",
+        "TEST_TARGET_NAME": rule1TargetName,
+        "TULSI_BUILD_PATH": rule2BuildPath,
+        "TULSI_TEST_RUNNER_ONLY": "YES",
+        "TULSI_USE_DSYM": "NO",
+        ]
+      let expectedTarget = TargetDefinition(
+        name: rule2TargetName,
+        buildConfigurations: [
+          BuildConfigurationDefinition(
+            name: "Debug",
+            expectedBuildSettings: debugBuildSettingsFromSettings(expectedBuildSettings)
+          ),
+          BuildConfigurationDefinition(
+            name: "Release",
+            expectedBuildSettings: releaseBuildSettingsFromSettings(expectedBuildSettings)
+          ),
+          BuildConfigurationDefinition(
+            name: "__TulsiTestRunner_Debug",
+            expectedBuildSettings: debugTestRunnerBuildSettingsFromSettings(expectedBuildSettings)
+          ),
+          BuildConfigurationDefinition(
+            name: "__TulsiTestRunner_Release",
+            expectedBuildSettings: releaseTestRunnerBuildSettingsFromSettings(expectedBuildSettings)
+          ),
+          ],
+        expectedBuildPhases: [
+          BazelShellScriptBuildPhaseDefinition(bazelURL: bazelURL, buildTarget: rule2BuildTarget)
+        ]
+      )
+      assertTarget(expectedTarget, inTargets: targets)
+    }
+  }
+
   func testGenerateTargetsForLinkedRuleEntriesWithSources() {
     checkGenerateTargetsForLinkedRuleEntriesWithSources("ios_test",
                                                         testHostAttributeName: "xctest_app")
@@ -655,7 +896,9 @@
     let testRule = makeTestRuleEntry(testRuleBuildTarget,
                                      type: testRuleType,
                                      attributes: testRuleAttributes as [String: AnyObject],
-                                     sourceFiles: testSources)
+                                     sourceFiles: testSources,
+                                     platformType: "ios",
+                                     osDeploymentTarget: "8.0")
     let rules = Set([
       makeTestRuleEntry(rule1BuildTarget, type: "ios_application"),
       testRule,
@@ -716,6 +959,7 @@
           "BUNDLE_LOADER": "$(TEST_HOST)",
           "DEBUG_INFORMATION_FORMAT": "dwarf",
           "INFOPLIST_FILE": stubPlistPaths.defaultStub,
+          "IPHONEOS_DEPLOYMENT_TARGET": "8.0",
           "PRODUCT_NAME": testRuleTargetName,
           "SDKROOT": "iphoneos",
           "TEST_HOST": "$(BUILT_PRODUCTS_DIR)/\(rule1TargetName).app/\(rule1TargetName)",
@@ -773,7 +1017,9 @@
     let testRuleEntry = makeTestRuleEntry("\(testRulePackage):\(testRuleTargetName)",
       type: "\(testRuleType)",
       attributes: ["test_bundle": testBundleRuleEntry.label.value as AnyObject,
-                   "test_host": testHostRuleEntry.label.value as AnyObject])
+                   "test_host": testHostRuleEntry.label.value as AnyObject],
+      platformType: "ios",
+      osDeploymentTarget: "8.0")
 
     let ruleEntryMap = makeRuleEntryMap(withRuleEntries: [objcLibraryRuleEntry,
                                                           appleBinaryRuleEntry,
@@ -799,6 +1045,7 @@
       "BUNDLE_LOADER": "$(TEST_HOST)",
       "DEBUG_INFORMATION_FORMAT": "dwarf",
       "INFOPLIST_FILE": stubPlistPaths.defaultStub,
+      "IPHONEOS_DEPLOYMENT_TARGET": "8.0",
       "PRODUCT_NAME": testRuleTargetName,
       "SDKROOT": "iphoneos",
       "TEST_HOST": "$(BUILT_PRODUCTS_DIR)/\(testHostTargetName).app/\(testHostTargetName)",
@@ -855,7 +1102,9 @@
     let testRuleEntry = makeTestRuleEntry("\(testRulePackage):\(testRuleTargetName)",
                                           type: "\(testRuleType)",
                                           attributes: ["test_bundle": testBundleRuleEntry.label.value as AnyObject,
-                                                       "test_host": testHostRuleEntry.label.value as AnyObject])
+                                                       "test_host": testHostRuleEntry.label.value as AnyObject],
+                                          platformType: "ios",
+                                          osDeploymentTarget: "8.0")
 
     let ruleEntryMap = makeRuleEntryMap(withRuleEntries: [swiftLibraryRuleEntry,
                                                           appleBinaryRuleEntry,
@@ -881,6 +1130,7 @@
       "BUNDLE_LOADER": "$(TEST_HOST)",
       "DEBUG_INFORMATION_FORMAT": "dwarf",
       "INFOPLIST_FILE": stubPlistPaths.defaultStub,
+      "IPHONEOS_DEPLOYMENT_TARGET": "8.0",
       "PRODUCT_NAME": testRuleTargetName,
       "SDKROOT": "iphoneos",
       "TEST_HOST": "$(BUILT_PRODUCTS_DIR)/\(testHostTargetName).app/\(testHostTargetName)",
@@ -940,7 +1190,9 @@
     let testRule = makeTestRuleEntry(testRuleBuildTarget,
                                      type: testRuleType,
                                      attributes: testRuleAttributes as [String: AnyObject],
-                                     sourceFiles: testSources)
+                                     sourceFiles: testSources,
+                                     platformType: "ios",
+                                     osDeploymentTarget: "8.0")
     let rules = Set([
       makeTestRuleEntry(rule1BuildTarget, type: "ios_application"),
       testRule,
@@ -1000,6 +1252,7 @@
         "BAZEL_TARGET_TYPE": testRuleType,
         "DEBUG_INFORMATION_FORMAT": "dwarf",
         "INFOPLIST_FILE": stubPlistPaths.defaultStub,
+        "IPHONEOS_DEPLOYMENT_TARGET": "8.0",
         "PRODUCT_NAME": testRuleTargetName,
         "SDKROOT": "iphoneos",
         "TEST_TARGET_NAME": rule1TargetName,
diff --git a/src/TulsiGeneratorTests/XcodeProjectGeneratorTests.swift b/src/TulsiGeneratorTests/XcodeProjectGeneratorTests.swift
index 0224c1a..0133d71 100644
--- a/src/TulsiGeneratorTests/XcodeProjectGeneratorTests.swift
+++ b/src/TulsiGeneratorTests/XcodeProjectGeneratorTests.swift
@@ -39,7 +39,8 @@
       cleanScript: URL(fileURLWithPath: "/scripts/Clean"),
       extraBuildScripts: [URL(fileURLWithPath: "/scripts/Logging")],
       postProcessor: URL(fileURLWithPath: "/utils/covmap_patcher"),
-      uiRunnerEntitlements: URL(fileURLWithPath: "/generatedProjectResources/XCTRunner.entitlements"),
+      iOSUIRunnerEntitlements: URL(fileURLWithPath: "/generatedProjectResources/iOSXCTRunner.entitlements"),
+      macOSUIRunnerEntitlements: URL(fileURLWithPath: "/generatedProjectResources/macOSXCTRunner.entitlements"),
       stubInfoPlist: URL(fileURLWithPath: "/generatedProjectResources/StubInfoPlist.plist"),
       stubIOSAppExInfoPlistTemplate: URL(fileURLWithPath: "/generatedProjectResources/stubIOSAppExInfoPlist.plist"),
       stubWatchOS2InfoPlist: URL(fileURLWithPath: "/generatedProjectResources/StubWatchOS2InfoPlist.plist"),
@@ -433,7 +434,9 @@
 
     var testTargetLinkages = [(PBXTarget, BuildLabel)]()
     for (name, entry) in namedRuleEntries {
-      let target = project.createNativeTarget(name, targetType: entry.pbxTargetType!)
+      let target = project.createNativeTarget(name,
+                                              deploymentTarget: entry.deploymentTarget,
+                                              targetType: entry.pbxTargetType!)
 
       for attribute in [.xctest_app, .test_host] as [RuleEntry.Attribute] {
         if let hostLabelString = entry.attributes[attribute] as? String {