Search in sources :

Example 16 with Artifact

use of com.google.devtools.build.lib.actions.Artifact in project bazel by bazelbuild.

the class CcBinary method init.

public static ConfiguredTarget init(CppSemantics semantics, RuleContext ruleContext, boolean fake) throws InterruptedException, RuleErrorException {
    ruleContext.checkSrcsSamePackage(true);
    CcCommon common = new CcCommon(ruleContext);
    CcToolchainProvider ccToolchain = common.getToolchain();
    FdoSupportProvider fdoSupport = common.getFdoSupport();
    FeatureConfiguration featureConfiguration = CcCommon.configureFeatures(ruleContext, ccToolchain);
    CppConfiguration cppConfiguration = ruleContext.getFragment(CppConfiguration.class);
    PrecompiledFiles precompiledFiles = new PrecompiledFiles(ruleContext);
    LinkTargetType linkType = isLinkShared(ruleContext) ? LinkTargetType.DYNAMIC_LIBRARY : LinkTargetType.EXECUTABLE;
    semantics.validateAttributes(ruleContext);
    if (ruleContext.hasErrors()) {
        return null;
    }
    List<String> linkopts = common.getLinkopts();
    LinkStaticness linkStaticness = getLinkStaticness(ruleContext, linkopts, cppConfiguration);
    // We currently only want link the dynamic library generated for test code separately.
    boolean linkCompileOutputSeparately = ruleContext.isTestTarget() && cppConfiguration.getLinkCompileOutputSeparately() && linkStaticness == LinkStaticness.DYNAMIC;
    CcLibraryHelper helper = new CcLibraryHelper(ruleContext, semantics, featureConfiguration, ccToolchain, fdoSupport).fromCommon(common).addSources(common.getSources()).addDeps(ImmutableList.of(CppHelper.mallocForTarget(ruleContext))).setFake(fake).addPrecompiledFiles(precompiledFiles).enableInterfaceSharedObjects();
    // When linking the object files directly into the resulting binary, we do not need
    // library-level link outputs; thus, we do not let CcLibraryHelper produce link outputs
    // (either shared object files or archives) for a non-library link type [*], and add
    // the object files explicitly in determineLinkerArguments.
    //
    // When linking the object files into their own library, we want CcLibraryHelper to
    // take care of creating the library link outputs for us, so we need to set the link
    // type to STATIC_LIBRARY.
    //
    // [*] The only library link type is STATIC_LIBRARY. EXECUTABLE specifies a normal
    // cc_binary output, while DYNAMIC_LIBRARY is a cc_binary rules that produces an
    // output matching a shared object, for example cc_binary(name="foo.so", ...) on linux.
    helper.setLinkType(linkCompileOutputSeparately ? LinkTargetType.STATIC_LIBRARY : linkType);
    CcLibraryHelper.Info info = helper.build();
    CppCompilationContext cppCompilationContext = info.getCppCompilationContext();
    CcCompilationOutputs ccCompilationOutputs = info.getCcCompilationOutputs();
    // if cc_binary includes "linkshared=1", then gcc will be invoked with
    // linkopt "-shared", which causes the result of linking to be a shared
    // library. In this case, the name of the executable target should end
    // in ".so" or "dylib" or ".dll".
    PathFragment binaryPath = new PathFragment(ruleContext.getTarget().getName());
    if (!isLinkShared(ruleContext)) {
        binaryPath = new PathFragment(binaryPath.getPathString() + OsUtils.executableExtension());
    }
    Artifact binary = ruleContext.getBinArtifact(binaryPath);
    if (isLinkShared(ruleContext) && !CppFileTypes.SHARED_LIBRARY.matches(binary.getFilename()) && !CppFileTypes.VERSIONED_SHARED_LIBRARY.matches(binary.getFilename())) {
        ruleContext.attributeError("linkshared", "'linkshared' used in non-shared library");
        return null;
    }
    CppLinkActionBuilder linkActionBuilder = determineLinkerArguments(ruleContext, ccToolchain, fdoSupport, common, precompiledFiles, info, cppCompilationContext.getTransitiveCompilationPrerequisites(), fake, binary, linkStaticness, linkopts, linkCompileOutputSeparately);
    linkActionBuilder.setUseTestOnlyFlags(ruleContext.isTestTarget());
    if (linkStaticness == LinkStaticness.DYNAMIC) {
        linkActionBuilder.setRuntimeInputs(ArtifactCategory.DYNAMIC_LIBRARY, ccToolchain.getDynamicRuntimeLinkMiddleman(), ccToolchain.getDynamicRuntimeLinkInputs());
    } else {
        linkActionBuilder.setRuntimeInputs(ArtifactCategory.STATIC_LIBRARY, ccToolchain.getStaticRuntimeLinkMiddleman(), ccToolchain.getStaticRuntimeLinkInputs());
        // TODO(bazel-team): Move this to CcToolchain.
        if (!ccToolchain.getStaticRuntimeLinkInputs().isEmpty()) {
            linkActionBuilder.addLinkopt("-static-libgcc");
        }
    }
    linkActionBuilder.setLinkType(linkType);
    linkActionBuilder.setLinkStaticness(linkStaticness);
    linkActionBuilder.setFake(fake);
    linkActionBuilder.setFeatureConfiguration(featureConfiguration);
    if (CppLinkAction.enableSymbolsCounts(cppConfiguration, fake, linkType)) {
        linkActionBuilder.setSymbolCountsOutput(ruleContext.getBinArtifact(CppLinkAction.symbolCountsFileName(binaryPath)));
    }
    if (isLinkShared(ruleContext)) {
        linkActionBuilder.setLibraryIdentifier(CcLinkingOutputs.libraryIdentifierOf(binary));
    }
    // Store immutable context for use in other *_binary rules that are implemented by
    // linking the interpreter (Java, Python, etc.) together with native deps.
    CppLinkAction.Context linkContext = new CppLinkAction.Context(linkActionBuilder);
    Iterable<LTOBackendArtifacts> ltoBackendArtifacts = ImmutableList.of();
    boolean usePic = CppHelper.usePic(ruleContext, !isLinkShared(ruleContext));
    if (featureConfiguration.isEnabled(CppRuleClasses.THIN_LTO)) {
        linkActionBuilder.setLTOIndexing(true);
        linkActionBuilder.setUsePicForLTOBackendActions(usePic);
        linkActionBuilder.setUseFissionForLTOBackendActions(cppConfiguration.useFission());
        CppLinkAction indexAction = linkActionBuilder.build();
        ruleContext.registerAction(indexAction);
        ltoBackendArtifacts = indexAction.getAllLTOBackendArtifacts();
        linkActionBuilder.setLTOIndexing(false);
    }
    CppLinkAction linkAction = linkActionBuilder.build();
    ruleContext.registerAction(linkAction);
    LibraryToLink outputLibrary = linkAction.getOutputLibrary();
    Iterable<Artifact> fakeLinkerInputs = fake ? linkAction.getInputs() : ImmutableList.<Artifact>of();
    Artifact executable = linkAction.getLinkOutput();
    CcLinkingOutputs.Builder linkingOutputsBuilder = new CcLinkingOutputs.Builder();
    if (isLinkShared(ruleContext)) {
        linkingOutputsBuilder.addDynamicLibrary(outputLibrary);
        linkingOutputsBuilder.addExecutionDynamicLibrary(outputLibrary);
    }
    // Also add all shared libraries from srcs.
    for (Artifact library : precompiledFiles.getSharedLibraries()) {
        Artifact symlink = common.getDynamicLibrarySymlink(library, true);
        LibraryToLink symlinkLibrary = LinkerInputs.solibLibraryToLink(symlink, library, CcLinkingOutputs.libraryIdentifierOf(library));
        linkingOutputsBuilder.addDynamicLibrary(symlinkLibrary);
        linkingOutputsBuilder.addExecutionDynamicLibrary(symlinkLibrary);
    }
    CcLinkingOutputs linkingOutputs = linkingOutputsBuilder.build();
    NestedSet<Artifact> filesToBuild = NestedSetBuilder.create(Order.STABLE_ORDER, executable);
    // Create the stripped binary, but don't add it to filesToBuild; it's only built when requested.
    Artifact strippedFile = ruleContext.getImplicitOutputArtifact(CppRuleClasses.CC_BINARY_STRIPPED);
    CppHelper.createStripAction(ruleContext, ccToolchain, cppConfiguration, executable, strippedFile);
    DwoArtifactsCollector dwoArtifacts = collectTransitiveDwoArtifacts(ruleContext, ccCompilationOutputs, linkStaticness, cppConfiguration.useFission(), usePic, ltoBackendArtifacts);
    Artifact dwpFile = ruleContext.getImplicitOutputArtifact(CppRuleClasses.CC_BINARY_DEBUG_PACKAGE);
    createDebugPackagerActions(ruleContext, ccToolchain, cppConfiguration, dwpFile, dwoArtifacts);
    // The debug package should include the dwp file only if it was explicitly requested.
    Artifact explicitDwpFile = dwpFile;
    if (!cppConfiguration.useFission()) {
        explicitDwpFile = null;
    } else {
        // built statically.
        if (TargetUtils.isTestRule(ruleContext.getRule()) && linkStaticness != LinkStaticness.DYNAMIC && cppConfiguration.shouldBuildTestDwp()) {
            filesToBuild = NestedSetBuilder.fromNestedSet(filesToBuild).add(dwpFile).build();
        }
    }
    // TODO(bazel-team): Do we need to put original shared libraries (along with
    // mangled symlinks) into the RunfilesSupport object? It does not seem
    // logical since all symlinked libraries will be linked anyway and would
    // not require manual loading but if we do, then we would need to collect
    // their names and use a different constructor below.
    Runfiles runfiles = collectRunfiles(ruleContext, ccToolchain, linkingOutputs, info, linkStaticness, filesToBuild, fakeLinkerInputs, fake, helper.getCompilationUnitSources(), linkCompileOutputSeparately);
    RunfilesSupport runfilesSupport = RunfilesSupport.withExecutable(ruleContext, runfiles, executable, ruleContext.getConfiguration().buildRunfiles());
    TransitiveLipoInfoProvider transitiveLipoInfo;
    if (cppConfiguration.isLipoContextCollector()) {
        transitiveLipoInfo = common.collectTransitiveLipoLabels(ccCompilationOutputs);
    } else {
        transitiveLipoInfo = TransitiveLipoInfoProvider.EMPTY;
    }
    RuleConfiguredTargetBuilder ruleBuilder = new RuleConfiguredTargetBuilder(ruleContext);
    addTransitiveInfoProviders(ruleContext, cppConfiguration, common, ruleBuilder, filesToBuild, ccCompilationOutputs, cppCompilationContext, linkingOutputs, dwoArtifacts, transitiveLipoInfo, fake);
    Map<Artifact, IncludeScannable> scannableMap = new LinkedHashMap<>();
    Map<PathFragment, Artifact> sourceFileMap = new LinkedHashMap<>();
    if (cppConfiguration.isLipoContextCollector()) {
        for (IncludeScannable scannable : transitiveLipoInfo.getTransitiveIncludeScannables()) {
            // These should all be CppCompileActions, which should have only one source file.
            // This is also checked when they are put into the nested set.
            Artifact source = Iterables.getOnlyElement(scannable.getIncludeScannerSources());
            scannableMap.put(source, scannable);
            sourceFileMap.put(source.getExecPath(), source);
        }
    }
    // Support test execution on darwin.
    if (Platform.isApplePlatform(cppConfiguration.getTargetCpu()) && TargetUtils.isTestRule(ruleContext.getRule())) {
        ruleBuilder.addNativeDeclaredProvider(new ExecutionInfoProvider(ImmutableMap.of(ExecutionRequirements.REQUIRES_DARWIN, "")));
    }
    return ruleBuilder.addProvider(RunfilesProvider.class, RunfilesProvider.simple(runfiles)).addProvider(CppDebugPackageProvider.class, new CppDebugPackageProvider(ruleContext.getLabel(), strippedFile, executable, explicitDwpFile)).setRunfilesSupport(runfilesSupport, executable).addProvider(LipoContextProvider.class, new LipoContextProvider(cppCompilationContext, ImmutableMap.copyOf(scannableMap), ImmutableMap.copyOf(sourceFileMap))).addProvider(CppLinkAction.Context.class, linkContext).addSkylarkTransitiveInfo(CcSkylarkApiProvider.NAME, new CcSkylarkApiProvider()).build();
}
Also used : NestedSetBuilder(com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder) RuleConfiguredTargetBuilder(com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) LinkedHashMap(java.util.LinkedHashMap) ExecutionInfoProvider(com.google.devtools.build.lib.rules.test.ExecutionInfoProvider) RunfilesSupport(com.google.devtools.build.lib.analysis.RunfilesSupport) RuleContext(com.google.devtools.build.lib.analysis.RuleContext) FeatureConfiguration(com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration) Artifact(com.google.devtools.build.lib.actions.Artifact) LinkTargetType(com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType) LibraryToLink(com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink) Runfiles(com.google.devtools.build.lib.analysis.Runfiles) LinkStaticness(com.google.devtools.build.lib.rules.cpp.Link.LinkStaticness) RuleConfiguredTargetBuilder(com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder)

Example 17 with Artifact

use of com.google.devtools.build.lib.actions.Artifact in project bazel by bazelbuild.

the class CcBinary method determineLinkerArguments.

/**
   * Given 'temps', traverse this target and its dependencies and collect up all the object files,
   * libraries, linker options, linkstamps attributes and linker scripts.
   */
private static CppLinkActionBuilder determineLinkerArguments(RuleContext context, CcToolchainProvider toolchain, FdoSupportProvider fdoSupport, CcCommon common, PrecompiledFiles precompiledFiles, CcLibraryHelper.Info info, ImmutableSet<Artifact> compilationPrerequisites, boolean fake, Artifact binary, LinkStaticness linkStaticness, List<String> linkopts, boolean linkCompileOutputSeparately) throws InterruptedException {
    CppLinkActionBuilder builder = new CppLinkActionBuilder(context, binary, toolchain, fdoSupport).setCrosstoolInputs(toolchain.getLink()).addNonCodeInputs(compilationPrerequisites);
    // generated dynamic library they are compiled into.
    if (linkCompileOutputSeparately) {
        for (LibraryToLink library : info.getCcLinkingOutputs().getDynamicLibraries()) {
            builder.addLibrary(library);
        }
    } else {
        boolean usePic = CppHelper.usePic(context, !isLinkShared(context));
        Iterable<Artifact> objectFiles = info.getCcCompilationOutputs().getObjectFiles(usePic);
        if (fake) {
            builder.addFakeObjectFiles(objectFiles);
        } else {
            builder.addObjectFiles(objectFiles);
        }
    }
    builder.addLTOBitcodeFiles(info.getCcCompilationOutputs().getLtoBitcodeFiles());
    builder.addNonCodeInputs(common.getLinkerScripts());
    // entries during linking process.
    for (Artifact library : precompiledFiles.getLibraries()) {
        if (Link.SHARED_LIBRARY_FILETYPES.matches(library.getFilename())) {
            builder.addLibrary(LinkerInputs.solibLibraryToLink(common.getDynamicLibrarySymlink(library, true), library, CcLinkingOutputs.libraryIdentifierOf(library)));
        } else if (Link.LINK_LIBRARY_FILETYPES.matches(library.getFilename())) {
            builder.addLibrary(LinkerInputs.precompiledLibraryToLink(library, ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY));
        } else if (Link.ARCHIVE_FILETYPES.matches(library.getFilename())) {
            builder.addLibrary(LinkerInputs.precompiledLibraryToLink(library, ArtifactCategory.STATIC_LIBRARY));
        } else {
            throw new IllegalStateException();
        }
    }
    // Then the link params from the closure of deps.
    CcLinkParams linkParams = collectCcLinkParams(context, linkStaticness != LinkStaticness.DYNAMIC, isLinkShared(context), linkopts);
    builder.addLinkParams(linkParams, context);
    return builder;
}
Also used : LibraryToLink(com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink) Artifact(com.google.devtools.build.lib.actions.Artifact)

Example 18 with Artifact

use of com.google.devtools.build.lib.actions.Artifact in project bazel by bazelbuild.

the class CcCommon method getLooseIncludeDirs.

/**
   * Determines a list of loose include directories that are only allowed to be referenced when
   * headers checking is {@link HeadersCheckingMode#LOOSE} or {@link HeadersCheckingMode#WARN}.
   */
List<PathFragment> getLooseIncludeDirs() {
    List<PathFragment> result = new ArrayList<>();
    // The package directory of the rule contributes includes. Note that this also covers all
    // non-subpackage sub-directories.
    PathFragment rulePackage = ruleContext.getLabel().getPackageIdentifier().getPathUnderExecRoot();
    result.add(rulePackage);
    // Gather up all the dirs from the rule's srcs as well as any of the srcs outputs.
    if (hasAttribute("srcs", BuildType.LABEL_LIST)) {
        for (TransitiveInfoCollection src : ruleContext.getPrerequisitesIf("srcs", Mode.TARGET, FileProvider.class)) {
            PathFragment packageDir = src.getLabel().getPackageIdentifier().getPathUnderExecRoot();
            for (Artifact a : src.getProvider(FileProvider.class).getFilesToBuild()) {
                result.add(packageDir);
                // Attempt to gather subdirectories that might contain include files.
                result.add(a.getRootRelativePath().getParentDirectory());
            }
        }
    }
    // Add in any 'includes' attribute values as relative path fragments
    if (ruleContext.getRule().isAttributeValueExplicitlySpecified("includes")) {
        PathFragment packageFragment = ruleContext.getLabel().getPackageIdentifier().getPathUnderExecRoot();
        // For now, anything with an 'includes' needs a blanket declaration
        result.add(packageFragment.getRelative("**"));
    }
    return result;
}
Also used : FileProvider(com.google.devtools.build.lib.analysis.FileProvider) ArrayList(java.util.ArrayList) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) TransitiveInfoCollection(com.google.devtools.build.lib.analysis.TransitiveInfoCollection) Artifact(com.google.devtools.build.lib.actions.Artifact)

Example 19 with Artifact

use of com.google.devtools.build.lib.actions.Artifact in project bazel by bazelbuild.

the class CcCommon method getSources.

/**
   * Returns a list of ({@link Artifact}, {@link Label}) pairs. Each pair represents an input
   * source file and the label of the rule that generates it (or the label of the source file
   * itself if it is an input file).
   */
List<Pair<Artifact, Label>> getSources() {
    Map<Artifact, Label> map = Maps.newLinkedHashMap();
    Iterable<? extends TransitiveInfoCollection> providers = ruleContext.getPrerequisitesIf("srcs", Mode.TARGET, FileProvider.class);
    for (TransitiveInfoCollection provider : providers) {
        for (Artifact artifact : provider.getProvider(FileProvider.class).getFilesToBuild()) {
            // TODO(bazel-team): We currently do not produce an error for duplicate headers and other
            // non-source artifacts with different labels, as that would require cleaning up the code
            // base without significant benefit; we should eventually make this consistent one way or
            // the other.
            Label oldLabel = map.put(artifact, provider.getLabel());
            boolean isHeader = CppFileTypes.CPP_HEADER.matches(artifact.getExecPath());
            if (!isHeader && SourceCategory.CC_AND_OBJC.getSourceTypes().matches(artifact.getExecPathString()) && oldLabel != null && !oldLabel.equals(provider.getLabel())) {
                ruleContext.attributeError("srcs", String.format("Artifact '%s' is duplicated (through '%s' and '%s')", artifact.getExecPathString(), oldLabel, provider.getLabel()));
            }
        }
    }
    ImmutableList.Builder<Pair<Artifact, Label>> result = ImmutableList.builder();
    for (Map.Entry<Artifact, Label> entry : map.entrySet()) {
        result.add(Pair.of(entry.getKey(), entry.getValue()));
    }
    return result.build();
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) FileProvider(com.google.devtools.build.lib.analysis.FileProvider) Label(com.google.devtools.build.lib.cmdline.Label) TransitiveInfoCollection(com.google.devtools.build.lib.analysis.TransitiveInfoCollection) Map(java.util.Map) Artifact(com.google.devtools.build.lib.actions.Artifact) Pair(com.google.devtools.build.lib.util.Pair)

Example 20 with Artifact

use of com.google.devtools.build.lib.actions.Artifact in project bazel by bazelbuild.

the class CcCommon method collectCompilationPrerequisites.

/**
   * Collects compilation prerequisite artifacts.
   */
static NestedSet<Artifact> collectCompilationPrerequisites(RuleContext ruleContext, CppCompilationContext context) {
    // TODO(bazel-team): Use context.getCompilationPrerequisites() instead; note that this will
    // need cleaning up the prerequisites, as the compilation context currently collects them
    // transitively (to get transitive headers), but source files are not transitive compilation
    // prerequisites.
    NestedSetBuilder<Artifact> prerequisites = NestedSetBuilder.stableOrder();
    if (ruleContext.attributes().has("srcs", BuildType.LABEL_LIST)) {
        for (FileProvider provider : ruleContext.getPrerequisites("srcs", Mode.TARGET, FileProvider.class)) {
            prerequisites.addAll(FileType.filter(provider.getFilesToBuild(), SourceCategory.CC_AND_OBJC.getSourceTypes()));
        }
    }
    prerequisites.addTransitive(context.getDeclaredIncludeSrcs());
    prerequisites.addTransitive(context.getAdditionalInputs());
    prerequisites.addTransitive(context.getTransitiveModules(true));
    prerequisites.addTransitive(context.getTransitiveModules(false));
    return prerequisites.build();
}
Also used : FileProvider(com.google.devtools.build.lib.analysis.FileProvider) Artifact(com.google.devtools.build.lib.actions.Artifact)

Aggregations

Artifact (com.google.devtools.build.lib.actions.Artifact)659 Test (org.junit.Test)242 PathFragment (com.google.devtools.build.lib.vfs.PathFragment)184 TreeFileArtifact (com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact)83 SpecialArtifact (com.google.devtools.build.lib.actions.Artifact.SpecialArtifact)65 NestedSetBuilder (com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder)64 ConfiguredTarget (com.google.devtools.build.lib.analysis.ConfiguredTarget)51 RuleConfiguredTargetBuilder (com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder)50 ImmutableList (com.google.common.collect.ImmutableList)46 Action (com.google.devtools.build.lib.actions.Action)42 IOException (java.io.IOException)42 ArrayList (java.util.ArrayList)40 SpawnAction (com.google.devtools.build.lib.analysis.actions.SpawnAction)38 Path (com.google.devtools.build.lib.vfs.Path)37 HashMap (java.util.HashMap)37 Map (java.util.Map)36 Root (com.google.devtools.build.lib.actions.Root)31 LinkedHashMap (java.util.LinkedHashMap)31 ImmutableMap (com.google.common.collect.ImmutableMap)28 TransitiveInfoCollection (com.google.devtools.build.lib.analysis.TransitiveInfoCollection)28