use of com.facebook.buck.cxx.NativeLinkable in project buck by facebook.
the class AndroidNativeLibsPackageableGraphEnhancer method enhance.
public AndroidNativeLibsGraphEnhancementResult enhance(AndroidPackageableCollection packageableCollection) throws NoSuchBuildTargetException {
@SuppressWarnings("PMD.PrematureDeclaration") AndroidNativeLibsGraphEnhancementResult.Builder resultBuilder = AndroidNativeLibsGraphEnhancementResult.builder();
ImmutableMultimap<APKModule, NativeLinkable> nativeLinkables = packageableCollection.getNativeLinkables();
ImmutableMultimap<APKModule, NativeLinkable> nativeLinkablesAssets = packageableCollection.getNativeLinkablesAssets();
if (nativeLibraryMergeMap.isPresent() && !nativeLibraryMergeMap.get().isEmpty()) {
NativeLibraryMergeEnhancementResult enhancement = NativeLibraryMergeEnhancer.enhance(cxxBuckConfig, ruleResolver, pathResolver, ruleFinder, buildRuleParams, nativePlatforms, nativeLibraryMergeMap.get(), nativeLibraryMergeGlue, nativeLinkables, nativeLinkablesAssets);
nativeLinkables = enhancement.getMergedLinkables();
nativeLinkablesAssets = enhancement.getMergedLinkablesAssets();
resultBuilder.setSonameMergeMap(enhancement.getSonameMapping());
}
// Iterate over all the {@link AndroidNativeLinkable}s from the collector and grab the shared
// libraries for all the {@link TargetCpuType}s that we care about. We deposit them into a map
// of CPU type and SONAME to the shared library path, which the {@link CopyNativeLibraries}
// rule will use to compose the destination name.
ImmutableMap.Builder<APKModule, CopyNativeLibraries> moduleMappedCopyNativeLibriesBuilder = ImmutableMap.builder();
boolean hasCopyNativeLibraries = false;
List<NdkCxxPlatform> platformsWithNativeLibs = new ArrayList<>();
List<NdkCxxPlatform> platformsWithNativeLibsAssets = new ArrayList<>();
// Make sure we process the root module last so that we know if any of the module contain
// libraries that depend on a non-system runtime and add it to the root module if needed.
ImmutableSet<APKModule> apkModules = FluentIterable.from(apkModuleGraph.getAPKModules()).filter(input -> !input.isRootModule()).append(apkModuleGraph.getRootAPKModule()).toSet();
for (APKModule module : apkModules) {
ImmutableMap.Builder<Pair<NdkCxxPlatforms.TargetCpuType, String>, SourcePath> nativeLinkableLibsBuilder = ImmutableMap.builder();
ImmutableMap.Builder<Pair<NdkCxxPlatforms.TargetCpuType, String>, SourcePath> nativeLinkableLibsAssetsBuilder = ImmutableMap.builder();
// TODO(andrewjcg): We currently treat an empty set of filters to mean to allow everything.
// We should fix this by assigning a default list of CPU filters in the descriptions, but
// until we do, if the set of filters is empty, just build for all available platforms.
ImmutableSet<NdkCxxPlatforms.TargetCpuType> filters = cpuFilters.isEmpty() ? nativePlatforms.keySet() : cpuFilters;
for (NdkCxxPlatforms.TargetCpuType targetCpuType : filters) {
NdkCxxPlatform platform = Preconditions.checkNotNull(nativePlatforms.get(targetCpuType), "Unknown platform type " + targetCpuType.toString());
// Populate nativeLinkableLibs and nativeLinkableLibsAssets with the appropriate entries.
if (populateMapWithLinkables(nativeLinkables.get(module), nativeLinkableLibsBuilder, targetCpuType, platform) && !platformsWithNativeLibs.contains(platform)) {
platformsWithNativeLibs.add(platform);
}
if (populateMapWithLinkables(nativeLinkablesAssets.get(module), nativeLinkableLibsAssetsBuilder, targetCpuType, platform) && !platformsWithNativeLibsAssets.contains(platform)) {
platformsWithNativeLibsAssets.add(platform);
}
if (module.isRootModule()) {
// If we're using a C/C++ runtime other than the system one, add it to the APK.
NdkCxxPlatforms.CxxRuntime cxxRuntime = platform.getCxxRuntime();
if ((platformsWithNativeLibs.contains(platform) || platformsWithNativeLibsAssets.contains(platform)) && !cxxRuntime.equals(NdkCxxPlatforms.CxxRuntime.SYSTEM)) {
nativeLinkableLibsBuilder.put(new Pair<>(targetCpuType, cxxRuntime.getSoname()), new PathSourcePath(buildRuleParams.getProjectFilesystem(), platform.getCxxSharedRuntimePath().get()));
}
}
}
ImmutableMap<Pair<NdkCxxPlatforms.TargetCpuType, String>, SourcePath> nativeLinkableLibs = nativeLinkableLibsBuilder.build();
ImmutableMap<Pair<NdkCxxPlatforms.TargetCpuType, String>, SourcePath> nativeLinkableLibsAssets = nativeLinkableLibsAssetsBuilder.build();
if (packageableCollection.getNativeLibsDirectories().get(module).isEmpty() && nativeLinkableLibs.isEmpty() && nativeLinkableLibsAssets.isEmpty()) {
continue;
}
if (relinkerMode == RelinkerMode.ENABLED && (!nativeLinkableLibs.isEmpty() || !nativeLinkableLibsAssets.isEmpty())) {
NativeRelinker relinker = new NativeRelinker(buildRuleParams.copyReplacingExtraDeps(Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>naturalOrder().addAll(ruleFinder.filterBuildRuleInputs(nativeLinkableLibs.values())).addAll(ruleFinder.filterBuildRuleInputs(nativeLinkableLibsAssets.values())).build())), pathResolver, ruleFinder, cxxBuckConfig, nativePlatforms, nativeLinkableLibs, nativeLinkableLibsAssets);
nativeLinkableLibs = relinker.getRelinkedLibs();
nativeLinkableLibsAssets = relinker.getRelinkedLibsAssets();
for (BuildRule rule : relinker.getRules()) {
ruleResolver.addToIndex(rule);
}
}
ImmutableMap<StripLinkable, StrippedObjectDescription> strippedLibsMap = generateStripRules(buildRuleParams, ruleFinder, ruleResolver, originalBuildTarget, nativePlatforms, nativeLinkableLibs);
ImmutableMap<StripLinkable, StrippedObjectDescription> strippedLibsAssetsMap = generateStripRules(buildRuleParams, ruleFinder, ruleResolver, originalBuildTarget, nativePlatforms, nativeLinkableLibsAssets);
ImmutableSortedSet<BuildRule> nativeLibsRules = BuildRules.toBuildRulesFor(originalBuildTarget, ruleResolver, packageableCollection.getNativeLibsTargets().get(module));
BuildRuleParams paramsForCopyNativeLibraries = buildRuleParams.withAppendedFlavor(InternalFlavor.of(COPY_NATIVE_LIBS + "_" + module.getName())).copyReplacingDeclaredAndExtraDeps(Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>naturalOrder().addAll(nativeLibsRules).addAll(ruleFinder.filterBuildRuleInputs(packageableCollection.getNativeLibsDirectories().get(module))).addAll(strippedLibsMap.keySet()).addAll(strippedLibsAssetsMap.keySet()).build()), Suppliers.ofInstance(ImmutableSortedSet.of()));
moduleMappedCopyNativeLibriesBuilder.put(module, new CopyNativeLibraries(paramsForCopyNativeLibraries, ImmutableSet.copyOf(packageableCollection.getNativeLibsDirectories().get(module)), ImmutableSet.copyOf(strippedLibsMap.values()), ImmutableSet.copyOf(strippedLibsAssetsMap.values()), cpuFilters, module.getName()));
hasCopyNativeLibraries = true;
}
return resultBuilder.setCopyNativeLibraries(hasCopyNativeLibraries ? Optional.of(moduleMappedCopyNativeLibriesBuilder.build()) : Optional.empty()).build();
}
use of com.facebook.buck.cxx.NativeLinkable in project buck by facebook.
the class AppleTestDescription method createTestHostInfo.
private TestHostInfo createTestHostInfo(BuildRuleParams params, BuildRuleResolver resolver, BuildTarget testHostAppBuildTarget, AppleDebugFormat debugFormat, Iterable<Flavor> additionalFlavors, ImmutableList<CxxPlatform> cxxPlatforms) throws NoSuchBuildTargetException {
BuildRule rule = resolver.requireRule(BuildTarget.builder(testHostAppBuildTarget).addAllFlavors(additionalFlavors).addFlavors(debugFormat.getFlavor()).addFlavors(StripStyle.NON_GLOBAL_SYMBOLS.getFlavor()).build());
if (!(rule instanceof AppleBundle)) {
throw new HumanReadableException("Apple test rule '%s' has test_host_app '%s' not of type '%s'.", params.getBuildTarget(), testHostAppBuildTarget, Description.getBuildRuleType(AppleBundleDescription.class));
}
AppleBundle testHostApp = (AppleBundle) rule;
SourcePath testHostAppBinarySourcePath = testHostApp.getBinaryBuildRule().getSourcePathToOutput();
ImmutableMap<BuildTarget, NativeLinkable> roots = NativeLinkables.getNativeLinkableRoots(testHostApp.getBinary().get().getDeps(), x -> true);
// Union the blacklist of all the platforms. This should give a superset for each particular
// platform, which should be acceptable as items in the blacklist thare are unmatched are simply
// ignored.
ImmutableSet.Builder<BuildTarget> blacklistBuilder = ImmutableSet.builder();
for (CxxPlatform platform : cxxPlatforms) {
blacklistBuilder.addAll(NativeLinkables.getTransitiveNativeLinkables(platform, roots.values()).keySet());
}
return TestHostInfo.of(testHostApp, testHostAppBinarySourcePath, blacklistBuilder.build());
}
use of com.facebook.buck.cxx.NativeLinkable in project buck by facebook.
the class LuaBinaryDescription method getPackageComponentsFromDeps.
private LuaBinaryPackageComponents getPackageComponentsFromDeps(BuildRuleParams baseParams, BuildRuleResolver ruleResolver, SourcePathResolver pathResolver, SourcePathRuleFinder ruleFinder, final CxxPlatform cxxPlatform, final PythonPlatform pythonPlatform, Optional<BuildTarget> nativeStarterLibrary, String mainModule, LuaConfig.PackageStyle packageStyle, Iterable<BuildRule> deps) throws NoSuchBuildTargetException {
final LuaPackageComponents.Builder builder = LuaPackageComponents.builder();
final OmnibusRoots.Builder omnibusRoots = OmnibusRoots.builder(cxxPlatform, ImmutableSet.of());
final Map<BuildTarget, NativeLinkable> nativeLinkableRoots = new LinkedHashMap<>();
final Map<BuildTarget, CxxLuaExtension> luaExtensions = new LinkedHashMap<>();
final Map<BuildTarget, CxxPythonExtension> pythonExtensions = new LinkedHashMap<>();
// Walk the deps to find all Lua packageables and native linkables.
new AbstractBreadthFirstThrowingTraversal<BuildRule, NoSuchBuildTargetException>(deps) {
private final ImmutableSet<BuildRule> empty = ImmutableSet.of();
@Override
public ImmutableSet<BuildRule> visit(BuildRule rule) throws NoSuchBuildTargetException {
ImmutableSet<BuildRule> deps = empty;
if (rule instanceof LuaPackageable) {
LuaPackageable packageable = (LuaPackageable) rule;
LuaPackageComponents components = packageable.getLuaPackageComponents();
LuaPackageComponents.addComponents(builder, components);
if (components.hasNativeCode(cxxPlatform)) {
for (BuildRule dep : rule.getDeps()) {
if (dep instanceof NativeLinkable) {
NativeLinkable linkable = (NativeLinkable) dep;
nativeLinkableRoots.put(linkable.getBuildTarget(), linkable);
omnibusRoots.addExcludedRoot(linkable);
}
}
}
deps = rule.getDeps();
} else if (rule instanceof CxxPythonExtension) {
CxxPythonExtension extension = (CxxPythonExtension) rule;
NativeLinkTarget target = extension.getNativeLinkTarget(pythonPlatform);
pythonExtensions.put(target.getBuildTarget(), (CxxPythonExtension) rule);
omnibusRoots.addIncludedRoot(target);
} else if (rule instanceof PythonPackagable) {
PythonPackagable packageable = (PythonPackagable) rule;
PythonPackageComponents components = packageable.getPythonPackageComponents(pythonPlatform, cxxPlatform);
builder.putAllPythonModules(MoreMaps.transformKeys(components.getModules(), Object::toString));
builder.putAllNativeLibraries(MoreMaps.transformKeys(components.getNativeLibraries(), Object::toString));
if (components.hasNativeCode(cxxPlatform)) {
for (BuildRule dep : rule.getDeps()) {
if (dep instanceof NativeLinkable) {
NativeLinkable linkable = (NativeLinkable) dep;
nativeLinkableRoots.put(linkable.getBuildTarget(), linkable);
omnibusRoots.addExcludedRoot(linkable);
}
}
}
deps = rule.getDeps();
} else if (rule instanceof CxxLuaExtension) {
CxxLuaExtension extension = (CxxLuaExtension) rule;
luaExtensions.put(extension.getBuildTarget(), extension);
omnibusRoots.addIncludedRoot(extension);
} else if (rule instanceof NativeLinkable) {
NativeLinkable linkable = (NativeLinkable) rule;
nativeLinkableRoots.put(linkable.getBuildTarget(), linkable);
omnibusRoots.addPotentialRoot(linkable);
}
return deps;
}
}.start();
// Build the starter.
Starter starter = createStarter(baseParams, ruleResolver, pathResolver, ruleFinder, cxxPlatform, nativeStarterLibrary, mainModule, packageStyle, !nativeLinkableRoots.isEmpty() || !omnibusRoots.isEmpty());
SourcePath starterPath = null;
if (luaConfig.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);
}
// Build the omnibus libraries.
OmnibusRoots roots = omnibusRoots.build();
OmnibusLibraries libraries = Omnibus.getSharedLibraries(baseParams, ruleResolver, ruleFinder, 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, 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(baseParams.getBuildTarget())) {
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", baseParams.getBuildTarget(), root.getKey());
NativeLinkTargetMode mode = target.getNativeLinkTargetMode(cxxPlatform);
String soname = Preconditions.checkNotNull(mode.getLibraryName().orElse(null), "%s: omnibus library for %s was built without soname", baseParams.getBuildTarget(), root.getKey());
builder.putNativeLibraries(soname, root.getValue().getPath());
}
// Add all remaining libraries as native libraries.
for (OmnibusLibrary library : libraries.getLibraries()) {
builder.putNativeLibraries(library.getSoname(), library.getPath());
}
} else {
// 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.getNativeLinkTargetDeps(cxxPlatform), NativeLinkable::getBuildTarget));
}
// Add in native executable deps.
if (starter instanceof NativeExecutableStarter) {
NativeExecutableStarter executableStarter = (NativeExecutableStarter) starter;
nativeLinkableRoots.putAll(Maps.uniqueIndex(executableStarter.getNativeStarterDeps(), NativeLinkable::getBuildTarget));
}
// python-platform specific deps to the native linkables.
for (Map.Entry<BuildTarget, CxxPythonExtension> entry : pythonExtensions.entrySet()) {
PythonPackageComponents components = entry.getValue().getPythonPackageComponents(pythonPlatform, cxxPlatform);
builder.putAllPythonModules(MoreMaps.transformKeys(components.getModules(), Object::toString));
builder.putAllNativeLibraries(MoreMaps.transformKeys(components.getNativeLibraries(), Object::toString));
nativeLinkableRoots.putAll(Maps.uniqueIndex(entry.getValue().getNativeLinkTarget(pythonPlatform).getNativeLinkTargetDeps(cxxPlatform), NativeLinkable::getBuildTarget));
}
// Add shared libraries from all native linkables.
for (NativeLinkable nativeLinkable : NativeLinkables.getTransitiveNativeLinkables(cxxPlatform, nativeLinkableRoots.values()).values()) {
NativeLinkable.Linkage linkage = nativeLinkable.getPreferredLinkage(cxxPlatform);
if (linkage != NativeLinkable.Linkage.STATIC) {
builder.putAllNativeLibraries(nativeLinkable.getSharedLibraries(cxxPlatform));
}
}
}
// building one directly from the starter.
if (starterPath == null) {
starterPath = starter.build();
}
return LuaBinaryPackageComponents.of(starterPath, builder.build());
}
use of com.facebook.buck.cxx.NativeLinkable in project buck by facebook.
the class NativeLibraryMergeEnhancer method getStructuralDeps.
/**
* Get the merged version of all deps, across all platforms.
*
* @param depType Function that returns the proper dep type: exported or not.
*/
private static List<MergedLibNativeLinkable> getStructuralDeps(MergedNativeLibraryConstituents constituents, Function<NativeLinkable, Iterable<? extends NativeLinkable>> depType, Map<NativeLinkable, MergedLibNativeLinkable> alreadyMerged) {
// Using IdentityHashMap as a hash set.
Map<MergedLibNativeLinkable, Void> structuralDeps = new HashMap<>();
for (NativeLinkable linkable : constituents.getLinkables()) {
for (NativeLinkable dep : depType.apply(linkable)) {
MergedLibNativeLinkable mappedDep = alreadyMerged.get(dep);
if (mappedDep == null) {
if (constituents.getLinkables().contains(dep)) {
// We're depending on one of our other constituents. We can drop this.
continue;
}
throw new RuntimeException("Can't find mapped dep of " + dep + " for " + linkable + ". This is a bug.");
}
structuralDeps.put(mappedDep, null);
}
}
// Sort here to ensure consistent ordering, because the build target depends on the order.
return structuralDeps.keySet().stream().sorted(Comparator.comparing(MergedLibNativeLinkable::getBuildTarget)).collect(MoreCollectors.toImmutableList());
}
use of com.facebook.buck.cxx.NativeLinkable in project buck by facebook.
the class NativeLibraryMergeEnhancer method enhance.
@SuppressWarnings("PMD.PrematureDeclaration")
static NativeLibraryMergeEnhancementResult enhance(CxxBuckConfig cxxBuckConfig, BuildRuleResolver ruleResolver, SourcePathResolver pathResolver, SourcePathRuleFinder ruleFinder, BuildRuleParams buildRuleParams, ImmutableMap<NdkCxxPlatforms.TargetCpuType, NdkCxxPlatform> nativePlatforms, Map<String, List<Pattern>> mergeMap, Optional<BuildTarget> nativeLibraryMergeGlue, ImmutableMultimap<APKModule, NativeLinkable> linkables, ImmutableMultimap<APKModule, NativeLinkable> linkablesAssets) throws NoSuchBuildTargetException {
NativeLibraryMergeEnhancer.ruleFinder = ruleFinder;
NativeLibraryMergeEnhancementResult.Builder builder = NativeLibraryMergeEnhancementResult.builder();
ImmutableSet<APKModule> modules = ImmutableSet.<APKModule>builder().addAll(linkables.keySet()).addAll(linkablesAssets.keySet()).build();
ImmutableSortedMap.Builder<String, String> sonameMapBuilder = ImmutableSortedMap.naturalOrder();
for (APKModule module : modules) {
// Sort by build target here to ensure consistent behavior.
Iterable<NativeLinkable> allLinkables = Stream.concat(linkables.get(module).stream(), linkablesAssets.get(module).stream()).sorted(Comparator.comparing(NativeLinkable::getBuildTarget)).collect(MoreCollectors.toImmutableList());
final ImmutableSet<NativeLinkable> linkableAssetSet = ImmutableSet.copyOf(linkablesAssets.get(module));
Map<NativeLinkable, MergedNativeLibraryConstituents> linkableMembership = makeConstituentMap(buildRuleParams, mergeMap, allLinkables, linkableAssetSet);
sonameMapBuilder.putAll(makeSonameMap(// so just pick the first platform and use that to get all the sonames.
nativePlatforms.values().iterator().next().getCxxPlatform(), linkableMembership));
Iterable<MergedNativeLibraryConstituents> orderedConstituents = getOrderedMergedConstituents(buildRuleParams, linkableMembership);
Optional<NativeLinkable> glueLinkable = Optional.empty();
if (nativeLibraryMergeGlue.isPresent()) {
BuildRule rule = ruleResolver.getRule(nativeLibraryMergeGlue.get());
if (!(rule instanceof NativeLinkable)) {
throw new RuntimeException("Native library merge glue " + rule.getBuildTarget() + " for application " + buildRuleParams.getBuildTarget() + " is not linkable.");
}
glueLinkable = Optional.of(((NativeLinkable) rule));
}
Set<MergedLibNativeLinkable> mergedLinkables = createLinkables(cxxBuckConfig, ruleResolver, pathResolver, buildRuleParams, glueLinkable, orderedConstituents);
for (MergedLibNativeLinkable linkable : mergedLinkables) {
if (Collections.disjoint(linkable.constituents.getLinkables(), linkableAssetSet)) {
builder.putMergedLinkables(module, linkable);
} else if (linkableAssetSet.containsAll(linkable.constituents.getLinkables())) {
builder.putMergedLinkablesAssets(module, linkable);
}
}
}
builder.setSonameMapping(sonameMapBuilder.build());
return builder.build();
}
Aggregations