Search in sources :

Example 6 with NativeLinkable

use of com.facebook.buck.cxx.NativeLinkable in project buck by facebook.

the class NativeLibraryMergeEnhancer method getOrderedMergedConstituents.

/**
   * Topo-sort the constituents objects so we can process deps first.
   */
private static Iterable<MergedNativeLibraryConstituents> getOrderedMergedConstituents(BuildRuleParams buildRuleParams, final Map<NativeLinkable, MergedNativeLibraryConstituents> linkableMembership) {
    MutableDirectedGraph<MergedNativeLibraryConstituents> graph = new MutableDirectedGraph<>();
    for (MergedNativeLibraryConstituents constituents : linkableMembership.values()) {
        graph.addNode(constituents);
        for (NativeLinkable constituentLinkable : constituents.getLinkables()) {
            // For each dep of each constituent of each merged lib...
            for (NativeLinkable dep : Iterables.concat(constituentLinkable.getNativeLinkableDeps(), constituentLinkable.getNativeLinkableExportedDeps())) {
                // If that dep is in a different merged lib, add a dependency.
                MergedNativeLibraryConstituents mergedDep = Preconditions.checkNotNull(linkableMembership.get(dep));
                if (mergedDep != constituents) {
                    graph.addEdge(constituents, mergedDep);
                }
            }
        }
    }
    // that actually shows the dependency cycle.
    for (ImmutableSet<MergedNativeLibraryConstituents> fullCycle : graph.findCycles()) {
        HashSet<MergedNativeLibraryConstituents> partialCycle = new LinkedHashSet<>();
        MergedNativeLibraryConstituents item = fullCycle.iterator().next();
        while (true) {
            if (partialCycle.contains(item)) {
                break;
            }
            partialCycle.add(item);
            item = Sets.intersection(ImmutableSet.copyOf(graph.getOutgoingNodesFor(item)), fullCycle).iterator().next();
        }
        StringBuilder cycleString = new StringBuilder().append("[ ");
        boolean foundStart = false;
        for (MergedNativeLibraryConstituents member : partialCycle) {
            if (member == item) {
                foundStart = true;
            }
            if (foundStart) {
                cycleString.append(member);
                cycleString.append(" -> ");
            }
        }
        cycleString.append(item);
        cycleString.append(" ]");
        throw new RuntimeException("Dependency cycle detected when merging native libs for " + buildRuleParams.getBuildTarget() + ": " + cycleString);
    }
    return TopologicalSort.sort(graph);
}
Also used : LinkedHashSet(java.util.LinkedHashSet) NativeLinkable(com.facebook.buck.cxx.NativeLinkable) MutableDirectedGraph(com.facebook.buck.graph.MutableDirectedGraph)

Example 7 with NativeLinkable

use of com.facebook.buck.cxx.NativeLinkable in project buck by facebook.

the class PythonUtil method getAllComponents.

static PythonPackageComponents getAllComponents(BuildRuleParams params, BuildRuleResolver ruleResolver, SourcePathRuleFinder ruleFinder, final PythonPackageComponents packageComponents, final PythonPlatform pythonPlatform, CxxBuckConfig cxxBuckConfig, final CxxPlatform cxxPlatform, ImmutableList<? extends Arg> extraLdflags, final NativeLinkStrategy nativeLinkStrategy, final ImmutableSet<BuildTarget> preloadDeps) throws NoSuchBuildTargetException {
    final PythonPackageComponents.Builder allComponents = new PythonPackageComponents.Builder(params.getBuildTarget());
    final Map<BuildTarget, CxxPythonExtension> extensions = new LinkedHashMap<>();
    final Map<BuildTarget, NativeLinkable> nativeLinkableRoots = new LinkedHashMap<>();
    final OmnibusRoots.Builder omnibusRoots = OmnibusRoots.builder(cxxPlatform, preloadDeps);
    // Add the top-level components.
    allComponents.addComponent(packageComponents, params.getBuildTarget());
    // Walk all our transitive deps to build our complete package that we'll
    // turn into an executable.
    new AbstractBreadthFirstThrowingTraversal<BuildRule, NoSuchBuildTargetException>(params.getDeps()) {

        private final ImmutableList<BuildRule> empty = ImmutableList.of();

        @Override
        public Iterable<BuildRule> visit(BuildRule rule) throws NoSuchBuildTargetException {
            Iterable<BuildRule> deps = empty;
            if (rule instanceof CxxPythonExtension) {
                CxxPythonExtension extension = (CxxPythonExtension) rule;
                NativeLinkTarget target = ((CxxPythonExtension) rule).getNativeLinkTarget(pythonPlatform);
                extensions.put(target.getBuildTarget(), extension);
                omnibusRoots.addIncludedRoot(target);
                List<BuildRule> cxxpydeps = new ArrayList<>();
                for (BuildRule dep : rule.getDeps()) {
                    if (dep instanceof CxxPythonExtension) {
                        cxxpydeps.add(dep);
                    }
                }
                deps = cxxpydeps;
            } else if (rule instanceof PythonPackagable) {
                PythonPackagable packagable = (PythonPackagable) rule;
                PythonPackageComponents comps = packagable.getPythonPackageComponents(pythonPlatform, cxxPlatform);
                allComponents.addComponent(comps, rule.getBuildTarget());
                if (comps.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 NativeLinkable) {
                NativeLinkable linkable = (NativeLinkable) rule;
                nativeLinkableRoots.put(linkable.getBuildTarget(), linkable);
                omnibusRoots.addPotentialRoot(linkable);
            }
            return deps;
        }
    }.start();
    // excluded native linkable roots.
    if (nativeLinkStrategy == NativeLinkStrategy.MERGED) {
        OmnibusRoots roots = omnibusRoots.build();
        OmnibusLibraries libraries = Omnibus.getSharedLibraries(params, ruleResolver, ruleFinder, cxxBuckConfig, cxxPlatform, extraLdflags, roots.getIncludedRoots().values(), roots.getExcludedRoots().values());
        // Otherwise, add it as a native library.
        for (Map.Entry<BuildTarget, OmnibusRoot> root : libraries.getRoots().entrySet()) {
            CxxPythonExtension extension = extensions.get(root.getKey());
            if (extension != null) {
                allComponents.addModule(extension.getModule(), root.getValue().getPath(), root.getKey());
            } else {
                NativeLinkTarget target = Preconditions.checkNotNull(roots.getIncludedRoots().get(root.getKey()), "%s: linked unexpected omnibus root: %s", params.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", params.getBuildTarget(), root.getKey());
                allComponents.addNativeLibraries(Paths.get(soname), root.getValue().getPath(), root.getKey());
            }
        }
        // Add all remaining libraries as native libraries.
        for (OmnibusLibrary library : libraries.getLibraries()) {
            allComponents.addNativeLibraries(Paths.get(library.getSoname()), library.getPath(), params.getBuildTarget());
        }
    } else {
        // For regular linking, add all extensions via the package components interface.
        Map<BuildTarget, NativeLinkable> extensionNativeDeps = new LinkedHashMap<>();
        for (Map.Entry<BuildTarget, CxxPythonExtension> entry : extensions.entrySet()) {
            allComponents.addComponent(entry.getValue().getPythonPackageComponents(pythonPlatform, cxxPlatform), entry.getValue().getBuildTarget());
            extensionNativeDeps.putAll(Maps.uniqueIndex(entry.getValue().getNativeLinkTarget(pythonPlatform).getNativeLinkTargetDeps(cxxPlatform), NativeLinkable::getBuildTarget));
        }
        // Add all the native libraries.
        ImmutableMap<BuildTarget, NativeLinkable> nativeLinkables = NativeLinkables.getTransitiveNativeLinkables(cxxPlatform, Iterables.concat(nativeLinkableRoots.values(), extensionNativeDeps.values()));
        for (NativeLinkable nativeLinkable : nativeLinkables.values()) {
            NativeLinkable.Linkage linkage = nativeLinkable.getPreferredLinkage(cxxPlatform);
            if (nativeLinkableRoots.containsKey(nativeLinkable.getBuildTarget()) || linkage != NativeLinkable.Linkage.STATIC) {
                ImmutableMap<String, SourcePath> libs = nativeLinkable.getSharedLibraries(cxxPlatform);
                for (Map.Entry<String, SourcePath> ent : libs.entrySet()) {
                    allComponents.addNativeLibraries(Paths.get(ent.getKey()), ent.getValue(), nativeLinkable.getBuildTarget());
                }
            }
        }
    }
    return allComponents.build();
}
Also used : FluentIterable(com.google.common.collect.FluentIterable) NativeLinkable(com.facebook.buck.cxx.NativeLinkable) NativeLinkTargetMode(com.facebook.buck.cxx.NativeLinkTargetMode) OmnibusRoot(com.facebook.buck.cxx.OmnibusRoot) LinkedHashMap(java.util.LinkedHashMap) OmnibusLibraries(com.facebook.buck.cxx.OmnibusLibraries) SourcePath(com.facebook.buck.rules.SourcePath) BuildTarget(com.facebook.buck.model.BuildTarget) OmnibusRoots(com.facebook.buck.cxx.OmnibusRoots) BuildRule(com.facebook.buck.rules.BuildRule) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) SourceList(com.facebook.buck.rules.coercer.SourceList) List(java.util.List) OmnibusLibrary(com.facebook.buck.cxx.OmnibusLibrary) NativeLinkTarget(com.facebook.buck.cxx.NativeLinkTarget) NoSuchBuildTargetException(com.facebook.buck.parser.NoSuchBuildTargetException) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap)

Example 8 with NativeLinkable

use of com.facebook.buck.cxx.NativeLinkable in project buck by facebook.

the class AndroidNativeLibsPackageableGraphEnhancer method populateMapWithLinkables.

// Populates an immutable map builder with all given linkables set to the given cpu type.
// Returns true iff linkables is not empty.
private boolean populateMapWithLinkables(Iterable<NativeLinkable> linkables, ImmutableMap.Builder<Pair<NdkCxxPlatforms.TargetCpuType, String>, SourcePath> builder, NdkCxxPlatforms.TargetCpuType targetCpuType, NdkCxxPlatform platform) throws NoSuchBuildTargetException {
    boolean hasNativeLibs = false;
    for (NativeLinkable nativeLinkable : linkables) {
        if (nativeLinkable.getPreferredLinkage(platform.getCxxPlatform()) != NativeLinkable.Linkage.STATIC) {
            ImmutableMap<String, SourcePath> solibs = nativeLinkable.getSharedLibraries(platform.getCxxPlatform());
            for (Map.Entry<String, SourcePath> entry : solibs.entrySet()) {
                builder.put(new Pair<>(targetCpuType, entry.getKey()), entry.getValue());
                hasNativeLibs = true;
            }
        }
    }
    return hasNativeLibs;
}
Also used : SourcePath(com.facebook.buck.rules.SourcePath) BuildTargetSourcePath(com.facebook.buck.rules.BuildTargetSourcePath) PathSourcePath(com.facebook.buck.rules.PathSourcePath) NativeLinkable(com.facebook.buck.cxx.NativeLinkable) Map(java.util.Map) ImmutableSortedMap(com.google.common.collect.ImmutableSortedMap) ImmutableMap(com.google.common.collect.ImmutableMap)

Example 9 with NativeLinkable

use of com.facebook.buck.cxx.NativeLinkable in project buck by facebook.

the class NativeLibraryMergeEnhancer method makeConstituentMap.

private static Map<NativeLinkable, MergedNativeLibraryConstituents> makeConstituentMap(BuildRuleParams buildRuleParams, Map<String, List<Pattern>> mergeMap, Iterable<NativeLinkable> allLinkables, ImmutableSet<NativeLinkable> linkableAssetSet) {
    List<MergedNativeLibraryConstituents> allConstituents = new ArrayList<>();
    for (Map.Entry<String, List<Pattern>> mergeConfigEntry : mergeMap.entrySet()) {
        String mergeSoname = mergeConfigEntry.getKey();
        List<Pattern> patterns = mergeConfigEntry.getValue();
        MergedNativeLibraryConstituents.Builder constituentsBuilder = MergedNativeLibraryConstituents.builder().setSoname(mergeSoname);
        for (Pattern pattern : patterns) {
            for (NativeLinkable linkable : allLinkables) {
                // TODO(dreiss): Might be a good idea to cache .getBuildTarget().toString().
                if (pattern.matcher(linkable.getBuildTarget().toString()).find()) {
                    constituentsBuilder.addLinkables(linkable);
                }
            }
        }
        allConstituents.add(constituentsBuilder.build());
    }
    Map<NativeLinkable, MergedNativeLibraryConstituents> linkableMembership = new HashMap<>();
    for (MergedNativeLibraryConstituents constituents : allConstituents) {
        boolean hasNonAssets = false;
        boolean hasAssets = false;
        for (NativeLinkable linkable : constituents.getLinkables()) {
            if (linkableMembership.containsKey(linkable)) {
                throw new RuntimeException(String.format("When processing %s, attempted to merge %s into both %s and %s", buildRuleParams.getBuildTarget(), linkable, linkableMembership.get(linkable), constituents));
            }
            linkableMembership.put(linkable, constituents);
            if (linkableAssetSet.contains(linkable)) {
                hasAssets = true;
            } else {
                hasNonAssets = true;
            }
        }
        if (hasAssets && hasNonAssets) {
            StringBuilder sb = new StringBuilder();
            sb.append(String.format("When processing %s, merged lib '%s' contains both asset and non-asset libraries.\n", buildRuleParams.getBuildTarget(), constituents));
            for (NativeLinkable linkable : constituents.getLinkables()) {
                sb.append(String.format("  %s -> %s\n", linkable, linkableAssetSet.contains(linkable) ? "asset" : "not asset"));
            }
            throw new RuntimeException(sb.toString());
        }
    }
    for (NativeLinkable linkable : allLinkables) {
        if (!linkableMembership.containsKey(linkable)) {
            linkableMembership.put(linkable, MergedNativeLibraryConstituents.builder().addLinkables(linkable).build());
        }
    }
    return linkableMembership;
}
Also used : Pattern(java.util.regex.Pattern) HashMap(java.util.HashMap) NativeLinkable(com.facebook.buck.cxx.NativeLinkable) ArrayList(java.util.ArrayList) List(java.util.List) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) HashMap(java.util.HashMap) ImmutableSortedMap(com.google.common.collect.ImmutableSortedMap)

Example 10 with NativeLinkable

use of com.facebook.buck.cxx.NativeLinkable in project buck by facebook.

the class NativeLibraryMergeEnhancer method createLinkables.

/**
   * Create the final Linkables that will be passed to the later stages of graph enhancement.
   */
private static Set<MergedLibNativeLinkable> createLinkables(CxxBuckConfig cxxBuckConfig, BuildRuleResolver ruleResolver, SourcePathResolver pathResolver, BuildRuleParams buildRuleParams, Optional<NativeLinkable> glueLinkable, Iterable<MergedNativeLibraryConstituents> orderedConstituents) {
    // Map from original linkables to the Linkables they have been merged into.
    final Map<NativeLinkable, MergedLibNativeLinkable> mergeResults = new HashMap<>();
    for (MergedNativeLibraryConstituents constituents : orderedConstituents) {
        final ImmutableCollection<NativeLinkable> preMergeLibs = constituents.getLinkables();
        List<MergedLibNativeLinkable> orderedDeps = getStructuralDeps(constituents, NativeLinkable::getNativeLinkableDeps, mergeResults);
        List<MergedLibNativeLinkable> orderedExportedDeps = getStructuralDeps(constituents, NativeLinkable::getNativeLinkableExportedDeps, mergeResults);
        MergedLibNativeLinkable mergedLinkable = new MergedLibNativeLinkable(cxxBuckConfig, ruleResolver, pathResolver, buildRuleParams, constituents, orderedDeps, orderedExportedDeps, glueLinkable);
        for (NativeLinkable lib : preMergeLibs) {
            // Track what was merged into this so later linkables can find us as a dependency.
            mergeResults.put(lib, mergedLinkable);
        }
    }
    return ImmutableSortedSet.copyOf(Comparator.comparing(NativeLinkable::getBuildTarget), mergeResults.values());
}
Also used : HashMap(java.util.HashMap) NativeLinkable(com.facebook.buck.cxx.NativeLinkable)

Aggregations

NativeLinkable (com.facebook.buck.cxx.NativeLinkable)13 BuildRule (com.facebook.buck.rules.BuildRule)6 SourcePath (com.facebook.buck.rules.SourcePath)6 ImmutableMap (com.google.common.collect.ImmutableMap)5 ImmutableSortedMap (com.google.common.collect.ImmutableSortedMap)5 Map (java.util.Map)5 NativeLinkTarget (com.facebook.buck.cxx.NativeLinkTarget)4 BuildTarget (com.facebook.buck.model.BuildTarget)4 HashMap (java.util.HashMap)4 NoSuchBuildTargetException (com.facebook.buck.parser.NoSuchBuildTargetException)3 BuildRuleResolver (com.facebook.buck.rules.BuildRuleResolver)3 ImmutableList (com.google.common.collect.ImmutableList)3 CxxBuckConfig (com.facebook.buck.cxx.CxxBuckConfig)2 CxxLibraryBuilder (com.facebook.buck.cxx.CxxLibraryBuilder)2 CxxPlatform (com.facebook.buck.cxx.CxxPlatform)2 NativeLinkTargetMode (com.facebook.buck.cxx.NativeLinkTargetMode)2 OmnibusLibraries (com.facebook.buck.cxx.OmnibusLibraries)2 OmnibusLibrary (com.facebook.buck.cxx.OmnibusLibrary)2 OmnibusRoot (com.facebook.buck.cxx.OmnibusRoot)2 OmnibusRoots (com.facebook.buck.cxx.OmnibusRoots)2