/**
   * 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;
  }
  /**
   * Adds bundle- and application-related settings to the given Xcode provider builder.
   *
   * @return this application support
   */
  ReleaseBundlingSupport addXcodeSettings(XcodeProvider.Builder xcodeProviderBuilder) {
    bundleSupport.addXcodeSettings(xcodeProviderBuilder);
    // Add application-related Xcode build settings to the main target only. The companion library
    // target does not need them.
    xcodeProviderBuilder.addMainTargetXcodeprojBuildSettings(buildSettings());

    return this;
  }
  /**
   * 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());
    AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class);
    Platform platform = appleConfiguration.getBundlingPlatform();
    ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext);

    NSDictionary result = new NSDictionary();

    if (uiDeviceFamily != null) {
      result.put("UIDeviceFamily", NSObject.wrap(uiDeviceFamily.toArray()));
    }
    result.put("DTPlatformName", NSObject.wrap(platform.getLowerCaseNameInPlist()));
    result.put(
        "DTSDKName",
        NSObject.wrap(platform.getLowerCaseNameInPlist() + appleConfiguration.getIosSdkVersion()));
    result.put("CFBundleSupportedPlatforms", new NSArray(NSObject.wrap(platform.getNameInPlist())));
    result.put("MinimumOSVersion", NSObject.wrap(objcConfiguration.getMinimumOs().toString()));

    return result;
  }
  /**
   * 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 (attributes.appIcon() != null) {
        ruleContext.attributeError(
            "app_icon", String.format(NO_ASSET_CATALOG_ERROR_FORMAT, attributes.appIcon()));
      }
      if (attributes.launchImage() != null) {
        ruleContext.attributeError(
            "launch_image", String.format(NO_ASSET_CATALOG_ERROR_FORMAT, attributes.launchImage()));
      }
    }

    if (bundleSupport.targetDeviceFamilies().isEmpty()) {
      ruleContext.attributeError("families", INVALID_FAMILIES_ERROR);
    }

    return this;
  }
  /** Returns this target's Xcode build settings. */
  private Iterable<XcodeprojBuildSetting> buildSettings() {
    ImmutableList.Builder<XcodeprojBuildSetting> buildSettings = new ImmutableList.Builder<>();
    if (attributes.appIcon() != null) {
      buildSettings.add(
          XcodeprojBuildSetting.newBuilder()
              .setName("ASSETCATALOG_COMPILER_APPICON_NAME")
              .setValue(attributes.appIcon())
              .build());
    }
    if (attributes.launchImage() != null) {
      buildSettings.add(
          XcodeprojBuildSetting.newBuilder()
              .setName("ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME")
              .setValue(attributes.launchImage())
              .build());
    }

    // Convert names to a sequence containing "1" and/or "2" for iPhone and iPad, respectively.
    ImmutableSet<TargetDeviceFamily> families = bundleSupport.targetDeviceFamilies();
    Iterable<Integer> familyIndexes =
        families.isEmpty() ? ImmutableList.<Integer>of() : UI_DEVICE_FAMILY_VALUES.get(families);
    buildSettings.add(
        XcodeprojBuildSetting.newBuilder()
            .setName("TARGETED_DEVICE_FAMILY")
            .setValue(Joiner.on(',').join(familyIndexes))
            .build());

    Artifact entitlements = attributes.entitlements();
    if (entitlements != null) {
      buildSettings.add(
          XcodeprojBuildSetting.newBuilder()
              .setName("CODE_SIGN_ENTITLEMENTS")
              .setValue("$(WORKSPACE_ROOT)/" + entitlements.getExecPathString())
              .build());
    }

    return buildSettings.build();
  }
 /**
  * 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.validate(objcProvider);
   return this;
 }