public BuildRule createBuildRule()

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