Example usage for com.google.common.collect ImmutableList stream

List of usage examples for com.google.common.collect ImmutableList stream

Introduction

In this page you can find the example usage for com.google.common.collect ImmutableList stream.

Prototype

default Stream<E> stream() 

Source Link

Document

Returns a sequential Stream with this collection as its source.

Usage

From source file:com.facebook.buck.rules.CachingBuildRuleBuilder.java

ListenableFuture<BuildResult> build() {
    final AtomicReference<Long> outputSize = Atomics.newReference();

    ListenableFuture<List<BuildResult>> depResults = Futures.immediateFuture(Collections.emptyList());

    // If we're performing a deep build, guarantee that all dependencies will *always* get
    // materialized locally
    if (buildMode == CachingBuildEngine.BuildMode.DEEP
            || buildMode == CachingBuildEngine.BuildMode.POPULATE_FROM_REMOTE_CACHE) {
        depResults = buildRuleBuilderDelegate.getDepResults(rule, buildContext, executionContext);
    }/*from w  ww. ja  v  a2s  .com*/

    ListenableFuture<BuildResult> buildResult = Futures.transformAsync(depResults,
            input -> buildOrFetchFromCache(),
            serviceByAdjustingDefaultWeightsTo(CachingBuildEngine.SCHEDULING_MORE_WORK_RESOURCE_AMOUNTS));

    // Check immediately (without posting a new task) for a failure so that we can short-circuit
    // pending work. Use .catchingAsync() instead of .catching() so that we can propagate unchecked
    // exceptions.
    buildResult = Futures.catchingAsync(buildResult, Throwable.class, throwable -> {
        Preconditions.checkNotNull(throwable);
        buildRuleBuilderDelegate.setFirstFailure(throwable);
        Throwables.throwIfInstanceOf(throwable, Exception.class);
        throw new RuntimeException(throwable);
    });

    buildResult = Futures.transform(buildResult, (result) -> {
        buildRuleBuilderDelegate.markRuleAsUsed(rule, buildContext.getEventBus());
        return result;
    }, MoreExecutors.directExecutor());

    // Setup a callback to handle either the cached or built locally cases.
    AsyncFunction<BuildResult, BuildResult> callback = input -> {

        // If we weren't successful, exit now.
        if (input.getStatus() != BuildRuleStatus.SUCCESS) {
            return Futures.immediateFuture(input);
        }

        try (Scope scope = LeafEvents.scope(buildContext.getEventBus(), "finalizing_build_rule")) {
            // We shouldn't see any build fail result at this point.
            BuildRuleSuccessType success = Preconditions.checkNotNull(input.getSuccess());

            // If we didn't build the rule locally, reload the recorded paths from the build
            // metadata.
            if (success != BuildRuleSuccessType.BUILT_LOCALLY) {
                try {
                    for (String str : onDiskBuildInfo.getValuesOrThrow(BuildInfo.MetadataKey.RECORDED_PATHS)) {
                        buildInfoRecorder.recordArtifact(Paths.get(str));
                    }
                } catch (IOException e) {
                    LOG.error(e, "Failed to read RECORDED_PATHS for %s", rule);
                    throw e;
                }
            }

            // Try get the output size now that all outputs have been recorded.
            if (success == BuildRuleSuccessType.BUILT_LOCALLY) {
                outputSize.set(buildInfoRecorder.getOutputSize());
            }

            // If the success type means the rule has potentially changed it's outputs...
            if (success.outputsHaveChanged()) {

                // The build has succeeded, whether we've fetched from cache, or built locally.
                // So run the post-build steps.
                if (rule instanceof HasPostBuildSteps) {
                    executePostBuildSteps(
                            ((HasPostBuildSteps) rule).getPostBuildSteps(buildContext.getBuildContext()));
                }

                // Invalidate any cached hashes for the output paths, since we've updated them.
                for (Path path : buildInfoRecorder.getRecordedPaths()) {
                    fileHashCache.invalidate(rule.getProjectFilesystem().resolve(path));
                }
            }

            if (SupportsInputBasedRuleKey.isSupported(rule) && success == BuildRuleSuccessType.BUILT_LOCALLY
                    && !buildInfoRecorder.getBuildMetadataFor(BuildInfo.MetadataKey.INPUT_BASED_RULE_KEY)
                            .isPresent()) {
                // Doing this here is probably not strictly necessary, however in the case of
                // pipelined rules built locally we will never do an input-based cache check.
                // That check would have written the key to metadata, and there are some asserts
                // during cache upload that try to ensure they are present.
                Optional<RuleKey> inputRuleKey = calculateInputBasedRuleKey(buildContext.getEventBus());
                if (inputRuleKey.isPresent()) {
                    buildInfoRecorder.addBuildMetadata(BuildInfo.MetadataKey.INPUT_BASED_RULE_KEY,
                            inputRuleKey.get().toString());
                }
            }

            // If this rule uses dep files and we built locally, make sure we store the new dep file
            // list and re-calculate the dep file rule key.
            if (useDependencyFileRuleKey() && success == BuildRuleSuccessType.BUILT_LOCALLY) {

                // Query the rule for the actual inputs it used.
                ImmutableList<SourcePath> inputs = ((SupportsDependencyFileRuleKey) rule)
                        .getInputsAfterBuildingLocally(buildContext.getBuildContext(),
                                executionContext.getCellPathResolver());

                // Record the inputs into our metadata for next time.
                // TODO(#9117006): We don't support a way to serlialize `SourcePath`s to the cache,
                // so need to use DependencyFileEntry's instead and recover them on deserialization.
                ImmutableList<String> inputStrings = inputs.stream()
                        .map(inputString -> DependencyFileEntry.fromSourcePath(inputString, pathResolver))
                        .map(MoreFunctions.toJsonFunction()).collect(MoreCollectors.toImmutableList());
                buildInfoRecorder.addMetadata(BuildInfo.MetadataKey.DEP_FILE, inputStrings);

                // Re-calculate and store the depfile rule key for next time.
                Optional<RuleKeyAndInputs> depFileRuleKeyAndInputs = calculateDepFileRuleKey(
                        Optional.of(inputStrings), /* allowMissingInputs */ false);
                if (depFileRuleKeyAndInputs.isPresent()) {
                    RuleKey depFileRuleKey = depFileRuleKeyAndInputs.get().getRuleKey();
                    buildInfoRecorder.addBuildMetadata(BuildInfo.MetadataKey.DEP_FILE_RULE_KEY,
                            depFileRuleKey.toString());

                    // Push an updated manifest to the cache.
                    if (useManifestCaching()) {
                        Optional<RuleKeyAndInputs> manifestKey = calculateManifestKey(
                                buildContext.getEventBus());
                        if (manifestKey.isPresent()) {
                            buildInfoRecorder.addBuildMetadata(BuildInfo.MetadataKey.MANIFEST_KEY,
                                    manifestKey.get().getRuleKey().toString());
                            updateAndStoreManifest(depFileRuleKeyAndInputs.get().getRuleKey(),
                                    depFileRuleKeyAndInputs.get().getInputs(), manifestKey.get(),
                                    buildContext.getArtifactCache());
                        }
                    }
                }
            }

            // If this rule was built locally, grab and record the output hashes in the build
            // metadata so that cache hits avoid re-hashing file contents.  Since we use output
            // hashes for input-based rule keys and for detecting non-determinism, we would spend
            // a lot of time re-hashing output paths -- potentially in serialized in a single step.
            // So, do the hashing here to distribute the workload across several threads and cache
            // the results.
            //
            // Also, since hashing outputs can potentially be expensive, we avoid doing this for
            // rules that are marked as uncacheable.  The rationale here is that they are likely not
            // cached due to the sheer size which would be costly to hash or builtin non-determinism
            // in the rule which somewhat defeats the purpose of logging the hash.
            if (success == BuildRuleSuccessType.BUILT_LOCALLY
                    && shouldUploadToCache(success, Preconditions.checkNotNull(outputSize.get()))) {
                ImmutableSortedMap.Builder<String, String> outputHashes = ImmutableSortedMap.naturalOrder();
                for (Path path : buildInfoRecorder.getOutputPaths()) {
                    outputHashes.put(path.toString(),
                            fileHashCache.get(rule.getProjectFilesystem().resolve(path)).toString());
                }
                buildInfoRecorder.addBuildMetadata(BuildInfo.MetadataKey.RECORDED_PATH_HASHES,
                        outputHashes.build());
            }

            // If this rule was fetched from cache, seed the file hash cache with the recorded
            // output hashes from the build metadata.  Since outputs which have been changed have
            // already been invalidated above, this is purely a best-effort optimization -- if the
            // the output hashes weren't recorded in the cache we do nothing.
            if (success != BuildRuleSuccessType.BUILT_LOCALLY && success.outputsHaveChanged()) {
                Optional<ImmutableMap<String, String>> hashes = onDiskBuildInfo
                        .getBuildMap(BuildInfo.MetadataKey.RECORDED_PATH_HASHES);

                // We only seed after first verifying the recorded path hashes.  This prevents the
                // optimization, but is useful to keep in place for a while to verify this optimization
                // is causing issues.
                if (hashes.isPresent() && verifyRecordedPathHashes(rule.getBuildTarget(),
                        rule.getProjectFilesystem(), hashes.get())) {

                    // Seed the cache with the hashes.
                    for (Map.Entry<String, String> ent : hashes.get().entrySet()) {
                        Path path = rule.getProjectFilesystem().getPath(ent.getKey());
                        HashCode hashCode = HashCode.fromString(ent.getValue());
                        fileHashCache.set(rule.getProjectFilesystem().resolve(path), hashCode);
                    }
                }
            }

            // Make sure the origin field is filled in.
            BuildId buildId = buildContext.getBuildId();
            if (success == BuildRuleSuccessType.BUILT_LOCALLY) {
                buildInfoRecorder.addBuildMetadata(BuildInfo.MetadataKey.ORIGIN_BUILD_ID, buildId.toString());
            } else if (success.outputsHaveChanged()) {
                Preconditions.checkState(
                        buildInfoRecorder.getBuildMetadataFor(BuildInfo.MetadataKey.ORIGIN_BUILD_ID)
                                .isPresent(),
                        "Cache hits must populate the %s field (%s)", BuildInfo.MetadataKey.ORIGIN_BUILD_ID,
                        success);
            }

            // Make sure that all of the local files have the same values they would as if the
            // rule had been built locally.
            buildInfoRecorder.addBuildMetadata(BuildInfo.MetadataKey.TARGET, rule.getBuildTarget().toString());
            buildInfoRecorder.addMetadata(BuildInfo.MetadataKey.RECORDED_PATHS,
                    buildInfoRecorder.getRecordedPaths().stream().map(Object::toString)
                            .collect(MoreCollectors.toImmutableList()));
            if (success.shouldWriteRecordedMetadataToDiskAfterBuilding()) {
                try {
                    boolean clearExistingMetadata = success.shouldClearAndOverwriteMetadataOnDisk();
                    buildInfoRecorder.writeMetadataToDisk(clearExistingMetadata);
                } catch (IOException e) {
                    throw new IOException(String.format("Failed to write metadata to disk for %s.", rule), e);
                }
            }

            // Give the rule a chance to populate its internal data structures now that all of
            // the files should be in a valid state.
            try {
                if (rule instanceof InitializableFromDisk) {
                    doInitializeFromDisk((InitializableFromDisk<?>) rule);
                }
            } catch (IOException e) {
                throw new IOException(
                        String.format("Error initializing %s from disk: %s.", rule, e.getMessage()), e);
            }
        }

        return Futures.immediateFuture(input);
    };
    buildResult = Futures.transformAsync(buildResult, ruleAsyncFunction(buildContext.getEventBus(), callback),
            serviceByAdjustingDefaultWeightsTo(CachingBuildEngine.RULE_KEY_COMPUTATION_RESOURCE_AMOUNTS));

    buildResult = Futures.catchingAsync(buildResult, Throwable.class, thrown -> {
        LOG.debug(thrown, "Building rule [%s] failed.", rule.getBuildTarget());

        if (consoleLogBuildFailuresInline) {
            buildContext.getEventBus().post(ConsoleEvent.severe(getErrorMessageIncludingBuildRule(thrown)));
        }

        thrown = maybeAttachBuildRuleNameToException(thrown);
        recordFailureAndCleanUp(thrown);

        return Futures.immediateFuture(BuildResult.failure(rule, thrown));
    });

    // Do things that need to happen after either success or failure, but don't block the dependents
    // while doing so:
    buildRuleBuilderDelegate
            .addAsyncCallback(MoreFutures.addListenableCallback(buildResult, new FutureCallback<BuildResult>() {

                private void uploadToCache(BuildRuleSuccessType success) {

                    // Collect up all the rule keys we have index the artifact in the cache with.
                    Set<RuleKey> ruleKeys = new HashSet<>();

                    // If the rule key has changed (and is not already in the cache), we need to push
                    // the artifact to cache using the new key.
                    ruleKeys.add(ruleKeyFactories.getDefaultRuleKeyFactory().build(rule));

                    // If the input-based rule key has changed, we need to push the artifact to cache
                    // using the new key.
                    if (SupportsInputBasedRuleKey.isSupported(rule)) {
                        Optional<RuleKey> calculatedRuleKey = calculateInputBasedRuleKey(
                                buildContext.getEventBus());
                        Optional<RuleKey> onDiskRuleKey = onDiskBuildInfo
                                .getRuleKey(BuildInfo.MetadataKey.INPUT_BASED_RULE_KEY);
                        Optional<RuleKey> metaDataRuleKey = buildInfoRecorder
                                .getBuildMetadataFor(BuildInfo.MetadataKey.INPUT_BASED_RULE_KEY)
                                .map(RuleKey::new);
                        Preconditions.checkState(calculatedRuleKey.equals(onDiskRuleKey),
                                "%s (%s): %s: invalid on-disk input-based rule key: %s != %s",
                                rule.getBuildTarget(), rule.getType(), success, calculatedRuleKey,
                                onDiskRuleKey);
                        Preconditions.checkState(calculatedRuleKey.equals(metaDataRuleKey),
                                "%s: %s: invalid meta-data input-based rule key: %s != %s",
                                rule.getBuildTarget(), success, calculatedRuleKey, metaDataRuleKey);
                        if (calculatedRuleKey.isPresent()) {
                            ruleKeys.add(calculatedRuleKey.get());
                        }
                    }

                    // If the manifest-based rule key has changed, we need to push the artifact to cache
                    // using the new key.
                    if (useManifestCaching()) {
                        Optional<RuleKey> onDiskRuleKey = onDiskBuildInfo
                                .getRuleKey(BuildInfo.MetadataKey.DEP_FILE_RULE_KEY);
                        Optional<RuleKey> metaDataRuleKey = buildInfoRecorder
                                .getBuildMetadataFor(BuildInfo.MetadataKey.DEP_FILE_RULE_KEY).map(RuleKey::new);
                        Preconditions.checkState(onDiskRuleKey.equals(metaDataRuleKey),
                                "%s: %s: inconsistent meta-data and on-disk dep-file rule key: %s != %s",
                                rule.getBuildTarget(), success, onDiskRuleKey, metaDataRuleKey);
                        if (onDiskRuleKey.isPresent()) {
                            ruleKeys.add(onDiskRuleKey.get());
                        }
                    }

                    // Do the actual upload.
                    try {

                        // Verify that the recorded path hashes are accurate.
                        Optional<String> recordedPathHashes = buildInfoRecorder
                                .getBuildMetadataFor(BuildInfo.MetadataKey.RECORDED_PATH_HASHES);
                        if (recordedPathHashes.isPresent() && !verifyRecordedPathHashes(rule.getBuildTarget(),
                                rule.getProjectFilesystem(), recordedPathHashes.get())) {
                            return;
                        }

                        // Push to cache.
                        buildInfoRecorder.performUploadToArtifactCache(ImmutableSet.copyOf(ruleKeys),
                                buildContext.getArtifactCache(), buildContext.getEventBus());

                    } catch (Throwable t) {
                        buildContext.getEventBus().post(
                                ThrowableConsoleEvent.create(t, "Error uploading to cache for %s.", rule));
                    }
                }

                private void handleResult(BuildResult input) {
                    Optional<Long> outputSize = Optional.empty();
                    Optional<HashCode> outputHash = Optional.empty();
                    Optional<BuildRuleSuccessType> successType = Optional.empty();
                    boolean shouldUploadToCache = false;

                    BuildRuleEvent.Resumed resumedEvent = BuildRuleEvent.resumed(rule, buildRuleDurationTracker,
                            ruleKeyFactories.getDefaultRuleKeyFactory());
                    LOG.verbose(resumedEvent.toString());
                    buildContext.getEventBus().post(resumedEvent);

                    if (input.getStatus() == BuildRuleStatus.SUCCESS) {
                        BuildRuleSuccessType success = Preconditions.checkNotNull(input.getSuccess());
                        successType = Optional.of(success);

                        // Try get the output size.
                        if (success == BuildRuleSuccessType.BUILT_LOCALLY
                                || success.shouldUploadResultingArtifact()) {
                            try {
                                outputSize = Optional.of(buildInfoRecorder.getOutputSize());
                            } catch (IOException e) {
                                buildContext.getEventBus().post(ThrowableConsoleEvent.create(e,
                                        "Error getting output size for %s.", rule));
                            }
                        }

                        // Compute it's output hash for logging/tracing purposes, as this artifact will
                        // be consumed by other builds.
                        if (outputSize.isPresent() && shouldHashOutputs(success, outputSize.get())) {
                            try {
                                outputHash = Optional.of(buildInfoRecorder.getOutputHash(fileHashCache));
                            } catch (IOException e) {
                                buildContext.getEventBus().post(ThrowableConsoleEvent.create(e,
                                        "Error getting output hash for %s.", rule));
                            }
                        }

                        // Determine if this is rule is cacheable.
                        shouldUploadToCache = outputSize.isPresent()
                                && shouldUploadToCache(success, outputSize.get());

                        // Upload it to the cache.
                        if (shouldUploadToCache) {
                            uploadToCache(success);
                        }
                    }

                    boolean failureOrBuiltLocally = input.getStatus() == BuildRuleStatus.FAIL
                            || input.getSuccess() == BuildRuleSuccessType.BUILT_LOCALLY;
                    // Log the result to the event bus.
                    BuildRuleEvent.Finished finished = BuildRuleEvent.finished(resumedEvent, getBuildRuleKeys(),
                            input.getStatus(), input.getCacheResult(),
                            onDiskBuildInfo.getBuildValue(BuildInfo.MetadataKey.ORIGIN_BUILD_ID)
                                    .map(BuildId::new),
                            successType, shouldUploadToCache, outputHash, outputSize,
                            getBuildRuleDiagnosticData(failureOrBuiltLocally));
                    LOG.verbose(finished.toString());
                    buildContext.getEventBus().post(finished);
                }

                @Override
                public void onSuccess(BuildResult input) {
                    handleResult(input);

                    // Reset interrupted flag once failure has been recorded.
                    if (input.getFailure() instanceof InterruptedException) {
                        Threads.interruptCurrentThread();
                    }
                }

                @Override
                public void onFailure(@Nonnull Throwable thrown) {
                    throw new AssertionError("Dead code");
                }
            }, serviceByAdjustingDefaultWeightsTo(CachingBuildEngine.RULE_KEY_COMPUTATION_RESOURCE_AMOUNTS)));
    return buildResult;
}

From source file:com.google.errorprone.bugpatterns.CatchFail.java

Optional<Fix> deleteFix(TryTree tree, ImmutableList<CatchTree> catchBlocks, VisitorState state) {
    SuggestedFix.Builder fix = SuggestedFix.builder();
    if (tree.getFinallyBlock() != null || catchBlocks.size() < tree.getCatches().size()) {
        // If the try statement has a finally region, or other catch blocks, delete only the
        // unnecessary blocks.
        catchBlocks.forEach(fix::delete);
    } else {/*from w  w w  .  java2 s.  co  m*/
        // The try statement has no finally region and all catch blocks are unnecessary. Replace it
        // with the try statements, deleting all catches.
        List<? extends StatementTree> tryStatements = tree.getBlock().getStatements();

        // If the try block is empty, all of the catches are dead, so just delete the whole try and
        // don't modify the signature of the method
        if (tryStatements.isEmpty()) {
            return Optional.of(fix.delete(tree).build());
        } else {
            String source = state.getSourceCode().toString();
            // Replace the full region to work around a GJF partial formatting bug that prevents it from
            // re-indenting unchanged lines. This means that fixes may overlap, but that's (hopefully)
            // unlikely.
            // TODO(b/24140798): emit more precise replacements if GJF is fixed
            fix.replace(tree, source.substring(((JCTree) tryStatements.get(0)).getStartPosition(),
                    state.getEndPosition(Iterables.getLast(tryStatements))));
        }
    }
    MethodTree enclosing = findEnclosing(state.getPath());
    if (enclosing == null) {
        // There isn't an enclosing method, possibly because we're in a lambda or initializer block.
        return Optional.empty();
    }
    if (isExpectedExceptionTest(ASTHelpers.getSymbol(enclosing), state)) {
        // Replacing the original exception with fail() may break badly-structured expected-exception
        // tests, so don't use that fix for methods annotated with @Test(expected=...).
        return Optional.empty();
    }

    // Fix up the enclosing method's throws declaration to include the new thrown exception types.
    Collection<Type> thrownTypes = ASTHelpers.getSymbol(enclosing).getThrownTypes();
    Types types = state.getTypes();
    // Find all types in the deleted catch blocks that are not already in the throws declaration.
    ImmutableList<Type> toThrow = catchBlocks.stream().map(c -> ASTHelpers.getType(c.getParameter()))
            // convert multi-catch to a list of component types
            .flatMap(t -> t instanceof UnionClassType
                    ? ImmutableList.copyOf(((UnionClassType) t).getAlternativeTypes()).stream()
                    : Stream.of(t))
            .filter(t -> thrownTypes.stream().noneMatch(x -> types.isAssignable(t, x)))
            .collect(toImmutableList());
    if (!toThrow.isEmpty()) {
        if (!JUnitMatchers.TEST_CASE.matches(enclosing, state)) {
            // Don't add throws declarations to methods that don't look like test cases, since it may
            // not be a safe local refactoring.
            return Optional.empty();
        }
        String throwsString = toThrow.stream().map(t -> SuggestedFixes.qualifyType(state, fix, t)).distinct()
                .collect(joining(", "));
        if (enclosing.getThrows().isEmpty()) {
            // Add a new throws declaration.
            fix.prefixWith(enclosing.getBody(), "throws " + throwsString);
        } else {
            // Append to an existing throws declaration.
            fix.postfixWith(Iterables.getLast(enclosing.getThrows()), ", " + throwsString);
        }
    }
    return Optional.of(fix.build());
}

From source file:com.google.gerrit.server.update.NoteDbBatchUpdate.java

static void execute(ImmutableList<NoteDbBatchUpdate> updates, BatchUpdateListener listener,
        @Nullable RequestId requestId, boolean dryrun) throws UpdateException, RestApiException {
    if (updates.isEmpty()) {
        return;//from   www  .  jav a 2s .  co  m
    }
    setRequestIds(updates, requestId);

    try {
        List<CheckedFuture<?, IOException>> indexFutures = new ArrayList<>();
        List<ChangesHandle> handles = new ArrayList<>(updates.size());
        Order order = getOrder(updates, listener);
        try {
            switch (order) {
            case REPO_BEFORE_DB:
                for (NoteDbBatchUpdate u : updates) {
                    u.executeUpdateRepo();
                }
                listener.afterUpdateRepos();
                for (NoteDbBatchUpdate u : updates) {
                    handles.add(u.executeChangeOps(dryrun));
                }
                for (ChangesHandle h : handles) {
                    h.execute();
                    indexFutures.addAll(h.startIndexFutures());
                }
                listener.afterUpdateRefs();
                listener.afterUpdateChanges();
                break;

            case DB_BEFORE_REPO:
                // Call updateChange for each op before updateRepo, but defer executing the
                // NoteDbUpdateManager until after calling updateRepo. They share an inserter and
                // BatchRefUpdate, so it will all execute as a single batch. But we have to let
                // NoteDbUpdateManager actually execute the update, since it has to interleave it
                // properly with All-Users updates.
                //
                // TODO(dborowitz): This may still result in multiple updates to All-Users, but that's
                // currently not a big deal because multi-change batches generally aren't affecting
                // drafts anyway.
                for (NoteDbBatchUpdate u : updates) {
                    handles.add(u.executeChangeOps(dryrun));
                }
                for (NoteDbBatchUpdate u : updates) {
                    u.executeUpdateRepo();
                }
                for (ChangesHandle h : handles) {
                    // TODO(dborowitz): This isn't quite good enough: in theory updateRepo may want to
                    // see the results of change meta commands, but they aren't actually added to the
                    // BatchUpdate until the body of execute. To fix this, execute needs to be split up
                    // into a method that returns a BatchRefUpdate before execution. Not a big deal at the
                    // moment, because this order is only used for deleting changes, and those updateRepo
                    // implementations definitely don't need to observe the updated change meta refs.
                    h.execute();
                    indexFutures.addAll(h.startIndexFutures());
                }
                break;
            default:
                throw new IllegalStateException("invalid execution order: " + order);
            }
        } finally {
            for (ChangesHandle h : handles) {
                h.close();
            }
        }

        ChangeIndexer.allAsList(indexFutures).get();

        // Fire ref update events only after all mutations are finished, since callers may assume a
        // patch set ref being created means the change was created, or a branch advancing meaning
        // some changes were closed.
        updates.stream().filter(u -> u.batchRefUpdate != null)
                .forEach(u -> u.gitRefUpdated.fire(u.project, u.batchRefUpdate, u.getAccount().orElse(null)));

        if (!dryrun) {
            for (NoteDbBatchUpdate u : updates) {
                u.executePostOps();
            }
        }
    } catch (Exception e) {
        wrapAndThrowException(e);
    }
}

From source file:com.facebook.buck.features.apple.project.ProjectGenerator.java

private PBXNativeTarget generateBinaryTarget(PBXProject project,
        Optional<? extends TargetNode<? extends HasAppleBundleFields>> bundle,
        TargetNode<? extends CxxLibraryDescription.CommonArg> targetNode, ProductType productType,
        String productOutputFormat, Optional<Path> infoPlistOptional, boolean includeFrameworks,
        ImmutableSet<AppleResourceDescriptionArg> recursiveResources,
        ImmutableSet<AppleResourceDescriptionArg> directResources,
        ImmutableSet<AppleAssetCatalogDescriptionArg> recursiveAssetCatalogs,
        ImmutableSet<AppleAssetCatalogDescriptionArg> directAssetCatalogs,
        ImmutableSet<AppleWrapperResourceArg> wrapperResources,
        Optional<Iterable<PBXBuildPhase>> copyFilesPhases,
        Optional<TargetNode<AppleBundleDescriptionArg>> bundleLoaderNode) throws IOException {

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

    TargetNode<?> buildTargetNode = bundle.isPresent() ? bundle.get() : targetNode;
    BuildTarget buildTarget = buildTargetNode.getBuildTarget();
    boolean containsSwiftCode = projGenerationStateCache.targetContainsSwiftSourceCode(targetNode);

    String buildTargetName = getProductNameForBuildTargetNode(buildTargetNode);
    CxxLibraryDescription.CommonArg arg = targetNode.getConstructorArg();
    NewNativeTargetProjectMutator mutator = new NewNativeTargetProjectMutator(pathRelativizer,
            this::resolveSourcePath);

    // 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));
    }/*from   w w  w. j  a  v a 2 s  . co  m*/

    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();
    boolean isFocusedOnTarget = focusModules.isFocusedOn(buildTarget);

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

    mutator.setTargetName(getXcodeTargetName(buildTarget)).setProduct(productType, buildTargetName,
            Paths.get(String.format(productOutputFormat, buildTargetName)));

    boolean isModularAppleLibrary = isModularAppleLibrary(targetNode) && isFocusedOnTarget;
    mutator.setFrameworkHeadersEnabled(isModularAppleLibrary);

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

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

    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 = ProjectGenerator
            .gatherExcludedSources(
                    appleCxxFlavors.stream().map(f -> applePlatformAndArchitecture(f).getFirst())
                            .collect(ImmutableSet.toImmutableSet()),
                    platformSources, platformHeadersIterable, outputDirectory, 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();

    if (!options.shouldGenerateHeaderSymlinkTreesOnly()) {
        if (isFocusedOnTarget) {
            filesAddedBuilder.addAll(
                    allSrcs.stream().map(s -> s.getSourcePath()).collect(ImmutableList.toImmutableList()));
            mutator.setLangPreprocessorFlags(ImmutableMap.copyOf(
                    Maps.transformValues(langPreprocessorFlags, f -> convertStringWithMacros(targetNode, f))))
                    .setPublicHeaders(exportedHeaders).setPrefixHeader(getPrefixHeaderSourcePath(arg))
                    .setSourcesWithFlags(ImmutableSet.copyOf(allSrcs)).setPrivateHeaders(headers)
                    .setRecursiveResources(recursiveResources).setDirectResources(directResources)
                    .setWrapperResources(wrapperResources)
                    .setExtraXcodeSources(ImmutableSet.copyOf(arg.getExtraXcodeSources()))
                    .setExtraXcodeFiles(ImmutableSet.copyOf(arg.getExtraXcodeFiles()));
        }

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

        mutator.setBridgingHeader(arg.getBridgingHeader());

        if (options.shouldCreateDirectoryStructure() && isFocusedOnTarget) {
            mutator.setTargetGroupPath(
                    RichStream.from(buildTarget.getBasePath()).map(Object::toString).toImmutableList());
        }

        if (!recursiveAssetCatalogs.isEmpty() && isFocusedOnTarget) {
            mutator.setRecursiveAssetCatalogs(recursiveAssetCatalogs);
        }

        if (!directAssetCatalogs.isEmpty() && isFocusedOnTarget) {
            mutator.setDirectAssetCatalogs(directAssetCatalogs);
        }

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

        if (includeFrameworks && isFocusedOnTarget) {

            if (!options.shouldAddLinkedLibrariesAsFlags()) {
                mutator.setFrameworks(getSytemFrameworksLibsForTargetNode(targetNode));
            }

            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());
            }

            ImmutableSet<PBXFileReference> targetNodeDeps = filterRecursiveLibraryDependenciesForLinkerPhase(
                    depTargetNodes);

            if (isTargetNodeApplicationTestTarget(targetNode, bundleLoaderNode)) {
                ImmutableSet<PBXFileReference> bundleLoaderDeps = bundleLoaderNode.isPresent()
                        ? collectRecursiveLibraryDependencies(bundleLoaderNode.get())
                        : ImmutableSet.of();
                mutator.setArchives(Sets.difference(targetNodeDeps, bundleLoaderDeps));
            } else {
                mutator.setArchives(targetNodeDeps);
            }
        }

        if (isFocusedOnTarget) {
            ImmutableSet<TargetNode<?>> swiftDepTargets = filterRecursiveLibraryDepTargetsWithSwiftSources(
                    depTargetNodes);

            if (!includeFrameworks && !swiftDepTargets.isEmpty()) {
                // If the current target, which is non-shared (e.g., static lib), depends on other focused
                // targets which include Swift code, we must ensure those are treated as dependencies so
                // that Xcode builds the targets in the correct order. Unfortunately, those deps can be
                // part of other projects which would require cross-project references.
                //
                // Thankfully, there's an easy workaround because we can just create a phony copy phase
                // which depends on the outputs of the deps (i.e., the static libs). The copy phase
                // will effectively say "Copy libX.a from Products Dir into Products Dir" which is a nop.
                // To be on the safe side, we're explicitly marking the copy phase as only running for
                // deployment postprocessing (i.e., "Copy only when installing") and disabling
                // deployment postprocessing (it's enabled by default for release builds).
                CopyFilePhaseDestinationSpec.Builder destSpecBuilder = CopyFilePhaseDestinationSpec.builder();
                destSpecBuilder.setDestination(PBXCopyFilesBuildPhase.Destination.PRODUCTS);
                PBXCopyFilesBuildPhase copyFiles = new PBXCopyFilesBuildPhase(destSpecBuilder.build());
                copyFiles.setRunOnlyForDeploymentPostprocessing(Optional.of(Boolean.TRUE));
                copyFiles.setName(Optional.of("Fake Swift Dependencies (Copy Files Phase)"));

                ImmutableSet<PBXFileReference> swiftDepsFileRefs = targetNodesSetToPBXFileReference(
                        swiftDepTargets);
                for (PBXFileReference fileRef : swiftDepsFileRefs) {
                    PBXBuildFile buildFile = new PBXBuildFile(fileRef);
                    copyFiles.getFiles().add(buildFile);
                }

                swiftDepsSettingsBuilder.put("DEPLOYMENT_POSTPROCESSING", "NO");

                mutator.setSwiftDependenciesBuildPhase(copyFiles);
            }

            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");
            }

            if (includeFrameworks && !swiftDepTargets.isEmpty() && swiftBuckConfig.getProjectAddASTPaths()) {
                for (TargetNode<?> swiftNode : swiftDepTargets) {
                    String swiftModulePath = String.format(
                            "${BUILT_PRODUCTS_DIR}/%s.swiftmodule/${CURRENT_ARCH}.swiftmodule",
                            getModuleName(swiftNode));
                    swiftDebugLinkerFlagsBuilder.add("-Xlinker");
                    swiftDebugLinkerFlagsBuilder.add("-add_ast_path");
                    swiftDebugLinkerFlagsBuilder.add("-Xlinker");
                    swiftDebugLinkerFlagsBuilder.add(swiftModulePath);
                }
            }
        }

        // TODO(Task #3772930): Go through all dependencies of the rule
        // and add any shell script rules here
        ImmutableList.Builder<TargetNode<?>> preScriptPhasesBuilder = ImmutableList.builder();
        ImmutableList.Builder<TargetNode<?>> postScriptPhasesBuilder = ImmutableList.builder();
        if (bundle.isPresent() && targetNode != bundle.get() && isFocusedOnTarget) {
            collectBuildScriptDependencies(targetGraph.getAll(bundle.get().getDeclaredDeps()),
                    preScriptPhasesBuilder, postScriptPhasesBuilder);
        }
        collectBuildScriptDependencies(targetGraph.getAll(targetNode.getDeclaredDeps()), preScriptPhasesBuilder,
                postScriptPhasesBuilder);
        if (isFocusedOnTarget) {
            ImmutableList<TargetNode<?>> preScriptPhases = preScriptPhasesBuilder.build();
            ImmutableList<TargetNode<?>> postScriptPhases = postScriptPhasesBuilder.build();

            mutator.setPreBuildRunScriptPhasesFromTargetNodes(preScriptPhases,
                    actionGraphBuilderForNode::apply);
            if (copyFilesPhases.isPresent()) {
                mutator.setCopyFilesPhases(copyFilesPhases.get());
            }
            mutator.setPostBuildRunScriptPhasesFromTargetNodes(postScriptPhases,
                    actionGraphBuilderForNode::apply);

            ImmutableList<TargetNode<?>> scriptPhases = Stream
                    .concat(preScriptPhases.stream(), postScriptPhases.stream())
                    .collect(ImmutableList.toImmutableList());
            mutator.collectFilesToCopyInXcode(filesToCopyInXcodeBuilder, scriptPhases, projectCell,
                    actionGraphBuilderForNode::apply);
        }
    }

    NewNativeTargetProjectMutator.Result targetBuilderResult = mutator.buildTargetAndAddToProject(project,
            isFocusedOnTarget);
    PBXNativeTarget target = targetBuilderResult.target;
    Optional<PBXGroup> targetGroup = targetBuilderResult.targetGroup;

    extraSettingsBuilder.putAll(swiftDepsSettingsBuilder.build());

    setAppIconSettings(recursiveAssetCatalogs, directAssetCatalogs, buildTarget, defaultSettingsBuilder);
    setLaunchImageSettings(recursiveAssetCatalogs, directAssetCatalogs, buildTarget, defaultSettingsBuilder);

    ImmutableSortedMap<Path, SourcePath> publicCxxHeaders = getPublicCxxHeaders(targetNode);
    if (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();
    }

    if (!options.shouldGenerateHeaderSymlinkTreesOnly()) {
        if (isFocusedOnTarget) {
            SourceTreePath buckFilePath = new SourceTreePath(PBXReference.SourceTree.SOURCE_ROOT,
                    pathRelativizer.outputPathToBuildTargetPath(buildTarget).resolve(buildFileName),
                    Optional.empty());
            PBXFileReference buckReference = targetGroup.get()
                    .getOrCreateFileReferenceBySourceTreePath(buckFilePath);
            buckReference.setExplicitFileType(Optional.of("text.script.python"));
        }

        // 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() && isFocusedOnTarget) {
            collectProjectTargetWatchDependencies(targetNode.getBuildTarget().getFlavorPostfix(), target,
                    targetGraph.getAll(bundle.get().getExtraDeps()));
        }

        // -- configurations
        extraSettingsBuilder.put("TARGET_NAME", buildTargetName).put("SRCROOT",
                pathRelativizer.outputPathToBuildTargetPath(buildTarget).toString());
        if (productType == ProductTypes.UI_TEST && isFocusedOnTarget) {
            if (bundleLoaderNode.isPresent()) {
                BuildTarget testTarget = bundleLoaderNode.get().getBuildTarget();
                extraSettingsBuilder.put("TEST_TARGET_NAME", getXcodeTargetName(testTarget));
                addPBXTargetDependency(target, 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() && isFocusedOnTarget) {
            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)");

            addPBXTargetDependency(target, 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", getModuleName(targetNode)));

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

            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");

        defaultSettingsBuilder.put("REPO_ROOT",
                projectFilesystem.getRootPath().toAbsolutePath().normalize().toString());
        if (hasSwiftVersionArg && containsSwiftCode && isFocusedOnTarget) {
            // 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 = getDerivedSourcesDirectoryForBuildTarget(buildTarget, projectFilesystem);
            Path derivedSourceDirRelativeToProjectRoot = pathRelativizer
                    .outputDirToRootRelative(derivedSourcesDir);

            defaultSettingsBuilder.put("DERIVED_FILE_DIR", derivedSourceDirRelativeToProjectRoot.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");
        }

        if (isFocusedOnTarget) {
            ImmutableSet<Path> recursiveHeaderSearchPaths = collectRecursiveHeaderSearchPaths(targetNode);
            ImmutableSet<Path> headerMapBases = collectRecursiveHeaderMapBases(targetNode);

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

            ImmutableList.Builder<String> targetSpecificSwiftFlags = ImmutableList.builder();
            Optional<TargetNode<SwiftCommonArg>> swiftTargetNode = TargetNodes.castArg(targetNode,
                    SwiftCommonArg.class);
            targetSpecificSwiftFlags.addAll(swiftTargetNode.map(
                    x -> convertStringWithMacros(targetNode, x.getConstructorArg().getSwiftCompilerFlags()))
                    .orElse(ImmutableList.of()));

            if (containsSwiftCode && isModularAppleLibrary && publicCxxHeaders.size() > 0) {
                targetSpecificSwiftFlags.addAll(collectModularTargetSpecificSwiftFlags(targetNode));
            }

            ImmutableList<String> testingOverlay = getFlagsForExcludesForModulesUnderTests(targetNode);
            Iterable<String> otherSwiftFlags = Iterables.concat(
                    swiftBuckConfig.getCompilerFlags().orElse(DEFAULT_SWIFTFLAGS),
                    targetSpecificSwiftFlags.build());

            Iterable<String> otherCFlags = ImmutableList.<String>builder()
                    .addAll(cxxBuckConfig.getCflags().orElse(DEFAULT_CFLAGS))
                    .addAll(cxxBuckConfig.getCppflags().orElse(DEFAULT_CPPFLAGS))
                    .addAll(convertStringWithMacros(targetNode,
                            collectRecursiveExportedPreprocessorFlags(targetNode)))
                    .addAll(convertStringWithMacros(targetNode,
                            targetNode.getConstructorArg().getCompilerFlags()))
                    .addAll(convertStringWithMacros(targetNode,
                            targetNode.getConstructorArg().getPreprocessorFlags()))
                    .addAll(convertStringWithMacros(targetNode,
                            collectRecursiveSystemPreprocessorFlags(targetNode)))
                    .addAll(testingOverlay).build();
            Iterable<String> otherCxxFlags = ImmutableList.<String>builder()
                    .addAll(cxxBuckConfig.getCxxflags().orElse(DEFAULT_CXXFLAGS))
                    .addAll(cxxBuckConfig.getCxxppflags().orElse(DEFAULT_CXXPPFLAGS))
                    .addAll(convertStringWithMacros(targetNode,
                            collectRecursiveExportedPreprocessorFlags(targetNode)))
                    .addAll(convertStringWithMacros(targetNode,
                            targetNode.getConstructorArg().getCompilerFlags()))
                    .addAll(convertStringWithMacros(targetNode,
                            targetNode.getConstructorArg().getPreprocessorFlags()))
                    .addAll(convertStringWithMacros(targetNode,
                            collectRecursiveSystemPreprocessorFlags(targetNode)))
                    .addAll(testingOverlay).build();

            appendConfigsBuilder
                    .put("OTHER_SWIFT_FLAGS",
                            Streams.stream(otherSwiftFlags).map(Escaper.BASH_ESCAPER)
                                    .collect(Collectors.joining(" ")))
                    .put("OTHER_CFLAGS",
                            Streams.stream(otherCFlags).map(Escaper.BASH_ESCAPER)
                                    .collect(Collectors.joining(" ")))
                    .put("OTHER_CPLUSPLUSFLAGS", Streams.stream(otherCxxFlags).map(Escaper.BASH_ESCAPER)
                            .collect(Collectors.joining(" ")));

            Iterable<String> otherLdFlags = ImmutableList.<String>builder()
                    .addAll(cxxBuckConfig.getLdflags().orElse(DEFAULT_LDFLAGS))
                    .addAll(appleConfig.linkAllObjC() ? ImmutableList.of("-ObjC") : ImmutableList.of())
                    .addAll(convertStringWithMacros(targetNode,
                            Iterables.concat(targetNode.getConstructorArg().getLinkerFlags(),
                                    collectRecursiveExportedLinkerFlags(targetNode))))
                    .addAll(swiftDebugLinkerFlagsBuilder.build()).build();

            updateOtherLinkerFlagsForOptions(targetNode, bundleLoaderNode, appendConfigsBuilder, otherLdFlags);

            ImmutableMultimap<String, ImmutableList<String>> platformFlags = convertPlatformFlags(targetNode,
                    Iterables.concat(
                            ImmutableList.of(targetNode.getConstructorArg().getPlatformCompilerFlags()),
                            ImmutableList.of(targetNode.getConstructorArg().getPlatformPreprocessorFlags()),
                            collectRecursiveExportedPlatformPreprocessorFlags(targetNode)));
            for (String platform : platformFlags.keySet()) {
                appendConfigsBuilder.put(generateConfigKey("OTHER_CFLAGS", platform),
                        Streams.stream(Iterables.transform(
                                Iterables.concat(otherCFlags, Iterables.concat(platformFlags.get(platform))),
                                Escaper.BASH_ESCAPER::apply)).collect(
                                        Collectors.joining(" ")))
                        .put(generateConfigKey("OTHER_CPLUSPLUSFLAGS", platform),
                                Streams.stream(Iterables.transform(
                                        Iterables.concat(otherCxxFlags,
                                                Iterables.concat(platformFlags.get(platform))),
                                        Escaper.BASH_ESCAPER::apply)).collect(Collectors.joining(" ")));
            }

            ImmutableMultimap<String, ImmutableList<String>> platformLinkerFlags = convertPlatformFlags(
                    targetNode,
                    Iterables.concat(ImmutableList.of(targetNode.getConstructorArg().getPlatformLinkerFlags()),
                            collectRecursiveExportedPlatformLinkerFlags(targetNode)));
            for (String platform : platformLinkerFlags.keySet()) {
                appendConfigsBuilder
                        .put(generateConfigKey("OTHER_LDFLAGS", platform),
                                Streams.stream(
                                        Iterables
                                                .transform(
                                                        Iterables.concat(otherLdFlags,
                                                                Iterables.concat(
                                                                        platformLinkerFlags.get(platform))),
                                                        Escaper.BASH_ESCAPER::apply))
                                        .collect(Collectors.joining(" ")));
            }

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

            Optional<ImmutableSortedMap<String, ImmutableMap<String, String>>> configs = getXcodeBuildConfigurationsForTargetNode(
                    targetNode);
            setTargetBuildConfigurations(buildTarget, target, project.getMainGroup(), configs.get(),
                    getTargetCxxBuildConfigurationForTargetNode(targetNode, appendedConfig),
                    extraSettingsBuilder.build(), defaultSettingsBuilder.build(), appendedConfig);
        }
    }

    Optional<String> moduleName = isModularAppleLibrary ? Optional.of(getModuleName(targetNode))
            : Optional.empty();
    // -- phases
    createHeaderSymlinkTree(publicCxxHeaders, getSwiftPublicHeaderMapEntriesForTarget(targetNode), moduleName,
            getPathToHeaderSymlinkTree(targetNode, HeaderVisibility.PUBLIC),
            arg.getXcodePublicHeadersSymlinks().orElse(cxxBuckConfig.getPublicHeadersSymlinksEnabled())
                    || !options.shouldUseHeaderMaps() || isModularAppleLibrary,
            !shouldMergeHeaderMaps(), options.shouldGenerateMissingUmbrellaHeader());
    if (isFocusedOnTarget) {
        createHeaderSymlinkTree(getPrivateCxxHeaders(targetNode), ImmutableMap.of(), // private interfaces never have a modulemap
                Optional.empty(), getPathToHeaderSymlinkTree(targetNode, HeaderVisibility.PRIVATE),
                arg.getXcodePrivateHeadersSymlinks().orElse(cxxBuckConfig.getPrivateHeadersSymlinksEnabled())
                        || !options.shouldUseHeaderMaps(),
                options.shouldUseHeaderMaps(), options.shouldGenerateMissingUmbrellaHeader());
    }

    Optional<TargetNode<AppleNativeTargetDescriptionArg>> appleTargetNode = TargetNodes.castArg(targetNode,
            AppleNativeTargetDescriptionArg.class);
    if (appleTargetNode.isPresent() && isFocusedOnTarget && !options.shouldGenerateHeaderSymlinkTreesOnly()) {
        // Use Core Data models from immediate dependencies only.
        addCoreDataModelsIntoTarget(appleTargetNode.get(), targetGroup.get());
        addSceneKitAssetsIntoTarget(appleTargetNode.get(), targetGroup.get());
    }

    if (bundle.isPresent() && isFocusedOnTarget && !options.shouldGenerateHeaderSymlinkTreesOnly()) {
        addEntitlementsPlistIntoTarget(bundle.get(), targetGroup.get());
    }

    return target;
}