in src/com/facebook/buck/features/haskell/HaskellLibraryDescription.java [567:870]
public BuildRule createBuildRule(
BuildRuleCreationContextWithTargetGraph context,
BuildTarget buildTarget,
BuildRuleParams params,
HaskellLibraryDescriptionArg args) {
ActionGraphBuilder graphBuilder = context.getActionGraphBuilder();
HaskellPlatformsProvider haskellPlatformsProvider =
getHaskellPlatformsProvider(buildTarget.getTargetConfiguration());
ProjectFilesystem projectFilesystem = context.getProjectFilesystem();
FlavorDomain<HaskellPlatform> platforms = haskellPlatformsProvider.getHaskellPlatforms();
CxxDeps allDeps =
CxxDeps.builder().addDeps(args.getDeps()).addPlatformDeps(args.getPlatformDeps()).build();
// 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, Type>> type = LIBRARY_TYPE.getFlavorAndValue(buildTarget);
HaskellPlatform platform = getPlatform(haskellPlatformsProvider, buildTarget, args);
if (type.isPresent()) {
// Get the base build, without any flavors referring to the library type or platform.
BuildTarget baseTarget =
buildTarget.withoutFlavors(Sets.union(Type.FLAVOR_VALUES, platforms.getFlavors()));
ImmutableSet<BuildRule> deps = allDeps.get(graphBuilder, platform.getCxxPlatform());
switch (type.get().getValue()) {
case PACKAGE_SHARED:
case PACKAGE_STATIC:
case PACKAGE_STATIC_PIC:
Linker.LinkableDepType depType;
if (type.get().getValue().equals(Type.PACKAGE_SHARED)) {
depType = Linker.LinkableDepType.SHARED;
} else if (type.get().getValue().equals(Type.PACKAGE_STATIC)) {
depType = Linker.LinkableDepType.STATIC;
} else {
depType = Linker.LinkableDepType.STATIC_PIC;
}
return requirePackage(
baseTarget,
projectFilesystem,
params,
graphBuilder,
haskellPlatformsProvider,
platform,
args,
deps,
depType,
args.isEnableProfiling());
case SHARED:
return requireSharedLibrary(
baseTarget,
projectFilesystem,
params,
graphBuilder,
haskellPlatformsProvider,
platform,
args,
deps,
args.isEnableProfiling());
case STATIC_PIC:
case STATIC:
return requireStaticLibrary(
baseTarget,
projectFilesystem,
params,
graphBuilder,
haskellPlatformsProvider,
platform,
args,
deps,
type.get().getValue() == Type.STATIC
? Linker.LinkableDepType.STATIC
: Linker.LinkableDepType.STATIC_PIC,
args.isEnableProfiling());
case HADDOCK:
return requireHaddockLibrary(
baseTarget, projectFilesystem, params, graphBuilder, platform, args);
case GHCI:
return HaskellDescriptionUtils.requireGhciRule(
// The GHCi rule is a user-facing "deployable" rule, rather than a factory rule, so
// make sure to use the original build target when generating it.
buildTarget,
projectFilesystem,
params,
context.getCellPathResolver(),
graphBuilder,
platform,
cxxBuckConfig,
args.getDeps(),
args.getPlatformDeps(),
args.getSrcs(),
args.getGhciPreloadDeps(),
args.getGhciPlatformPreloadDeps(),
args.getCompilerFlags(),
Optional.empty(),
Optional.empty(),
ImmutableList.of(),
args.isEnableProfiling());
}
throw new IllegalStateException(
String.format("%s: unexpected type `%s`", buildTarget, type.get().getValue()));
}
return new HaskellLibrary(buildTarget, projectFilesystem, params) {
private final PlatformLockedNativeLinkableGroup.Cache linkableCache =
LegacyNativeLinkableGroup.getNativeLinkableCache(this);
@Override
public Iterable<BuildRule> getCompileDeps(HaskellPlatform platform) {
return RichStream.from(allDeps.get(graphBuilder, platform.getCxxPlatform()))
.filter(dep -> dep instanceof HaskellCompileDep || dep instanceof CxxPreprocessorDep)
.toImmutableList();
}
@Override
public HaskellCompileInput getCompileInput(
HaskellPlatform platform, Linker.LinkableDepType depType, boolean hsProfile) {
HaskellPackageRule rule =
requirePackage(
getBaseBuildTarget(haskellPlatformsProvider, getBuildTarget()),
projectFilesystem,
params,
graphBuilder,
haskellPlatformsProvider,
platform,
args,
allDeps.get(graphBuilder, platform.getCxxPlatform()),
depType,
hsProfile);
return ImmutableHaskellCompileInput.of(ImmutableList.of(), rule.getPackage());
}
@Override
public HaskellHaddockInput getHaddockInput(HaskellPlatform platform) {
BuildTarget target =
buildTarget.withAppendedFlavors(Type.HADDOCK.getFlavor(), platform.getFlavor());
HaskellHaddockLibRule rule = (HaskellHaddockLibRule) graphBuilder.requireRule(target);
return ImmutableHaskellHaddockInput.of(rule.getInterfaces(), rule.getHaddockOutputDirs());
}
@Override
public CxxPreprocessorInput getCxxPreprocessorInput(
CxxPlatform cxxPlatform, ActionGraphBuilder graphBuilder) {
CxxPreprocessorInput.Builder builder = CxxPreprocessorInput.builder();
Optional<Linker.LinkableDepType> depType =
platforms.getValue(cxxPlatform.getFlavor()).getLinkStyleForStubHeader();
if (depType.isPresent()) {
HaskellCompileRule compileRule =
requireCompileRule(
buildTarget,
projectFilesystem,
params,
graphBuilder,
platforms.getValue(cxxPlatform.getFlavor()),
args,
allDeps.get(graphBuilder, cxxPlatform),
depType.get(),
args.isEnableProfiling());
builder.addIncludes(
CxxHeadersDir.of(CxxPreprocessables.IncludeType.SYSTEM, compileRule.getStubsDir()));
}
return builder.build();
}
@Override
public Iterable<CxxPreprocessorDep> getCxxPreprocessorDeps(
CxxPlatform cxxPlatform, BuildRuleResolver ruleResolver) {
return RichStream.from(allDeps.get(graphBuilder, cxxPlatform))
.filter(CxxPreprocessorDep.class)
.toImmutableList();
}
@Override
public ImmutableMap<BuildTarget, CxxPreprocessorInput> getTransitiveCxxPreprocessorInput(
CxxPlatform cxxPlatform, ActionGraphBuilder graphBuilder) {
return transitiveCxxPreprocessorInputCache.getUnchecked(cxxPlatform, graphBuilder);
}
@Override
public Iterable<? extends NativeLinkableGroup> getNativeLinkableDeps(
BuildRuleResolver ruleResolver) {
return ImmutableList.of();
}
@Override
public Optional<Iterable<? extends NativeLinkableGroup>> getOmnibusPassthroughDeps(
CxxPlatform platform, ActionGraphBuilder graphBuilder) {
ImmutableSet<? extends NativeLinkable> platformDeps =
ImmutableSet.copyOf(
getNativeLinkable(platform, graphBuilder)
.getNativeLinkableExportedDeps(graphBuilder));
Iterable<? extends NativeLinkableGroup> allDeps =
getNativeLinkableExportedDeps(graphBuilder);
return Optional.of(
Iterables.filter(
allDeps, g -> platformDeps.contains(g.getNativeLinkable(platform, graphBuilder))));
}
private final TransitiveCxxPreprocessorInputCache transitiveCxxPreprocessorInputCache =
new TransitiveCxxPreprocessorInputCache(this);
@Override
public Iterable<? extends NativeLinkableGroup> getNativeLinkableExportedDepsForPlatform(
CxxPlatform cxxPlatform, ActionGraphBuilder graphBuilder) {
return RichStream.from(allDeps.get(graphBuilder, cxxPlatform))
.filter(NativeLinkableGroup.class)
.toImmutableList();
}
@Override
public Iterable<? extends NativeLinkableGroup> getNativeLinkableExportedDeps(
BuildRuleResolver ruleResolver) {
return RichStream.from(allDeps.getForAllPlatforms(graphBuilder))
.filter(NativeLinkableGroup.class)
.toImmutableList();
}
@Override
public NativeLinkableInput getNativeLinkableInput(
CxxPlatform cxxPlatform,
Linker.LinkableDepType type,
boolean forceLinkWhole,
ActionGraphBuilder graphBuilder,
TargetConfiguration targetConfiguration) {
Iterable<Arg> linkArgs;
switch (type) {
case STATIC:
case STATIC_PIC:
Archive archive =
requireStaticLibrary(
getBaseBuildTarget(haskellPlatformsProvider, getBuildTarget()),
projectFilesystem,
params,
graphBuilder,
haskellPlatformsProvider,
platforms.getValue(cxxPlatform.getFlavor()),
args,
allDeps.get(graphBuilder, cxxPlatform),
type,
args.isEnableProfiling());
linkArgs =
args.getLinkWhole() || forceLinkWhole
? cxxPlatform
.getLd()
.resolve(graphBuilder, targetConfiguration)
.linkWhole(archive.toArg(), graphBuilder.getSourcePathResolver())
: ImmutableList.of(archive.toArg());
break;
case SHARED:
BuildRule rule =
requireSharedLibrary(
getBaseBuildTarget(haskellPlatformsProvider, getBuildTarget()),
projectFilesystem,
params,
graphBuilder,
haskellPlatformsProvider,
platforms.getValue(cxxPlatform.getFlavor()),
args,
allDeps.get(graphBuilder, cxxPlatform),
args.isEnableProfiling());
linkArgs = ImmutableList.of(SourcePathArg.of(rule.getSourcePathToOutput()));
break;
default:
throw new IllegalStateException();
}
return NativeLinkableInput.builder().addAllArgs(linkArgs).build();
}
@Override
public Linkage getPreferredLinkage(CxxPlatform cxxPlatform) {
return args.getPreferredLinkage();
}
@Override
public ImmutableMap<String, SourcePath> getSharedLibraries(
CxxPlatform cxxPlatform, ActionGraphBuilder graphBuilder) {
ImmutableMap.Builder<String, SourcePath> libs = ImmutableMap.builder();
String sharedLibrarySoname =
CxxDescriptionEnhancer.getSharedLibrarySoname(
Optional.empty(), getBuildTarget(), cxxPlatform, projectFilesystem);
BuildRule sharedLibraryBuildRule =
requireSharedLibrary(
getBaseBuildTarget(haskellPlatformsProvider, getBuildTarget()),
projectFilesystem,
params,
graphBuilder,
haskellPlatformsProvider,
platforms.getValue(cxxPlatform.getFlavor()),
args,
allDeps.get(graphBuilder, cxxPlatform),
args.isEnableProfiling());
libs.put(sharedLibrarySoname, sharedLibraryBuildRule.getSourcePathToOutput());
return libs.build();
}
@Override
public PlatformLockedNativeLinkableGroup.Cache getNativeLinkableCompatibilityCache() {
return linkableCache;
}
};
}