/*
* Copyright 2014-present Facebook, Inc.
*
* 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.
*/
package com.facebook.buck.apple;
import static com.facebook.buck.testutil.HasConsecutiveItemsMatcher.hasConsecutiveItems;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.matchesPattern;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.dd.plist.NSDictionary;
import com.facebook.buck.cli.BuckConfig;
import com.facebook.buck.cli.FakeBuckConfig;
import com.facebook.buck.cxx.CxxLinkableEnhancer;
import com.facebook.buck.cxx.CxxPlatform;
import com.facebook.buck.cxx.CxxPlatformUtils;
import com.facebook.buck.cxx.CxxPreprocessAndCompile;
import com.facebook.buck.cxx.CxxSource;
import com.facebook.buck.cxx.CxxSourceRuleFactory;
import com.facebook.buck.cxx.Linker;
import com.facebook.buck.cxx.NativeLinkableInput;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.model.Flavor;
import com.facebook.buck.model.InternalFlavor;
import com.facebook.buck.parser.NoSuchBuildTargetException;
import com.facebook.buck.rules.BinaryBuildRule;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.DefaultTargetNodeToBuildRuleTransformer;
import com.facebook.buck.rules.FakeBuildRuleParamsBuilder;
import com.facebook.buck.rules.FakeSourcePath;
import com.facebook.buck.rules.RuleKey;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.SourcePathRuleFinder;
import com.facebook.buck.rules.TargetGraph;
import com.facebook.buck.rules.Tool;
import com.facebook.buck.rules.VersionedTool;
import com.facebook.buck.rules.args.SourcePathArg;
import com.facebook.buck.rules.keys.DefaultRuleKeyFactory;
import com.facebook.buck.swift.SwiftPlatform;
import com.facebook.buck.testutil.FakeFileHashCache;
import com.facebook.buck.testutil.FakeProjectFilesystem;
import com.facebook.buck.testutil.TestLogSink;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.buck.util.environment.Platform;
import com.google.common.base.Charsets;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.easymock.EasyMock;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public class AppleCxxPlatformsTest {
@Rule public ExpectedException thrown = ExpectedException.none();
@Rule public TestLogSink logSink = new TestLogSink(AppleCxxPlatforms.class);
private ProjectFilesystem projectFilesystem;
private Path developerDir;
@Before
public void setUp() throws InterruptedException {
assumeTrue(Platform.detect() == Platform.MACOS || Platform.detect() == Platform.LINUX);
projectFilesystem = FakeProjectFilesystem.createJavaOnlyFilesystem();
developerDir = projectFilesystem.getPath("/Developer");
}
/** Get paths in a developer dir that should be set up for a sdk. */
private static ImmutableSet<Path> getCommonKnownPaths(Path root) {
return ImmutableSet.of(
root.resolve("Toolchains/XcodeDefault.xctoolchain/usr/bin/clang"),
root.resolve("Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++"),
root.resolve("Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil"),
root.resolve("Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo"),
root.resolve("Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib"),
root.resolve("Toolchains/XcodeDefault.xctoolchain/usr/bin/strip"),
root.resolve("Toolchains/XcodeDefault.xctoolchain/usr/bin/nm"),
root.resolve("usr/bin/actool"),
root.resolve("usr/bin/ibtool"),
root.resolve("usr/bin/momc"),
root.resolve("usr/bin/copySceneKitAssets"),
root.resolve("usr/bin/lldb"),
root.resolve("usr/bin/xctest"));
}
private void touchFile(Path file) {
Preconditions.checkArgument(
file.getFileSystem().equals(projectFilesystem.getRootPath().getFileSystem()),
"Should only make changes to in-memory filesystem files.");
try {
Files.createDirectories(file.getParent());
Files.createFile(file);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Test
public void iphoneOSSdkPathsBuiltFromDirectory() throws Exception {
AppleSdkPaths appleSdkPaths =
AppleSdkPaths.builder()
.setDeveloperPath(developerDir)
.addToolchainPaths(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setPlatformPath(developerDir.resolve("Platforms/iPhoneOS.platform"))
.setSdkPath(
developerDir.resolve("Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.0.sdk"))
.build();
AppleToolchain toolchain =
AppleToolchain.builder()
.setIdentifier("com.apple.dt.XcodeDefault")
.setPath(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setVersion("1")
.build();
AppleSdk targetSdk =
AppleSdk.builder()
.setApplePlatform(ApplePlatform.IPHONEOS)
.setName("iphoneos8.0")
.setVersion("8.0")
.setToolchains(ImmutableList.of(toolchain))
.build();
ImmutableSet<Path> paths =
ImmutableSet.<Path>builder()
.addAll(getCommonKnownPaths(developerDir))
.add(
developerDir.resolve(
"Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate"))
.add(developerDir.resolve("Platforms/iPhoneOS.platform/Developer/usr/bin/libtool"))
.add(developerDir.resolve("Platforms/iPhoneOS.platform/Developer/usr/bin/ar"))
.add(developerDir.resolve("Tools/otest"))
.build();
paths.forEach(this::touchFile);
AppleCxxPlatform appleCxxPlatform =
AppleCxxPlatforms.buildWithExecutableChecker(
projectFilesystem,
targetSdk,
"7.0",
"armv7",
appleSdkPaths,
FakeBuckConfig.builder().build(),
new XcodeToolFinder(),
new AppleCxxPlatforms.XcodeBuildVersionCache(),
Optional.empty());
CxxPlatform cxxPlatform = appleCxxPlatform.getCxxPlatform();
BuildRuleResolver ruleResolver =
new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer());
SourcePathResolver resolver = new SourcePathResolver(new SourcePathRuleFinder(ruleResolver));
assertEquals(
ImmutableList.of("/Developer/usr/bin/actool"),
appleCxxPlatform.getActool().getCommandPrefix(resolver));
assertEquals(
ImmutableList.of("/Developer/usr/bin/ibtool"),
appleCxxPlatform.getIbtool().getCommandPrefix(resolver));
assertEquals(
ImmutableList.of("/Developer/usr/bin/lldb"),
appleCxxPlatform.getLldb().getCommandPrefix(resolver));
assertEquals(
ImmutableList.of("/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil"),
appleCxxPlatform.getDsymutil().getCommandPrefix(resolver));
assertEquals(
ImmutableList.of(
"/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate"),
appleCxxPlatform.getCodesignAllocate().get().getCommandPrefix(resolver));
assertEquals(
ImmutableList.of("/Developer/usr/bin/xctest"),
appleCxxPlatform.getXctest().getCommandPrefix(resolver));
assertEquals(InternalFlavor.of("iphoneos8.0-armv7"), cxxPlatform.getFlavor());
assertEquals(
"/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang",
cxxPlatform.getCc().resolve(ruleResolver).getCommandPrefix(resolver).get(0));
assertThat(
ImmutableList.<String>builder()
.addAll(cxxPlatform.getCc().resolve(ruleResolver).getCommandPrefix(resolver))
.addAll(cxxPlatform.getCflags())
.build(),
hasConsecutiveItems(
"-isysroot", "/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.0.sdk"));
assertThat(cxxPlatform.getCflags(), hasConsecutiveItems("-arch", "armv7"));
assertThat(cxxPlatform.getAsflags(), hasConsecutiveItems("-arch", "armv7"));
assertThat(cxxPlatform.getCflags(), hasConsecutiveItems("-mios-version-min=7.0"));
assertThat(cxxPlatform.getLdflags(), hasConsecutiveItems("-Wl,-sdk_version", "-Wl,8.0"));
assertEquals(
"/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++",
cxxPlatform.getCxx().resolve(ruleResolver).getCommandPrefix(resolver).get(0));
assertEquals(
"/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ar",
cxxPlatform.getAr().getCommandPrefix(resolver).get(0));
}
@Test
public void watchOSSdkPathsBuiltFromDirectory() throws Exception {
AppleSdkPaths appleSdkPaths =
AppleSdkPaths.builder()
.setDeveloperPath(developerDir)
.addToolchainPaths(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setPlatformPath(developerDir.resolve("Platforms/WatchOS.platform"))
.setSdkPath(
developerDir.resolve("Platforms/WatchOS.platform/Developer/SDKs/WatchOS2.0.sdk"))
.build();
AppleToolchain toolchain =
AppleToolchain.builder()
.setIdentifier("com.apple.dt.XcodeDefault")
.setPath(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setVersion("1")
.build();
AppleSdk targetSdk =
AppleSdk.builder()
.setApplePlatform(ApplePlatform.WATCHOS)
.setName("watchos2.0")
.setVersion("2.0")
.setToolchains(ImmutableList.of(toolchain))
.build();
ImmutableSet<Path> paths =
ImmutableSet.<Path>builder()
.addAll(getCommonKnownPaths(developerDir))
.add(developerDir.resolve("Platforms/WatchOS.platform/Developer/usr/bin/libtool"))
.add(developerDir.resolve("Platforms/WatchOS.platform/Developer/usr/bin/ar"))
.build();
paths.forEach(this::touchFile);
AppleCxxPlatform appleCxxPlatform =
AppleCxxPlatforms.buildWithExecutableChecker(
projectFilesystem,
targetSdk,
"2.0",
"armv7k",
appleSdkPaths,
FakeBuckConfig.builder().build(),
new XcodeToolFinder(),
new AppleCxxPlatforms.XcodeBuildVersionCache(),
Optional.empty());
CxxPlatform cxxPlatform = appleCxxPlatform.getCxxPlatform();
BuildRuleResolver ruleResolver =
new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer());
SourcePathResolver resolver = new SourcePathResolver(new SourcePathRuleFinder(ruleResolver));
assertEquals(
ImmutableList.of("/Developer/usr/bin/actool"),
appleCxxPlatform.getActool().getCommandPrefix(resolver));
assertEquals(
ImmutableList.of("/Developer/usr/bin/ibtool"),
appleCxxPlatform.getIbtool().getCommandPrefix(resolver));
assertEquals(
ImmutableList.of("/Developer/usr/bin/lldb"),
appleCxxPlatform.getLldb().getCommandPrefix(resolver));
assertEquals(
ImmutableList.of("/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil"),
appleCxxPlatform.getDsymutil().getCommandPrefix(resolver));
assertEquals(
ImmutableList.of("/Developer/usr/bin/xctest"),
appleCxxPlatform.getXctest().getCommandPrefix(resolver));
assertEquals(InternalFlavor.of("watchos2.0-armv7k"), cxxPlatform.getFlavor());
assertEquals(
"/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang",
cxxPlatform.getCc().resolve(ruleResolver).getCommandPrefix(resolver).get(0));
assertThat(
ImmutableList.<String>builder()
.addAll(cxxPlatform.getCc().resolve(ruleResolver).getCommandPrefix(resolver))
.addAll(cxxPlatform.getCflags())
.build(),
hasConsecutiveItems(
"-isysroot", "/Developer/Platforms/WatchOS.platform/Developer/SDKs/WatchOS2.0.sdk"));
assertThat(cxxPlatform.getCflags(), hasConsecutiveItems("-arch", "armv7k"));
assertThat(cxxPlatform.getCflags(), hasConsecutiveItems("-mwatchos-version-min=2.0"));
assertThat(cxxPlatform.getLdflags(), hasConsecutiveItems("-Wl,-sdk_version", "-Wl,2.0"));
assertEquals(
"/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++",
cxxPlatform.getCxx().resolve(ruleResolver).getCommandPrefix(resolver).get(0));
assertEquals(
"/Developer/Platforms/WatchOS.platform/Developer/usr/bin/ar",
cxxPlatform.getAr().getCommandPrefix(resolver).get(0));
}
@Test
public void appleTVOSSdkPathsBuiltFromDirectory() throws Exception {
AppleSdkPaths appleSdkPaths =
AppleSdkPaths.builder()
.setDeveloperPath(developerDir)
.addToolchainPaths(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setPlatformPath(developerDir.resolve("Platforms/AppleTVOS.platform"))
.setSdkPath(
developerDir.resolve(
"Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.1.sdk"))
.build();
AppleToolchain toolchain =
AppleToolchain.builder()
.setIdentifier("com.apple.dt.XcodeDefault")
.setPath(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setVersion("1")
.build();
AppleSdk targetSdk =
AppleSdk.builder()
.setApplePlatform(ApplePlatform.APPLETVOS)
.setName("appletvos9.1")
.setVersion("9.1")
.setToolchains(ImmutableList.of(toolchain))
.build();
ImmutableSet<Path> paths =
ImmutableSet.<Path>builder()
.addAll(getCommonKnownPaths(developerDir))
.add(developerDir.resolve("Platforms/AppleTVOS.platform/Developer/usr/bin/libtool"))
.add(developerDir.resolve("Platforms/AppleTVOS.platform/Developer/usr/bin/ar"))
.build();
paths.forEach(this::touchFile);
AppleCxxPlatform appleCxxPlatform =
AppleCxxPlatforms.buildWithExecutableChecker(
projectFilesystem,
targetSdk,
"9.1",
"arm64",
appleSdkPaths,
FakeBuckConfig.builder().build(),
new XcodeToolFinder(),
new AppleCxxPlatforms.XcodeBuildVersionCache(),
Optional.empty());
CxxPlatform cxxPlatform = appleCxxPlatform.getCxxPlatform();
BuildRuleResolver ruleResolver =
new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer());
SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(ruleResolver);
SourcePathResolver resolver = new SourcePathResolver(ruleFinder);
assertEquals(
ImmutableList.of("/Developer/usr/bin/actool"),
appleCxxPlatform.getActool().getCommandPrefix(resolver));
assertEquals(
ImmutableList.of("/Developer/usr/bin/ibtool"),
appleCxxPlatform.getIbtool().getCommandPrefix(resolver));
assertEquals(
ImmutableList.of("/Developer/usr/bin/lldb"),
appleCxxPlatform.getLldb().getCommandPrefix(resolver));
assertEquals(
ImmutableList.of("/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil"),
appleCxxPlatform.getDsymutil().getCommandPrefix(resolver));
assertEquals(
ImmutableList.of("/Developer/usr/bin/xctest"),
appleCxxPlatform.getXctest().getCommandPrefix(resolver));
assertEquals(InternalFlavor.of("appletvos9.1-arm64"), cxxPlatform.getFlavor());
assertEquals(
"/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang",
cxxPlatform.getCc().resolve(ruleResolver).getCommandPrefix(resolver).get(0));
assertThat(
ImmutableList.<String>builder()
.addAll(cxxPlatform.getCc().resolve(ruleResolver).getCommandPrefix(resolver))
.addAll(cxxPlatform.getCflags())
.build(),
hasConsecutiveItems(
"-isysroot",
"/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.1.sdk"));
assertThat(cxxPlatform.getCflags(), hasConsecutiveItems("-arch", "arm64"));
assertThat(cxxPlatform.getCflags(), hasConsecutiveItems("-mtvos-version-min=9.1"));
assertThat(cxxPlatform.getLdflags(), hasConsecutiveItems("-Wl,-sdk_version", "-Wl,9.1"));
assertEquals(
"/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++",
cxxPlatform.getCxx().resolve(ruleResolver).getCommandPrefix(resolver).get(0));
assertEquals(
"/Developer/Platforms/AppleTVOS.platform/Developer/usr/bin/ar",
cxxPlatform.getAr().getCommandPrefix(resolver).get(0));
}
@Test
public void invalidFlavorCharactersInSdkAreEscaped() throws Exception {
AppleSdkPaths appleSdkPaths =
AppleSdkPaths.builder()
.setDeveloperPath(developerDir)
.addToolchainPaths(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setPlatformPath(developerDir.resolve("Platforms/iPhoneOS.platform"))
.setSdkPath(
developerDir.resolve("Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.0.sdk"))
.build();
ImmutableSet<Path> paths =
ImmutableSet.<Path>builder()
.addAll(getCommonKnownPaths(developerDir))
.add(developerDir.resolve("Platforms/iPhoneOS.platform/Developer/usr/bin/libtool"))
.add(developerDir.resolve("Platforms/iPhoneOS.platform/Developer/usr/bin/ar"))
.add(developerDir.resolve("Tools/otest"))
.build();
paths.forEach(this::touchFile);
AppleToolchain toolchain =
AppleToolchain.builder()
.setIdentifier("com.apple.dt.XcodeDefault")
.setPath(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setVersion("1")
.build();
AppleSdk targetSdk =
AppleSdk.builder()
.setApplePlatform(ApplePlatform.IPHONEOS)
.setName("_(in)+va|id_")
.setVersion("8.0")
.setToolchains(ImmutableList.of(toolchain))
.build();
AppleCxxPlatform appleCxxPlatform =
AppleCxxPlatforms.buildWithExecutableChecker(
projectFilesystem,
targetSdk,
"7.0",
"cha+rs",
appleSdkPaths,
FakeBuckConfig.builder().build(),
new XcodeToolFinder(),
new AppleCxxPlatforms.XcodeBuildVersionCache(),
Optional.empty());
assertEquals(
InternalFlavor.of("__in__va_id_-cha_rs"), appleCxxPlatform.getCxxPlatform().getFlavor());
}
@Test
public void cxxToolParamsReadFromBuckConfig() throws Exception {
AppleSdkPaths appleSdkPaths =
AppleSdkPaths.builder()
.setDeveloperPath(developerDir)
.addToolchainPaths(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setPlatformPath(developerDir.resolve("Platforms/iPhoneOS.platform"))
.setSdkPath(
developerDir.resolve("Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.0.sdk"))
.build();
ImmutableSet<Path> paths =
ImmutableSet.<Path>builder()
.addAll(getCommonKnownPaths(developerDir))
.add(developerDir.resolve("Platforms/iPhoneOS.platform/Developer/usr/bin/libtool"))
.add(developerDir.resolve("Platforms/iPhoneOS.platform/Developer/usr/bin/ar"))
.add(developerDir.resolve("Tools/otest"))
.build();
paths.forEach(this::touchFile);
AppleToolchain toolchain =
AppleToolchain.builder()
.setIdentifier("com.apple.dt.XcodeDefault")
.setPath(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setVersion("1")
.build();
AppleSdk targetSdk =
AppleSdk.builder()
.setApplePlatform(ApplePlatform.IPHONEOS)
.setName("iphoneos8.0")
.setVersion("8.0")
.setToolchains(ImmutableList.of(toolchain))
.build();
AppleCxxPlatform appleCxxPlatform =
AppleCxxPlatforms.buildWithExecutableChecker(
projectFilesystem,
targetSdk,
"7.0",
"armv7",
appleSdkPaths,
FakeBuckConfig.builder()
.setSections(
ImmutableMap.of(
"cxx",
ImmutableMap.of(
"cflags", "-std=gnu11",
"cppflags", "-DCTHING",
"cxxflags", "-std=c++11",
"cxxppflags", "-DCXXTHING")))
.build(),
new XcodeToolFinder(),
new AppleCxxPlatforms.XcodeBuildVersionCache(),
Optional.empty());
CxxPlatform cxxPlatform = appleCxxPlatform.getCxxPlatform();
assertThat(cxxPlatform.getCflags(), hasItem("-std=gnu11"));
assertThat(cxxPlatform.getCppflags(), hasItems("-DCTHING"));
assertThat(cxxPlatform.getCxxflags(), hasItem("-std=c++11"));
assertThat(cxxPlatform.getCxxppflags(), hasItems("-DCXXTHING"));
}
@Test
public void pathNotFoundThrows() throws Exception {
thrown.expect(HumanReadableException.class);
thrown.expectMessage(containsString("Cannot find tool"));
AppleSdkPaths appleSdkPaths =
AppleSdkPaths.builder()
.setDeveloperPath(developerDir)
.addToolchainPaths(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setPlatformPath(developerDir.resolve("Platforms/iPhoneOS.platform"))
.setSdkPath(
developerDir.resolve("Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.0.sdk"))
.build();
AppleToolchain toolchain =
AppleToolchain.builder()
.setIdentifier("com.apple.dt.XcodeDefault")
.setPath(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setVersion("1")
.build();
AppleSdk targetSdk =
AppleSdk.builder()
.setApplePlatform(ApplePlatform.IPHONEOS)
.setName("iphoneos8.0")
.setVersion("8.0")
.setToolchains(ImmutableList.of(toolchain))
.build();
AppleCxxPlatforms.buildWithExecutableChecker(
projectFilesystem,
targetSdk,
"7.0",
"armv7",
appleSdkPaths,
FakeBuckConfig.builder().build(),
new XcodeToolFinder(),
new AppleCxxPlatforms.XcodeBuildVersionCache(),
Optional.empty());
}
@Test
public void iphoneOSSimulatorPlatformSetsLinkerFlags() throws Exception {
AppleSdkPaths appleSdkPaths =
AppleSdkPaths.builder()
.setDeveloperPath(developerDir)
.addToolchainPaths(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setPlatformPath(developerDir.resolve("Platforms/iPhoneOS.platform"))
.setSdkPath(
developerDir.resolve(
"Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneSimulator8.0.sdk"))
.build();
ImmutableSet<Path> paths =
ImmutableSet.<Path>builder()
.addAll(getCommonKnownPaths(developerDir))
.add(developerDir.resolve("Platforms/iPhoneOS.platform/Developer/usr/bin/libtool"))
.add(developerDir.resolve("Platforms/iPhoneOS.platform/Developer/usr/bin/ar"))
.add(developerDir.resolve("Tools/otest"))
.build();
paths.forEach(this::touchFile);
AppleToolchain toolchain =
AppleToolchain.builder()
.setIdentifier("com.apple.dt.XcodeDefault")
.setPath(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setVersion("1")
.build();
AppleSdk targetSdk =
AppleSdk.builder()
.setApplePlatform(ApplePlatform.IPHONESIMULATOR)
.setName("iphonesimulator8.0")
.setVersion("8.0")
.setToolchains(ImmutableList.of(toolchain))
.build();
AppleCxxPlatform appleCxxPlatform =
AppleCxxPlatforms.buildWithExecutableChecker(
projectFilesystem,
targetSdk,
"7.0",
"armv7",
appleSdkPaths,
FakeBuckConfig.builder().build(),
new XcodeToolFinder(),
new AppleCxxPlatforms.XcodeBuildVersionCache(),
Optional.empty());
CxxPlatform cxxPlatform = appleCxxPlatform.getCxxPlatform();
assertThat(cxxPlatform.getCflags(), hasItem("-mios-simulator-version-min=7.0"));
assertThat(cxxPlatform.getLdflags(), hasItem("-mios-simulator-version-min=7.0"));
}
@Test
public void watchOSSimulatorPlatformSetsLinkerFlags() throws Exception {
AppleSdkPaths appleSdkPaths =
AppleSdkPaths.builder()
.setDeveloperPath(developerDir)
.addToolchainPaths(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setPlatformPath(developerDir.resolve("Platforms/WatchSimulator.platform"))
.setSdkPath(
developerDir.resolve(
"Platforms/WatchSimulator.platform/Developer/SDKs/WatchSimulator2.0.sdk"))
.build();
ImmutableSet<Path> paths =
ImmutableSet.<Path>builder()
.addAll(getCommonKnownPaths(developerDir))
.add(
developerDir.resolve("Platforms/WatchSimulator.platform/Developer/usr/bin/libtool"))
.add(developerDir.resolve("Platforms/WatchSimulator.platform/Developer/usr/bin/ar"))
.build();
paths.forEach(this::touchFile);
AppleToolchain toolchain =
AppleToolchain.builder()
.setIdentifier("com.apple.dt.XcodeDefault")
.setPath(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setVersion("1")
.build();
AppleSdk targetSdk =
AppleSdk.builder()
.setApplePlatform(ApplePlatform.WATCHSIMULATOR)
.setName("watchsimulator2.0")
.setVersion("2.0")
.setToolchains(ImmutableList.of(toolchain))
.build();
AppleCxxPlatform appleCxxPlatform =
AppleCxxPlatforms.buildWithExecutableChecker(
projectFilesystem,
targetSdk,
"2.0",
"armv7k",
appleSdkPaths,
FakeBuckConfig.builder().build(),
new XcodeToolFinder(),
new AppleCxxPlatforms.XcodeBuildVersionCache(),
Optional.empty());
CxxPlatform cxxPlatform = appleCxxPlatform.getCxxPlatform();
assertThat(cxxPlatform.getCflags(), hasItem("-mwatchos-simulator-version-min=2.0"));
assertThat(cxxPlatform.getLdflags(), hasItem("-mwatchos-simulator-version-min=2.0"));
}
@Test
public void appleTVOSSimulatorPlatformSetsLinkerFlags() throws Exception {
AppleSdkPaths appleSdkPaths =
AppleSdkPaths.builder()
.setDeveloperPath(developerDir)
.addToolchainPaths(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setPlatformPath(developerDir.resolve("Platforms/AppleTVSimulator.platform"))
.setSdkPath(
developerDir.resolve(
"Platforms/AppleTVSimulator.platform/Developer/SDKs/AppleTVSimulator9.1.sdk"))
.build();
ImmutableSet<Path> paths =
ImmutableSet.<Path>builder()
.addAll(getCommonKnownPaths(developerDir))
.add(
developerDir.resolve(
"Platforms/AppleTVSimulator.platform/Developer/usr/bin/libtool"))
.add(developerDir.resolve("Platforms/AppleTVSimulator.platform/Developer/usr/bin/ar"))
.build();
paths.forEach(this::touchFile);
AppleToolchain toolchain =
AppleToolchain.builder()
.setIdentifier("com.apple.dt.XcodeDefault")
.setPath(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setVersion("1")
.build();
AppleSdk targetSdk =
AppleSdk.builder()
.setApplePlatform(ApplePlatform.APPLETVSIMULATOR)
.setName("appletvsimulator9.1")
.setVersion("9.1")
.setToolchains(ImmutableList.of(toolchain))
.build();
AppleCxxPlatform appleCxxPlatform =
AppleCxxPlatforms.buildWithExecutableChecker(
projectFilesystem,
targetSdk,
"9.1",
"arm64",
appleSdkPaths,
FakeBuckConfig.builder().build(),
new XcodeToolFinder(),
new AppleCxxPlatforms.XcodeBuildVersionCache(),
Optional.empty());
CxxPlatform cxxPlatform = appleCxxPlatform.getCxxPlatform();
assertThat(cxxPlatform.getCflags(), hasItem("-mtvos-simulator-version-min=9.1"));
assertThat(cxxPlatform.getLdflags(), hasItem("-mtvos-simulator-version-min=9.1"));
}
enum Operation {
COMPILE,
PREPROCESS_AND_COMPILE,
}
// Create and return some rule keys from a dummy source for the given platforms.
private ImmutableMap<Flavor, RuleKey> constructCompileRuleKeys(
Operation operation, ImmutableMap<Flavor, AppleCxxPlatform> cxxPlatforms) {
BuildRuleResolver resolver =
new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer());
SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(resolver);
SourcePathResolver pathResolver = new SourcePathResolver(ruleFinder);
String source = "source.cpp";
DefaultRuleKeyFactory ruleKeyFactory =
new DefaultRuleKeyFactory(
0,
FakeFileHashCache.createFromStrings(
ImmutableMap.<String, String>builder()
.put("source.cpp", Strings.repeat("a", 40))
.build()),
pathResolver,
ruleFinder);
BuildTarget target = BuildTargetFactory.newInstance("//:target");
ImmutableMap.Builder<Flavor, RuleKey> ruleKeys = ImmutableMap.builder();
for (Map.Entry<Flavor, AppleCxxPlatform> entry : cxxPlatforms.entrySet()) {
CxxSourceRuleFactory cxxSourceRuleFactory =
CxxSourceRuleFactory.builder()
.setParams(new FakeBuildRuleParamsBuilder(target).build())
.setResolver(resolver)
.setPathResolver(pathResolver)
.setRuleFinder(ruleFinder)
.setCxxBuckConfig(CxxPlatformUtils.DEFAULT_CONFIG)
.setCxxPlatform(entry.getValue().getCxxPlatform())
.setPicType(CxxSourceRuleFactory.PicType.PIC)
.build();
CxxPreprocessAndCompile rule;
switch (operation) {
case PREPROCESS_AND_COMPILE:
rule =
cxxSourceRuleFactory.createPreprocessAndCompileBuildRule(
source,
CxxSource.of(CxxSource.Type.CXX, new FakeSourcePath(source), ImmutableList.of()));
break;
case COMPILE:
rule =
cxxSourceRuleFactory.createCompileBuildRule(
source,
CxxSource.of(
CxxSource.Type.CXX_CPP_OUTPUT,
new FakeSourcePath(source),
ImmutableList.of()));
break;
default:
throw new IllegalStateException();
}
ruleKeys.put(entry.getKey(), ruleKeyFactory.build(rule));
}
return ruleKeys.build();
}
// Create and return some rule keys from a dummy source for the given platforms.
private ImmutableMap<Flavor, RuleKey> constructLinkRuleKeys(
ImmutableMap<Flavor, AppleCxxPlatform> cxxPlatforms) throws NoSuchBuildTargetException {
BuildRuleResolver resolver =
new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer());
SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(resolver);
SourcePathResolver pathResolver = new SourcePathResolver(ruleFinder);
DefaultRuleKeyFactory ruleKeyFactory =
new DefaultRuleKeyFactory(
0,
FakeFileHashCache.createFromStrings(
ImmutableMap.<String, String>builder()
.put("input.o", Strings.repeat("a", 40))
.build()),
pathResolver,
ruleFinder);
BuildTarget target = BuildTargetFactory.newInstance("//:target");
ImmutableMap.Builder<Flavor, RuleKey> ruleKeys = ImmutableMap.builder();
for (Map.Entry<Flavor, AppleCxxPlatform> entry : cxxPlatforms.entrySet()) {
BuildRule rule =
CxxLinkableEnhancer.createCxxLinkableBuildRule(
CxxPlatformUtils.DEFAULT_CONFIG,
entry.getValue().getCxxPlatform(),
new FakeBuildRuleParamsBuilder(target).build(),
resolver,
pathResolver,
ruleFinder,
target,
Linker.LinkType.EXECUTABLE,
Optional.empty(),
projectFilesystem.getPath("output"),
Linker.LinkableDepType.SHARED,
/* thinLto */ false,
ImmutableList.of(),
Optional.empty(),
Optional.empty(),
ImmutableSet.of(),
NativeLinkableInput.builder()
.setArgs(SourcePathArg.from(new FakeSourcePath("input.o")))
.build());
ruleKeys.put(entry.getKey(), ruleKeyFactory.build(rule));
}
return ruleKeys.build();
}
private AppleCxxPlatform buildAppleCxxPlatform(Path root, BuckConfig config) {
AppleSdkPaths appleSdkPaths =
AppleSdkPaths.builder()
.setDeveloperPath(root)
.addToolchainPaths(root.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setPlatformPath(root.resolve("Platforms/iPhoneOS.platform"))
.setSdkPath(
root.resolve("Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneSimulator8.0.sdk"))
.build();
AppleToolchain toolchain =
AppleToolchain.builder()
.setIdentifier("com.apple.dt.XcodeDefault")
.setPath(root.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setVersion("1")
.build();
AppleSdk targetSdk =
AppleSdk.builder()
.setApplePlatform(ApplePlatform.IPHONESIMULATOR)
.setName("iphonesimulator8.0")
.setVersion("8.0")
.setToolchains(ImmutableList.of(toolchain))
.build();
getCommonKnownPaths(root).forEach(this::touchFile);
this.touchFile(root.resolve("Toolchains/XcodeDefault.xctoolchain/usr/bin/ar"));
return AppleCxxPlatforms.buildWithExecutableChecker(
projectFilesystem,
targetSdk,
"7.0",
"armv7",
appleSdkPaths,
config,
new XcodeToolFinder(),
FakeAppleRuleDescriptions.FAKE_XCODE_BUILD_VERSION_CACHE,
Optional.empty());
}
private AppleCxxPlatform buildAppleCxxPlatform(Path root) {
return buildAppleCxxPlatform(
root, FakeBuckConfig.builder().setFilesystem(projectFilesystem).build());
}
private AppleCxxPlatform buildAppleCxxPlatform() {
return buildAppleCxxPlatform(
developerDir, FakeBuckConfig.builder().setFilesystem(projectFilesystem).build());
}
@Test
public void byDefaultCodesignToolIsConstant() {
AppleCxxPlatform appleCxxPlatform = buildAppleCxxPlatform();
BuildRuleResolver buildRuleResolver = EasyMock.createMock(BuildRuleResolver.class);
SourcePathResolver sourcePathResolver = EasyMock.createMock(SourcePathResolver.class);
assertThat(
appleCxxPlatform
.getCodesignProvider()
.resolve(buildRuleResolver)
.getCommandPrefix(sourcePathResolver),
is(Arrays.asList("/usr/bin/codesign")));
}
@Test
public void buckTargetIsUsedWhenBuildTargetIsSpecified() {
AppleCxxPlatform appleCxxPlatform =
buildAppleCxxPlatform(
developerDir,
FakeBuckConfig.builder().setSections("[apple]", "codesign = //foo:bar").build());
BuildTarget buildTarget = BuildTargetFactory.newInstance("//foo:bar");
BinaryBuildRule buildRule = EasyMock.createMock(BinaryBuildRule.class);
Tool codesign = EasyMock.createMock(Tool.class);
EasyMock.expect(buildRule.getExecutableCommand()).andReturn(codesign);
BuildRuleResolver buildRuleResolver = EasyMock.createMock(BuildRuleResolver.class);
EasyMock.expect(buildRuleResolver.getRuleOptional(buildTarget))
.andReturn(Optional.of(buildRule));
EasyMock.replay(buildRule, buildRuleResolver);
assertThat(appleCxxPlatform.getCodesignProvider().resolve(buildRuleResolver), is(codesign));
}
@Test
public void filePathIsUsedWhenBuildTargetDoesNotExist() throws IOException {
Path codesignPath = projectFilesystem.getPath("/foo/fakecodesign");
touchFile(codesignPath);
AppleCxxPlatform appleCxxPlatform =
buildAppleCxxPlatform(
developerDir,
FakeBuckConfig.builder()
.setFilesystem(projectFilesystem)
.setSections("[apple]", "codesign = " + codesignPath)
.build());
BuildRuleResolver buildRuleResolver = EasyMock.createMock(BuildRuleResolver.class);
SourcePathResolver sourcePathResolver = EasyMock.createMock(SourcePathResolver.class);
assertThat(
appleCxxPlatform
.getCodesignProvider()
.resolve(buildRuleResolver)
.getCommandPrefix(sourcePathResolver),
is(Arrays.asList(codesignPath.toString())));
}
// The important aspects we check for in rule keys is that the host platform and the path
// to the NDK don't cause changes.
@Test
public void checkRootAndPlatformDoNotAffectRuleKeys() throws Exception {
Map<String, ImmutableMap<Flavor, RuleKey>> preprocessAndCompileRukeKeys = new HashMap<>();
Map<String, ImmutableMap<Flavor, RuleKey>> compileRukeKeys = new HashMap<>();
Map<String, ImmutableMap<Flavor, RuleKey>> linkRukeKeys = new HashMap<>();
// Iterate building up rule keys for combinations of different platforms and NDK root
// directories.
for (String dir : ImmutableList.of("something", "something else")) {
AppleCxxPlatform platform = buildAppleCxxPlatform(projectFilesystem.getPath(dir));
preprocessAndCompileRukeKeys.put(
String.format("AppleCxxPlatform(%s)", dir),
constructCompileRuleKeys(
Operation.PREPROCESS_AND_COMPILE,
ImmutableMap.of(platform.getCxxPlatform().getFlavor(), platform)));
compileRukeKeys.put(
String.format("AppleCxxPlatform(%s)", dir),
constructCompileRuleKeys(
Operation.COMPILE, ImmutableMap.of(platform.getCxxPlatform().getFlavor(), platform)));
linkRukeKeys.put(
String.format("AppleCxxPlatform(%s)", dir),
constructLinkRuleKeys(ImmutableMap.of(platform.getCxxPlatform().getFlavor(), platform)));
}
// If everything worked, we should be able to collapse all the generated rule keys down
// to a singleton set.
assertThat(
Arrays.toString(preprocessAndCompileRukeKeys.entrySet().toArray()),
Sets.newHashSet(preprocessAndCompileRukeKeys.values()),
Matchers.hasSize(1));
assertThat(
Arrays.toString(compileRukeKeys.entrySet().toArray()),
Sets.newHashSet(compileRukeKeys.values()),
Matchers.hasSize(1));
assertThat(
Arrays.toString(linkRukeKeys.entrySet().toArray()),
Sets.newHashSet(linkRukeKeys.values()),
Matchers.hasSize(1));
}
@Test
public void nonExistentPlatformVersionPlistIsLogged() {
AppleCxxPlatform platform =
buildAppleCxxPlatform(projectFilesystem.getPath("/nonexistentjabberwock"));
assertThat(platform.getBuildVersion(), equalTo(Optional.empty()));
assertThat(
logSink.getRecords(),
hasItem(
TestLogSink.logRecordWithMessage(
matchesPattern(".*does not exist.*Build version will be unset.*"))));
}
@Test
public void invalidPlatformVersionPlistIsLogged() throws Exception {
Path platformRoot = developerDir.resolve("Platforms/iPhoneOS.platform");
Files.createDirectories(platformRoot);
Files.write(
platformRoot.resolve("version.plist"),
"I am, as a matter of fact, an extremely invalid plist.".getBytes(Charsets.UTF_8));
AppleCxxPlatform platform = buildAppleCxxPlatform();
assertThat(platform.getBuildVersion(), equalTo(Optional.empty()));
assertThat(
logSink.getRecords(),
hasItem(
TestLogSink.logRecordWithMessage(
matchesPattern("Failed to parse.*Build version will be unset.*"))));
}
@Test
public void platformVersionPlistWithMissingFieldIsLogged() throws Exception {
Path platformRoot = developerDir.resolve("Platforms/iPhoneOS.platform");
Files.createDirectories(platformRoot);
Files.write(
platformRoot.resolve("version.plist"),
new NSDictionary().toXMLPropertyList().getBytes(Charsets.UTF_8));
AppleCxxPlatform platform = buildAppleCxxPlatform();
assertThat(platform.getBuildVersion(), equalTo(Optional.empty()));
assertThat(
logSink.getRecords(),
hasItem(
TestLogSink.logRecordWithMessage(
matchesPattern(".*missing ProductBuildVersion. Build version will be unset.*"))));
}
@Test
public void appleCxxPlatformWhenNoSwiftToolchainPreferredShouldUseDefaultSwift()
throws IOException {
AppleCxxPlatform platformWithDefaultSwift = buildAppleCxxPlatformWithSwiftToolchain(true);
Optional<SwiftPlatform> swiftPlatformOptional = platformWithDefaultSwift.getSwiftPlatform();
assertThat(swiftPlatformOptional.isPresent(), is(true));
Tool swiftcTool = swiftPlatformOptional.get().getSwiftc();
assertTrue(swiftcTool instanceof VersionedTool);
assertThat(
((VersionedTool) swiftcTool).getPath(),
equalTo(
projectFilesystem.getPath(
"/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc")));
assertThat(swiftPlatformOptional.get().getSwiftRuntimePaths(), Matchers.empty());
}
@Test
public void appleCxxPlatformShouldUsePreferredSwiftVersion() throws IOException {
AppleCxxPlatform platformWithConfiguredSwift = buildAppleCxxPlatformWithSwiftToolchain(false);
Optional<SwiftPlatform> swiftPlatformOptional = platformWithConfiguredSwift.getSwiftPlatform();
assertThat(swiftPlatformOptional.isPresent(), is(true));
Tool swiftcTool = swiftPlatformOptional.get().getSwiftc();
assertThat(
((VersionedTool) swiftcTool).getPath(),
equalTo(projectFilesystem.getPath("/TEMP_ROOT/usr/bin/swiftc")));
assertThat(
swiftPlatformOptional.get().getSwiftRuntimePaths(),
equalTo(ImmutableSet.of(projectFilesystem.getPath("/TEMP_ROOT/usr/lib/swift/iphoneos"))));
}
@Test
public void checkSwiftPlatformUsesCorrectMinTargetSdk() throws IOException {
AppleCxxPlatform platformWithConfiguredSwift = buildAppleCxxPlatformWithSwiftToolchain(true);
Tool swiftc = platformWithConfiguredSwift.getSwiftPlatform().get().getSwiftc();
assertThat(swiftc, notNullValue());
assertThat(swiftc, instanceOf(VersionedTool.class));
VersionedTool versionedSwiftc = (VersionedTool) swiftc;
assertThat(versionedSwiftc.getExtraArgs(), hasItem("i386-apple-ios7.0"));
}
@Test
public void testXcodeBuildVersionCache() throws Exception {
Path developerDir = projectFilesystem.getPath("/Xcode.app/Contents/Developer");
Path versionPlist = projectFilesystem.getPath("/Xcode.app/Contents/version.plist");
Files.createDirectories(developerDir);
Files.write(
versionPlist,
("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "
+ "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
+ "<plist version=\"1.0\">\n"
+ "<dict>\n"
+ "\t<key>ProductBuildVersion</key>\n"
+ "\t<string>9F9999</string>\n"
+ "</dict>\n"
+ "</plist>")
.getBytes(Charsets.UTF_8));
AppleCxxPlatforms.XcodeBuildVersionCache cache = new AppleCxxPlatforms.XcodeBuildVersionCache();
assertEquals(Optional.of("9F9999"), cache.lookup(developerDir));
}
private AppleCxxPlatform buildAppleCxxPlatformWithSwiftToolchain(boolean useDefaultSwift)
throws IOException {
Path tempRoot = projectFilesystem.getPath("/TEMP_ROOT");
AppleToolchain swiftToolchain =
AppleToolchain.builder()
.setIdentifier("com.apple.dt.XcodeDefault")
.setPath(tempRoot)
.setVersion("1")
.build();
touchFile(tempRoot.resolve("usr/bin/swiftc"));
touchFile(tempRoot.resolve("usr/bin/swift-stdlib-tool"));
Files.createDirectories(tempRoot.resolve("usr/lib/swift/iphoneos"));
Files.createDirectories(tempRoot.resolve("usr/lib/swift_static/iphoneos"));
Optional<AppleToolchain> selectedSwiftToolChain =
useDefaultSwift ? Optional.empty() : Optional.of(swiftToolchain);
final ImmutableSet<Path> knownPaths =
ImmutableSet.<Path>builder()
.addAll(getCommonKnownPaths(developerDir))
.add(developerDir.resolve("Platforms/iPhoneOS.platform/Developer/usr/bin/libtool"))
.add(developerDir.resolve("Platforms/iPhoneOS.platform/Developer/usr/bin/ar"))
.add(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc"))
.add(
developerDir.resolve(
"Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-stdlib-tool"))
.build();
knownPaths.forEach(this::touchFile);
return AppleCxxPlatforms.buildWithExecutableChecker(
projectFilesystem,
FakeAppleRuleDescriptions.DEFAULT_IPHONEOS_SDK,
"7.0",
"i386",
AppleSdkPaths.builder()
.setDeveloperPath(developerDir)
.addToolchainPaths(developerDir.resolve("Toolchains/XcodeDefault.xctoolchain"))
.setPlatformPath(developerDir.resolve("Platforms/iPhoneOS.platform"))
.setSdkPath(
developerDir.resolve("Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk"))
.build(),
FakeBuckConfig.builder().build(),
new XcodeToolFinder(),
FakeAppleRuleDescriptions.FAKE_XCODE_BUILD_VERSION_CACHE,
selectedSwiftToolChain);
}
}