private ImmutableList generateBinaryTarget()

in src/com/facebook/buck/features/apple/projectV2/XcodeNativeTargetGenerator.java [1073:1561]


  private ImmutableList<BuildTarget> generateBinaryTarget(
      ImmutableXCodeNativeTargetAttributes.Builder xcodeNativeTargetAttributesBuilder,
      ImmutableSet.Builder<BuildTarget> requiredBuildTargetsBuilder,
      ImmutableSet.Builder<Path> xcconfigPathsBuilder,
      ImmutableSet.Builder<String> targetConfigNamesBuilder,
      HeaderSearchPathAttributes headerSearchPathAttributes,
      Optional<? extends TargetNode<? extends HasAppleBundleFields>> bundle,
      TargetNode<? extends CommonArg> targetNode,
      String productOutputFormat,
      Optional<Path> infoPlistOptional,
      boolean includeFrameworks,
      ImmutableSet<AppleResourceDescriptionArg> directResources,
      ImmutableSet<AppleAssetCatalogDescriptionArg> directAssetCatalogs,
      ImmutableSet<AppleWrapperResourceArg> wrapperResources,
      ImmutableSet<AppleWrapperResourceArg> coreDataResources,
      Optional<TargetNode<AppleBundleDescriptionArg>> bundleLoaderNode)
      throws IOException {

    LOG.debug("Generating binary target for node %s", targetNode);

    TargetNode<?> buildTargetNode = bundle.isPresent() ? bundle.get() : targetNode;

    // TODO(chatatap): Whenever generateBinaryTarget is called, productType should be set. As we
    // upstream XcodeNativeTargetGenerator, this should become a precondition check for any of its
    // uses.
    ProductType productType = getProductType(buildTargetNode, targetGraph).get();

    BuildTarget buildTarget = buildTargetNode.getBuildTarget();
    boolean containsSwiftCode = projGenerationStateCache.targetContainsSwiftSourceCode(targetNode);

    xcodeNativeTargetAttributesBuilder.setTarget(Optional.of(buildTarget));

    String buildTargetName = getProductNameForBuildTargetNode(buildTargetNode);
    CommonArg arg = targetNode.getConstructorArg();

    // Both exported headers and exported platform headers will be put into the symlink tree
    // exported platform headers will be excluded and then included by platform
    ImmutableSet.Builder<SourcePath> exportedHeadersBuilder = ImmutableSet.builder();
    exportedHeadersBuilder.addAll(getHeaderSourcePaths(arg.getExportedHeaders()));
    PatternMatchedCollection<SourceSortedSet> exportedPlatformHeaders =
        arg.getExportedPlatformHeaders();
    for (SourceSortedSet headersSet : exportedPlatformHeaders.getValues()) {
      exportedHeadersBuilder.addAll(getHeaderSourcePaths(headersSet));
    }

    ImmutableSet<SourcePath> exportedHeaders = exportedHeadersBuilder.build();
    ImmutableSet.Builder<SourcePath> headersBuilder = ImmutableSet.builder();
    headersBuilder.addAll(getHeaderSourcePaths(arg.getHeaders()));
    for (SourceSortedSet headersSet : arg.getPlatformHeaders().getValues()) {
      headersBuilder.addAll(getHeaderSourcePaths(headersSet));
    }
    ImmutableSet<SourcePath> headers = headersBuilder.build();
    ImmutableMap<CxxSource.Type, ImmutableList<StringWithMacros>> langPreprocessorFlags =
        targetNode.getConstructorArg().getLangPreprocessorFlags();

    SwiftAttributes swiftAttributes = swiftAttributeParser.parseSwiftAttributes(targetNode);

    Optional<String> swiftVersion = swiftAttributes.swiftVersion();
    boolean hasSwiftVersionArg = swiftVersion.isPresent();
    if (!swiftVersion.isPresent()) {
      swiftVersion = swiftBuckConfig.getVersion();
    }

    xcodeNativeTargetAttributesBuilder.setProduct(
        Optional.of(
            new XcodeProductMetadata(
                productType,
                buildTargetName,
                Paths.get(String.format(productOutputFormat, buildTargetName)))));

    boolean isModularAppleLibrary = NodeHelper.isModularAppleLibrary(targetNode);
    xcodeNativeTargetAttributesBuilder.setFrameworkHeadersEnabled(isModularAppleLibrary);

    Builder<String, String> swiftDepsSettingsBuilder = ImmutableMap.builder();

    Builder<String, String> extraSettingsBuilder = ImmutableMap.builder();
    Builder<String, String> defaultSettingsBuilder = ImmutableMap.builder();

    // XCConfigs treat '//' as comments and must be escaped.
    String cellRelativeBuildTarget = buildTarget.getCellRelativeName();
    extraSettingsBuilder.put(
        BUILD_TARGET,
        cellRelativeBuildTarget.replaceAll(BuildTargetLanguageConstants.ROOT_SYMBOL, "\\\\/\\\\/"));

    ImmutableList<Pair<Pattern, SourceSortedSet>> platformHeaders =
        arg.getPlatformHeaders().getPatternsAndValues();
    ImmutableList.Builder<Pair<Pattern, Iterable<SourcePath>>> platformHeadersIterableBuilder =
        ImmutableList.builder();
    for (Pair<Pattern, SourceSortedSet> platformHeader : platformHeaders) {
      platformHeadersIterableBuilder.add(
          new Pair<>(platformHeader.getFirst(), getHeaderSourcePaths(platformHeader.getSecond())));
    }

    ImmutableList<Pair<Pattern, SourceSortedSet>> exportedPlatformHeadersPatternsAndValues =
        exportedPlatformHeaders.getPatternsAndValues();
    for (Pair<Pattern, SourceSortedSet> exportedPlatformHeader :
        exportedPlatformHeadersPatternsAndValues) {
      platformHeadersIterableBuilder.add(
          new Pair<>(
              exportedPlatformHeader.getFirst(),
              getHeaderSourcePaths(exportedPlatformHeader.getSecond())));
    }

    ImmutableList<Pair<Pattern, Iterable<SourcePath>>> platformHeadersIterable =
        platformHeadersIterableBuilder.build();

    ImmutableList<Pair<Pattern, ImmutableSortedSet<SourceWithFlags>>> platformSources =
        arg.getPlatformSrcs().getPatternsAndValues();
    ImmutableMap<String, ImmutableSortedSet<String>> platformExcludedSourcesMapping =
        XcodeNativeTargetGenerator.gatherExcludedSources(
            appleCxxFlavors,
            platformSources,
            platformHeadersIterable,
            sourceRoot,
            defaultPathResolver);
    for (Map.Entry<String, ImmutableSortedSet<String>> platformExcludedSources :
        platformExcludedSourcesMapping.entrySet()) {
      if (platformExcludedSources.getValue().size() > 0) {
        extraSettingsBuilder.put(
            platformExcludedSources.getKey(), String.join(" ", platformExcludedSources.getValue()));
      }
    }

    ImmutableSortedSet<SourceWithFlags> nonPlatformSrcs = arg.getSrcs();
    ImmutableSortedSet.Builder<SourceWithFlags> allSrcsBuilder = ImmutableSortedSet.naturalOrder();
    allSrcsBuilder.addAll(nonPlatformSrcs);
    for (Pair<Pattern, ImmutableSortedSet<SourceWithFlags>> platformSource : platformSources) {
      allSrcsBuilder.addAll(platformSource.getSecond());
    }

    ImmutableSortedSet<SourceWithFlags> allSrcs = allSrcsBuilder.build();

    xcodeNativeTargetAttributesBuilder
        .setLangPreprocessorFlags(
            ImmutableMap.copyOf(
                Maps.transformValues(
                    langPreprocessorFlags,
                    f ->
                        flagParser.convertStringWithMacros(
                            targetNode, f, requiredBuildTargetsBuilder))))
        .setPublicHeaders(exportedHeaders)
        .setPrefixHeader(getPrefixHeaderSourcePath(arg))
        .setSourcesWithFlags(ImmutableSet.copyOf(allSrcs))
        .setPrivateHeaders(headers)
        .setDirectResources(directResources)
        .setWrapperResources(wrapperResources)
        .setExtraXcodeSources(ImmutableSet.copyOf(arg.getExtraXcodeSources()))
        .setExtraXcodeFiles(ImmutableSet.copyOf(arg.getExtraXcodeFiles()));

    if (bundle.isPresent()) {
      HasAppleBundleFields bundleArg = bundle.get().getConstructorArg();
      xcodeNativeTargetAttributesBuilder.setInfoPlist(Optional.of(bundleArg.getInfoPlist()));
    }

    xcodeNativeTargetAttributesBuilder.setBridgingHeader(arg.getBridgingHeader());

    if (!directAssetCatalogs.isEmpty()) {
      xcodeNativeTargetAttributesBuilder.setDirectAssetCatalogs(directAssetCatalogs);
    }

    FluentIterable<TargetNode<?>> depTargetNodes = collectRecursiveLibraryDepTargets(targetNode);

    if (includeFrameworks) {
      if (!options.shouldAddLinkedLibrariesAsFlags()) {
        ImmutableSet.Builder<FrameworkPath> frameworksBuilder = ImmutableSet.builder();
        frameworksBuilder.addAll(collectRecursiveFrameworkDependencies(targetNode));
        frameworksBuilder.addAll(targetNode.getConstructorArg().getFrameworks());
        frameworksBuilder.addAll(targetNode.getConstructorArg().getLibraries());

        xcodeNativeTargetAttributesBuilder.setSystemFrameworks(frameworksBuilder.build());
      }

      if (sharedLibraryToBundle.isPresent()) {
        // Replace target nodes of libraries which are actually constituents of embedded
        // frameworks to the bundle representing the embedded framework.
        // This will be converted to a reference to the xcode build product for the embedded
        // framework rather than the dylib
        depTargetNodes = swapSharedLibrariesForBundles(depTargetNodes, sharedLibraryToBundle.get());
      }
    }

    FluentIterable<TargetNode<?>> swiftDepTargets =
        filterRecursiveLibraryDepTargetsWithSwiftSources(depTargetNodes);

    if (includeFrameworks
        && !swiftDepTargets.isEmpty()
        && shouldEmbedSwiftRuntimeInBundleTarget(bundle)
        && swiftBuckConfig.getProjectEmbedRuntime()) {
      // This is a binary that transitively depends on a library that uses Swift. We must ensure
      // that the Swift runtime is bundled.
      swiftDepsSettingsBuilder.put("ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "YES");
    }

    // Assume the BUCK file path is at the the base path of this target
    Path buckFilePath =
        buildTarget
            .getCellRelativeBasePath()
            .getPath()
            .toPath(projectFilesystem.getFileSystem())
            .resolve(buildFileName);
    xcodeNativeTargetAttributesBuilder.setBuckFilePath(Optional.of(buckFilePath));

    Optional<TargetNode<AppleNativeTargetDescriptionArg>> appleTargetNode =
        TargetNodes.castArg(targetNode, AppleNativeTargetDescriptionArg.class);
    if (appleTargetNode.isPresent()) {
      // Use Core Data models from immediate dependencies only.

      ImmutableList.Builder<CoreDataResource> coreDataFileBuilder = ImmutableList.builder();
      for (AppleWrapperResourceArg appleWrapperResourceArg : coreDataResources) {
        coreDataFileBuilder.add(
            CoreDataResource.fromResourceArgs(appleWrapperResourceArg, projectFilesystem));
      }
      xcodeNativeTargetAttributesBuilder.setCoreDataResources(coreDataFileBuilder.build());
    }

    ImmutableList.Builder<BuildTarget> dependencies = ImmutableList.builder();

    extraSettingsBuilder.putAll(swiftDepsSettingsBuilder.build());

    ImmutableSortedMap<Path, SourcePath> publicCxxHeaders =
        headerSearchPathAttributes.publicCxxHeaders();
    publicCxxHeaders.values().stream()
        .map(Utils::sourcePathTryIntoBuildTargetSourcePath)
        .filter(Optional::isPresent)
        .forEach(
            sourcePath ->
                Utils.addRequiredBuildTargetFromSourcePath(
                    sourcePath.get(),
                    requiredBuildTargetsBuilder,
                    targetGraph,
                    actionGraphBuilderForNode));

    if (NodeHelper.isModularAppleLibrary(targetNode) && isFrameworkProductType(productType)) {
      // Modular frameworks should not include Buck-generated hmaps as they break the VFS overlay
      // that's generated by Xcode and consequently, all headers part of a framework's umbrella
      // header fail the modularity test, as they're expected to be mapped by the VFS layer under
      // $BUILT_PRODUCTS_DIR/Module.framework/Versions/A/Headers.
      publicCxxHeaders = ImmutableSortedMap.of();
    }

    // Watch dependencies need to have explicit target dependencies setup in order for Xcode to
    // build them properly within the IDE.  It is unable to match the implicit dependency because
    // of the different in flavor between the targets (iphoneos vs watchos).
    if (bundle.isPresent()) {
      for (TargetNode<?> watchTargetNode : targetGraph.getAll(bundle.get().getExtraDeps())) {
        String targetNodeFlavorPostfix = watchTargetNode.getBuildTarget().getFlavorPostfix();
        if (targetNodeFlavorPostfix.startsWith("#watch")
            && !targetNodeFlavorPostfix.equals(targetNode.getBuildTarget().getFlavorPostfix())
            && watchTargetNode.getDescription() instanceof AppleBundleDescription) {
          dependencies.add(watchTargetNode.getBuildTarget());
        }
      }
    }

    // -- configurations
    extraSettingsBuilder
        .put("TARGET_NAME", buildTargetName)
        .put("SRCROOT", pathRelativizer.outputPathToBuildTargetPath(buildTarget).toString());
    if (productType == ProductTypes.UI_TEST) {
      if (bundleLoaderNode.isPresent()) {
        BuildTarget testTarget = bundleLoaderNode.get().getBuildTarget();
        extraSettingsBuilder.put("TEST_TARGET_NAME", testTarget.getFullyQualifiedName());
        dependencies.add(testTarget);
      } else {
        throw new HumanReadableException(
            "The test rule '%s' is configured with 'is_ui_test' but has no test_host_app",
            buildTargetName);
      }
    } else if (bundleLoaderNode.isPresent()) {
      TargetNode<AppleBundleDescriptionArg> bundleLoader = bundleLoaderNode.get();
      String bundleLoaderProductName = getProductName(bundleLoader);
      String bundleLoaderBundleName =
          bundleLoaderProductName
              + "."
              + getExtensionString(bundleLoader.getConstructorArg().getExtension());
      // NOTE(grp): This is a hack. We need to support both deep (OS X) and flat (iOS)
      // style bundles for the bundle loader, but at this point we don't know what platform
      // the bundle loader (or current target) is going to be built for. However, we can be
      // sure that it's the same as the target (presumably a test) we're building right now.
      //
      // Using that knowledge, we can do build setting tricks to defer choosing the bundle
      // loader path until Xcode build time, when the platform is known. There's no build
      // setting that conclusively says whether the current platform uses deep bundles:
      // that would be too easy. But in the cases we care about (unit test bundles), the
      // current bundle will have a style matching the style of the bundle loader app, so
      // we can take advantage of that to do the determination.
      //
      // Unfortunately, the build setting for the bundle structure (CONTENTS_FOLDER_PATH)
      // includes the WRAPPER_NAME, so we can't just interpolate that in. Instead, we have
      // to use another trick with build setting operations and evaluation. By using the
      // $(:file) operation, we can extract the last component of the contents path: either
      // "Contents" or the current bundle name. Then, we can interpolate with that expected
      // result in the build setting name to conditionally choose a different loader path.

      // The conditional that decides which path is used. This is a complex Xcode build setting
      // expression that expands to one of two values, depending on the last path component of
      // the CONTENTS_FOLDER_PATH variable. As described above, this will be either "Contents"
      // for deep bundles or the bundle file name itself for flat bundles. Finally, to santiize
      // the potentially invalid build setting names from the bundle file name, it converts that
      // to an identifier. We rely on BUNDLE_LOADER_BUNDLE_STYLE_CONDITIONAL_<bundle file name>
      // being undefined (and thus expanding to nothing) for the path resolution to work.
      //
      // The operations on the CONTENTS_FOLDER_PATH are documented here:
      // http://codeworkshop.net/posts/xcode-build-setting-transformations
      String bundleLoaderOutputPathConditional =
          "$(BUNDLE_LOADER_BUNDLE_STYLE_CONDITIONAL_$(CONTENTS_FOLDER_PATH:file:identifier))";

      // If the $(CONTENTS_FOLDER_PATH:file:identifier) expands to this, we add the deep bundle
      // path into the bundle loader. See above for the case when it will expand to this value.
      extraSettingsBuilder.put(
          "BUNDLE_LOADER_BUNDLE_STYLE_CONDITIONAL_Contents",
          Joiner.on('/')
              .join(
                  getTargetOutputPath(bundleLoader),
                  bundleLoaderBundleName,
                  "Contents/MacOS",
                  bundleLoaderProductName));

      extraSettingsBuilder.put(
          "BUNDLE_LOADER_BUNDLE_STYLE_CONDITIONAL_"
              + getProductName(bundle.get())
              + "_"
              + getExtensionString(bundle.get().getConstructorArg().getExtension()),
          Joiner.on('/')
              .join(
                  getTargetOutputPath(bundleLoader),
                  bundleLoaderBundleName,
                  bundleLoaderProductName));

      extraSettingsBuilder
          .put("BUNDLE_LOADER", bundleLoaderOutputPathConditional)
          .put("TEST_HOST", "$(BUNDLE_LOADER)");

      dependencies.add(bundleLoader.getBuildTarget());
    }
    if (infoPlistOptional.isPresent()) {
      Path infoPlistPath = pathRelativizer.outputDirToRootRelative(infoPlistOptional.get());
      extraSettingsBuilder.put("INFOPLIST_FILE", infoPlistPath.toString());
    }
    if (arg.getBridgingHeader().isPresent()) {
      Path bridgingHeaderPath =
          pathRelativizer.outputDirToRootRelative(resolveSourcePath(arg.getBridgingHeader().get()));
      extraSettingsBuilder.put(
          "SWIFT_OBJC_BRIDGING_HEADER",
          Joiner.on('/').join("$(SRCROOT)", bridgingHeaderPath.toString()));
    }

    swiftVersion.ifPresent(s -> extraSettingsBuilder.put("SWIFT_VERSION", s));
    swiftVersion.ifPresent(
        s -> extraSettingsBuilder.put("PRODUCT_MODULE_NAME", swiftAttributes.moduleName()));

    if (hasSwiftVersionArg && containsSwiftCode) {
      extraSettingsBuilder.put(
          "SWIFT_OBJC_INTERFACE_HEADER_NAME",
          SwiftAttributeParser.getSwiftObjCGeneratedHeaderName(buildTargetNode, Optional.empty()));

      if (swiftBuckConfig.getProjectWMO()) {
        // We must disable "Index While Building" as there's a bug in the LLVM infra which
        // makes the compilation fail.
        extraSettingsBuilder.put("COMPILER_INDEX_STORE_ENABLE", "NO");

        // This is a hidden Xcode setting which is needed for two reasons:
        // - Stops Xcode adding .o files for each Swift compilation unit to dependency db
        //   which is used during linking (which will fail with WMO).
        // - Turns on WMO itself.
        //
        // Note that setting SWIFT_OPTIMIZATION_LEVEL (which is public) to '-Owholemodule'
        // ends up crashing the Swift compiler for some reason while this doesn't.
        extraSettingsBuilder.put("SWIFT_WHOLE_MODULE_OPTIMIZATION", "YES");
      }
    }

    Optional<SourcePath> prefixHeaderOptional =
        getPrefixHeaderSourcePath(targetNode.getConstructorArg());
    if (prefixHeaderOptional.isPresent()) {
      Path prefixHeaderRelative = resolveSourcePath(prefixHeaderOptional.get());
      Path prefixHeaderPath = pathRelativizer.outputDirToRootRelative(prefixHeaderRelative);
      extraSettingsBuilder.put("GCC_PREFIX_HEADER", prefixHeaderPath.toString());
      extraSettingsBuilder.put("GCC_PRECOMPILE_PREFIX_HEADER", "YES");
    }

    boolean shouldSetUseHeadermap = false;
    if (isModularAppleLibrary) {
      extraSettingsBuilder.put("CLANG_ENABLE_MODULES", "YES");
      extraSettingsBuilder.put("DEFINES_MODULE", "YES");

      if (isFrameworkProductType(productType)) {
        // Modular frameworks need to have both USE_HEADERMAP enabled so that Xcode generates
        // .framework VFS overlays, in modular libraries we handle this in buck
        shouldSetUseHeadermap = true;
      }
    }
    extraSettingsBuilder.put("USE_HEADERMAP", shouldSetUseHeadermap ? "YES" : "NO");

    AbsPath repoRoot = projectFilesystem.getRootPath().normalize();
    defaultSettingsBuilder.put("REPO_ROOT", repoRoot.toString());
    if (hasSwiftVersionArg && containsSwiftCode) {
      // We need to be able to control the directory where Xcode places the derived sources, so
      // that the Obj-C Generated Header can be included in the header map and imported through
      // a framework-style import like <Module/Module-Swift.h>
      Path derivedSourcesDir =
          com.facebook.buck.features.apple.projectV2.Utils.getDerivedSourcesDirectoryForBuildTarget(
              buildTarget, projectFilesystem);
      defaultSettingsBuilder.put(
          "DERIVED_FILE_DIR", repoRoot.resolve(derivedSourcesDir).toString());
    }

    defaultSettingsBuilder.put(PRODUCT_NAME, getProductName(buildTargetNode));
    bundle.ifPresent(
        bundleNode ->
            defaultSettingsBuilder.put(
                "WRAPPER_EXTENSION",
                getExtensionString(bundleNode.getConstructorArg().getExtension())));

    // We use BUILT_PRODUCTS_DIR as the root for the everything being built. Target-
    // specific output is placed within CONFIGURATION_BUILD_DIR, inside BUILT_PRODUCTS_DIR.
    // That allows Copy Files build phases to reference files in the CONFIGURATION_BUILD_DIR
    // of other targets by using paths relative to the target-independent BUILT_PRODUCTS_DIR.
    defaultSettingsBuilder.put(
        "BUILT_PRODUCTS_DIR",
        // $EFFECTIVE_PLATFORM_NAME starts with a dash, so this expands to something like:
        // $SYMROOT/Debug-iphonesimulator
        Joiner.on('/').join("$SYMROOT", "$CONFIGURATION$EFFECTIVE_PLATFORM_NAME"));
    defaultSettingsBuilder.put("CONFIGURATION_BUILD_DIR", "$BUILT_PRODUCTS_DIR");
    boolean nodeIsAppleLibrary = targetNode.getDescription() instanceof AppleLibraryDescription;
    boolean nodeIsCxxLibrary = targetNode.getDescription() instanceof CxxLibraryDescription;
    if (!bundle.isPresent() && (nodeIsAppleLibrary || nodeIsCxxLibrary)) {
      defaultSettingsBuilder.put("EXECUTABLE_PREFIX", "lib");
    }

    Set<Path> recursivePublicSystemIncludeDirectories =
        headerSearchPathAttributes.recursivePublicSystemIncludeDirectories();

    Builder<String, String> appendConfigsBuilder = ImmutableMap.builder();
    appendConfigsBuilder.putAll(
        getFrameworkAndLibrarySearchPathConfigs(
            targetNode, xcodeNativeTargetAttributesBuilder, includeFrameworks));
    appendConfigsBuilder.put(
        "HEADER_SEARCH_PATHS",
        Joiner.on(' ')
            .join(
                Iterables.concat(
                    headerSearchPathAttributes.recursiveHeaderSearchPaths(),
                    recursivePublicSystemIncludeDirectories,
                    headerSearchPathAttributes.recursivePublicIncludeDirectories(),
                    headerSearchPathAttributes.includeDirectories())));
    if (hasSwiftVersionArg) {
      Stream<String> allValues =
          Streams.concat(
              Stream.of("$BUILT_PRODUCTS_DIR"),
              Streams.stream(headerSearchPathAttributes.swiftIncludePaths())
                  .map((path) -> path.toString())
                  .map(Escaper.BASH_ESCAPER));
      appendConfigsBuilder.put("SWIFT_INCLUDE_PATHS", allValues.collect(Collectors.joining(" ")));
    }

    flagParser.parseFlags(
        targetNode,
        includeFrameworks,
        swiftDepTargets,
        containsSwiftCode,
        isModularAppleLibrary,
        publicCxxHeaders.size() > 0,
        recursivePublicSystemIncludeDirectories,
        appendConfigsBuilder,
        requiredBuildTargetsBuilder);

    ImmutableMap<String, String> appendedConfig = appendConfigsBuilder.build();

    BuildConfiguration.writeBuildConfigurationsForTarget(
        targetNode,
        buildTarget,
        defaultCxxPlatform,
        defaultPathResolver,
        xcodeNativeTargetAttributesBuilder,
        extraSettingsBuilder.build(),
        defaultSettingsBuilder.build(),
        appendedConfig,
        projectFilesystem,
        options.shouldGenerateReadOnlyFiles(),
        targetConfigNamesBuilder,
        xcconfigPathsBuilder);

    if (bundle.isPresent()) {
      addEntitlementsPlistIntoTarget(bundle.get(), xcodeNativeTargetAttributesBuilder);
    }

    return dependencies.build();
  }