Set up tests to make sure that indexing targets are buildable.

Add targets for Objective C, C++ to complement the swift targets.

PiperOrigin-RevId: 253246501
diff --git a/Tulsi.tulsiproj/project.tulsiconf b/Tulsi.tulsiproj/project.tulsiconf
index b30a980..7b96d5b 100644
--- a/Tulsi.tulsiproj/project.tulsiconf
+++ b/Tulsi.tulsiproj/project.tulsiconf
@@ -3,14 +3,17 @@
     "optionSet" : {
       "GenerateRunfiles" : {
         "p" : "YES"
+      },
+      "TreeArtifactOutputs" : {
+        "p" : "NO"
       }
     }
   },
-  "projectName" : "Tulsi",
   "packages" : [
     "",
     "src/TulsiGeneratorIntegrationTests",
     "src/TulsiGeneratorTests"
   ],
+  "projectName" : "Tulsi",
   "workspaceRoot" : ".."
 }
diff --git a/src/TulsiEndToEndTests/ButtonsEndToEndTest.swift b/src/TulsiEndToEndTests/ButtonsEndToEndTest.swift
index 59be9e2..b4cf3f4 100644
--- a/src/TulsiEndToEndTests/ButtonsEndToEndTest.swift
+++ b/src/TulsiEndToEndTests/ButtonsEndToEndTest.swift
@@ -37,6 +37,19 @@
     testXcodeProject(xcodeProjectURL, scheme: "ButtonsTests")
   }
 
+  /// Verifies that all of the _idx_ targets in the project build.
+  func testIndexingTargetsBuild() throws {
+    let xcodeProjectURL = generateXcodeProject(tulsiProject: buttonsProjectPath,
+                                               config: "Buttons")
+    XCTAssert(fileManager.fileExists(atPath: xcodeProjectURL.path), "Xcode project was not generated.")
+    let targets = targetsOfXcodeProject(xcodeProjectURL)
+    let indexTargets = targets.filter{ $0.hasPrefix("_idx_") }
+    XCTAssertEqual(indexTargets.count, 8)
+    for target in indexTargets {
+      buildXcodeTarget(xcodeProjectURL, target: target)
+    }
+  }
+
   func testInvalidConfig() throws {
     let xcodeProjectURL = generateXcodeProject(tulsiProject: buttonsProjectPath,
                                                config: "InvalidConfig")
diff --git a/src/TulsiEndToEndTests/Resources/Buttons.tulsiproj/Configs/Buttons.tulsigen b/src/TulsiEndToEndTests/Resources/Buttons.tulsiproj/Configs/Buttons.tulsigen
index 73e51a2..c579948 100644
--- a/src/TulsiEndToEndTests/Resources/Buttons.tulsiproj/Configs/Buttons.tulsigen
+++ b/src/TulsiEndToEndTests/Resources/Buttons.tulsiproj/Configs/Buttons.tulsigen
@@ -1,26 +1,30 @@
 {
-  "sourceFilters" : [
+  "additionalFilePaths" : [
+    "src/TulsiEndToEndTests/Resources/Buttons/BUILD"
   ],
   "buildTargets" : [
-    "\/\/third_party\/tulsi\/src\/TulsiEndToEndTests\/Resources\/Buttons:ButtonsTests",
-    "\/\/third_party\/tulsi\/src\/TulsiEndToEndTests\/Resources\/Buttons:ButtonsLogicTests",
-    "\/\/third_party\/tulsi\/src\/TulsiEndToEndTests\/Resources\/Buttons:ButtonsUITests"
+    "//srcTulsiEndToEndTests/Resources/Buttons:Buttons",
+    "//srcTulsiEndToEndTests/Resources/Buttons:ButtonsLib",
+    "//srcTulsiEndToEndTests/Resources/Buttons:ButtonsLogicTests",
+    "//srcTulsiEndToEndTests/Resources/Buttons:ButtonsTests",
+    "//srcTulsiEndToEndTests/Resources/Buttons:ButtonsUITests",
+    "//srcTulsiEndToEndTests/Resources/Buttons:CppLib",
+    "//srcTulsiEndToEndTests/Resources/Buttons:ObjCLib"
   ],
-  "projectName" : "Buttons",
   "optionSet" : {
     "BazelBuildOptionsDebug" : {
       "p" : "$(inherited) --define=RULES_SWIFT_BUILD_DUMMY_WORKER=1"
     },
-    "BazelBuildStartupOptionsRelease" : {
-      "p" : "$(inherited)"
-    },
-    "LaunchActionPreActionScript" : {
-      "p" : "$(inherited)"
-    },
     "BazelBuildOptionsRelease" : {
       "p" : "$(inherited)"
     },
-    "EnvironmentVariables" : {
+    "BazelBuildStartupOptionsDebug" : {
+      "p" : "$(inherited)"
+    },
+    "BazelBuildStartupOptionsRelease" : {
+      "p" : "$(inherited)"
+    },
+    "BuildActionPostActionScript" : {
       "p" : "$(inherited)"
     },
     "BuildActionPreActionScript" : {
@@ -29,23 +33,26 @@
     "CommandlineArguments" : {
       "p" : "$(inherited)"
     },
-    "TestActionPreActionScript" : {
+    "EnvironmentVariables" : {
+      "p" : "$(inherited)"
+    },
+    "LaunchActionPostActionScript" : {
+      "p" : "$(inherited)"
+    },
+    "LaunchActionPreActionScript" : {
       "p" : "$(inherited)"
     },
     "TestActionPostActionScript" : {
       "p" : "$(inherited)"
     },
-    "BuildActionPostActionScript" : {
-      "p" : "$(inherited)"
-    },
-    "BazelBuildStartupOptionsDebug" : {
-      "p" : "$(inherited)"
-    },
-    "LaunchActionPostActionScript" : {
+    "TestActionPreActionScript" : {
       "p" : "$(inherited)"
     }
   },
-  "additionalFilePaths" : [
-    "third_party\/tulsi\/src\/TulsiEndToEndTests\/Resources\/Buttons\/BUILD"
+  "projectName" : "Buttons",
+  "sourceFilters" : [
+    "src/TulsiEndToEndTests/Resources/Buttons",
+    "src/TulsiEndToEndTests/Resources/Buttons/Buttons",
+    "src/TulsiEndToEndTests/Resources/Buttons/Buttons/Base.lproj"
   ]
 }
diff --git a/src/TulsiEndToEndTests/Resources/Buttons/BUILD b/src/TulsiEndToEndTests/Resources/Buttons/BUILD
index 3a786f6..d250337 100644
--- a/src/TulsiEndToEndTests/Resources/Buttons/BUILD
+++ b/src/TulsiEndToEndTests/Resources/Buttons/BUILD
@@ -29,6 +29,28 @@
 
 licenses(["notice"])
 
+# Platform agnostic
+
+objc_library(
+    name = "ObjCLib",
+    srcs = [
+        "ObjCFoo.m",
+    ],
+    hdrs = [
+        "ObjCFoo.h",
+    ],
+)
+
+cc_library(
+    name = "CppLib",
+    srcs = [
+        "CppFoo.cc",
+    ],
+    hdrs = [
+        "CppFoo.h",
+    ],
+)
+
 # iOS
 
 ## Code
@@ -81,6 +103,8 @@
     deps = [
         ":ButtonsLib",
         ":ButtonsResources",
+        ":CppLib",
+        ":ObjCLib",
     ],
 )
 
@@ -164,6 +188,8 @@
     minimum_os_version = "3.0",
     deps = [
         ":ButtonsWatchExtensionLib",
+        ":CppLib",
+        ":ObjCLib",
     ],
 )
 
@@ -220,6 +246,8 @@
     deps = [
         ":ButtonsTVLib",
         ":ButtonsTVResources",
+        ":CppLib",
+        ":ObjCLib",
     ],
 )
 
@@ -278,6 +306,8 @@
     deps = [
         ":ButtonsMacLib",
         ":ButtonsMacResources",
+        ":CppLib",
+        ":ObjCLib",
     ],
 )
 
diff --git a/src/TulsiEndToEndTests/Resources/Buttons/CppFoo.cc b/src/TulsiEndToEndTests/Resources/Buttons/CppFoo.cc
new file mode 100644
index 0000000..88d50ba
--- /dev/null
+++ b/src/TulsiEndToEndTests/Resources/Buttons/CppFoo.cc
@@ -0,0 +1,17 @@
+// Copyright 2019 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.
+
+#include "third_party/tulsi/src/TulsiEndToEndTests/Resources/Buttons/CppFoo.h"
+
+CppFoo::CppFoo() {}
diff --git a/src/TulsiEndToEndTests/Resources/Buttons/CppFoo.h b/src/TulsiEndToEndTests/Resources/Buttons/CppFoo.h
new file mode 100644
index 0000000..ce46a18
--- /dev/null
+++ b/src/TulsiEndToEndTests/Resources/Buttons/CppFoo.h
@@ -0,0 +1,22 @@
+// Copyright 2019 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.
+
+#ifndef THIRD_PARTY_TULSI_SRC_TULSIENDTOENDTESTS_RESOURCES_BUTTONS_CPPFOO_H_
+#define THIRD_PARTY_TULSI_SRC_TULSIENDTOENDTESTS_RESOURCES_BUTTONS_CPPFOO_H_
+
+class CppFoo {
+  CppFoo();
+};
+
+#endif  // THIRD_PARTY_TULSI_SRC_TULSIENDTOENDTESTS_RESOURCES_BUTTONS_CPPFOO_H_
diff --git a/src/TulsiEndToEndTests/Resources/Buttons/ObjCFoo.h b/src/TulsiEndToEndTests/Resources/Buttons/ObjCFoo.h
new file mode 100644
index 0000000..b72fa8f
--- /dev/null
+++ b/src/TulsiEndToEndTests/Resources/Buttons/ObjCFoo.h
@@ -0,0 +1,18 @@
+// Copyright 2019 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/Foundation.h>
+
+@interface ObjCFoo : NSObject
+@end
diff --git a/src/TulsiEndToEndTests/Resources/Buttons/ObjCFoo.m b/src/TulsiEndToEndTests/Resources/Buttons/ObjCFoo.m
new file mode 100644
index 0000000..68d2188
--- /dev/null
+++ b/src/TulsiEndToEndTests/Resources/Buttons/ObjCFoo.m
@@ -0,0 +1,23 @@
+// Copyright 2019 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 "third_party/tulsi/src/TulsiEndToEndTests/Resources/Buttons/ObjCFoo.h"
+
+@implementation ObjCFoo
+
+- (NSString *)description {
+  return @"What a useless class!";
+}
+
+@end
diff --git a/src/TulsiEndToEndTests/TulsiEndToEndTest.swift b/src/TulsiEndToEndTests/TulsiEndToEndTest.swift
index 6b129ce..2efa943 100644
--- a/src/TulsiEndToEndTests/TulsiEndToEndTest.swift
+++ b/src/TulsiEndToEndTests/TulsiEndToEndTest.swift
@@ -175,6 +175,92 @@
     return xcodeProjectURL
   }
 
+  /// Returns the "json" style dictionary of a project.
+  ///
+  /// - Parameters:
+  ///   - xcodeProjectURL: URL of project.
+  /// - Returns
+  ///   - Dictionary of string to json style objects.
+  fileprivate func xcodeProjectDictionary(_ xcodeProjectURL: URL) -> [String: Any]? {
+    let completionInfo = ProcessRunner.launchProcessSync("/usr/bin/xcodebuild",
+                                                         arguments: ["-list",
+                                                                     "-json",
+                                                                     "-project",
+                                                                     xcodeProjectURL.path])
+    guard let stdoutput = String(data: completionInfo.stdout, encoding: .utf8),
+         !stdoutput.isEmpty else {
+      if let error = String(data: completionInfo.stderr, encoding: .utf8), !error.isEmpty {
+        XCTFail(error)
+      } else {
+        XCTFail("Xcode project tests did not return success.")
+      }
+      return nil
+    }
+    guard let jsonDeserialized = try? JSONSerialization.jsonObject(with: completionInfo.stdout, options: []) else {
+      XCTFail("Unable to decode from json: \(stdoutput)")
+      return nil
+    }
+    guard let jsonResponse = jsonDeserialized as? [String: Any] else {
+      XCTFail("Unable to decode from json as [String: Any]: \(stdoutput)")
+      return nil
+    }
+    guard let project = jsonResponse["project"] as? [String: Any] else {
+      XCTFail("Unable to extract project from \(jsonResponse)")
+      return nil
+    }
+    return project
+  }
+
+  /// Returns targets of a project.
+  ///
+  /// - Parameters:
+  ///   - xcodeProjectURL: URL of project.
+  /// - Returns
+  ///   - Array of target names.
+  func targetsOfXcodeProject(_ xcodeProjectURL: URL) -> [String] {
+    guard let project = xcodeProjectDictionary(xcodeProjectURL) else {
+      XCTFail("Unable to extract project for \(xcodeProjectURL)")
+      return []
+    }
+    guard let targets = project["targets"] as? [String] else {
+      XCTFail("Unable to extract targets from \(project)")
+      return []
+    }
+    return targets
+  }
+
+
+  /// Builds an Xcode Target
+  ///
+  /// - Parameters:
+  ///   - xcodeProjectURL: URL of project.
+  ///   - target: target name
+  func buildXcodeTarget(_ xcodeProjectURL: URL, target: String) {
+    let destination = "platform=iOS Simulator,name=\(TulsiEndToEndTest.simulatorName),OS=\(TulsiEndToEndTest.targetVersion)"
+    let completionInfo = ProcessRunner.launchProcessSync("/usr/bin/xcodebuild",
+                                                         arguments: ["build",
+                                                                     "-project",
+                                                                     xcodeProjectURL.path,
+                                                                     "-target",
+                                                                     target,
+                                                                     "-destination",
+                                                                     destination,
+                                                                     "SYMROOT=xcodeBuild"])
+
+    if let stdoutput = String(data: completionInfo.stdout, encoding: .utf8),
+        !stdoutput.isEmpty,
+        let result = stdoutput.split(separator: "\n").last {
+      if (String(result) != "** BUILD SUCCEEDED **") {
+        print(stdoutput)
+        XCTFail("\(completionInfo.commandlineString) did not return build success. Exit code: \(completionInfo.terminationStatus)")
+      }
+    } else if let error = String(data: completionInfo.stderr, encoding: .utf8), !error.isEmpty {
+      XCTFail(error)
+    } else {
+      XCTFail("Xcode project build did not return success \(xcodeProjectURL):\(target).")
+    }
+  }
+
   // Runs Xcode tests on the given Xcode project and scheme. This verifies that
   // the test passes and that rsync behavior is used to copy files.
   func testXcodeProject(_ xcodeProjectURL: URL, scheme: String) {
@@ -189,7 +275,8 @@
                                                                      destination])
 
     if let stdoutput = String(data: completionInfo.stdout, encoding: .utf8),
-      let result = stdoutput.split(separator: "\n").last {
+        !stdoutput.isEmpty,
+        let result = stdoutput.split(separator: "\n").last {
       XCTAssert(stdoutput.contains("Rsyncing"), "Failed to find 'Rsyncing' in:\n\(stdoutput)")
       if (String(result) != "** TEST SUCCEEDED **") {
         print(stdoutput)
@@ -198,7 +285,7 @@
     } else if let error = String(data: completionInfo.stderr, encoding: .utf8), !error.isEmpty {
       XCTFail(error)
     } else {
-      XCTFail("Xcode project tests did not return  success.")
+      XCTFail("Xcode project tests did not return success \(xcodeProjectURL):\(scheme).")
     }
   }