@VisibleForTesting static AppleCxxPlatform buildWithExecutableChecker( AppleSdk targetSdk, String minVersion, String targetArchitecture, AppleSdkPaths sdkPaths, BuckConfig buckConfig, ExecutableFinder executableFinder) { ImmutableList.Builder<Path> toolSearchPathsBuilder = ImmutableList.builder(); // Search for tools from most specific to least specific. toolSearchPathsBuilder .add(sdkPaths.getSdkPath().resolve(USR_BIN)) .add(sdkPaths.getSdkPath().resolve("Developer").resolve(USR_BIN)) .add(sdkPaths.getPlatformPath().resolve("Developer").resolve(USR_BIN)); for (Path toolchainPath : sdkPaths.getToolchainPaths()) { toolSearchPathsBuilder.add(toolchainPath.resolve(USR_BIN)); } if (sdkPaths.getDeveloperPath().isPresent()) { toolSearchPathsBuilder.add(sdkPaths.getDeveloperPath().get().resolve(USR_BIN)); toolSearchPathsBuilder.add(sdkPaths.getDeveloperPath().get().resolve("Tools")); } ImmutableList<Path> toolSearchPaths = toolSearchPathsBuilder.build(); // TODO(user): Add more and better cflags. ImmutableList.Builder<String> cflagsBuilder = ImmutableList.builder(); cflagsBuilder.add("-isysroot", sdkPaths.getSdkPath().toString()); cflagsBuilder.add("-arch", targetArchitecture); switch (targetSdk.getApplePlatform().getName()) { case ApplePlatform.Name.IPHONEOS: cflagsBuilder.add("-mios-version-min=" + minVersion); break; case ApplePlatform.Name.IPHONESIMULATOR: cflagsBuilder.add("-mios-simulator-version-min=" + minVersion); break; default: // For Mac builds, -mmacosx-version-min=<version>. cflagsBuilder.add( "-m" + targetSdk.getApplePlatform().getName() + "-version-min=" + minVersion); break; } ImmutableList<String> ldflags = ImmutableList.of("-sdk_version", targetSdk.getVersion()); ImmutableList.Builder<String> versionsBuilder = ImmutableList.builder(); versionsBuilder.add(targetSdk.getVersion()); for (AppleToolchain toolchain : targetSdk.getToolchains()) { versionsBuilder.add(toolchain.getVersion()); } String version = Joiner.on(':').join(versionsBuilder.build()); Tool clangPath = new VersionedTool( getToolPath("clang", toolSearchPaths, executableFinder), ImmutableList.<String>of(), "apple-clang", version); Tool clangXxPath = new VersionedTool( getToolPath("clang++", toolSearchPaths, executableFinder), ImmutableList.<String>of(), "apple-clang++", version); Tool ar = new VersionedTool( getToolPath("ar", toolSearchPaths, executableFinder), ImmutableList.<String>of(), "apple-ar", version); Tool actool = new VersionedTool( getToolPath("actool", toolSearchPaths, executableFinder), ImmutableList.<String>of(), "apple-actool", version); Tool ibtool = new VersionedTool( getToolPath("ibtool", toolSearchPaths, executableFinder), ImmutableList.<String>of(), "apple-ibtool", version); Tool xctest = new VersionedTool( getToolPath("xctest", toolSearchPaths, executableFinder), ImmutableList.<String>of(), "apple-xctest", version); Optional<Tool> otest = getOptionalTool("otest", toolSearchPaths, executableFinder, version); Tool dsymutil = new VersionedTool( getToolPath("dsymutil", toolSearchPaths, executableFinder), ImmutableList.<String>of(), "apple-dsymutil", version); CxxBuckConfig config = new CxxBuckConfig(buckConfig); ImmutableFlavor targetFlavor = ImmutableFlavor.of( ImmutableFlavor.replaceInvalidCharacters( targetSdk.getName() + "-" + targetArchitecture)); ImmutableBiMap.Builder<Path, Path> sanitizerPaths = ImmutableBiMap.builder(); sanitizerPaths.put(sdkPaths.getSdkPath(), Paths.get("APPLE_SDKROOT")); sanitizerPaths.put(sdkPaths.getPlatformPath(), Paths.get("APPLE_PLATFORM_DIR")); if (sdkPaths.getDeveloperPath().isPresent()) { sanitizerPaths.put(sdkPaths.getDeveloperPath().get(), Paths.get("APPLE_DEVELOPER_DIR")); } DebugPathSanitizer debugPathSanitizer = new DebugPathSanitizer(250, File.separatorChar, Paths.get("."), sanitizerPaths.build()); ImmutableList<String> cflags = cflagsBuilder.build(); CxxPlatform cxxPlatform = CxxPlatforms.build( targetFlavor, Platform.MACOS, config, clangPath, clangPath, new ClangCompiler(clangPath), new ClangCompiler(clangXxPath), clangPath, clangXxPath, clangXxPath, Optional.of(CxxPlatform.LinkerType.DARWIN), clangXxPath, ldflags, new BsdArchiver(ar), cflags, ImmutableList.<String>of(), getOptionalTool("lex", toolSearchPaths, executableFinder, version), getOptionalTool("yacc", toolSearchPaths, executableFinder, version), Optional.of(debugPathSanitizer)); return AppleCxxPlatform.builder() .setCxxPlatform(cxxPlatform) .setAppleSdk(targetSdk) .setAppleSdkPaths(sdkPaths) .setActool(actool) .setIbtool(ibtool) .setXctest(xctest) .setOtest(otest) .setDsymutil(dsymutil) .build(); }
AppleBundle( BuildRuleParams params, SourcePathResolver resolver, Either<AppleBundleExtension, String> extension, SourcePath infoPlist, Map<String, String> infoPlistSubstitutions, Optional<BuildRule> binary, AppleBundleDestinations destinations, Set<SourcePath> resourceDirs, Set<SourcePath> resourceFiles, Set<SourcePath> dirsContainingResourceDirs, ImmutableSet<SourcePath> extensionBundlePaths, Optional<ImmutableSet<SourcePath>> resourceVariantFiles, Tool ibtool, Tool dsymutil, Tool strip, Optional<AppleAssetCatalog> assetCatalog, Set<BuildTarget> tests, AppleSdk sdk, ImmutableSet<CodeSignIdentity> allValidCodeSignIdentities, Optional<SourcePath> provisioningProfileSearchPath) { super(params, resolver); this.extension = extension.isLeft() ? extension.getLeft().toFileExtension() : extension.getRight(); this.infoPlist = infoPlist; this.infoPlistSubstitutions = ImmutableMap.copyOf(infoPlistSubstitutions); this.binary = binary; this.destinations = destinations; this.resourceDirs = resourceDirs; this.resourceFiles = resourceFiles; this.dirsContainingResourceDirs = dirsContainingResourceDirs; this.extensionBundlePaths = extensionBundlePaths; this.resourceVariantFiles = resourceVariantFiles; this.ibtool = ibtool; this.dsymutil = dsymutil; this.strip = strip; this.assetCatalog = assetCatalog; this.binaryName = getBinaryName(getBuildTarget()); this.bundleRoot = getBundleRoot(getBuildTarget(), this.extension); this.binaryPath = this.destinations.getExecutablesPath().resolve(this.binaryName); this.tests = ImmutableSortedSet.copyOf(tests); this.platformName = sdk.getApplePlatform().getName(); this.sdkName = sdk.getName(); // We need to resolve the possible set of profiles and code sign identity at construction time // because they form part of the rule key. if (binary.isPresent() && ApplePlatform.needsCodeSign(this.platformName)) { final Path searchPath; if (provisioningProfileSearchPath.isPresent()) { searchPath = resolver.getResolvedPath(provisioningProfileSearchPath.get()); } else { searchPath = Paths.get( System.getProperty("user.home") + "/Library/MobileDevice/Provisioning Profiles"); } Optional<ImmutableSet<ProvisioningProfileMetadata>> provisioningProfiles; try { provisioningProfiles = Optional.of(ProvisioningProfileCopyStep.findProfilesInPath(searchPath)); } catch (InterruptedException e) { // We get here if the user pressed Ctrl-C during the profile discovery step. // In this case, we'll fail anyway since the set of profiles will be empty. provisioningProfiles = Optional.of(ImmutableSet.<ProvisioningProfileMetadata>of()); } this.provisioningProfiles = provisioningProfiles; Optional<CodeSignIdentity> foundIdentity = Optional.absent(); Optional<String> customIdentity = InfoPlistSubstitution.getVariableExpansionForPlatform( CODE_SIGN_IDENTITY, this.platformName, this.infoPlistSubstitutions); if (customIdentity.isPresent()) { LOG.debug("Bundle specifies custom code signing identity: " + customIdentity.get()); if (CodeSignIdentity.isHash(customIdentity.get())) { for (CodeSignIdentity identity : allValidCodeSignIdentities) { if (identity.getHash().equals(customIdentity.get())) { foundIdentity = Optional.of(identity); break; } } } else { for (CodeSignIdentity identity : allValidCodeSignIdentities) { if (identity.getFullName().startsWith(customIdentity.get())) { foundIdentity = Optional.of(identity); break; } } } } else if (!allValidCodeSignIdentities.isEmpty()) { LOG.debug("Using default code signing identity"); Iterator<CodeSignIdentity> it = allValidCodeSignIdentities.iterator(); foundIdentity = Optional.of(it.next()); } if (!foundIdentity.isPresent()) { throw new HumanReadableException( "The platform " + platformName + " for this target " + "requires code signing but couldn't find a compatible code signing identity to use."); } LOG.debug("Code signing identity is " + foundIdentity.toString()); this.codeSignIdentity = foundIdentity; } else { this.provisioningProfiles = Optional.absent(); this.codeSignIdentity = Optional.absent(); } }