diff options
author | 2016-01-08 00:42:14 +0000 | |
---|---|---|
committer | 2016-01-08 07:27:44 +0000 | |
commit | f488818ce168dca4760944d1378b00b9fe74d4d6 (patch) | |
tree | a3d20c6d8a15c45d6820a7fac67a07d7472be260 /src | |
parent | bf98f39d5d69d14d74dad79e705f76966f348766 (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/BUILD | 2 | ||||
-rw-r--r-- | src/main/tools/BUILD | 22 | ||||
-rw-r--r-- | src/main/tools/xcode_locator.m | 153 | ||||
-rwxr-xr-x | src/main/tools/xcode_locator_stub.sh | 19 | ||||
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java | 3 |
5 files changed, 198 insertions, 1 deletions
@@ -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. |