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