diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java | 1250 |
1 files changed, 0 insertions, 1250 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java deleted file mode 100644 index b73b8cbe4c..0000000000 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java +++ /dev/null @@ -1,1250 +0,0 @@ -// 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. - -package com.google.devtools.build.lib.rules.objc; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.devtools.build.lib.packages.ImplicitOutputsFunction.fromTemplates; -import static com.google.devtools.build.lib.rules.objc.ObjcProvider.Flag.USES_SWIFT; -import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.APP_ICON_ATTR; -import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.DEBUG_ENTITLEMENTS_ATTR; -import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.EXTRA_ENTITLEMENTS_ATTR; - -import com.dd.plist.NSArray; -import com.dd.plist.NSDictionary; -import com.dd.plist.NSObject; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Optional; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; -import com.google.devtools.build.lib.actions.Artifact; -import com.google.devtools.build.lib.analysis.BuildInfo; -import com.google.devtools.build.lib.analysis.FilesToRunProvider; -import com.google.devtools.build.lib.analysis.RuleContext; -import com.google.devtools.build.lib.analysis.Runfiles; -import com.google.devtools.build.lib.analysis.RunfilesSupport; -import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; -import com.google.devtools.build.lib.analysis.actions.BinaryFileWriteAction; -import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; -import com.google.devtools.build.lib.analysis.actions.FileWriteAction; -import com.google.devtools.build.lib.analysis.actions.SpawnAction; -import com.google.devtools.build.lib.analysis.actions.SymlinkAction; -import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction; -import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.Substitution; -import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode; -import com.google.devtools.build.lib.collect.nestedset.NestedSet; -import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; -import com.google.devtools.build.lib.collect.nestedset.Order; -import com.google.devtools.build.lib.packages.BuildType; -import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction; -import com.google.devtools.build.lib.rules.apple.AppleConfiguration; -import com.google.devtools.build.lib.rules.apple.ApplePlatform; -import com.google.devtools.build.lib.rules.apple.ApplePlatform.PlatformType; -import com.google.devtools.build.lib.rules.apple.DottedVersion; -import com.google.devtools.build.lib.rules.apple.XcodeConfig; -import com.google.devtools.build.lib.rules.apple.XcodeConfigProvider; -import com.google.devtools.build.lib.rules.objc.BundleSupport.ExtraActoolArgs; -import com.google.devtools.build.lib.rules.objc.Bundling.Builder; -import com.google.devtools.build.lib.shell.ShellUtils; -import java.util.List; -import java.util.Map.Entry; -import javax.annotation.Nullable; - -/** - * Support for released bundles, such as an application or extension. Such a bundle is generally - * composed of a top-level {@link BundleSupport bundle}, potentially signed, as well as some debug - * information, if {@link ObjcConfiguration#generateDsym() requested}. - * - * <p>Contains actions, validation logic and provider value generation. - * - * <p>Methods on this class can be called in any order without impacting the result. - * - * @deprecated The native bundling rules have been deprecated. This class will be removed in the - * future. - */ -@Deprecated -public final class ReleaseBundlingSupport { - - /** - * Template for the containing application folder. - */ - public static final SafeImplicitOutputsFunction IPA = fromTemplates("%{name}.ipa"); - - @VisibleForTesting - static final String NO_ASSET_CATALOG_ERROR_FORMAT = - "a value was specified (%s), but this app does not have any asset catalogs"; - @VisibleForTesting - static final String DEVICE_NO_PROVISIONING_PROFILE = - "Provisioning profile must be set for device build"; - - @VisibleForTesting - static final String PROVISIONING_PROFILE_BUNDLE_FILE = "embedded.mobileprovision"; - @VisibleForTesting - static final String APP_BUNDLE_DIR_FORMAT = "Payload/%s.app"; - @VisibleForTesting - static final String XCTEST_BUNDLE_DIR_FORMAT = "Payload/%s.xctest"; - @VisibleForTesting - static final String EXTENSION_BUNDLE_DIR_FORMAT = "PlugIns/%s.appex"; - @VisibleForTesting - static final String FRAMEWORK_BUNDLE_DIR_FORMAT = "Frameworks/%s.framework"; - - /** - * Command string for "sed" that tries to extract the application version number from a larger - * string. For example, from "foo_1.2.3_RC00" this would extract "1.2.3". This regex looks for - * versions of the format "x.y" or "x.y.z", which may be preceded and/or followed by other text, - * such as a project name or release candidate number. - * - * <p>This command also preserves double quotes around the string, if any. - */ - private static final String EXTRACT_VERSION_NUMBER_SED_COMMAND = - "s#\\(\"\\)\\{0,1\\}\\(.*_\\)\\{0,1\\}\\([0-9][0-9]*\\(\\.[0-9][0-9]*\\)\\{1,2\\}\\)" - + "\\(_[^\"]*\\)\\{0,1\\}\\(\"\\)\\{0,1\\}#\\1\\3\\6#"; - - private final Attributes attributes; - private final BundleSupport bundleSupport; - private final RuleContext ruleContext; - private final Bundling bundling; - private final ObjcProvider objcProvider; - private final LinkedBinary linkedBinary; - private final IntermediateArtifacts intermediateArtifacts; - private final ReleaseBundling releaseBundling; - private final ApplePlatform platform; - - /** - * Indicator as to whether this rule generates a binary directly or whether only dependencies - * should be considered. - */ - enum LinkedBinary { - /** - * This rule generates its own binary which should be included as well as dependency-generated - * binaries. - */ - LOCAL_AND_DEPENDENCIES, - - /** - * This rule does not generate its own binary, only consider binaries from dependencies. - */ - DEPENDENCIES_ONLY - } - - /** - * Creates a new release bundling support within the given rule context. - * - * @param ruleContext context for the application-generating rule - * @param objcProvider provider containing all dependencies' information as well as some of this - * rule's - * @param linkedBinary whether to look for a linked binary from this rule and dependencies or just - * the latter - * @param bundleDirFormat format string representing the bundle's directory with a single - * placeholder for the target name (e.g. {@code "Payload/%s.app"}) - * @param bundleName name of the bundle, used with bundleDirFormat - * @param bundleMinimumOsVersion the minimum OS version this bundle's plist should be generated - * for (<b>not</b> the minimum OS version its binary is compiled with, that needs to be set - * through the configuration) - * @param releaseBundling the {@link ReleaseBundling} containing information for creating a - * releaseable bundle. - * @param platform the platform that bundles will be created for using this support - */ - ReleaseBundlingSupport( - RuleContext ruleContext, - ObjcProvider objcProvider, - LinkedBinary linkedBinary, - String bundleDirFormat, - String bundleName, - DottedVersion bundleMinimumOsVersion, - ReleaseBundling releaseBundling, - ApplePlatform platform) { - this.platform = platform; - this.linkedBinary = linkedBinary; - this.attributes = new Attributes(ruleContext); - this.ruleContext = ruleContext; - this.objcProvider = objcProvider; - this.releaseBundling = releaseBundling; - this.intermediateArtifacts = releaseBundling.getIntermediateArtifacts(); - this.bundling = bundling(ruleContext, objcProvider, bundleDirFormat, bundleName, - bundleMinimumOsVersion); - // TODO(cparsons): Take the rule configuration as a param instead of inferring. - bundleSupport = new BundleSupport(ruleContext, - ruleContext.getFragment(AppleConfiguration.class), platform, - bundling, extraActoolArgs()); - } - - /** - * Creates a new application support within the given rule context. - * - * @param ruleContext context for the application-generating rule - * @param objcProvider provider containing all dependencies' information as well as some of this - * rule's - * @param linkedBinary whether to look for a linked binary from this rule and dependencies or just - * the latter - * @param bundleDirFormat format string representing the bundle's directory with a single - * placeholder for the target name (e.g. {@code "Payload/%s.app"}) - * @param bundleName name of the bundle, used with bundleDirFormat - * @param platform the platform that bundles will be created for using this support - */ - ReleaseBundlingSupport( - RuleContext ruleContext, - ObjcProvider objcProvider, - LinkedBinary linkedBinary, - String bundleDirFormat, - String bundleName, - DottedVersion bundleMinimumOsVersion, - ApplePlatform platform) - throws InterruptedException { - this( - ruleContext, - objcProvider, - linkedBinary, - bundleDirFormat, - bundleName, - bundleMinimumOsVersion, - ReleaseBundling.releaseBundling(ruleContext), - platform); - } - - /** - * Creates a new application support within the given rule context. - * - * <p>{@code bundleName} defaults to label name - * - * @param ruleContext context for the application-generating rule - * @param objcProvider provider containing all dependencies' information as well as some of this - * rule's - * @param linkedBinary whether to look for a linked binary from this rule and dependencies or just - * the latter - * @param bundleDirFormat format string representing the bundle's directory with a single - * placeholder for the target name (e.g. {@code "Payload/%s.app"}) - * @param bundleMinimumOsVersion the minimum OS version this bundle's plist should be generated - * for (<b>not</b> the minimum OS version its binary is compiled with, that needs to be set - * through the configuration) - * @param platform the platform that bundles will be created for using this support - * @throws InterruptedException - */ - ReleaseBundlingSupport( - RuleContext ruleContext, - ObjcProvider objcProvider, - LinkedBinary linkedBinary, - String bundleDirFormat, - DottedVersion bundleMinimumOsVersion, - ApplePlatform platform) - throws InterruptedException { - this(ruleContext, objcProvider, linkedBinary, bundleDirFormat, ruleContext.getLabel().getName(), - bundleMinimumOsVersion, platform); - } - - /** - * Validates application-related attributes set on this rule and registers any errors with the - * rule context. - * - * @return this application support - */ - ReleaseBundlingSupport validateAttributes() { - // No asset catalogs. That means you cannot specify app_icon or - // launch_image attributes, since they must not exist. However, we don't - // run actool in this case, which means it does not do validity checks, - // and we MUST raise our own error somehow... - if (!objcProvider.hasAssetCatalogs()) { - if (releaseBundling.getAppIcon() != null) { - ruleContext.attributeError(APP_ICON_ATTR, - String.format(NO_ASSET_CATALOG_ERROR_FORMAT, releaseBundling.getAppIcon())); - } - if (releaseBundling.getLaunchImage() != null) { - ruleContext.attributeError("launch_image", - String.format(NO_ASSET_CATALOG_ERROR_FORMAT, releaseBundling.getLaunchImage())); - } - } - - if (releaseBundling.getProvisioningProfile() == null && platform.isDevice()) { - ruleContext.attributeError(releaseBundling.getProvisioningProfileAttrName(), - DEVICE_NO_PROVISIONING_PROFILE); - } - - return this; - } - - /** - * Validates that resources defined in this rule and its dependencies and written to this bundle - * are legal. - * - * @return this release bundling support - */ - ReleaseBundlingSupport validateResources() { - bundleSupport - .validatePlatform() - .validateResources(objcProvider); - return this; - } - - /** - * Registers actions required to build an application. This includes any - * {@link BundleSupport#registerActions(ObjcProvider) bundle} and bundle merge actions, signing - * this application if appropriate and combining several single-architecture binaries into one - * multi-architecture binary. - * - * @param dsymOutputType the file type of the dSYM bundle to be generated - * - * @return this application support - */ - ReleaseBundlingSupport registerActions(DsymOutputType dsymOutputType) - throws InterruptedException { - bundleSupport.registerActions(objcProvider); - - Artifact combinedArchBinary = prepareCombinedArchitecturesArtifact(); - registerCopyDsymFilesAction(dsymOutputType); - registerCopyDsymPlistAction(dsymOutputType); - registerCopyLinkmapFilesAction(); - registerSwiftStdlibActionsIfNecessary(combinedArchBinary); - registerSwiftSupportActionsIfNecessary(combinedArchBinary); - - registerEmbedLabelPlistAction(); - registerEnvironmentPlistAction(); - registerAutomaticPlistAction(); - - if (releaseBundling.getLaunchStoryboard() != null) { - registerLaunchStoryboardPlistAction(); - } - - registerBundleMergeActions(); - registerPostProcessAndSigningActions(); - - return this; - } - - private void registerEmbedLabelPlistAction() throws InterruptedException { - Artifact buildInfo = Iterables.getOnlyElement( - ruleContext.getBuildInfo(ObjcBuildInfoFactory.KEY)); - String generatedVersionPlistPath = getGeneratedVersionPlist().getShellEscapedExecPathString(); - String shellCommand = "VERSION=\"$(" - + "grep \"^" + BuildInfo.BUILD_EMBED_LABEL + "\" " - + buildInfo.getShellEscapedExecPathString() - + " | cut -d' ' -f2- | sed -e '" + EXTRACT_VERSION_NUMBER_SED_COMMAND + "' | " - + "sed -e 's#\"#\\\"#g')\" && " - + "cat >" + generatedVersionPlistPath + " <<EOF\n" - + "<?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" - + "EOF\n" - - + "if [[ -n \"${VERSION}\" ]]; then\n" - + " for KEY in CFBundleVersion CFBundleShortVersionString; do\n" - + " echo \" <key>${KEY}</key>\n\" >> " - + generatedVersionPlistPath + "\n" - + " echo \" <string>${VERSION}</string>\n\" >> " - + generatedVersionPlistPath + "\n" - + " done\n" - + "fi\n" - - + "cat >>" + generatedVersionPlistPath + " <<EOF\n" - + "</dict>\n" - + "</plist>\n" - + "EOF\n"; - ruleContext.registerAction(new SpawnAction.Builder() - .setMnemonic("ObjcVersionPlist") - .setShellCommand(shellCommand) - .addInput(buildInfo) - .addOutput(getGeneratedVersionPlist()) - .build(ruleContext)); - } - - private void registerLaunchStoryboardPlistAction() { - String launchStoryboard = releaseBundling.getLaunchStoryboard().getFilename(); - String launchStoryboardName = launchStoryboard.substring(0, launchStoryboard.lastIndexOf('.')); - NSDictionary result = new NSDictionary(); - result.put("UILaunchStoryboardName", launchStoryboardName); - String contents = result.toGnuStepASCIIPropertyList(); - ruleContext.registerAction( - FileWriteAction.create(ruleContext, getLaunchStoryboardPlist(), contents, false)); - } - - private void registerEnvironmentPlistAction() { - // Generates a .plist that contains environment values (such as the SDK used to build, the Xcode - // version, etc), which are parsed from various .plist files of the OS, namely Xcodes' and - // Platforms' plists. - // The resulting file is meant to be merged with the final bundle. - String platformWithVersion = - String.format( - "%s%s", - platform.getLowerCaseNameInPlist(), - XcodeConfig.getSdkVersionForPlatform(ruleContext, platform)); - ruleContext.registerAction( - ObjcRuleClasses.spawnAppleEnvActionBuilder( - XcodeConfigProvider.fromRuleContext(ruleContext), platform) - .setMnemonic("EnvironmentPlist") - .setExecutable(attributes.environmentPlist()) - .addOutput(getGeneratedEnvironmentPlist()) - .addCommandLine( - CustomCommandLine.builder() - .add("--platform", platformWithVersion) - .addExecPath("--output", getGeneratedEnvironmentPlist()) - .build()) - .build(ruleContext)); - } - - private void registerAutomaticPlistAction() { - ruleContext.registerAction( - FileWriteAction.create( - ruleContext, - getGeneratedAutomaticPlist(), - automaticEntries().toGnuStepASCIIPropertyList(), - /*makeExecutable=*/ false)); - } - - /** - * Returns a map containing entries that should be added to the merged plist. These are usually - * generated by Xcode automatically during the build process. - */ - private NSDictionary automaticEntries() { - List<Integer> uiDeviceFamily = - TargetDeviceFamily.UI_DEVICE_FAMILY_VALUES.get(bundleSupport.targetDeviceFamilies()); - NSDictionary result = new NSDictionary(); - - if (uiDeviceFamily != null) { - result.put("UIDeviceFamily", uiDeviceFamily.toArray()); - } - result.put("DTPlatformName", platform.getLowerCaseNameInPlist()); - result.put( - "DTSDKName", - platform.getLowerCaseNameInPlist() - + XcodeConfig.getSdkVersionForPlatform(ruleContext, platform)); - result.put("CFBundleSupportedPlatforms", new NSArray(NSObject.wrap(platform.getNameInPlist()))); - result.put("MinimumOSVersion", bundling.getMinimumOsVersion().toString()); - - return result; - } - - /** - * Registers all actions necessary to create a processed and signed IPA from the initial merged - * IPA. - * - * <p>Includes user-provided actions to process IPA contents (via {@code ipa_post_processor}), - * and signing actions if the IPA is being built for device architectures. If signing is necessary - * also includes entitlements generation and processing actions. - * - * <p>Note that multiple "actions" on the IPA contents may be run in a single blaze action to - * avoid excessive zipping/unzipping of IPA contents. - */ - private void registerPostProcessAndSigningActions() { - Artifact processedIpa = releaseBundling.getIpaArtifact(); - Artifact unprocessedIpa = intermediateArtifacts.unprocessedIpa(); - - NestedSetBuilder<Artifact> inputs = - NestedSetBuilder.<Artifact>stableOrder().add(unprocessedIpa); - - String actionCommandLine = - "set -e && " - + "t=$(mktemp -d \"${TMPDIR:-/tmp}/signing_intermediate.XXXXXX\") && " - + "trap \"rm -rf ${t}\" EXIT && " - // Get an absolute path since we need to cd into the temp directory for zip. - + "signed_ipa=${PWD}/" - + processedIpa.getShellEscapedExecPathString() - + " && " - + "/usr/bin/unzip -qq " - + unprocessedIpa.getShellEscapedExecPathString() - + " -d ${t} && "; - - FilesToRunProvider processor = attributes.ipaPostProcessor(); - if (processor != null) { - actionCommandLine += processor.getExecutable().getShellEscapedExecPathString() + " ${t} && "; - } - - if (platform.isDevice()) { - actionCommandLine += deviceSigningCommandLine(); - - registerEntitlementsActions(); - inputs.add(releaseBundling.getProvisioningProfile()) - .add(intermediateArtifacts.entitlements()); - } else { - actionCommandLine += simulatorSigningCommandLine(); - } - - actionCommandLine += "cd ${t} && /usr/bin/zip -q -r \"${signed_ipa}\" ."; - - SpawnAction.Builder processAction = - ObjcRuleClasses.spawnBashOnDarwinActionBuilder(actionCommandLine) - .setEnvironment( - ObjcRuleClasses.appleToolchainEnvironment( - XcodeConfigProvider.fromRuleContext(ruleContext), platform)) - .setMnemonic("ObjcProcessIpa") - .setProgressMessage("Processing iOS IPA: %s", ruleContext.getLabel()) - .disableSandboxing() - .addTransitiveInputs(inputs.build()) - .addOutput(processedIpa); - - if (processor != null) { - processAction.addTool(processor); - } - - ruleContext.registerAction(processAction.build(ruleContext)); - } - - private String deviceSigningCommandLine() { - StringBuilder codesignCommandLineBuilder = new StringBuilder(); - for (String dir : getDirsToSign()) { - codesignCommandLineBuilder.append(deviceCodesignCommand("${t}/" + dir)).append(" && "); - } - return codesignCommandLineBuilder.toString(); - } - - private String simulatorSigningCommandLine() { - StringBuilder codesignCommandLineBuilder = new StringBuilder(); - for (String dir : getDirsToSign()) { - codesignCommandLineBuilder - .append("/usr/bin/codesign --force --sign \"-\" ${t}/") - .append(dir) - .append(" && "); - } - return codesignCommandLineBuilder.toString(); - } - - private ImmutableList<String> getDirsToSign() { - // The order here is important. The innermost code must signed first. - ImmutableList.Builder<String> dirsToSign = new ImmutableList.Builder<>(); - String bundleDir = ShellUtils.shellEscape(bundling.getBundleDir()); - - // Explicitly sign the frameworks (raw .dylib files and .framework directories in Frameworks/). - // Unfortunately the --deep option on codesign doesn't do this automatically. - if (objcProvider.is(USES_SWIFT) - || !objcProvider.get(ObjcProvider.DYNAMIC_FRAMEWORK_FILE).isEmpty()) { - dirsToSign.add(bundleDir + "/Frameworks/*"); - } - dirsToSign.add(bundleDir); - - return dirsToSign.build(); - } - - /** - * Creates entitlement actions such that an entitlements file is generated in - * {@link IntermediateArtifacts#entitlements()} which can be used for signing in this bundle. - * - * <p>Entitlements are generated based on a plist-format entitlements file passed to this bundle's - * {@code entitlements} attribute or, if that is not set, entitlements extracted from the provided - * mobile provisioning profile. The team prefix is extracted from the provisioning profile and - * the following substitutions performed (assuming the prefix extracted was {@code PREFIX}): - * <ol> - * <li>"PREFIX.*" -> "PREFIX.BUNDLE_ID" (where BUNDLE_ID is this bundle's id) - * <li>"$(AppIdentifierPrefix)" -> "PREFIX." - * <li>"$(CFBundleIdentifier)" -> "BUNDLE_ID" (where BUNDLE_ID is this bundle's id) - * </ol> - * - * <p>Finally, if an entitlements file was provided via {@code --extra_entitlements} it is merged - * into the substituted entitlements. - */ - private void registerEntitlementsActions() { - Artifact teamPrefixFile = - intermediateArtifacts.appendExtensionForEntitlementArtifact(".team_prefix_file"); - registerExtractTeamPrefixAction(teamPrefixFile); - - Artifact entitlementsNeedingSubstitution = releaseBundling.getEntitlements(); - if (entitlementsNeedingSubstitution == null) { - entitlementsNeedingSubstitution = - intermediateArtifacts.appendExtensionForEntitlementArtifact( - ".entitlements_with_variables"); - registerExtractEntitlementsAction(entitlementsNeedingSubstitution); - } - - Artifact substitutedEntitlements = intermediateArtifacts.entitlements(); - if (attributes.extraEntitlements() != null || includeDebugEntitlements()) { - substitutedEntitlements = - intermediateArtifacts.appendExtensionForEntitlementArtifact(".substituted"); - - NestedSetBuilder<Artifact> entitlements = - NestedSetBuilder.<Artifact>stableOrder().add(substitutedEntitlements); - if (attributes.extraEntitlements() != null) { - entitlements.add(attributes.extraEntitlements()); - } - if (includeDebugEntitlements()) { - entitlements.add(attributes.deviceDebugEntitlements()); - } - - registerMergeEntitlementsAction(entitlements.build()); - } - - registerEntitlementsVariableSubstitutionAction( - entitlementsNeedingSubstitution, teamPrefixFile, substitutedEntitlements); - } - - private boolean includeDebugEntitlements() { - return attributes.deviceDebugEntitlements() != null - && ObjcRuleClasses.objcConfiguration(ruleContext).useDeviceDebugEntitlements(); - } - - private void registerMergeEntitlementsAction(NestedSet<Artifact> entitlements) { - PlMergeControlBytes controlBytes = - PlMergeControlBytes.fromPlists( - entitlements, - intermediateArtifacts.entitlements(), - PlMergeControlBytes.OutputFormat.XML); - - Artifact plMergeControlArtifact = ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, - artifactName(".merge-entitlements-control")); - - ruleContext.registerAction( - new BinaryFileWriteAction( - ruleContext.getActionOwner(), - plMergeControlArtifact, - controlBytes, - /*makeExecutable=*/ false)); - - ruleContext.registerAction( - new SpawnAction.Builder() - .setMnemonic("MergeEntitlementsFiles") - .setExecutable(attributes.plmerge()) - .addTransitiveInputs(entitlements) - .addOutput(intermediateArtifacts.entitlements()) - .addInput(plMergeControlArtifact) - .addCommandLine( - CustomCommandLine.builder() - .addExecPath("--control", plMergeControlArtifact) - .build()) - .build(ruleContext)); - } - - /** - * Adds any files to the given nested set builder that should be built if this application is the - * top level target in a blaze invocation. - * - * @param filesToBuild a collection of files to be built, where new artifacts to be built are - * going to be placed - * @param dsymOutputType the file type of the dSYM bundle to be built, or absent if no - * dSYM should be built for this bundle. A dSYM bundle will only be created if both this - * is present and the configuration values dictate dSYM is enabled - * - * @return this application support - */ - ReleaseBundlingSupport addFilesToBuild( - NestedSetBuilder<Artifact> filesToBuild, Optional<DsymOutputType> dsymOutputType) { - NestedSetBuilder<Artifact> debugSymbolBuilder = NestedSetBuilder.<Artifact>stableOrder(); - - for (Artifact linkmapFile : getLinkmapFiles().values()) { - filesToBuild.add(linkmapFile); - } - - if (ObjcRuleClasses.objcConfiguration(ruleContext).generateDsym() - && dsymOutputType.isPresent()) { - filesToBuild.addAll(getDsymFiles(dsymOutputType.get()).values()); - - // TODO(bazel-team): Remove the 'if' when the objc_binary rule does not generate a bundle any - // more. The reason this 'if' is here is because the plist is obtained from the ObjcProvider. - // Since objc_binary is the rule that adds this file to the provider, and not before, when - // running this the provider does not have the plist yet. This gets called again when running - // the *_application targets, and since they depend on objc_binaries, the provider has the - // files configured. When objc_binary stops bundling ipas as output, the bundling methods will - // only get called by *_application rules, with the plist configured in the provider. - Artifact cpuPlist = getAnyCpuSpecificDsymPlist(); - if (cpuPlist != null) { - filesToBuild.add(intermediateArtifacts.dsymPlist(dsymOutputType.get())); - } - - if (linkedBinary == LinkedBinary.LOCAL_AND_DEPENDENCIES) { - debugSymbolBuilder - .add(intermediateArtifacts.dsymPlist(dsymOutputType.get())) - .add(intermediateArtifacts.dsymSymbol(dsymOutputType.get())); - } - } - - filesToBuild - .add(releaseBundling.getIpaArtifact()) - .addTransitive(debugSymbolBuilder.build()) - .addTransitive(objcProvider.get(ObjcProvider.EXPORTED_DEBUG_ARTIFACTS)); - - return this; - } - - /** - * Adds dSYM artifacts (plist, arch-speficic binaries) to the {@link ObjcProvider} for export. - */ - public void addExportedDebugArtifacts( - ObjcProvider.Builder objcBuilder, DsymOutputType dsymOutputType) { - if (ObjcRuleClasses.objcConfiguration(ruleContext).generateDsym()) { - objcBuilder - .addAll(ObjcProvider.EXPORTED_DEBUG_ARTIFACTS, getDsymFiles(dsymOutputType).values()) - .add( - ObjcProvider.EXPORTED_DEBUG_ARTIFACTS, - intermediateArtifacts.dsymPlist(dsymOutputType)); - } - } - - /** - * Registers an action to generate a runner script based on a template. - */ - ReleaseBundlingSupport registerGenerateRunnerScriptAction(Artifact runnerScript, - Artifact ipaInput) { - ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext); - String escapedSimDevice = ShellUtils.shellEscape(objcConfiguration.getIosSimulatorDevice()); - String escapedSdkVersion = - ShellUtils.shellEscape(objcConfiguration.getIosSimulatorVersion().toString()); - ImmutableList<Substitution> substitutions = ImmutableList.of( - Substitution.of("%app_name%", ruleContext.getLabel().getName()), - Substitution.of("%ipa_file%", ipaInput.getRunfilesPathString()), - Substitution.of("%sim_device%", escapedSimDevice), - Substitution.of("%sdk_version%", escapedSdkVersion), - Substitution.of("%std_redirect_dylib_path%", - attributes.stdRedirectDylib().getRunfilesPathString())); - - ruleContext.registerAction( - new TemplateExpansionAction(ruleContext.getActionOwner(), attributes.runnerScriptTemplate(), - runnerScript, substitutions, true)); - return this; - } - - /** - * Returns a {@link RunfilesSupport} that uses the provided runner script as the executable. - */ - RunfilesSupport runfilesSupport(Artifact runnerScript) { - Runfiles runfiles = new Runfiles.Builder( - ruleContext.getWorkspaceName(), ruleContext.getConfiguration().legacyExternalRunfiles()) - .addArtifact(releaseBundling.getIpaArtifact()) - .addArtifact(runnerScript) - .addArtifact(attributes.stdRedirectDylib()) - .build(); - return RunfilesSupport.withExecutable(ruleContext, runfiles, runnerScript); - } - - private ExtraActoolArgs extraActoolArgs() { - ImmutableList.Builder<String> extraArgs = ImmutableList.builder(); - if (releaseBundling.getAppIcon() != null) { - extraArgs.add("--app-icon", releaseBundling.getAppIcon()); - } - if (releaseBundling.getLaunchImage() != null) { - extraArgs.add("--launch-image", releaseBundling.getLaunchImage()); - } - return new ExtraActoolArgs(extraArgs.build()); - } - - private Bundling bundling( - RuleContext ruleContext, - ObjcProvider objcProvider, - String bundleDirFormat, - String bundleName, - DottedVersion minimumOsVersion) { - ImmutableList<BundleableFile> extraBundleFiles; - AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class); - if (platform.isDevice()) { - extraBundleFiles = ImmutableList.of(new BundleableFile( - releaseBundling.getProvisioningProfile(), PROVISIONING_PROFILE_BUNDLE_FILE)); - } else { - extraBundleFiles = ImmutableList.of(); - } - - Bundling.Builder bundling = - new Builder() - .setName(bundleName) - .setExecutableName(bundleName) - // Architecture that determines which nested bundles are kept. - .setArchitecture(appleConfiguration.getDependencySingleArchitecture()) - .setBundleDirFormat(bundleDirFormat) - .addExtraBundleFiles(extraBundleFiles) - .setObjcProvider(objcProvider) - .setIntermediateArtifacts(intermediateArtifacts) - .setPrimaryBundleId(releaseBundling.getPrimaryBundleId()) - .setFallbackBundleId(releaseBundling.getFallbackBundleId()) - .setMinimumOsVersion(minimumOsVersion) - .setArtifactPrefix(releaseBundling.getArtifactPrefix()) - .setTargetDeviceFamilies(releaseBundling.getTargetDeviceFamilies()); - - // Add plists from rule first. - if (releaseBundling.getInfoPlistsFromRule() != null) { - bundling.addInfoplistInputs(releaseBundling.getInfoPlistsFromRule()); - } else { - bundling.addInfoplistInputFromRule(ruleContext); - } - - // Add generated plists next so that generated values can override the default values in the - // plists from rule. - bundling.setAutomaticEntriesInfoplistInput(getGeneratedAutomaticPlist()) - .addInfoplistInput(getGeneratedVersionPlist()) - .addInfoplistInput(getGeneratedEnvironmentPlist()) - .addInfoplistInputs(releaseBundling.getInfoplistInputs()); - - if (releaseBundling.getLaunchStoryboard() != null) { - bundling.addInfoplistInput(getLaunchStoryboardPlist()); - } - - return bundling.build(); - } - - private Artifact prepareCombinedArchitecturesArtifact() { - Artifact dependentMultiArchBinary = attributes.dependentMultiArchBinary(); - if (dependentMultiArchBinary != null) { - return dependentMultiArchBinary; - } - - Artifact resultingLinkedBinary = intermediateArtifacts.combinedArchitectureBinary(); - - new LipoSupport(ruleContext).registerCombineArchitecturesAction(linkedBinaries(), - resultingLinkedBinary, platform); - return resultingLinkedBinary; - } - - private NestedSet<Artifact> linkedBinaries() { - NestedSetBuilder<Artifact> linkedBinariesBuilder = NestedSetBuilder.<Artifact>stableOrder() - .addTransitive(attributes.dependentLinkedBinaries()); - if (linkedBinary == LinkedBinary.LOCAL_AND_DEPENDENCIES) { - linkedBinariesBuilder.add(intermediateArtifacts.strippedSingleArchitectureBinary()); - } - return linkedBinariesBuilder.build(); - } - - private void registerBundleMergeActions() { - Artifact bundleMergeControlArtifact = ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, - artifactName(".ipa-control")); - - BundleMergeControlBytes controlBytes = - new BundleMergeControlBytes( - bundling, - intermediateArtifacts.unprocessedIpa(), - XcodeConfig.getSdkVersionForPlatform(ruleContext, ApplePlatform.IOS_DEVICE), - ruleContext.getFragment(AppleConfiguration.class) - .getMultiArchPlatform(PlatformType.IOS)); - - ruleContext.registerAction( - new BinaryFileWriteAction( - ruleContext.getActionOwner(), bundleMergeControlArtifact, controlBytes, - /*makeExecutable=*/false)); - - ruleContext.registerAction( - new SpawnAction.Builder() - .setMnemonic("IosBundle") - .setProgressMessage("Bundling iOS application: %s", ruleContext.getLabel()) - .setExecutable(attributes.bundleMergeExecutable()) - .addInput(bundleMergeControlArtifact) - .addTransitiveInputs(bundling.getBundleContentArtifacts()) - .addOutput(intermediateArtifacts.unprocessedIpa()) - .addCommandLine( - CustomCommandLine.builder().addExecPath(bundleMergeControlArtifact).build()) - .build(ruleContext)); - } - - private void registerCopyLinkmapFilesAction() { - for (Entry<Artifact, Artifact> linkmapFile : getLinkmapFiles().entrySet()) { - ruleContext.registerAction( - new SymlinkAction(ruleContext.getActionOwner(), linkmapFile.getKey(), - linkmapFile.getValue(), String.format("Copying Linkmap %s", - linkmapFile.getValue().prettyPrint()))); - } - } - - /** - * Registers the actions that copy the debug symbol files from the CPU-specific binaries that are - * part of this application. The only one step executed is that he dsym files have to be renamed - * to include their corresponding CPU architecture as a suffix. - * - * @param dsymOutputType the file type of the dSYM bundle to be copied - */ - private void registerCopyDsymFilesAction(DsymOutputType dsymOutputType) { - for (Entry<Artifact, Artifact> dsymFiles : getDsymFiles(dsymOutputType).entrySet()) { - ruleContext.registerAction( - new SymlinkAction( - ruleContext.getActionOwner(), - dsymFiles.getKey(), - dsymFiles.getValue(), - "Symlinking dSYM files")); - } - } - - /** - * Registers the action that copies the debug symbol plist from the binary. - * - * @param dsymOutputType the file type of the dSYM bundle to be copied - */ - private void registerCopyDsymPlistAction(DsymOutputType dsymOutputType) { - Artifact dsymPlist = getAnyCpuSpecificDsymPlist(); - if (dsymPlist != null) { - ruleContext.registerAction( - new SymlinkAction( - ruleContext.getActionOwner(), - dsymPlist, - intermediateArtifacts.dsymPlist(dsymOutputType), - "Symlinking dSYM plist")); - } - } - - /** - * Returns a map of input dsym artifacts from the CPU-specific binaries built for this - * ios_application to the new output dsym artifacts. - * - * @param dsymOutputType the file type of the dSYM bundle to be generated - */ - private ImmutableMap<Artifact, Artifact> getDsymFiles(DsymOutputType dsymOutputType) { - ImmutableMap.Builder<Artifact, Artifact> results = ImmutableMap.builder(); - for (Entry<String, Artifact> dsymFile : attributes.cpuSpecificDsymFiles().entrySet()) { - Artifact destDsym = intermediateArtifacts.dsymSymbol(dsymOutputType, dsymFile.getKey()); - results.put(dsymFile.getValue(), destDsym); - } - return results.build(); - } - - /** - * Returns any available CPU specific dSYM plist file. - */ - @Nullable - private Artifact getAnyCpuSpecificDsymPlist() { - for (Artifact dsymPlist : attributes.cpuSpecificDsymPlists().values()) { - // The plist files generated by the dsym tool are all equal, and don't really have any - // useful information. For now, just retrieving any one is OK, but ideally all of them should - // be merged. - return dsymPlist; - } - return null; - } - - /** - * Returns a map of input linkmap artifacts from the CPU-specific binaries built for this - * ios_application to the new output linkmap artifacts. - */ - private ImmutableMap<Artifact, Artifact> getLinkmapFiles() { - ImmutableMap.Builder<Artifact, Artifact> results = ImmutableMap.builder(); - for (Entry<String, Artifact> linkmapFile : attributes.cpuSpecificLinkmapFiles().entrySet()) { - Artifact destLinkMap = intermediateArtifacts.linkmap(linkmapFile.getKey()); - results.put(linkmapFile.getValue(), destLinkMap); - } - return results.build(); - } - - private void registerExtractTeamPrefixAction(Artifact teamPrefixFile) { - String shellCommand = "set -e && " - + "PLIST=$(mktemp -t teamprefix.plist) && trap \"rm ${PLIST}\" EXIT && " - + extractPlistCommand(releaseBundling.getProvisioningProfile()) + " > ${PLIST} && " - + "/usr/libexec/PlistBuddy -c 'Print ApplicationIdentifierPrefix:0' ${PLIST} > " - + teamPrefixFile.getShellEscapedExecPathString(); - ruleContext.registerAction( - ObjcRuleClasses.spawnBashOnDarwinActionBuilder(shellCommand) - .setMnemonic("ExtractIosTeamPrefix") - .disableSandboxing() - .addInput(releaseBundling.getProvisioningProfile()) - .addOutput(teamPrefixFile) - .build(ruleContext)); - } - - private ReleaseBundlingSupport registerExtractEntitlementsAction(Artifact entitlements) { - // See Apple Glossary (http://goo.gl/EkhXOb) - // An Application Identifier is constructed as: TeamID.BundleID - // TeamID is extracted from the provisioning profile. - // BundleID consists of a reverse-DNS string to identify the app, where the last component - // is the application name, and is specified as an attribute. - String shellCommand = "set -e && " - + "PLIST=$(mktemp -t entitlements.plist) && trap \"rm ${PLIST}\" EXIT && " - + extractPlistCommand(releaseBundling.getProvisioningProfile()) + " > ${PLIST} && " - + "/usr/libexec/PlistBuddy -x -c 'Print Entitlements' ${PLIST} > " - + entitlements.getShellEscapedExecPathString(); - ruleContext.registerAction( - ObjcRuleClasses.spawnBashOnDarwinActionBuilder(shellCommand) - .setMnemonic("ExtractIosEntitlements") - .disableSandboxing() - .setProgressMessage("Extracting entitlements: %s", ruleContext.getLabel()) - .addInput(releaseBundling.getProvisioningProfile()) - .addOutput(entitlements) - .build(ruleContext)); - - return this; - } - - private void registerEntitlementsVariableSubstitutionAction( - Artifact inputEntitlements, Artifact prefix, Artifact substitutedEntitlements) { - String escapedBundleId = ShellUtils.shellEscape(releaseBundling.getBundleId()); - String shellCommand = - "set -e && " - + "PREFIX=\"$(cat " - + prefix.getShellEscapedExecPathString() - + ")\" && " - + "sed " - // Replace .* from default entitlements file with bundle ID where suitable. - + "-e \"s#${PREFIX}\\.\\*#${PREFIX}." - + escapedBundleId - + "#g\" " - - // Replace some variables that people put in their own entitlements files - + "-e \"s#\\$(AppIdentifierPrefix)#${PREFIX}.#g\" " - + "-e \"s#\\$(CFBundleIdentifier)#" - + escapedBundleId - + "#g\" " - + inputEntitlements.getShellEscapedExecPathString() - + " > " - + substitutedEntitlements.getShellEscapedExecPathString(); - ruleContext.registerAction( - new SpawnAction.Builder() - .setMnemonic("SubstituteIosEntitlements") - .setShellCommand(shellCommand) - .addInput(inputEntitlements) - .addInput(prefix) - .addOutput(substitutedEntitlements) - .build(ruleContext)); - } - - /** Registers an action to copy Swift standard library dylibs into app bundle. */ - private void registerSwiftStdlibActionsIfNecessary(Artifact combinedArchBinary) { - if (!objcProvider.is(USES_SWIFT)) { - return; - } - - - CustomCommandLine.Builder commandLine = CustomCommandLine.builder(); - - commandLine - .add("--output_zip_path") - .addPath(intermediateArtifacts.swiftFrameworksFileZip().getExecPath()) - .add("--bundle_path") - .add("Frameworks") - .add("--platform") - .addDynamicString(platform.getLowerCaseNameInPlist()) - .addExecPath("--scan-executable", combinedArchBinary); - - ruleContext.registerAction( - ObjcRuleClasses.spawnAppleEnvActionBuilder( - XcodeConfigProvider.fromRuleContext(ruleContext), platform) - .setMnemonic("SwiftStdlibCopy") - .setExecutable(attributes.swiftStdlibToolWrapper()) - .addCommandLine(commandLine.build()) - .addOutput(intermediateArtifacts.swiftFrameworksFileZip()) - .addInput(combinedArchBinary) - .build(ruleContext)); - } - - /** Registers an action to copy Swift standard library dylibs into SwiftSupport root directory. */ - private void registerSwiftSupportActionsIfNecessary(Artifact combinedArchBinary) { - if (!objcProvider.is(USES_SWIFT)) { - return; - } - - - CustomCommandLine.Builder commandLine = CustomCommandLine.builder(); - commandLine - .add("--output_zip_path") - .addPath(intermediateArtifacts.swiftSupportZip().getExecPath()) - .add("--bundle_path") - .addDynamicString("SwiftSupport/" + platform.getLowerCaseNameInPlist()) - .add("--platform") - .addDynamicString(platform.getLowerCaseNameInPlist()) - .addExecPath("--scan-executable", combinedArchBinary); - - ruleContext.registerAction( - ObjcRuleClasses.spawnAppleEnvActionBuilder( - XcodeConfigProvider.fromRuleContext(ruleContext), platform) - .setMnemonic("SwiftCopySwiftSupport") - .setExecutable(attributes.swiftStdlibToolWrapper()) - .addCommandLine(commandLine.build()) - .addOutput(intermediateArtifacts.swiftSupportZip()) - .addInput(combinedArchBinary) - .build(ruleContext)); - } - - private String extractPlistCommand(Artifact provisioningProfile) { - return "security cms -D -i " + ShellUtils.shellEscape(provisioningProfile.getExecPathString()); - } - - private String deviceCodesignCommand(String appDir) { - String signingCertName = ObjcRuleClasses.objcConfiguration(ruleContext).getSigningCertName(); - Artifact entitlements = intermediateArtifacts.entitlements(); - - final String identity; - if (signingCertName != null) { - identity = '"' + signingCertName + '"'; - } else { - // Extracts an identity hash from the configured provisioning profile. Note that this will use - // the first certificate identity in the profile, regardless of how many identities are - // configured in it (DeveloperCertificates:0). - identity = - "$(PLIST=$(mktemp -t cert.plist) && trap \"rm ${PLIST}\" EXIT && " - + extractPlistCommand(releaseBundling.getProvisioningProfile()) - + " > ${PLIST} && " - + "/usr/libexec/PlistBuddy -c 'Print DeveloperCertificates:0' ${PLIST} | " - + "openssl x509 -inform DER -noout -fingerprint | " - + "cut -d= -f2 | sed -e 's#:##g')"; - } - - return String.format( - "/usr/bin/codesign --force --sign %s --entitlements %s %s", - identity, - entitlements.getShellEscapedExecPathString(), - appDir); - } - - private Artifact getGeneratedVersionPlist() { - return ruleContext.getRelatedArtifact( - ruleContext.getUniqueDirectory("plists"), artifactName("-version.plist")); - } - - private Artifact getGeneratedEnvironmentPlist() { - return ruleContext.getRelatedArtifact( - ruleContext.getUniqueDirectory("plists"), artifactName("-environment.plist")); - } - - private Artifact getGeneratedAutomaticPlist() { - return ruleContext.getRelatedArtifact( - ruleContext.getUniqueDirectory("plists"), artifactName("-automatic.plist")); - } - - private Artifact getLaunchStoryboardPlist() { - return ruleContext.getRelatedArtifact( - ruleContext.getUniqueDirectory("plists"), artifactName("-launchstoryboard.plist")); - } - - /** - * Returns artifact name prefixed with prefix given in {@link ReleaseBundling} if available. - * This helps in creating unique artifact name when multiple bundles are created with a different - * name than the target name. - */ - private String artifactName(String artifactName) { - if (releaseBundling.getArtifactPrefix() != null) { - return String.format("-%s%s", releaseBundling.getArtifactPrefix(), artifactName); - } - return artifactName; - } - - /** - * Logic to access attributes to access tools required by application support. - * Attributes are required and guaranteed to return a value or throw unless they are annotated - * with {@link Nullable} in which case they can return {@code null} if no value is defined. - */ - private static class Attributes { - private final RuleContext ruleContext; - - private Attributes(RuleContext ruleContext) { - this.ruleContext = ruleContext; - } - - /** - * Returns this target's user-specified {@code ipa_post_processor} or null if not present. - */ - @Nullable - FilesToRunProvider ipaPostProcessor() { - if (!ruleContext.attributes().has("ipa_post_processor", BuildType.LABEL)) { - return null; - } - return ruleContext.getExecutablePrerequisite("ipa_post_processor", Mode.TARGET); - } - - /** - * Returns the multi-arch binary provided by the label under the "binary" attribute of the - * current rule, or null if there is no such binary available. - */ - @Nullable Artifact dependentMultiArchBinary() { - if (ruleContext.attributes().getAttributeDefinition("binary") == null) { - return null; - } - - for (ObjcProvider provider - : ruleContext.getPrerequisites( - "binary", Mode.DONT_CHECK, ObjcProvider.SKYLARK_CONSTRUCTOR)) { - if (!provider.get(ObjcProvider.MULTI_ARCH_LINKED_BINARIES).isEmpty()) { - return Iterables.getOnlyElement(provider.get(ObjcProvider.MULTI_ARCH_LINKED_BINARIES)); - } - } - return null; - } - - NestedSet<? extends Artifact> dependentLinkedBinaries() { - if (ruleContext.attributes().getAttributeDefinition("binary") == null) { - return NestedSetBuilder.emptySet(Order.STABLE_ORDER); - } - - NestedSetBuilder<Artifact> linkedBinaries = NestedSetBuilder.stableOrder(); - for (ObjcProvider provider - : ruleContext.getPrerequisites( - "binary", Mode.DONT_CHECK, ObjcProvider.SKYLARK_CONSTRUCTOR)) { - linkedBinaries.addTransitive(provider.get(ObjcProvider.LINKED_BINARY)); - } - - return linkedBinaries.build(); - } - - FilesToRunProvider bundleMergeExecutable() { - return checkNotNull(ruleContext.getExecutablePrerequisite("$bundlemerge", Mode.HOST)); - } - - /** - * Returns a reference to the plmerge executable. - */ - FilesToRunProvider plmerge() { - return ruleContext.getExecutablePrerequisite("$plmerge", Mode.HOST); - } - - Artifact stdRedirectDylib() { - return checkNotNull(ruleContext.getPrerequisiteArtifact("$std_redirect_dylib", Mode.HOST)); - } - - Artifact runnerScriptTemplate() { - return checkNotNull( - ruleContext.getPrerequisiteArtifact("$runner_script_template", Mode.HOST)); - } - - /** Returns the location of the swiftstdlibtoolwrapper. */ - FilesToRunProvider swiftStdlibToolWrapper() { - return ruleContext.getExecutablePrerequisite("$swiftstdlibtoolwrapper", Mode.HOST); - } - - /** - * Returns the location of the environment_plist. - */ - FilesToRunProvider environmentPlist() { - return ruleContext.getExecutablePrerequisite("$environment_plist", Mode.HOST); - } - - /** - * Returns a plist specified by the user via {@code --extra_entitlements} or {@code null}. - */ - @Nullable - Artifact extraEntitlements() { - if (ruleContext.attributes().getAttributeDefinition(EXTRA_ENTITLEMENTS_ATTR) == null) { - return null; - } - return ruleContext.getPrerequisiteArtifact(EXTRA_ENTITLEMENTS_ATTR, Mode.HOST); - } - - /** - * Returns a plist containing entitlements that allow the signed IPA to be debugged. - */ - @Nullable - Artifact deviceDebugEntitlements() { - if (ruleContext.attributes().getAttributeDefinition(DEBUG_ENTITLEMENTS_ATTR) == null) { - return null; - } - return ruleContext.getPrerequisiteArtifact(DEBUG_ENTITLEMENTS_ATTR, Mode.HOST); - } - - ImmutableMap<String, Artifact> cpuSpecificDsymFiles() { - return cpuSpecificArtifacts(ObjcProvider.DEBUG_SYMBOLS); - } - - ImmutableMap<String, Artifact> cpuSpecificDsymPlists() { - return cpuSpecificArtifacts(ObjcProvider.DEBUG_SYMBOLS_PLIST); - } - - ImmutableMap<String, Artifact> cpuSpecificLinkmapFiles() { - return cpuSpecificArtifacts(ObjcProvider.LINKMAP_FILE); - } - - ImmutableMap<String, Artifact> cpuSpecificArtifacts(ObjcProvider.Key<Artifact> key) { - ImmutableMap.Builder<String, Artifact> results = ImmutableMap.builder(); - if (ruleContext.attributes().has("binary", BuildType.LABEL)) { - for (TransitiveInfoCollection prerequisite - : ruleContext.getPrerequisites("binary", Mode.DONT_CHECK)) { - ObjcProvider prerequisiteProvider = prerequisite.get(ObjcProvider.SKYLARK_CONSTRUCTOR); - if (prerequisiteProvider != null) { - Artifact sourceArtifact = Iterables.getOnlyElement(prerequisiteProvider.get(key), null); - if (sourceArtifact != null) { - String cpu = - prerequisite.getConfiguration().getFragment(AppleConfiguration.class).getIosCpu(); - results.put(cpu, sourceArtifact); - } - } - } - } - return results.build(); - } - } -} |