aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Chris Parsons <cparsons@google.com>2016-01-08 00:42:14 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2016-01-08 07:27:44 +0000
commitf488818ce168dca4760944d1378b00b9fe74d4d6 (patch)
treea3d20c6d8a15c45d6820a7fac67a07d7472be260 /src
parentbf98f39d5d69d14d74dad79e705f76966f348766 (diff)
Add xcode_locator to bazel's embedded binaries.
For bazel on non-darwin architectures, this will simply be a stub, and should never be invoked. On darwin arcitectures, the tool will map xcode version to xcode path on the host system. -- MOS_MIGRATED_REVID=111651147
Diffstat (limited to 'src')
-rw-r--r--src/BUILD2
-rw-r--r--src/main/tools/BUILD22
-rw-r--r--src/main/tools/xcode_locator.m153
-rwxr-xr-xsrc/main/tools/xcode_locator_stub.sh19
-rw-r--r--src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java3
5 files changed, 198 insertions, 1 deletions
diff --git a/src/BUILD b/src/BUILD
index 1904986cec..879736d28f 100644
--- a/src/BUILD
+++ b/src/BUILD
@@ -24,6 +24,7 @@ filegroup(
":libunix",
"//src/main/tools:build-runfiles",
"//src/main/tools:process-wrapper",
+ "//src/main/tools:xcode-locator",
"//src/main/tools:namespace-sandbox",
"//src/main/tools:build_interface_so",
] + embedded_tools,
@@ -100,6 +101,7 @@ genrule(
":libunix",
"//src/main/tools:build-runfiles",
"//src/main/tools:process-wrapper",
+ "//src/main/tools:xcode-locator",
"//src/main/tools:jdk-support",
"//src/main/tools:namespace-sandbox",
"//src/main/tools:build_interface_so",
diff --git a/src/main/tools/BUILD b/src/main/tools/BUILD
index fdcfbdb914..c212f8e9e2 100644
--- a/src/main/tools/BUILD
+++ b/src/main/tools/BUILD
@@ -50,6 +50,28 @@ cc_binary(
}),
)
+DARWIN_XCODE_LOCATOR_COMPILE_COMMAND = """
+ /usr/bin/xcrun clang -fobjc-arc -framework CoreServices \
+ -framework Foundation -o $@ $<
+"""
+
+genrule(
+ name = "xcode-locator-genrule",
+ srcs = select({
+ "//src:darwin": ["xcode_locator.m"],
+ "//src:darwin_x86_64": ["xcode_locator.m"],
+ "//conditions:default": ["xcode_locator_stub.sh"],
+ }),
+ outs = ["xcode-locator"],
+ cmd = select({
+ "//src:darwin": DARWIN_XCODE_LOCATOR_COMPILE_COMMAND,
+ "//src:darwin_x86_64": DARWIN_XCODE_LOCATOR_COMPILE_COMMAND,
+ "//conditions:default": "cp $< $@",
+ }),
+ local = 1,
+ output_to_bindir = 1,
+)
+
filegroup(
name = "jdk-support",
srcs = [
diff --git a/src/main/tools/xcode_locator.m b/src/main/tools/xcode_locator.m
new file mode 100644
index 0000000000..6b8fffc700
--- /dev/null
+++ b/src/main/tools/xcode_locator.m
@@ -0,0 +1,153 @@
+// Copyright 2015 Google Inc. 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.
+
+// Application that finds all Xcodes installed on a given Mac and will return a path
+// for a given version number.
+// If you have 7.0, 6.4.1 and 6.3 installed the inputs will map to:
+// 7,7.0,7.0.0 = 7.0
+// 6,6.4,6.4.1 = 6.4.1
+// 6.3,6.3.0 = 6.3
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+#import <CoreServices/CoreServices.h>
+#import <Foundation/Foundation.h>
+
+// Simple data structure for tracking a version of Xcode (i.e. 6.4) with an URL to the
+// appplication.
+@interface XcodeVersionEntry : NSObject
+@property(readonly) NSString *version;
+@property(readonly) NSURL *url;
+@end
+
+@implementation XcodeVersionEntry
+
+- (id)initWithVersion:(NSString *)version url:(NSURL *)url {
+ if ((self = [super init])) {
+ _version = version;
+ _url = url;
+ }
+ return self;
+}
+
+- (id)description {
+ return [NSString stringWithFormat:@"<%@ %p>: %@ %@", [self class], self, _version, _url];
+}
+
+@end
+
+// Given an entry, insert it into a dictionary that is keyed by versions.
+// For an entry that is 6.4.1:/Applications/Xcode.app
+// Add it for 6.4.1, and optionally add it for 6.4 if it is newer than any entry that may already
+// be there, and add it for 6 if it is newer than what is there.
+static void AddEntryToDictionary(XcodeVersionEntry *entry, NSMutableDictionary *dict) {
+ NSString *entryVersion = entry.version;
+ NSString *subversion = entryVersion;
+ dict[entryVersion] = entry;
+ while (YES) {
+ NSRange range = [subversion rangeOfString:@"." options:NSBackwardsSearch];
+ if (range.length == 0 || range.location == 0) {
+ break;
+ }
+ subversion = [subversion substringToIndex:range.location];
+ XcodeVersionEntry *subversionEntry = dict[subversion];
+ if (subversionEntry) {
+ if ([subversionEntry.version compare:entry.version] == NSOrderedAscending) {
+ dict[subversion] = entry;
+ }
+ } else {
+ dict[subversion] = entry;
+ }
+ }
+}
+
+// Given a "version", expand it to at least 3 components by adding .0 as necessary.
+static NSString *ExpandVersion(NSString *version) {
+ NSArray *components = [version componentsSeparatedByString:@"."];
+ NSString *appendage = nil;
+ if (components.count == 2) {
+ appendage = @".0";
+ } else if (components.count == 1) {
+ appendage = @".0.0";
+ }
+ if (appendage) {
+ version = [version stringByAppendingString:appendage];
+ }
+ return version;
+}
+
+int main(int argc, const char * argv[]) {
+ @autoreleasepool {
+ NSString *version = nil;
+ if (argc == 1) {
+ version = @"";
+ } else if (argc == 2) {
+ version = [NSString stringWithUTF8String:argv[1]];
+ NSCharacterSet *versSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789."];
+ if ([version rangeOfCharacterFromSet:versSet.invertedSet].length != 0) {
+ version = nil;
+ }
+ }
+ if (version == nil) {
+ printf("xcode_locator <version_number>\n"
+ "Given a version number, or partial version number in x.y.z format, will attempt "
+ "to return the path to the appropriate Xcode.app.\nOmitting a version number will "
+ "list all available versions in JSON format.\n");
+ return 1;
+ }
+
+ NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
+ CFErrorRef cfError;
+ NSArray *array = CFBridgingRelease(LSCopyApplicationURLsForBundleIdentifier(
+ CFSTR("com.apple.dt.Xcode"), &cfError));
+ if (array == nil) {
+ NSError *nsError = (__bridge NSError *)cfError;
+ printf("error: %s\n", nsError.description.UTF8String);
+ return 1;
+ }
+ for (NSURL *url in array) {
+ NSBundle *bundle = [NSBundle bundleWithURL:url];
+ if (!bundle) {
+ printf("error: Unable to open bundle at URL: %s\n", url.description.UTF8String);
+ return 1;
+ }
+ NSString *version = bundle.infoDictionary[@"CFBundleShortVersionString"];
+ if (!version) {
+ printf("error: Unable to extract CFBundleShortVersionString from URL: %s\n",
+ url.description.UTF8String);
+ return 1;
+ }
+ version = ExpandVersion(version);
+ XcodeVersionEntry *entry = [[XcodeVersionEntry alloc] initWithVersion:version url:url];
+ AddEntryToDictionary(entry, dict);
+ }
+
+ XcodeVersionEntry *entry = [dict objectForKey:version];
+ if (entry) {
+ printf("%s\n", entry.url.fileSystemRepresentation);
+ return 0;
+ }
+
+ // Print out list in json format.
+ printf("{\n");
+ for (NSString *version in dict) {
+ XcodeVersionEntry *entry = dict[version];
+ printf("\t\"%s\": \"%s\",\n", version.UTF8String, entry.url.fileSystemRepresentation);
+ }
+ printf("}\n");
+ return (version == nil ? 0 : 1);
+ }
+}
diff --git a/src/main/tools/xcode_locator_stub.sh b/src/main/tools/xcode_locator_stub.sh
new file mode 100755
index 0000000000..33191c9b87
--- /dev/null
+++ b/src/main/tools/xcode_locator_stub.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+#
+# Copyright 2015 The Bazel 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.
+
+printf 'xcode_locator should not be invoked on non-darwin systems\n' >&2
+
+exit 1
diff --git a/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java b/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java
index 701487fa18..96bcfcaf00 100644
--- a/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java
+++ b/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java
@@ -30,7 +30,8 @@ public class TestConstants {
"build_interface_so",
"build-runfiles",
"namespace-sandbox",
- "process-wrapper");
+ "process-wrapper",
+ "xcode-locator");
/**
* Location in the bazel repo where embedded binaries come from.