private LuaBinaryPackageComponents getPackageComponentsFromDeps()

in src/com/facebook/buck/features/lua/LuaBinaryDescription.java [281:519]


  private LuaBinaryPackageComponents getPackageComponentsFromDeps(
      BuildTarget buildTarget,
      ProjectFilesystem projectFilesystem,
      BuildRuleParams baseParams,
      ActionGraphBuilder graphBuilder,
      LuaPlatform luaPlatform,
      PythonPlatform pythonPlatform,
      Optional<BuildTarget> nativeStarterLibrary,
      String mainModule,
      LuaPlatform.PackageStyle packageStyle,
      Iterable<BuildRule> deps,
      CellPathResolver cellPathResolver) {

    CxxPlatform cxxPlatform = luaPlatform.getCxxPlatform();

    LuaPackageComponents.Builder builder = LuaPackageComponents.builder();
    OmnibusRoots.Builder omnibusRoots = OmnibusRoots.builder(ImmutableSet.of(), graphBuilder);

    Map<BuildTarget, NativeLinkable> nativeLinkableRoots = new LinkedHashMap<>();
    Map<BuildTarget, CxxLuaExtension> luaExtensions = new LinkedHashMap<>();
    Map<BuildTarget, CxxPythonExtension> pythonExtensions = new LinkedHashMap<>();

    // Walk the deps to find all Lua packageables and native linkables.
    new AbstractBreadthFirstTraversal<BuildRule>(deps) {
      private final ImmutableSet<BuildRule> empty = ImmutableSet.of();

      @Override
      public Iterable<BuildRule> visit(BuildRule rule) {
        Iterable<BuildRule> deps = empty;
        if (rule instanceof LuaPackageable) {
          LuaPackageable packageable = (LuaPackageable) rule;
          LuaPackageComponents components =
              packageable.getLuaPackageComponents(graphBuilder.getSourcePathResolver());
          LuaPackageComponents.addComponents(builder, components);
          deps = packageable.getLuaPackageDeps(cxxPlatform, graphBuilder);
          if (components.hasNativeCode(cxxPlatform)) {
            for (BuildRule dep : deps) {
              if (dep instanceof NativeLinkableGroup) {
                NativeLinkable linkable =
                    ((NativeLinkableGroup) dep).getNativeLinkable(cxxPlatform, graphBuilder);
                nativeLinkableRoots.put(linkable.getBuildTarget(), linkable);
                omnibusRoots.addExcludedRoot(linkable);
              }
            }
          }
        } else if (rule instanceof CxxPythonExtension) {
          CxxPythonExtension extension = (CxxPythonExtension) rule;
          NativeLinkTarget target =
              extension.getNativeLinkTarget(pythonPlatform, cxxPlatform, graphBuilder, false);
          pythonExtensions.put(target.getBuildTarget(), (CxxPythonExtension) rule);
          omnibusRoots.addIncludedRoot(target);
        } else if (rule instanceof PythonPackagable) {
          PythonPackagable packageable = (PythonPackagable) rule;
          packageable
              .getPythonModules(pythonPlatform, cxxPlatform, graphBuilder)
              .ifPresent(
                  modules -> {
                    // TODO(agallagher): This doesn't support prebuilt python libs.
                    if (modules instanceof PythonMappedComponents) {
                      builder.putAllPythonModules(
                          MoreMaps.transformKeys(
                              ((PythonMappedComponents) modules).getComponents(),
                              Object::toString));
                    }
                  });
          deps = packageable.getPythonPackageDeps(pythonPlatform, cxxPlatform, graphBuilder);
          if (packageable.doesPythonPackageDisallowOmnibus(
              pythonPlatform, cxxPlatform, graphBuilder)) {
            for (BuildRule dep : deps) {
              if (dep instanceof NativeLinkableGroup) {
                NativeLinkable linkable =
                    ((NativeLinkableGroup) dep).getNativeLinkable(cxxPlatform, graphBuilder);
                nativeLinkableRoots.put(linkable.getBuildTarget(), linkable);
                omnibusRoots.addExcludedRoot(linkable);
              }
            }
          }
        } else if (rule instanceof CxxLuaExtension) {
          CxxLuaExtension extension = (CxxLuaExtension) rule;
          luaExtensions.put(extension.getBuildTarget(), extension);
          omnibusRoots.addIncludedRoot(extension.getTargetForPlatform(cxxPlatform, false));
        } else if (rule instanceof NativeLinkableGroup) {
          NativeLinkable linkable =
              ((NativeLinkableGroup) rule).getNativeLinkable(cxxPlatform, graphBuilder);
          nativeLinkableRoots.put(linkable.getBuildTarget(), linkable);
          omnibusRoots.addPotentialRoot(linkable, false);
        }
        return deps;
      }
    }.start();

    // Build the starter.
    Starter starter =
        createStarter(
            cellPathResolver,
            projectFilesystem,
            buildTarget,
            baseParams,
            graphBuilder,
            luaPlatform,
            nativeStarterLibrary,
            mainModule,
            packageStyle,
            !nativeLinkableRoots.isEmpty() || !omnibusRoots.isEmpty());
    SourcePath starterPath = null;

    if (luaPlatform.getNativeLinkStrategy() == NativeLinkStrategy.MERGED) {

      // If we're using a native starter, include it in omnibus linking.
      if (starter instanceof NativeExecutableStarter) {
        NativeExecutableStarter nativeStarter = (NativeExecutableStarter) starter;
        omnibusRoots.addIncludedRoot(nativeStarter.getNativeLinkTargetInfo());
      }

      // Build the omnibus libraries.
      OmnibusRoots roots = omnibusRoots.build();
      Omnibus.OmnibusLibraries libraries =
          Omnibus.getSharedLibraries(
              buildTarget,
              projectFilesystem,
              baseParams,
              cellPathResolver,
              graphBuilder,
              cxxBuckConfig,
              cxxPlatform,
              ImmutableList.of(),
              roots.getIncludedRoots().values(),
              roots.getExcludedRoots().values());

      // Add all the roots from the omnibus link.  If it's an extension, add it as a module.
      for (Map.Entry<BuildTarget, Omnibus.OmnibusRoot> root : libraries.getRoots().entrySet()) {

        // If it's a Lua extension add it as a module.
        CxxLuaExtension luaExtension = luaExtensions.get(root.getKey());
        if (luaExtension != null) {
          builder.putModules(luaExtension.getModule(cxxPlatform), root.getValue().getPath());
          continue;
        }

        // If it's a Python extension, add it as a python module.
        CxxPythonExtension pythonExtension = pythonExtensions.get(root.getKey());
        if (pythonExtension != null) {
          builder.putPythonModules(
              pythonExtension.getModule().toString(), root.getValue().getPath());
          continue;
        }

        // A root named after the top-level target is our native starter.
        if (root.getKey().equals(buildTarget)) {
          starterPath = root.getValue().getPath();
          continue;
        }

        // Otherwise, add it as a native library.
        NativeLinkTarget target =
            Preconditions.checkNotNull(
                roots.getIncludedRoots().get(root.getKey()),
                "%s: linked unexpected omnibus root: %s",
                buildTarget,
                root.getKey());
        NativeLinkTargetMode mode = target.getNativeLinkTargetMode();
        String soname =
            Preconditions.checkNotNull(
                mode.getLibraryName().orElse(null),
                "%s: omnibus library for %s was built without soname",
                buildTarget,
                root.getKey());
        builder.putNativeLibraries(soname, root.getValue().getPath());
      }

      // Add all remaining libraries as native libraries.
      for (Omnibus.OmnibusLibrary library : libraries.getLibraries()) {
        builder.putNativeLibraries(library.getSoname(), library.getPath());
      }

    } else {

      // For regular linking, add all Lua extensions as modules and their deps as native linkable
      // roots.
      for (Map.Entry<BuildTarget, CxxLuaExtension> entry : luaExtensions.entrySet()) {
        CxxLuaExtension extension = entry.getValue();
        builder.putModules(extension.getModule(cxxPlatform), extension.getExtension(cxxPlatform));
        nativeLinkableRoots.putAll(
            Maps.uniqueIndex(
                extension
                    .getTargetForPlatform(cxxPlatform, true)
                    .getNativeLinkTargetDeps(graphBuilder),
                NativeLinkable::getBuildTarget));
      }

      // Add in native executable deps.
      if (starter instanceof NativeExecutableStarter) {
        NativeExecutableStarter executableStarter = (NativeExecutableStarter) starter;
        nativeLinkableRoots.putAll(
            Maps.uniqueIndex(
                Iterables.transform(
                    executableStarter.getNativeStarterDeps(),
                    g -> g.getNativeLinkable(cxxPlatform, graphBuilder)),
                NativeLinkable::getBuildTarget));
      }

      // For regular linking, add all extensions via the package components interface and their
      // python-platform specific deps to the native linkables.
      for (Map.Entry<BuildTarget, CxxPythonExtension> entry : pythonExtensions.entrySet()) {
        entry
            .getValue()
            .getPythonModules(pythonPlatform, cxxPlatform, graphBuilder)
            .ifPresent(
                modules ->
                    builder.putAllPythonModules(
                        MoreMaps.transformKeys(modules.getComponents(), Object::toString)));
        nativeLinkableRoots.putAll(
            Maps.uniqueIndex(
                entry
                    .getValue()
                    .getNativeLinkTarget(pythonPlatform, cxxPlatform, graphBuilder, true)
                    .getNativeLinkTargetDeps(graphBuilder),
                NativeLinkable::getBuildTarget));
      }

      // Add shared libraries from all native linkables.
      for (NativeLinkable nativeLinkableGroup :
          NativeLinkables.getTransitiveNativeLinkables(
              graphBuilder, nativeLinkableRoots.values())) {
        NativeLinkableGroup.Linkage linkage = nativeLinkableGroup.getPreferredLinkage();
        if (linkage != NativeLinkableGroup.Linkage.STATIC) {
          builder.putAllNativeLibraries(nativeLinkableGroup.getSharedLibraries(graphBuilder));
        }
      }
    }

    // If an explicit starter path override hasn't been set (e.g. from omnibus linking), default to
    // building one directly from the starter.
    if (starterPath == null) {
      starterPath = starter.build();
    }

    return LuaBinaryPackageComponents.of(starterPath, builder.build());
  }