public ImmutableList getBuildSteps()

in src/com/facebook/buck/apple/AppleBundle.java [363:680]


  public ImmutableList<Step> getBuildSteps(
      BuildContext context, BuildableContext buildableContext) {
    ImmutableList.Builder<Step> stepsBuilder = ImmutableList.builder();

    stepsBuilder.addAll(
        MakeCleanDirectoryStep.of(
            BuildCellRelativePath.fromCellRelativePath(
                context.getBuildCellRootPath(), getProjectFilesystem(), bundleRoot)));

    Path resourcesDestinationPath = bundleRoot.resolve(this.destinations.getResourcesPath());
    if (assetCatalog.isPresent()) {
      stepsBuilder.add(
          MkdirStep.of(
              BuildCellRelativePath.fromCellRelativePath(
                  context.getBuildCellRootPath(),
                  getProjectFilesystem(),
                  resourcesDestinationPath)));
      Path bundleDir = assetCatalog.get().getOutputDir();
      stepsBuilder.add(
          CopyStep.forDirectory(
              getProjectFilesystem(),
              bundleDir,
              resourcesDestinationPath,
              CopyStep.DirectoryMode.CONTENTS_ONLY));
    }

    if (coreDataModel.isPresent()) {
      stepsBuilder.add(
          MkdirStep.of(
              BuildCellRelativePath.fromCellRelativePath(
                  context.getBuildCellRootPath(),
                  getProjectFilesystem(),
                  resourcesDestinationPath)));
      stepsBuilder.add(
          CopyStep.forDirectory(
              getProjectFilesystem(),
              context
                  .getSourcePathResolver()
                  .getRelativePath(coreDataModel.get().getSourcePathToOutput()),
              resourcesDestinationPath,
              CopyStep.DirectoryMode.CONTENTS_ONLY));
    }

    if (sceneKitAssets.isPresent()) {
      stepsBuilder.add(
          MkdirStep.of(
              BuildCellRelativePath.fromCellRelativePath(
                  context.getBuildCellRootPath(),
                  getProjectFilesystem(),
                  resourcesDestinationPath)));
      stepsBuilder.add(
          CopyStep.forDirectory(
              getProjectFilesystem(),
              context
                  .getSourcePathResolver()
                  .getRelativePath(sceneKitAssets.get().getSourcePathToOutput()),
              resourcesDestinationPath,
              CopyStep.DirectoryMode.CONTENTS_ONLY));
    }

    Path metadataPath = getMetadataPath();

    AbsPath infoPlistInputPath =
        AbsPath.of(context.getSourcePathResolver().getAbsolutePath(infoPlist));
    Path infoPlistSubstitutionTempPath =
        BuildTargetPaths.getScratchPath(getProjectFilesystem(), getBuildTarget(), "%s.plist");
    Path infoPlistOutputPath = metadataPath.resolve("Info.plist");

    stepsBuilder.add(
        MkdirStep.of(
            BuildCellRelativePath.fromCellRelativePath(
                context.getBuildCellRootPath(), getProjectFilesystem(), metadataPath)));

    if (needsPkgInfoFile()) {
      // TODO(bhamiltoncx): This is only appropriate for .app bundles.
      stepsBuilder.add(
          new WriteFileStep(
              getProjectFilesystem(),
              "APPLWRUN",
              metadataPath.resolve("PkgInfo"),
              /* executable */ false));
    }

    stepsBuilder.add(
        MkdirStep.of(
            BuildCellRelativePath.fromCellRelativePath(
                context.getBuildCellRootPath(),
                getProjectFilesystem(),
                infoPlistSubstitutionTempPath.getParent())),
        new FindAndReplaceStep(
            getProjectFilesystem(),
            infoPlistInputPath,
            infoPlistSubstitutionTempPath,
            InfoPlistSubstitution.createVariableExpansionFunction(
                withDefaults(
                    infoPlistSubstitutions,
                    ImmutableMap.of(
                        "EXECUTABLE_NAME", binaryName,
                        "PRODUCT_NAME", binaryName)))),
        new PlistProcessStep(
            getProjectFilesystem(),
            infoPlistSubstitutionTempPath,
            assetCatalog.map(AppleAssetCatalog::getOutputPlist),
            infoPlistOutputPath,
            getInfoPlistAdditionalKeys(),
            getInfoPlistOverrideKeys(),
            PlistProcessStep.OutputFormat.BINARY));

    if (hasBinary) {
      appendCopyBinarySteps(stepsBuilder, context);
      appendCopyDsymStep(stepsBuilder, buildableContext, context);
    }

    ImmutableList.Builder<Path> codeSignOnCopyPathsBuilder = ImmutableList.builder();

    AppleResourceProcessing.addStepsToCopyResources(
        context,
        stepsBuilder,
        codeSignOnCopyPathsBuilder,
        resources,
        verifyResources,
        bundleRoot,
        destinations,
        getProjectFilesystem(),
        ibtoolFlags,
        isLegacyWatchApp(),
        platform,
        LOG,
        ibtool,
        ibtoolModuleFlag,
        getBuildTarget(),
        Optional.of(binaryName));

    addStepsToCopyExtensionBundlesDependencies(context, stepsBuilder, codeSignOnCopyPathsBuilder);

    AppleResourceProcessing.addVariantFileProcessingSteps(
        resources,
        context,
        bundleRoot,
        destinations,
        stepsBuilder,
        getProjectFilesystem(),
        ibtoolFlags,
        isLegacyWatchApp(),
        platform,
        LOG,
        ibtool,
        ibtoolModuleFlag,
        getBuildTarget(),
        Optional.of(binaryName));
    AppleResourceProcessing.addFrameworksProcessingSteps(
        frameworks,
        bundleRoot,
        destinations,
        stepsBuilder,
        context,
        getProjectFilesystem(),
        codeSignOnCopyPathsBuilder);

    if (needCodeSign()) {
      Optional<Path> signingEntitlementsTempPath = Optional.empty();
      Supplier<CodeSignIdentity> codeSignIdentitySupplier;

      if (adHocCodeSignIsSufficient()) {
        if (useEntitlementsWhenAdhocCodeSigning) {
          signingEntitlementsTempPath = prepareEntitlementsPlistFile(context, stepsBuilder);
        }
        CodeSignIdentity identity =
            codesignIdentitySubjectName
                .map(id -> CodeSignIdentity.ofAdhocSignedWithSubjectCommonName(id))
                .orElse(CodeSignIdentity.AD_HOC);
        codeSignIdentitySupplier = () -> identity;
      } else {
        // Copy the .mobileprovision file if the platform requires it, and sign the executable.
        Optional<Path> entitlementsPlist = prepareEntitlementsPlistFile(context, stepsBuilder);
        signingEntitlementsTempPath =
            Optional.of(
                BuildTargetPaths.getScratchPath(
                    getProjectFilesystem(), getBuildTarget(), "%s.xcent"));

        Path dryRunResultPath = bundleRoot.resolve(PP_DRY_RUN_RESULT_FILE);

        ProvisioningProfileCopyStep provisioningProfileCopyStep =
            new ProvisioningProfileCopyStep(
                getProjectFilesystem(),
                infoPlistOutputPath,
                platform,
                Optional.empty(), // Provisioning profile UUID -- find automatically.
                entitlementsPlist,
                provisioningProfileStore,
                resourcesDestinationPath.resolve("embedded.mobileprovision"),
                dryRunCodeSigning
                    ? bundleRoot.resolve(CODE_SIGN_DRY_RUN_ENTITLEMENTS_FILE)
                    : signingEntitlementsTempPath.get(),
                codeSignIdentitiesSupplier,
                dryRunCodeSigning ? Optional.of(dryRunResultPath) : Optional.empty());
        stepsBuilder.add(provisioningProfileCopyStep);

        codeSignIdentitySupplier =
            () -> {
              // Using getUnchecked here because the previous step should already throw if exception
              // occurred, and this supplier would never be evaluated.
              Optional<ProvisioningProfileMetadata> selectedProfile =
                  Futures.getUnchecked(
                      provisioningProfileCopyStep.getSelectedProvisioningProfileFuture());

              if (!selectedProfile.isPresent()) {
                // This should only happen in dry-run codesign mode (since otherwise an exception
                // would have been thrown already.)  Still, we need to return *something*.
                Preconditions.checkState(dryRunCodeSigning);
                return CodeSignIdentity.AD_HOC;
              }

              ImmutableSet<HashCode> fingerprints =
                  selectedProfile.get().getDeveloperCertificateFingerprints();
              if (fingerprints.isEmpty()) {
                // No constraints, pick an arbitrary identity.
                // If no identities are available, use an ad-hoc identity.
                return Iterables.getFirst(
                    codeSignIdentitiesSupplier.get(), CodeSignIdentity.AD_HOC);
              }
              for (CodeSignIdentity identity : codeSignIdentitiesSupplier.get()) {
                if (identity.getFingerprint().isPresent()
                    && fingerprints.contains(identity.getFingerprint().get())) {
                  return identity;
                }
              }

              throw new HumanReadableException(
                  "No code sign identity available for provisioning profile: %s\n"
                      + "Profile requires an identity with one of the following SHA1 fingerprints "
                      + "available in your keychain: \n  %s",
                  selectedProfile.get().getProfilePath(), Joiner.on("\n  ").join(fingerprints));
            };
      }

      AppleResourceProcessing.addSwiftStdlibStepIfNeeded(
          context.getSourcePathResolver(),
          bundleRoot.resolve(destinations.getFrameworksPath()),
          bundleRoot,
          dryRunCodeSigning ? Optional.empty() : Optional.of(codeSignIdentitySupplier),
          stepsBuilder,
          false,
          extension,
          copySwiftStdlibToFrameworks,
          useLipoThin,
          swiftStdlibTool,
          getProjectFilesystem(),
          getBuildTarget(),
          sdkPath,
          lipo,
          bundleBinaryPath,
          destinations,
          isAppClip.orElse(false));

      for (BuildRule extraBinary : extraBinaries) {
        Path outputPath = getBundleBinaryPathForBuildRule(extraBinary);
        codeSignOnCopyPathsBuilder.add(outputPath);
      }

      for (Path codeSignOnCopyPath : codeSignOnCopyPathsBuilder.build()) {
        stepsBuilder.add(
            new CodeSignStep(
                getProjectFilesystem(),
                context.getSourcePathResolver(),
                codeSignOnCopyPath,
                Optional.empty(),
                codeSignIdentitySupplier,
                codesign,
                codesignAllocatePath,
                dryRunCodeSigning
                    ? Optional.of(codeSignOnCopyPath.resolve(CODE_SIGN_DRY_RUN_ARGS_FILE))
                    : Optional.empty(),
                codesignFlags,
                codesignTimeout));
      }

      stepsBuilder.add(
          new CodeSignStep(
              getProjectFilesystem(),
              context.getSourcePathResolver(),
              bundleRoot,
              signingEntitlementsTempPath,
              codeSignIdentitySupplier,
              codesign,
              codesignAllocatePath,
              dryRunCodeSigning
                  ? Optional.of(bundleRoot.resolve(CODE_SIGN_DRY_RUN_ARGS_FILE))
                  : Optional.empty(),
              codesignFlags,
              codesignTimeout));
    } else {
      AppleResourceProcessing.addSwiftStdlibStepIfNeeded(
          context.getSourcePathResolver(),
          bundleRoot.resolve(destinations.getFrameworksPath()),
          bundleRoot,
          Optional.empty(),
          stepsBuilder,
          false,
          extension,
          copySwiftStdlibToFrameworks,
          useLipoThin,
          swiftStdlibTool,
          getProjectFilesystem(),
          getBuildTarget(),
          sdkPath,
          lipo,
          bundleBinaryPath,
          destinations,
          isAppClip.orElse(false));
    }

    // Ensure the bundle directory is archived so we can fetch it later.
    buildableContext.recordArtifact(
        context.getSourcePathResolver().getRelativePath(getSourcePathToOutput()));

    return stepsBuilder.build();
  }