in src/com/facebook/buck/features/haskell/HaskellDescriptionUtils.java [400:583]
public static HaskellGhciRule requireGhciRule(
BuildTarget buildTarget,
ProjectFilesystem projectFilesystem,
BuildRuleParams params,
CellPathResolver cellPathResolver,
ActionGraphBuilder graphBuilder,
HaskellPlatform platform,
CxxBuckConfig cxxBuckConfig,
ImmutableSortedSet<BuildTarget> argDeps,
PatternMatchedCollection<ImmutableSortedSet<BuildTarget>> argPlatformDeps,
SourceSortedSet argSrcs,
ImmutableSortedSet<BuildTarget> argPreloadDeps,
PatternMatchedCollection<ImmutableSortedSet<BuildTarget>> argPlatformPreloadDeps,
ImmutableList<String> argCompilerFlags,
Optional<BuildTarget> argGhciBinDep,
Optional<SourcePath> argGhciInit,
ImmutableList<SourcePath> argExtraScriptTemplates,
boolean hsProfile) {
ImmutableSet.Builder<BuildRule> depsBuilder = ImmutableSet.builder();
depsBuilder.addAll(
CxxDeps.builder()
.addDeps(argDeps)
.addPlatformDeps(argPlatformDeps)
.build()
.get(graphBuilder, platform.getCxxPlatform()));
ImmutableSet<BuildRule> deps = depsBuilder.build();
ImmutableSet.Builder<BuildRule> preloadDepsBuilder = ImmutableSet.builder();
preloadDepsBuilder.addAll(
CxxDeps.builder()
.addDeps(argPreloadDeps)
.addPlatformDeps(argPlatformPreloadDeps)
.build()
.get(graphBuilder, platform.getCxxPlatform()));
ImmutableSet<BuildRule> preloadDeps = preloadDepsBuilder.build();
// Haskell visitor
ImmutableSet.Builder<HaskellPackage> haskellPackages = ImmutableSet.builder();
ImmutableSet.Builder<HaskellPackage> prebuiltHaskellPackages = ImmutableSet.builder();
ImmutableSet.Builder<HaskellPackage> firstOrderHaskellPackages = ImmutableSet.builder();
AbstractBreadthFirstTraversal<BuildRule> haskellVisitor =
new AbstractBreadthFirstTraversal<BuildRule>(deps) {
@Override
public ImmutableSet<BuildRule> visit(BuildRule rule) {
ImmutableSet.Builder<BuildRule> traverse = ImmutableSet.builder();
if (rule instanceof HaskellLibrary || rule instanceof PrebuiltHaskellLibrary) {
HaskellCompileDep haskellRule = (HaskellCompileDep) rule;
// Always use pic packages so we can use `+RTS -xp -RTS` to load
// the objects anywhere in the address space without the
// limitation of lower 2G address space.
HaskellCompileInput ci =
haskellRule.getCompileInput(
platform, Linker.LinkableDepType.STATIC_PIC, hsProfile);
if (params.getBuildDeps().contains(rule)) {
firstOrderHaskellPackages.add(ci.getPackage());
}
if (rule instanceof HaskellLibrary) {
haskellPackages.add(ci.getPackage());
} else if (rule instanceof PrebuiltHaskellLibrary) {
prebuiltHaskellPackages.add(ci.getPackage());
}
traverse.addAll(haskellRule.getCompileDeps(platform));
}
return traverse.build();
}
};
haskellVisitor.start();
// Build the omnibus composition spec.
HaskellGhciDescription.HaskellGhciOmnibusSpec omnibusSpec =
HaskellGhciDescription.getOmnibusSpec(
buildTarget,
graphBuilder,
FluentIterable.from(
NativeLinkableGroups.getNativeLinkableRoots(
RichStream.from(deps)
.filter(NativeLinkableGroup.class)
.toImmutableList(),
n -> {
if (n instanceof HaskellLibrary
|| n instanceof PrebuiltHaskellLibrary) {
HaskellOmnibusLinkable haskellLinkable = (HaskellOmnibusLinkable) n;
return haskellLinkable.getOmnibusPassthroughDeps(
platform.getCxxPlatform(), graphBuilder);
} else {
return Optional.empty();
}
})
.values())
.transform(g -> g.getNativeLinkable(platform.getCxxPlatform(), graphBuilder))
.toList(),
// The preloaded deps form our excluded roots, which we need to keep them separate from
// the omnibus library so that they can be `LD_PRELOAD`ed early.
FluentIterable.from(preloadDeps)
.filter(NativeLinkableGroup.class)
.transform(g -> g.getNativeLinkable(platform.getCxxPlatform(), graphBuilder))
.toList());
// Add an -rpath to the omnibus for shared library dependencies
Path symlinkRelDir = HaskellGhciDescription.getSoLibsRelDir(buildTarget);
ImmutableList.Builder<Arg> extraLinkFlags = ImmutableList.builder();
extraLinkFlags.addAll(
StringArg.from(
Linkers.iXlinker(
"-rpath",
String.format(
"%s/%s",
platform
.getCxxPlatform()
.getLd()
.resolve(graphBuilder, buildTarget.getTargetConfiguration())
.origin(),
symlinkRelDir.toString()))));
// Construct the omnibus shared library.
BuildRule omnibusSharedObject =
HaskellGhciDescription.requireOmnibusSharedObject(
cellPathResolver,
buildTarget,
projectFilesystem,
graphBuilder,
platform.getCxxPlatform(),
cxxBuckConfig,
omnibusSpec.getBody(),
omnibusSpec.getDeps(),
extraLinkFlags.build());
// Build up a map of all transitive shared libraries the the monolithic omnibus library depends
// on (basically, stuff we couldn't statically link in). At this point, this should *not* be
// pulling in any excluded deps.
ImmutableList<? extends NativeLinkable> transitiveDeps =
NativeLinkables.getTransitiveNativeLinkables(graphBuilder, omnibusSpec.getDeps());
NativeLinkables.SharedLibrariesBuilder sharedLibsBuilder =
new NativeLinkables.SharedLibrariesBuilder();
sharedLibsBuilder.addAll(
graphBuilder,
transitiveDeps.stream()
// Skip statically linked libraries.
.filter(l -> l.getPreferredLinkage() != Linkage.STATIC)
.collect(Collectors.toList()));
ImmutableSortedMap<String, SourcePath> sharedLibs = sharedLibsBuilder.build();
// Build up a set of all transitive preload libs, which are the ones that have been "excluded"
// from the omnibus link. These are the ones we need to LD_PRELOAD.
NativeLinkables.SharedLibrariesBuilder preloadLibsBuilder =
new NativeLinkables.SharedLibrariesBuilder();
preloadLibsBuilder.addAll(
graphBuilder,
omnibusSpec.getExcludedTransitiveDeps().values().stream()
// Don't include shared libs for static libraries -- except for preload roots, which we
// always link dynamically.
.filter(
l ->
l.getPreferredLinkage() != Linkage.STATIC
|| omnibusSpec.getExcludedRoots().contains(l.getBuildTarget()))
.collect(Collectors.toList()));
ImmutableSortedMap<String, SourcePath> preloadLibs = preloadLibsBuilder.build();
HaskellSources srcs = HaskellSources.from(buildTarget, graphBuilder, platform, "srcs", argSrcs);
return HaskellGhciRule.from(
buildTarget,
projectFilesystem,
params,
graphBuilder,
srcs,
argCompilerFlags,
argGhciBinDep.map(
target -> Objects.requireNonNull(graphBuilder.getRule(target).getSourcePathToOutput())),
argGhciInit,
omnibusSharedObject,
sharedLibs,
preloadLibs,
firstOrderHaskellPackages.build(),
haskellPackages.build(),
prebuiltHaskellPackages.build(),
hsProfile,
platform,
argExtraScriptTemplates);
}