private void registerExtractTeamPrefixAction(Artifact teamPrefixFile) {
   String shellCommand =
       "set -e && "
           + "PLIST=$(mktemp -t teamprefix.plist) && trap \"rm ${PLIST}\" EXIT && "
           + extractPlistCommand(attributes.provisioningProfile())
           + " > ${PLIST} && "
           + "/usr/libexec/PlistBuddy -c 'Print ApplicationIdentifierPrefix:0' ${PLIST} > "
           + teamPrefixFile.getShellEscapedExecPathString();
   ruleContext.registerAction(
       ObjcRuleClasses.spawnBashOnDarwinActionBuilder(ruleContext, shellCommand)
           .setMnemonic("ExtractIosTeamPrefix")
           .addInput(attributes.provisioningProfile())
           .addOutput(teamPrefixFile)
           .build(ruleContext));
 }
  /**
   * 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.
   *
   * @return this application support
   * @throws InterruptedException
   */
  ReleaseBundlingSupport registerActions() throws InterruptedException {
    bundleSupport.registerActions(objcProvider);

    registerCombineArchitecturesAction();
    registerTransformAndCopyBreakpadFilesAction();
    registerSwiftStdlibActionsIfNecessary();

    ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext);
    Artifact ipaOutput = ruleContext.getImplicitOutputArtifact(IPA);

    Artifact maybeSignedIpa;
    if (objcConfiguration.getBundlingPlatform() == Platform.IOS_SIMULATOR) {
      maybeSignedIpa = ipaOutput;
    } else if (attributes.provisioningProfile() == null) {
      throw new IllegalStateException(DEVICE_NO_PROVISIONING_PROFILE);
    } else {
      maybeSignedIpa = registerBundleSigningActions(ipaOutput);
    }

    registerEmbedLabelPlistAction();
    registerEnvironmentPlistAction();

    BundleMergeControlBytes bundleMergeControlBytes =
        new BundleMergeControlBytes(
            bundling, maybeSignedIpa, objcConfiguration, bundleSupport.targetDeviceFamilies());
    registerBundleMergeActions(
        maybeSignedIpa, bundling.getBundleContentArtifacts(), bundleMergeControlBytes);

    return this;
  }
  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(attributes.provisioningProfile())
            + " > ${PLIST} && "
            + "/usr/libexec/PlistBuddy -x -c 'Print Entitlements' ${PLIST} > "
            + entitlements.getShellEscapedExecPathString();
    ruleContext.registerAction(
        ObjcRuleClasses.spawnBashOnDarwinActionBuilder(ruleContext, shellCommand)
            .setMnemonic("ExtractIosEntitlements")
            .setProgressMessage("Extracting entitlements: " + ruleContext.getLabel())
            .addInput(attributes.provisioningProfile())
            .addOutput(entitlements)
            .build(ruleContext));

    return this;
  }
  private ReleaseBundlingSupport registerSignBundleAction(
      Artifact entitlements, Artifact ipaOutput, Artifact ipaUnsigned) {
    // TODO(bazel-team): Support variable substitution

    ImmutableList.Builder<String> dirsToSign = new ImmutableList.Builder<>();

    // Explicitly sign Swift dylibs. Unfortunately --deep option on codesign doesn't do this
    // automatically.
    // The order here is important. The innermost code must singed first.
    String bundleDir = ShellUtils.shellEscape(bundling.getBundleDir());
    if (objcProvider.is(USES_SWIFT)) {
      dirsToSign.add(bundleDir + "/Frameworks/*");
    }
    dirsToSign.add(bundleDir);

    StringBuilder codesignCommandLineBuilder = new StringBuilder();
    for (String dir : dirsToSign.build()) {
      codesignCommandLineBuilder
          .append(codesignCommand(entitlements, "${t}/" + dir))
          .append(" && ");
    }

    // TODO(bazel-team): Support nested code signing.
    String shellCommand =
        "set -e && "
            + "t=$(mktemp -d -t signing_intermediate) && "
            + "trap \"rm -rf ${t}\" EXIT && "
            // Get an absolute path since we need to cd into the temp directory for zip.
            + "signed_ipa=${PWD}/"
            + ipaOutput.getShellEscapedExecPathString()
            + " && "
            + "/usr/bin/unzip -qq "
            + ipaUnsigned.getShellEscapedExecPathString()
            + " -d ${t} && "
            + codesignCommandLineBuilder.toString()
            // Using zip since we need to preserve permissions
            + "cd ${t} && /usr/bin/zip -q -r \"${signed_ipa}\" .";
    ruleContext.registerAction(
        ObjcRuleClasses.spawnBashOnDarwinActionBuilder(ruleContext, shellCommand)
            .setMnemonic("IosSignBundle")
            .setProgressMessage("Signing iOS bundle: " + ruleContext.getLabel())
            .addInput(ipaUnsigned)
            .addInput(attributes.provisioningProfile())
            .addInput(entitlements)
            .addOutput(ipaOutput)
            .build(ruleContext));

    return this;
  }
  private String codesignCommand(Artifact entitlements, String appDir) {
    String signingCertName = ObjcRuleClasses.objcConfiguration(ruleContext).getSigningCertName();

    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(attributes.provisioningProfile())
              + " > ${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);
  }