Skip to content

Commit

Permalink
Add xcode_locator to bazel's embedded binaries.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
c-parsons authored and damienmg committed Jan 8, 2016
1 parent bf98f39 commit f488818
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 2 deletions.
9 changes: 8 additions & 1 deletion scripts/bootstrap/compile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,13 @@ run_silent "${CXX}" -o ${OUTPUT_DIR}/build-runfiles -std=c++0x src/main/tools/bu
log "Compiling process-wrapper..."
run_silent "${CC}" -o ${OUTPUT_DIR}/process-wrapper -std=c99 src/main/tools/process-wrapper.c src/main/tools/process-tools.c -lm ${LDFLAGS}

log "Compiling xcode-locator..."
if [[ $PLATFORM == "darwin" ]]; then
run_silent /usr/bin/xcrun clang -fobjc-arc -framework CoreServices -framework Foundation -o ${OUTPUT_DIR}/xcode-locator src/main/tools/xcode_locator.m
else
cp src/main/tools/xcode_locator_stub.sh ${OUTPUT_DIR}/xcode-locator
fi

log "Compiling namespace-sandbox..."
if [[ $PLATFORM == "linux" ]]; then
run_silent "${CC}" -o ${OUTPUT_DIR}/namespace-sandbox -std=c99 src/main/tools/namespace-sandbox.c src/main/tools/network-tools.c src/main/tools/process-tools.c -lm ${LDFLAGS}
Expand All @@ -343,7 +350,7 @@ cp src/main/tools/jdk.* ${OUTPUT_DIR}

log "Creating Bazel self-extracting archive..."
ARCHIVE_DIR=${OUTPUT_DIR}/archive
for i in libblaze.jar ${JNILIB} build-runfiles${EXE_EXT} process-wrapper${EXE_EXT} namespace-sandbox${EXE_EXT} build_interface_so ${MSYS_DLLS} jdk.BUILD; do
for i in libblaze.jar ${JNILIB} build-runfiles${EXE_EXT} process-wrapper${EXE_EXT} xcode-locator${EXE_EXT} namespace-sandbox${EXE_EXT} build_interface_so ${MSYS_DLLS} jdk.BUILD; do
mkdir -p $(dirname $ARCHIVE_DIR/$i);
cp $OUTPUT_DIR/$i $ARCHIVE_DIR/$i;
done
Expand Down
2 changes: 2 additions & 0 deletions src/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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",
Expand Down
22 changes: 22 additions & 0 deletions src/main/tools/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down
153 changes: 153 additions & 0 deletions src/main/tools/xcode_locator.m
Original file line number Diff line number Diff line change
@@ -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);
}
}
19 changes: 19 additions & 0 deletions src/main/tools/xcode_locator_stub.sh
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ private TestConstants() {
"build_interface_so",
"build-runfiles",
"namespace-sandbox",
"process-wrapper");
"process-wrapper",
"xcode-locator");

/**
* Location in the bazel repo where embedded binaries come from.
Expand Down

0 comments on commit f488818

Please sign in to comment.