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