in src/com/facebook/buck/cxx/CxxLibraryFactory.java [87:369]
public BuildRule createBuildRule(
TargetGraph targetGraph,
BuildTarget buildTarget,
ProjectFilesystem projectFilesystem,
BuildRuleParams metadataRuleParams,
ActionGraphBuilder graphBuilder,
CellPathResolver cellRoots,
CxxLibraryDescriptionArg args,
Optional<Linker.LinkableDepType> linkableDepType,
Optional<SourcePath> bundleLoader,
ImmutableSet<BuildTarget> blacklist,
ImmutableSortedSet<BuildTarget> extraDeps,
CxxLibraryDescription.TransitiveCxxPreprocessorInputFunction
transitiveCxxPreprocessorInputFunction,
CxxLibraryDescriptionDelegate delegate) {
CxxPlatformsProvider cxxPlatformsProvider =
getCxxPlatformsProvider(buildTarget.getTargetConfiguration());
Flavor defaultCxxFlavor = cxxPlatformsProvider.getDefaultUnresolvedCxxPlatform().getFlavor();
// See if we're building a particular "type" and "platform" of this library, and if so, extract
// them from the flavors attached to the build target.
Optional<Map.Entry<Flavor, CxxLibraryDescription.Type>> type =
CxxLibraryDescription.getLibType(buildTarget);
Optional<CxxPlatform> platform =
cxxPlatformsProvider
.getUnresolvedCxxPlatforms()
.getValue(buildTarget)
.map(
unresolved ->
unresolved.resolve(graphBuilder, buildTarget.getTargetConfiguration()));
CxxDeps cxxDeps = CxxDeps.builder().addDeps(args.getCxxDeps()).addDeps(extraDeps).build();
Supplier<CxxPlatform> cxxPlatformOrDefaultSupplier =
() ->
platform.orElse(
cxxPlatformsProvider
.getUnresolvedCxxPlatforms()
.getValue(args.getDefaultPlatform().orElse(defaultCxxFlavor))
.resolve(graphBuilder, buildTarget.getTargetConfiguration()));
if (buildTarget.getFlavors().contains(CxxCompilationDatabase.COMPILATION_DATABASE)) {
CxxPlatform cxxPlatformOrDefault = cxxPlatformOrDefaultSupplier.get();
Optional<CxxLibraryDescriptionDelegate.ConfiguredDelegate> configuredDelegate =
delegate.requireDelegate(buildTarget, cxxPlatformOrDefault, graphBuilder);
// XXX: This needs bundleLoader for tests..
// TODO(T21900763): We should be using `requireObjects` instead but those would not
// necessarily be `CxxPreprocessAndCompile` rules (e.g., Swift in `apple_library`).
ImmutableMap<CxxPreprocessAndCompile, SourcePath> objects =
requireCxxObjects(
buildTarget.withoutFlavors(CxxCompilationDatabase.COMPILATION_DATABASE),
projectFilesystem,
graphBuilder,
cellRoots,
cxxBuckConfig,
cxxPlatformOrDefault,
cxxPlatformOrDefault.getPicTypeForSharedLinking(),
args,
cxxDeps.get(graphBuilder, cxxPlatformOrDefault),
transitiveCxxPreprocessorInputFunction,
configuredDelegate);
return CxxCompilationDatabase.createCompilationDatabase(
buildTarget, projectFilesystem, objects.keySet());
} else if (buildTarget
.getFlavors()
.contains(CxxCompilationDatabase.UBER_COMPILATION_DATABASE)) {
return CxxDescriptionEnhancer.createUberCompilationDatabase(
platform.isPresent()
? buildTarget
: buildTarget.withAppendedFlavors(args.getDefaultPlatform().orElse(defaultCxxFlavor)),
projectFilesystem,
graphBuilder);
} else if (CxxInferEnhancer.INFER_FLAVOR_DOMAIN.containsAnyOf(buildTarget.getFlavors())) {
return CxxInferEnhancer.requireInferRule(
buildTarget,
projectFilesystem,
graphBuilder,
cellRoots,
cxxBuckConfig,
cxxPlatformOrDefaultSupplier.get(),
args,
inferBuckConfig);
} else if (type.isPresent() && !platform.isPresent()) {
BuildTarget untypedBuildTarget = CxxLibraryDescription.getUntypedBuildTarget(buildTarget);
switch (type.get().getValue()) {
case EXPORTED_HEADERS:
Optional<HeaderMode> mode = CxxLibraryDescription.HEADER_MODE.getValue(buildTarget);
if (mode.isPresent()) {
return createExportedHeaderSymlinkTreeBuildRule(
untypedBuildTarget, projectFilesystem, graphBuilder, mode.get(), args);
}
break;
// $CASES-OMITTED$
default:
}
} else if (type.isPresent() && platform.isPresent()) {
Optional<CxxLibraryDescriptionDelegate.ConfiguredDelegate> configuredDelegate =
delegate.requireDelegate(buildTarget, platform.get(), graphBuilder);
// If we *are* building a specific type of this lib, call into the type specific
// rule builder methods.
BuildTarget untypedBuildTarget = CxxLibraryDescription.getUntypedBuildTarget(buildTarget);
switch (type.get().getValue()) {
case HEADERS:
return createHeaderSymlinkTreeBuildRule(
untypedBuildTarget, projectFilesystem, graphBuilder, platform.get(), args);
case EXPORTED_HEADERS:
return createExportedPlatformHeaderSymlinkTreeBuildRule(
untypedBuildTarget, projectFilesystem, graphBuilder, platform.get(), args);
case SHARED:
return createSharedLibraryBuildRule(
untypedBuildTarget,
projectFilesystem,
graphBuilder,
cellRoots,
cxxBuckConfig,
platform.get(),
args,
cxxDeps.get(graphBuilder, platform.get()),
Linker.LinkType.SHARED,
linkableDepType.orElse(Linker.LinkableDepType.SHARED),
makeLinkableListFilter(args, targetGraph),
Optional.empty(),
blacklist,
transitiveCxxPreprocessorInputFunction,
configuredDelegate);
case SHARED_INTERFACE:
return createSharedLibraryInterface(
untypedBuildTarget,
projectFilesystem,
graphBuilder,
platform.get(),
cxxBuckConfig.isIndependentSharedLibraryInterfaces());
case MACH_O_BUNDLE:
return createSharedLibraryBuildRule(
untypedBuildTarget,
projectFilesystem,
graphBuilder,
cellRoots,
cxxBuckConfig,
platform.get(),
args,
cxxDeps.get(graphBuilder, platform.get()),
Linker.LinkType.MACH_O_BUNDLE,
linkableDepType.orElse(Linker.LinkableDepType.SHARED),
makeLinkableListFilter(args, targetGraph),
bundleLoader,
blacklist,
transitiveCxxPreprocessorInputFunction,
configuredDelegate);
case STATIC:
return createStaticLibraryBuildRule(
untypedBuildTarget,
projectFilesystem,
graphBuilder,
cellRoots,
cxxBuckConfig,
platform.get(),
args,
cxxDeps.get(graphBuilder, platform.get()),
PicType.PDC,
transitiveCxxPreprocessorInputFunction,
configuredDelegate);
case STATIC_PIC:
return createStaticLibraryBuildRule(
untypedBuildTarget,
projectFilesystem,
graphBuilder,
cellRoots,
cxxBuckConfig,
platform.get(),
args,
cxxDeps.get(graphBuilder, platform.get()),
PicType.PIC,
transitiveCxxPreprocessorInputFunction,
configuredDelegate);
}
throw new RuntimeException("unhandled library build type");
}
boolean hasObjectsForAnyPlatform = !args.getSrcs().isEmpty();
Predicate<CxxPlatform> hasObjects;
if (hasObjectsForAnyPlatform) {
hasObjects = x -> true;
} else {
hasObjects =
input ->
!args.getPlatformSrcs().getMatchingValues(input.getFlavor().toString()).isEmpty();
}
// Otherwise, we return the generic placeholder of this library, that dependents can use
// get the real build rules via querying the action graph.
return new CxxLibraryGroup(
buildTarget,
projectFilesystem,
metadataRuleParams,
args.getPrivateCxxDeps(),
args.getExportedCxxDeps(),
hasObjects.negate(),
(input, graphBuilderInner) -> {
ImmutableList<Arg> delegateExportedLinkerFlags =
delegate
.requireDelegate(buildTarget, input, graphBuilderInner)
.map(d -> d.getAdditionalExportedLinkerFlags())
.orElse(ImmutableList.of());
ImmutableList<StringWithMacros> flags =
CxxFlags.getFlagsWithMacrosWithPlatformMacroExpansion(
args.getExportedLinkerFlags(), args.getExportedPlatformLinkerFlags(), input);
return RichStream.from(flags)
.map(
CxxDescriptionEnhancer.getStringWithMacrosArgsConverter(
buildTarget, cellRoots, graphBuilderInner, input)
::convert)
.concat(RichStream.from(delegateExportedLinkerFlags))
.toImmutableList();
},
(input, graphBuilderInner) -> {
ImmutableList<Arg> delegatePostExportedLinkerFlags = ImmutableList.of();
ImmutableList<StringWithMacros> flags =
CxxFlags.getFlagsWithMacrosWithPlatformMacroExpansion(
args.getExportedPostLinkerFlags(),
args.getExportedPostPlatformLinkerFlags(),
input);
return RichStream.from(flags)
.map(
CxxDescriptionEnhancer.getStringWithMacrosArgsConverter(
buildTarget, cellRoots, graphBuilderInner, input)
::convert)
.concat(RichStream.from(delegatePostExportedLinkerFlags))
.toImmutableList();
},
(cxxPlatform, ruleResolverInner, pathResolverInner, includePrivateLinkerFlags) ->
getSharedLibraryNativeLinkTargetInput(
buildTarget,
projectFilesystem,
ruleResolverInner,
cellRoots,
cxxBuckConfig,
cxxPlatform,
args,
cxxDeps.get(ruleResolverInner, cxxPlatform),
includePrivateLinkerFlags
? CxxFlags.getFlagsWithMacrosWithPlatformMacroExpansion(
args.getLinkerFlags(), args.getPlatformLinkerFlags(), cxxPlatform)
: ImmutableList.of(),
CxxFlags.getFlagsWithMacrosWithPlatformMacroExpansion(
args.getExportedLinkerFlags(),
args.getExportedPlatformLinkerFlags(),
cxxPlatform),
includePrivateLinkerFlags
? CxxFlags.getFlagsWithMacrosWithPlatformMacroExpansion(
args.getPostLinkerFlags(), args.getPostPlatformLinkerFlags(), cxxPlatform)
: ImmutableList.of(),
CxxFlags.getFlagsWithMacrosWithPlatformMacroExpansion(
args.getExportedPostLinkerFlags(),
args.getExportedPostPlatformLinkerFlags(),
cxxPlatform),
args.getFrameworks(),
args.getLibraries(),
transitiveCxxPreprocessorInputFunction,
delegate.requireDelegate(buildTarget, cxxPlatform, ruleResolverInner)),
args.getSupportedPlatformsRegex(),
args.getFrameworks(),
args.getLibraries(),
args.getForceStatic().orElse(false)
? NativeLinkableGroup.Linkage.STATIC
: args.getPreferredLinkage().orElse(NativeLinkableGroup.Linkage.ANY),
args.getLinkWhole().orElse(false),
args.getSoname(),
args.getTests(),
args.getCanBeAsset().orElse(false),
!buildTarget
.getFlavors()
.contains(CxxDescriptionEnhancer.EXPORTED_HEADER_SYMLINK_TREE_FLAVOR),
args.isReexportAllHeaderDependencies()
.orElse(cxxBuckConfig.getDefaultReexportAllHeaderDependencies()),
args.getSupportsMergedLinking().orElse(true),
delegate);
}