public static HaskellGhciRule requireGhciRule()

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