public static CxxLinkAndCompileRules createBuildRuleForCxxThinLtoBinary()

in src/com/facebook/buck/cxx/CxxDescriptionEnhancer.java [737:1004]


  public static CxxLinkAndCompileRules createBuildRuleForCxxThinLtoBinary(
      BuildTarget target,
      ProjectFilesystem projectFilesystem,
      ActionGraphBuilder graphBuilder,
      CellPathResolver cellRoots,
      CxxBuckConfig cxxBuckConfig,
      CxxPlatform cxxPlatform,
      CommonArg args,
      ImmutableSet<BuildTarget> extraDeps,
      Optional<StripStyle> stripStyle,
      Optional<LinkerMapMode> flavoredLinkerMapMode) {
    ImmutableMap<String, CxxSource> srcs = parseCxxSources(target, graphBuilder, cxxPlatform, args);
    ImmutableMap<Path, SourcePath> headers =
        parseHeaders(target, graphBuilder, projectFilesystem, Optional.of(cxxPlatform), args);

    // Build the binary deps.
    ImmutableSortedSet.Builder<BuildRule> depsBuilder = ImmutableSortedSet.naturalOrder();
    // Add original declared and extra deps.
    args.getCxxDeps().get(graphBuilder, cxxPlatform).forEach(depsBuilder::add);
    // Add in deps found via deps query.
    ImmutableList<BuildRule> depQueryDeps =
        args.getDepsQuery().map(query -> Objects.requireNonNull(query.getResolvedQuery()))
            .orElse(ImmutableSortedSet.of()).stream()
            .map(graphBuilder::getRule)
            .collect(ImmutableList.toImmutableList());
    depsBuilder.addAll(depQueryDeps);
    // Add any extra deps passed in.
    extraDeps.stream().map(graphBuilder::getRule).forEach(depsBuilder::add);
    ImmutableSortedSet<BuildRule> deps = depsBuilder.build();

    CxxLinkOptions linkOptions =
        CxxLinkOptions.of(
            false, false
            );

    ImmutableMap<CxxPreprocessAndCompile, SourcePath> objects =
        createCompileRulesForCxxBinary(
            target,
            projectFilesystem,
            graphBuilder,
            cellRoots,
            cxxBuckConfig,
            cxxPlatform,
            srcs,
            headers,
            deps,
            args.getLinkStyle().orElse(Linker.LinkableDepType.STATIC),
            linkOptions,
            args.getPreprocessorFlags(),
            args.getPlatformPreprocessorFlags(),
            args.getLangPreprocessorFlags(),
            args.getLangPlatformPreprocessorFlags(),
            args.getFrameworks(),
            args.getCompilerFlags(),
            args.getLangCompilerFlags(),
            args.getPlatformCompilerFlags(),
            args.getLangPlatformCompilerFlags(),
            args.getPrefixHeader(),
            args.getPrecompiledHeader(),
            args.getRawHeaders(),
            args.getIncludeDirectories());

    BuildTarget thinIndexTarget = target.withAppendedFlavors(CXX_LINK_THININDEX_FLAVOR);
    Path indexOutput =
        getBinaryOutputPath(
            thinIndexTarget, projectFilesystem, Optional.empty(), Optional.of("thinlto.indices"));

    CommandTool.Builder executableBuilder = new CommandTool.Builder();
    Linker linker = cxxPlatform.getLd().resolve(graphBuilder, target.getTargetConfiguration());

    ImmutableList<Arg> indexArgs =
        createLinkArgsForCxxBinary(
            target,
            projectFilesystem,
            graphBuilder,
            cellRoots,
            cxxPlatform,
            objects,
            deps,
            executableBuilder,
            linker,
            args.getLinkStyle().orElse(Linker.LinkableDepType.STATIC),
            indexOutput,
            args.getLinkerFlags(),
            args.getPlatformLinkerFlags());

    CxxThinLTOIndex cxxThinLTOIndex =
        (CxxThinLTOIndex)
            graphBuilder.computeIfAbsent(
                thinIndexTarget,
                ignored ->
                    CxxLinkableEnhancer.createCxxThinLTOIndexBuildRule(
                        cxxBuckConfig,
                        cxxPlatform,
                        projectFilesystem,
                        graphBuilder,
                        thinIndexTarget,
                        indexOutput,
                        args.getLinkStyle().orElse(Linker.LinkableDepType.STATIC),
                        Optional.empty(),
                        RichStream.from(deps)
                            .filter(NativeLinkableGroup.class)
                            .map(g -> g.getNativeLinkable(cxxPlatform, graphBuilder))
                            .toImmutableList(),
                        args.getCxxRuntimeType(),
                        ImmutableSet.of(),
                        args.getLinkDepsQueryWhole()
                            ? RichStream.from(depQueryDeps)
                                .map(BuildRule::getBuildTarget)
                                .toImmutableSet()
                            : ImmutableSet.of(),
                        NativeLinkableInput.builder()
                            .setArgs(indexArgs)
                            .setFrameworks(args.getFrameworks())
                            .setLibraries(args.getLibraries())
                            .build()));

    ImmutableMap.Builder<String, CxxSource> srcObjects = ImmutableMap.builder();
    // We need a map<key, val>.
    // key is the filename of the output thin object file, with the full directory structure
    // of the original input source. The directory structure is required to disambiguate
    // source files with the same name.
    // val is the sourcePath of the output of the compile phase.
    // Example:
    // lib/item.cpp.o -> buck-out/gen/binary/target#flavors-item.cpp.o/item.cpp.o
    objects.entrySet().stream()
        .forEach(
            entry -> {
              final CxxPreprocessAndCompile rule = entry.getKey();
              final SourcePath path = entry.getValue();
              final String filenameWithPath =
                  rule.getSourceInputPath(graphBuilder.getSourcePathResolver());
              final String outputNameWithPath =
                  filenameWithPath + "." + cxxPlatform.getObjectFileExtension();

              Preconditions.checkState(
                  srcs.get(filenameWithPath) != null,
                  "Requesting flags for non existent source file in ThinLTO build");

              srcObjects.put(
                  outputNameWithPath,
                  CxxSource.of(Type.CXX_THINLINK, path, srcs.get(filenameWithPath).getFlags()));
            });

    ImmutableMap<CxxThinLTOOpt, SourcePath> nativeObjects =
        createThinOptRulesForCxxBinary(
            target,
            projectFilesystem,
            graphBuilder,
            cellRoots,
            cxxBuckConfig,
            cxxPlatform,
            srcObjects.build(),
            args.getLinkStyle().orElse(Linker.LinkableDepType.STATIC),
            linkOptions,
            args.getCompilerFlags(),
            args.getLangCompilerFlags(),
            args.getPlatformCompilerFlags(),
            args.getLangPlatformCompilerFlags(),
            args.getPrefixHeader(),
            args.getPrecompiledHeader(),
            cxxThinLTOIndex.getSourcePathToOutput());

    Path linkOutput =
        getBinaryOutputPath(
            flavoredLinkerMapMode.isPresent()
                ? target.withAppendedFlavors(flavoredLinkerMapMode.get().getFlavor())
                : target,
            projectFilesystem,
            cxxPlatform.getBinaryExtension(),
            args.getExecutableName());

    ImmutableList<Arg> linkArgs =
        createLinkArgsForCxxBinary(
            target,
            projectFilesystem,
            graphBuilder,
            cellRoots,
            cxxPlatform,
            nativeObjects,
            deps,
            executableBuilder,
            linker,
            args.getLinkStyle().orElse(Linker.LinkableDepType.STATIC),
            indexOutput,
            args.getLinkerFlags(),
            args.getPlatformLinkerFlags());

    BuildTarget linkRuleTarget = createCxxLinkTarget(target, flavoredLinkerMapMode);

    CxxLink cxxLink =
        (CxxLink)
            graphBuilder.computeIfAbsent(
                linkRuleTarget,
                ignored ->
                    // Generate the final link rule.  We use the top-level target as the link rule's
                    // target, so that it corresponds to the actual binary we build.
                    CxxLinkableEnhancer.createCxxLinkableBuildRule(
                        cxxBuckConfig,
                        cxxPlatform,
                        projectFilesystem,
                        graphBuilder,
                        linkRuleTarget,
                        Linker.LinkType.EXECUTABLE,
                        Optional.empty(),
                        linkOutput,
                        args.getLinkerExtraOutputs(),
                        args.getLinkStyle().orElse(Linker.LinkableDepType.STATIC),
                        Optional.empty(),
                        CxxLinkOptions.of(
                            args.getThinLto(),
                            args.getFatLto()
                            ),
                        RichStream.from(deps)
                            .filter(NativeLinkableGroup.class)
                            .map(g -> g.getNativeLinkable(cxxPlatform, graphBuilder))
                            .toImmutableList(),
                        args.getCxxRuntimeType(),
                        Optional.empty(),
                        ImmutableSet.of(),
                        args.getLinkDepsQueryWhole()
                            ? RichStream.from(depQueryDeps)
                                .map(BuildRule::getBuildTarget)
                                .toImmutableSet()
                            : ImmutableSet.of(),
                        NativeLinkableInput.builder()
                            .setArgs(linkArgs)
                            .setFrameworks(args.getFrameworks())
                            .setLibraries(args.getLibraries())
                            .build(),
                        Optional.empty(),
                        cellRoots));

    BuildRule binaryRuleForExecutable;
    Optional<CxxStrip> cxxStrip = Optional.empty();
    if (stripStyle.isPresent()) {
      BuildTarget cxxTarget = target;
      if (flavoredLinkerMapMode.isPresent()) {
        cxxTarget = cxxTarget.withAppendedFlavors(flavoredLinkerMapMode.get().getFlavor());
      }
      CxxStrip stripRule =
          createCxxStripRule(
              cxxTarget,
              projectFilesystem,
              graphBuilder,
              stripStyle.get(),
              cxxBuckConfig.shouldCacheStrip(),
              cxxLink,
              cxxPlatform,
              args.getExecutableName());
      cxxStrip = Optional.of(stripRule);
      binaryRuleForExecutable = stripRule;
    } else {
      binaryRuleForExecutable = cxxLink;
    }

    SourcePath sourcePathToExecutable = binaryRuleForExecutable.getSourcePathToOutput();

    // Add the output of the link as the lone argument needed to invoke this binary as a tool.
    executableBuilder.addArg(SourcePathArg.of(sourcePathToExecutable));

    return new CxxLinkAndCompileRules(
        cxxLink,
        cxxStrip,
        ImmutableSortedSet.copyOf(objects.keySet()),
        executableBuilder.build(),
        deps);
  }