Search in sources :

Example 6 with LibraryToLink

use of com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink in project bazel by bazelbuild.

the class CcLibrary method init.

public static void init(CppSemantics semantics, RuleContext ruleContext, RuleConfiguredTargetBuilder targetBuilder, LinkTargetType linkType, boolean neverLink, boolean linkStatic, boolean collectLinkstamp, boolean addDynamicRuntimeInputArtifactsToRunfiles) throws RuleErrorException, InterruptedException {
    final CcCommon common = new CcCommon(ruleContext);
    CcToolchainProvider ccToolchain = common.getToolchain();
    FdoSupportProvider fdoSupport = common.getFdoSupport();
    FeatureConfiguration featureConfiguration = CcCommon.configureFeatures(ruleContext, ccToolchain);
    PrecompiledFiles precompiledFiles = new PrecompiledFiles(ruleContext);
    semantics.validateAttributes(ruleContext);
    if (ruleContext.hasErrors()) {
        return;
    }
    CcLibraryHelper helper = new CcLibraryHelper(ruleContext, semantics, featureConfiguration, ccToolchain, fdoSupport).fromCommon(common).addLinkopts(common.getLinkopts()).addSources(common.getSources()).addPublicHeaders(common.getHeaders()).enableCcNativeLibrariesProvider().enableCompileProviders().enableInterfaceSharedObjects().setGenerateLinkActionsIfEmpty(ruleContext.getRule().getImplicitOutputsFunction() != ImplicitOutputsFunction.NONE).setLinkType(linkType).setNeverLink(neverLink).addPrecompiledFiles(precompiledFiles);
    if (collectLinkstamp) {
        helper.addLinkstamps(ruleContext.getPrerequisites("linkstamp", Mode.TARGET));
    }
    Artifact soImplArtifact = null;
    boolean supportsDynamicLinker = ruleContext.getFragment(CppConfiguration.class).supportsDynamicLinker();
    // TODO(djasper): This is hacky. We should actually try to figure out whether we generate
    // ccOutputs.
    boolean createDynamicLibrary = !linkStatic && supportsDynamicLinker && (appearsToHaveObjectFiles(ruleContext.attributes()) || featureConfiguration.isEnabled(CppRuleClasses.HEADER_MODULE_CODEGEN));
    if (ruleContext.getRule().isAttrDefined("outs", Type.STRING_LIST)) {
        List<String> outs = ruleContext.attributes().get("outs", Type.STRING_LIST);
        if (outs.size() > 1) {
            ruleContext.attributeError("outs", "must be a singleton list");
        } else if (outs.size() == 1) {
            PathFragment soImplFilename = new PathFragment(ruleContext.getLabel().getName());
            soImplFilename = soImplFilename.replaceName(outs.get(0));
            if (!soImplFilename.getPathString().endsWith(".so")) {
                // Sanity check.
                ruleContext.attributeError("outs", "file name must end in '.so'");
            }
            if (createDynamicLibrary) {
                soImplArtifact = ruleContext.getBinArtifact(soImplFilename);
            }
        }
    }
    if (ruleContext.getRule().isAttrDefined("srcs", BuildType.LABEL_LIST)) {
        ruleContext.checkSrcsSamePackage(true);
    }
    if (ruleContext.getRule().isAttrDefined("textual_hdrs", BuildType.LABEL_LIST)) {
        helper.addPublicTextualHeaders(ruleContext.getPrerequisiteArtifacts("textual_hdrs", Mode.TARGET).list());
    }
    if (common.getLinkopts().contains("-static")) {
        ruleContext.attributeWarning("linkopts", "Using '-static' here won't work. " + "Did you mean to use 'linkstatic=1' instead?");
    }
    helper.setCreateDynamicLibrary(createDynamicLibrary);
    helper.setDynamicLibrary(soImplArtifact);
    // which only happens when some rule explicitly depends on the dynamic library.
    if (!createDynamicLibrary && !supportsDynamicLinker) {
        Artifact solibArtifact = CppHelper.getLinuxLinkedArtifact(ruleContext, ruleContext.getConfiguration(), LinkTargetType.DYNAMIC_LIBRARY);
        ruleContext.registerAction(new FailAction(ruleContext.getActionOwner(), ImmutableList.of(solibArtifact), "Toolchain does not support dynamic linking"));
    } else if (!createDynamicLibrary && ruleContext.attributes().isConfigurable("srcs")) {
        // If "srcs" is configurable, the .so output is always declared because the logic that
        // determines implicit outs doesn't know which value of "srcs" will ultimately get chosen.
        // Here, where we *do* have the correct value, it may not contain any source files to
        // generate an .so with. If that's the case, register a fake generating action to prevent
        // a "no generating action for this artifact" error.
        Artifact solibArtifact = CppHelper.getLinuxLinkedArtifact(ruleContext, ruleContext.getConfiguration(), LinkTargetType.DYNAMIC_LIBRARY);
        ruleContext.registerAction(new FailAction(ruleContext.getActionOwner(), ImmutableList.of(solibArtifact), "configurable \"srcs\" triggers an implicit .so output " + "even though there are no sources to compile in this configuration"));
    }
    /*
     * Add the libraries from srcs, if any. For static/mostly static
     * linking we setup the dynamic libraries if there are no static libraries
     * to choose from. Path to the libraries will be mangled to avoid using
     * absolute path names on the -rpath, but library filenames will be
     * preserved (since some libraries might have SONAME tag) - symlink will
     * be created to the parent directory instead.
     *
     * For compatibility with existing BUILD files, any ".a" or ".lo" files listed in
     * srcs are assumed to be position-independent code, or at least suitable for
     * inclusion in shared libraries, unless they end with ".nopic.a" or ".nopic.lo".
     *
     * Note that some target platforms do not require shared library code to be PIC.
     */
    Iterable<LibraryToLink> staticLibrariesFromSrcs = LinkerInputs.opaqueLibrariesToLink(ArtifactCategory.STATIC_LIBRARY, precompiledFiles.getStaticLibraries());
    Iterable<LibraryToLink> alwayslinkLibrariesFromSrcs = LinkerInputs.opaqueLibrariesToLink(ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY, precompiledFiles.getAlwayslinkStaticLibraries());
    Iterable<LibraryToLink> picStaticLibrariesFromSrcs = LinkerInputs.opaqueLibrariesToLink(ArtifactCategory.STATIC_LIBRARY, precompiledFiles.getPicStaticLibraries());
    Iterable<LibraryToLink> picAlwayslinkLibrariesFromSrcs = LinkerInputs.opaqueLibrariesToLink(ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY, precompiledFiles.getPicAlwayslinkLibraries());
    helper.addStaticLibraries(staticLibrariesFromSrcs);
    helper.addStaticLibraries(alwayslinkLibrariesFromSrcs);
    helper.addPicStaticLibraries(picStaticLibrariesFromSrcs);
    helper.addPicStaticLibraries(picAlwayslinkLibrariesFromSrcs);
    helper.addDynamicLibraries(Iterables.transform(precompiledFiles.getSharedLibraries(), new Function<Artifact, LibraryToLink>() {

        @Override
        public LibraryToLink apply(Artifact library) {
            return LinkerInputs.solibLibraryToLink(common.getDynamicLibrarySymlink(library, true), library, CcLinkingOutputs.libraryIdentifierOf(library));
        }
    }));
    CcLibraryHelper.Info info = helper.build();
    /*
     * We always generate a static library, even if there aren't any source files.
     * This keeps things simpler by avoiding special cases when making use of the library.
     * For example, this is needed to ensure that building a library with "bazel build"
     * will also build all of the library's "deps".
     * However, we only generate a dynamic library if there are source files.
     */
    // For now, we don't add the precompiled libraries to the files to build.
    CcLinkingOutputs linkedLibraries = info.getCcLinkingOutputsExcludingPrecompiledLibraries();
    NestedSetBuilder<Artifact> filesBuilder = NestedSetBuilder.stableOrder();
    filesBuilder.addAll(LinkerInputs.toLibraryArtifacts(linkedLibraries.getStaticLibraries()));
    filesBuilder.addAll(LinkerInputs.toLibraryArtifacts(linkedLibraries.getPicStaticLibraries()));
    filesBuilder.addAll(LinkerInputs.toNonSolibArtifacts(linkedLibraries.getDynamicLibraries()));
    filesBuilder.addAll(LinkerInputs.toNonSolibArtifacts(linkedLibraries.getExecutionDynamicLibraries()));
    CcLinkingOutputs linkingOutputs = info.getCcLinkingOutputs();
    if (!featureConfiguration.isEnabled(CppRuleClasses.HEADER_MODULE_CODEGEN)) {
        warnAboutEmptyLibraries(ruleContext, info.getCcCompilationOutputs(), linkStatic);
    }
    NestedSet<Artifact> filesToBuild = filesBuilder.build();
    Runfiles staticRunfiles = collectRunfiles(ruleContext, linkingOutputs, ccToolchain, neverLink, addDynamicRuntimeInputArtifactsToRunfiles, true);
    Runfiles sharedRunfiles = collectRunfiles(ruleContext, linkingOutputs, ccToolchain, neverLink, addDynamicRuntimeInputArtifactsToRunfiles, false);
    List<Artifact> instrumentedObjectFiles = new ArrayList<>();
    instrumentedObjectFiles.addAll(info.getCcCompilationOutputs().getObjectFiles(false));
    instrumentedObjectFiles.addAll(info.getCcCompilationOutputs().getObjectFiles(true));
    InstrumentedFilesProvider instrumentedFilesProvider = common.getInstrumentedFilesProvider(instrumentedObjectFiles, /*withBaselineCoverage=*/
    true);
    CppHelper.maybeAddStaticLinkMarkerProvider(targetBuilder, ruleContext);
    targetBuilder.setFilesToBuild(filesToBuild).addProviders(info.getProviders()).addSkylarkTransitiveInfo(CcSkylarkApiProvider.NAME, new CcSkylarkApiProvider()).addOutputGroups(info.getOutputGroups()).addProvider(InstrumentedFilesProvider.class, instrumentedFilesProvider).addProvider(RunfilesProvider.class, RunfilesProvider.withData(staticRunfiles, sharedRunfiles)).addProvider(CppRunfilesProvider.class, new CppRunfilesProvider(staticRunfiles, sharedRunfiles)).addOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL, collectHiddenTopLevelArtifacts(ruleContext, info.getCcCompilationOutputs())).addOutputGroup(CcLibraryHelper.HIDDEN_HEADER_TOKENS, CcLibraryHelper.collectHeaderTokens(ruleContext, info.getCcCompilationOutputs()));
}
Also used : FailAction(com.google.devtools.build.lib.actions.FailAction) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) ArrayList(java.util.ArrayList) Function(com.google.common.base.Function) ImplicitOutputsFunction(com.google.devtools.build.lib.packages.ImplicitOutputsFunction) InstrumentedFilesProvider(com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider) FeatureConfiguration(com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration) RunfilesProvider(com.google.devtools.build.lib.analysis.RunfilesProvider) Artifact(com.google.devtools.build.lib.actions.Artifact) LibraryToLink(com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink) Runfiles(com.google.devtools.build.lib.analysis.Runfiles)

Example 7 with LibraryToLink

use of com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink in project bazel by bazelbuild.

the class CcLinkingOutputs method filterCandidates.

/**
   * Helper method to filter the candidates by removing equivalent library
   * entries from the list of candidates.
   *
   * @param candidates the library candidates to filter
   * @return the list of libraries with equivalent duplicate libraries removed.
   */
private List<LibraryToLink> filterCandidates(List<LibraryToLink> candidates) {
    List<LibraryToLink> libraries = new ArrayList<>();
    Set<String> identifiers = new HashSet<>();
    for (LibraryToLink library : candidates) {
        Preconditions.checkNotNull(library.getLibraryIdentifier());
        if (identifiers.add(library.getLibraryIdentifier())) {
            libraries.add(library);
        }
    }
    return libraries;
}
Also used : LibraryToLink(com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 8 with LibraryToLink

use of com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink in project bazel by bazelbuild.

the class ObjcProvider method subtractSubtrees.

/**
   * Subtracts dependency subtrees from this provider and returns the result (subtraction does not
   * mutate this provider). Note that not all provider keys are subtracted; generally only keys
   * which correspond with compiled libraries will be subtracted.
   * 
   * <p>This is an expensive operation, as it requires flattening of all nested sets contained
   * in each provider.
   *
   * @param avoidObjcProviders objc providers which contain the dependency subtrees to subtract
   * @param avoidCcProviders cc providers which contain the dependency subtrees to subtract
   */
// TODO(b/19795062): Investigate subtraction generalized to NestedSet.
public ObjcProvider subtractSubtrees(Iterable<ObjcProvider> avoidObjcProviders, Iterable<CcLinkParamsProvider> avoidCcProviders) {
    // LIBRARY and CC_LIBRARY need to be special cased for objc-cc interop.
    // A library which is a dependency of a cc_library may be present in all or any of 
    // three possible locations (and may be duplicated!):
    // 1. ObjcProvider.LIBRARY
    // 2. ObjcProvider.CC_LIBRARY
    // 3. CcLinkParamsProvider->LibraryToLink->getArtifact()
    // TODO(cpeyser): Clean up objc-cc interop.
    HashSet<Artifact> avoidLibrariesSet = new HashSet<>();
    for (CcLinkParamsProvider linkProvider : avoidCcProviders) {
        NestedSet<LibraryToLink> librariesToLink = linkProvider.getCcLinkParams(true, false).getLibraries();
        for (LibraryToLink libraryToLink : librariesToLink.toList()) {
            avoidLibrariesSet.add(libraryToLink.getArtifact());
        }
    }
    for (ObjcProvider avoidProvider : avoidObjcProviders) {
        avoidLibrariesSet.addAll(avoidProvider.getCcLibraries());
        for (Artifact libraryToAvoid : avoidProvider.getPropagable(LIBRARY)) {
            avoidLibrariesSet.add(libraryToAvoid);
        }
    }
    ObjcProvider.Builder objcProviderBuilder = new ObjcProvider.Builder();
    for (Key<?> key : getValuedKeys()) {
        if (key == CC_LIBRARY) {
            addTransitiveAndFilter(objcProviderBuilder, CC_LIBRARY, ccLibraryNotYetLinked(avoidLibrariesSet));
        } else if (key == LIBRARY) {
            addTransitiveAndFilter(objcProviderBuilder, LIBRARY, notContainedIn(avoidLibrariesSet));
        } else if (NON_SUBTRACTABLE_KEYS.contains(key)) {
            addTransitiveAndAvoid(objcProviderBuilder, key, ImmutableList.<ObjcProvider>of());
        } else {
            addTransitiveAndAvoid(objcProviderBuilder, key, avoidObjcProviders);
        }
    }
    return objcProviderBuilder.build();
}
Also used : LibraryToLink(com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink) CcLinkParamsProvider(com.google.devtools.build.lib.rules.cpp.CcLinkParamsProvider) NestedSetBuilder(com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder) Artifact(com.google.devtools.build.lib.actions.Artifact) HashSet(java.util.HashSet)

Example 9 with LibraryToLink

use of com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink in project bazel by bazelbuild.

the class NativeDepsHelper method createNativeDepsAction.

public static NativeDepsRunfiles createNativeDepsAction(final RuleContext ruleContext, CcLinkParams linkParams, Collection<String> extraLinkOpts, BuildConfiguration configuration, CcToolchainProvider toolchain, Artifact nativeDeps, String libraryIdentifier, Root bindirIfShared, boolean useDynamicRuntime) throws InterruptedException {
    Preconditions.checkState(ruleContext.isLegalFragment(CppConfiguration.class), "%s does not have access to CppConfiguration", ruleContext.getRule().getRuleClass());
    List<String> linkopts = new ArrayList<>(extraLinkOpts);
    linkopts.addAll(linkParams.flattenedLinkopts());
    Map<Artifact, NestedSet<Artifact>> linkstamps = CppHelper.resolveLinkstamps(ruleContext, linkParams);
    List<Artifact> buildInfoArtifacts = linkstamps.isEmpty() ? ImmutableList.<Artifact>of() : ruleContext.getAnalysisEnvironment().getBuildInfo(ruleContext, CppBuildInfo.KEY, configuration);
    boolean shareNativeDeps = configuration.getFragment(CppConfiguration.class).shareNativeDeps();
    NestedSet<LibraryToLink> linkerInputs = linkParams.getLibraries();
    Artifact sharedLibrary;
    if (shareNativeDeps) {
        PathFragment sharedPath = getSharedNativeDepsPath(LinkerInputs.toLibraryArtifacts(linkerInputs), linkopts, linkstamps.keySet(), buildInfoArtifacts, ruleContext.getFeatures());
        libraryIdentifier = sharedPath.getPathString();
        sharedLibrary = ruleContext.getShareableArtifact(sharedPath.replaceName(sharedPath.getBaseName() + ".so"), configuration.getBinDirectory(ruleContext.getRule().getRepository()));
    } else {
        sharedLibrary = nativeDeps;
    }
    FdoSupportProvider fdoSupport = CppHelper.getFdoSupport(ruleContext, ":cc_toolchain");
    CppLinkActionBuilder builder = new CppLinkActionBuilder(ruleContext, sharedLibrary, configuration, toolchain, fdoSupport);
    if (useDynamicRuntime) {
        builder.setRuntimeInputs(ArtifactCategory.DYNAMIC_LIBRARY, toolchain.getDynamicRuntimeLinkMiddleman(), toolchain.getDynamicRuntimeLinkInputs());
    } else {
        builder.setRuntimeInputs(ArtifactCategory.STATIC_LIBRARY, toolchain.getStaticRuntimeLinkMiddleman(), toolchain.getStaticRuntimeLinkInputs());
    }
    CppLinkAction linkAction = builder.setLinkArtifactFactory(SHAREABLE_LINK_ARTIFACT_FACTORY).setCrosstoolInputs(toolchain.getLink()).addLibraries(linkerInputs).setLinkType(LinkTargetType.DYNAMIC_LIBRARY).setLinkStaticness(LinkStaticness.MOSTLY_STATIC).setLibraryIdentifier(libraryIdentifier).addLinkopts(linkopts).setNativeDeps(true).addLinkstamps(linkstamps).build();
    ruleContext.registerAction(linkAction);
    Artifact linkerOutput = linkAction.getPrimaryOutput();
    if (shareNativeDeps) {
        // Collect dynamic-linker-resolvable symlinks for C++ runtime library dependencies.
        // Note we only need these symlinks when --share_native_deps is on, as shared native deps
        // mangle path names such that the library's conventional _solib RPATH entry
        // no longer resolves (because the target directory's relative depth gets lost).
        List<Artifact> runtimeSymlinks;
        if (useDynamicRuntime) {
            runtimeSymlinks = new LinkedList<>();
            for (final Artifact runtimeInput : toolchain.getDynamicRuntimeLinkInputs()) {
                final Artifact runtimeSymlink = ruleContext.getPackageRelativeArtifact(getRuntimeLibraryPath(ruleContext, runtimeInput), bindirIfShared);
                // Since runtime library symlinks are underneath the target's output directory and
                // multiple targets may share the same output directory, we need to make sure this
                // symlink's generating action is only set once.
                ruleContext.registerAction(new SymlinkAction(ruleContext.getActionOwner(), runtimeInput, runtimeSymlink, null));
                runtimeSymlinks.add(runtimeSymlink);
            }
        } else {
            runtimeSymlinks = ImmutableList.of();
        }
        ruleContext.registerAction(new SymlinkAction(ruleContext.getActionOwner(), linkerOutput, nativeDeps, null));
        return new NativeDepsRunfiles(nativeDeps, runtimeSymlinks);
    }
    return new NativeDepsRunfiles(linkerOutput, ImmutableList.<Artifact>of());
}
Also used : NestedSet(com.google.devtools.build.lib.collect.nestedset.NestedSet) FdoSupportProvider(com.google.devtools.build.lib.rules.cpp.FdoSupportProvider) SymlinkAction(com.google.devtools.build.lib.analysis.actions.SymlinkAction) ArrayList(java.util.ArrayList) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) Artifact(com.google.devtools.build.lib.actions.Artifact) LibraryToLink(com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink) CppLinkAction(com.google.devtools.build.lib.rules.cpp.CppLinkAction) CppConfiguration(com.google.devtools.build.lib.rules.cpp.CppConfiguration) CppLinkActionBuilder(com.google.devtools.build.lib.rules.cpp.CppLinkActionBuilder)

Example 10 with LibraryToLink

use of com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink in project bazel by bazelbuild.

the class CppLinkActionTest method testToolchainFeatureFlags.

@Test
public void testToolchainFeatureFlags() throws Exception {
    FeatureConfiguration featureConfiguration = CcToolchainFeaturesTest.buildFeatures("feature {", "   name: 'a'", "   flag_set {", "      action: '" + Link.LinkTargetType.EXECUTABLE.getActionName() + "'", "      flag_group { flag: 'some_flag' }", "   }", "}", "action_config {", "   config_name: '" + Link.LinkTargetType.EXECUTABLE.getActionName() + "'", "   action_name: '" + Link.LinkTargetType.EXECUTABLE.getActionName() + "'", "   tool {", "      tool_path: 'toolchain/mock_tool'", "   }", "}").getFeatureConfiguration("a", Link.LinkTargetType.EXECUTABLE.getActionName());
    CppLinkAction linkAction = createLinkBuilder(Link.LinkTargetType.EXECUTABLE, "dummyRuleContext/out", ImmutableList.<Artifact>of(), ImmutableList.<LibraryToLink>of(), featureConfiguration).build();
    assertThat(linkAction.getArgv()).contains("some_flag");
}
Also used : LibraryToLink(com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink) FeatureConfiguration(com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration) Artifact(com.google.devtools.build.lib.actions.Artifact) Test(org.junit.Test)

Aggregations

LibraryToLink (com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink)14 Artifact (com.google.devtools.build.lib.actions.Artifact)12 PathFragment (com.google.devtools.build.lib.vfs.PathFragment)6 NestedSetBuilder (com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder)4 FeatureConfiguration (com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration)4 ArrayList (java.util.ArrayList)4 Runfiles (com.google.devtools.build.lib.analysis.Runfiles)3 ImmutableList (com.google.common.collect.ImmutableList)2 ImmutableSet (com.google.common.collect.ImmutableSet)2 NestedSet (com.google.devtools.build.lib.collect.nestedset.NestedSet)2 LinkTargetType (com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 LinkedHashSet (java.util.LinkedHashSet)2 Test (org.junit.Test)2 Function (com.google.common.base.Function)1 Builder (com.google.common.collect.ImmutableSet.Builder)1 ImmutableSetMultimap (com.google.common.collect.ImmutableSetMultimap)1 Action (com.google.devtools.build.lib.actions.Action)1 FailAction (com.google.devtools.build.lib.actions.FailAction)1