/** Registers an action to copy Swift standard library dylibs into app bundle. */
  private void registerSwiftStdlibActionsIfNecessary() {
    if (!objcProvider.is(USES_SWIFT)) {
      return;
    }

    ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext);

    CustomCommandLine.Builder commandLine =
        CustomCommandLine.builder()
            .addPath(intermediateArtifacts.swiftFrameworksFileZip().getExecPath())
            .add("--platform")
            .add(IosSdkCommands.swiftPlatform(objcConfiguration))
            .addExecPath("--scan-executable", intermediateArtifacts.combinedArchitectureBinary());

    ruleContext.registerAction(
        ObjcRuleClasses.spawnOnDarwinActionBuilder(ruleContext)
            .setMnemonic("SwiftStdlibCopy")
            .setExecutable(attributes.swiftStdlibToolWrapper())
            .setCommandLine(commandLine.build())
            .addOutput(intermediateArtifacts.swiftFrameworksFileZip())
            .addInput(intermediateArtifacts.combinedArchitectureBinary())
            // TODO(dmaclach): Adding realpath and xcrunwrapper should not be required once
            // https://github.com/google/bazel/issues/285 is fixed.
            .addInput(attributes.realpath())
            .addInput(CompilationSupport.xcrunwrapper(ruleContext).getExecutable())
            .build(ruleContext));
  }
  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;
  }