// 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));
    }
  }

  /**
   * Creates the {@link XcTestAppProvider} that can be used if this application is used as an
   * {@code xctest_app}.
   */
  XcTestAppProvider xcTestAppProvider() {
    // We want access to #import-able things from our test rig's dependency graph, but we don't
    // want to link anything since that stuff is shared automatically by way of the
    // -bundle_loader linker flag.
    // TODO(bazel-team): Handle the FRAMEWORK_DIR key properly. We probably want to add it to
    // framework search paths, but not actually link it with the -framework flag.
    ObjcProvider partialObjcProvider =
        new ObjcProvider.Builder()
            .addTransitiveAndPropagate(ObjcProvider.HEADER, objcProvider)
            .addTransitiveAndPropagate(ObjcProvider.INCLUDE, objcProvider)
            .addTransitiveAndPropagate(ObjcProvider.DEFINE, objcProvider)
            .addTransitiveAndPropagate(ObjcProvider.SDK_DYLIB, objcProvider)
            .addTransitiveAndPropagate(ObjcProvider.SDK_FRAMEWORK, objcProvider)
            .addTransitiveAndPropagate(ObjcProvider.SOURCE, objcProvider)
            .addTransitiveAndPropagate(ObjcProvider.WEAK_SDK_FRAMEWORK, objcProvider)
            .addTransitiveAndPropagate(ObjcProvider.STATIC_FRAMEWORK_FILE, objcProvider)
            .addTransitiveAndPropagate(ObjcProvider.DYNAMIC_FRAMEWORK_FILE, objcProvider)
            .addTransitiveAndPropagate(
                ObjcProvider.FRAMEWORK_SEARCH_PATH_ONLY,
                objcProvider.get(ObjcProvider.STATIC_FRAMEWORK_DIR))
            .addTransitiveAndPropagate(
                ObjcProvider.FRAMEWORK_SEARCH_PATH_ONLY,
                objcProvider.get(ObjcProvider.DYNAMIC_FRAMEWORK_DIR))
            .build();
    return new XcTestAppProvider(
        intermediateArtifacts.combinedArchitectureBinary(),
        releaseBundling.getIpaArtifact(),
        partialObjcProvider);
  }

  /**
   * 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;
    }

    AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class);

    CustomCommandLine.Builder commandLine = CustomCommandLine.builder();
    if (appleConfiguration.getXcodeToolchain() != null) {
      commandLine.add("--toolchain", appleConfiguration.getXcodeToolchain());
    }

    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;
    }

    AppleConfiguration configuration = ruleContext.getFragment(AppleConfiguration.class);

    CustomCommandLine.Builder commandLine = CustomCommandLine.builder();
    if (configuration.getXcodeToolchain() != null) {
      commandLine.add("--toolchain", configuration.getXcodeToolchain());
    }

    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();
    }
  }
}
