Search in sources :

Example 26 with Artifact

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

the class CppLinkActionBuilder method createLTOArtifacts.

private Iterable<LTOBackendArtifacts> createLTOArtifacts(PathFragment ltoOutputRootPrefix, NestedSet<LibraryToLink> uniqueLibraries) {
    Set<Artifact> compiled = new LinkedHashSet<>();
    for (LibraryToLink lib : uniqueLibraries) {
        Iterables.addAll(compiled, lib.getLTOBitcodeFiles());
    }
    // This flattens the set of object files, so for M binaries and N .o files,
    // this is O(M*N). If we had a nested set of .o files, we could have O(M + N) instead.
    Map<PathFragment, Artifact> allBitcode = new HashMap<>();
    for (LibraryToLink lib : uniqueLibraries) {
        if (!lib.containsObjectFiles()) {
            continue;
        }
        for (Artifact a : lib.getObjectFiles()) {
            if (compiled.contains(a)) {
                allBitcode.put(a.getExecPath(), a);
            }
        }
    }
    for (LinkerInput input : objectFiles) {
        if (this.ltoBitcodeFiles.contains(input.getArtifact())) {
            allBitcode.put(input.getArtifact().getExecPath(), input.getArtifact());
        }
    }
    ImmutableList.Builder<LTOBackendArtifacts> ltoOutputs = ImmutableList.builder();
    for (Artifact a : allBitcode.values()) {
        LTOBackendArtifacts ltoArtifacts = new LTOBackendArtifacts(ltoOutputRootPrefix, a, allBitcode, ruleContext, configuration, linkArtifactFactory);
        ltoOutputs.add(ltoArtifacts);
    }
    return ltoOutputs.build();
}
Also used : LinkedHashSet(java.util.LinkedHashSet) LibraryToLink(com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink) HashMap(java.util.HashMap) ImmutableList(com.google.common.collect.ImmutableList) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) Artifact(com.google.devtools.build.lib.actions.Artifact)

Example 27 with Artifact

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

the class CppModel method createCcLinkActions.

/**
   * Constructs the C++ linker actions. It generally generates two actions, one for a static library
   * and one for a dynamic library. If PIC is required for shared libraries, but not for binaries,
   * it additionally creates a third action to generate a PIC static library.
   *
   * <p>For dynamic libraries, this method can additionally create an interface shared library that
   * can be used for linking, but doesn't contain any executable code. This increases the number of
   * cache hits for link actions. Call {@link #setAllowInterfaceSharedObjects(boolean)} to enable
   * this behavior.
   *
   * @throws RuleErrorException
   */
public CcLinkingOutputs createCcLinkActions(CcCompilationOutputs ccOutputs, Iterable<Artifact> nonCodeLinkerInputs) throws RuleErrorException, InterruptedException {
    // For now only handle static links. Note that the dynamic library link below ignores linkType.
    // TODO(bazel-team): Either support non-static links or move this check to setLinkType().
    Preconditions.checkState(linkType.staticness() == Staticness.STATIC, "can only handle static links");
    CcLinkingOutputs.Builder result = new CcLinkingOutputs.Builder();
    if (cppConfiguration.isLipoContextCollector()) {
        // because it needs some data that's not available at this point.
        return result.build();
    }
    AnalysisEnvironment env = ruleContext.getAnalysisEnvironment();
    boolean usePicForBinaries = CppHelper.usePic(ruleContext, true);
    boolean usePicForSharedLibs = CppHelper.usePic(ruleContext, false);
    // Create static library (.a). The linkType only reflects whether the library is alwayslink or
    // not. The PIC-ness is determined by whether we need to use PIC or not. There are three cases
    // for (usePicForSharedLibs usePicForBinaries):
    //
    // (1) (false false) -> no pic code
    // (2) (true false)  -> shared libraries as pic, but not binaries
    // (3) (true true)   -> both shared libraries and binaries as pic
    //
    // In case (3), we always need PIC, so only create one static library containing the PIC object
    // files. The name therefore does not match the content.
    //
    // Presumably, it is done this way because the .a file is an implicit output of every cc_library
    // rule, so we can't use ".pic.a" that in the always-PIC case.
    // If the crosstool is configured to select an output artifact, we use that selection.
    // Otherwise, we use linux defaults.
    Artifact linkedArtifact = getLinkedArtifact(linkType);
    PathFragment labelName = new PathFragment(ruleContext.getLabel().getName());
    String libraryIdentifier = ruleContext.getPackageDirectory().getRelative(labelName.replaceName("lib" + labelName.getBaseName())).getPathString();
    CppLinkAction maybePicAction = newLinkActionBuilder(linkedArtifact).addObjectFiles(ccOutputs.getObjectFiles(usePicForBinaries)).addNonCodeInputs(nonCodeLinkerInputs).addLTOBitcodeFiles(ccOutputs.getLtoBitcodeFiles()).setLinkType(linkType).setLinkStaticness(LinkStaticness.FULLY_STATIC).addActionInputs(linkActionInputs).setLibraryIdentifier(libraryIdentifier).addVariablesExtensions(variablesExtensions).setFeatureConfiguration(featureConfiguration).build();
    env.registerAction(maybePicAction);
    if (linkType != LinkTargetType.EXECUTABLE) {
        result.addStaticLibrary(maybePicAction.getOutputLibrary());
    }
    // one contains the PIC code, so the names match the content.
    if (!usePicForBinaries && usePicForSharedLibs) {
        LinkTargetType picLinkType = (linkType == LinkTargetType.ALWAYS_LINK_STATIC_LIBRARY) ? LinkTargetType.ALWAYS_LINK_PIC_STATIC_LIBRARY : LinkTargetType.PIC_STATIC_LIBRARY;
        // If the crosstool is configured to select an output artifact, we use that selection.
        // Otherwise, we use linux defaults.
        Artifact picArtifact = getLinkedArtifact(picLinkType);
        CppLinkAction picAction = newLinkActionBuilder(picArtifact).addObjectFiles(ccOutputs.getObjectFiles(true)).addLTOBitcodeFiles(ccOutputs.getLtoBitcodeFiles()).setLinkType(picLinkType).setLinkStaticness(LinkStaticness.FULLY_STATIC).addActionInputs(linkActionInputs).setLibraryIdentifier(libraryIdentifier).addVariablesExtensions(variablesExtensions).setFeatureConfiguration(featureConfiguration).build();
        env.registerAction(picAction);
        if (linkType != LinkTargetType.EXECUTABLE) {
            result.addPicStaticLibrary(picAction.getOutputLibrary());
        }
    }
    if (!createDynamicLibrary) {
        return result.build();
    }
    // Create dynamic library.
    Artifact soImpl;
    String mainLibraryIdentifier;
    if (soImplArtifact == null) {
        // If the crosstool is configured to select an output artifact, we use that selection.
        // Otherwise, we use linux defaults.
        soImpl = getLinkedArtifact(LinkTargetType.DYNAMIC_LIBRARY);
        mainLibraryIdentifier = libraryIdentifier;
    } else {
        // This branch is only used for vestigial Google-internal rules where the name of the output
        // file is explicitly specified in the BUILD file and as such, is platform-dependent. Thus,
        // we just hardcode some reasonable logic to compute the library identifier and hope that this
        // will eventually go away.
        soImpl = soImplArtifact;
        mainLibraryIdentifier = FileSystemUtils.removeExtension(soImpl.getRootRelativePath().getPathString());
    }
    List<String> sonameLinkopts = ImmutableList.of();
    Artifact soInterface = null;
    if (cppConfiguration.useInterfaceSharedObjects() && allowInterfaceSharedObjects) {
        soInterface = CppHelper.getLinuxLinkedArtifact(ruleContext, configuration, LinkTargetType.INTERFACE_DYNAMIC_LIBRARY, linkedArtifactNameSuffix);
        sonameLinkopts = ImmutableList.of("-Wl,-soname=" + SolibSymlinkAction.getDynamicLibrarySoname(soImpl.getRootRelativePath(), false));
    }
    // Should we also link in any libraries that this library depends on?
    // That is required on some systems...
    CppLinkActionBuilder linkActionBuilder = newLinkActionBuilder(soImpl).setInterfaceOutput(soInterface).addObjectFiles(ccOutputs.getObjectFiles(usePicForSharedLibs)).addNonCodeInputs(ccOutputs.getHeaderTokenFiles()).addLTOBitcodeFiles(ccOutputs.getLtoBitcodeFiles()).setLinkType(LinkTargetType.DYNAMIC_LIBRARY).setLinkStaticness(LinkStaticness.DYNAMIC).addActionInputs(linkActionInputs).setLibraryIdentifier(mainLibraryIdentifier).addLinkopts(linkopts).addLinkopts(sonameLinkopts).setRuntimeInputs(ArtifactCategory.DYNAMIC_LIBRARY, ccToolchain.getDynamicRuntimeLinkMiddleman(), ccToolchain.getDynamicRuntimeLinkInputs()).setFeatureConfiguration(featureConfiguration).addVariablesExtensions(variablesExtensions);
    if (!ccOutputs.getLtoBitcodeFiles().isEmpty() && featureConfiguration.isEnabled(CppRuleClasses.THIN_LTO)) {
        linkActionBuilder.setLTOIndexing(true);
        linkActionBuilder.setUsePicForLTOBackendActions(usePicForSharedLibs);
        // If support is ever added for generating a dwp file for shared
        // library targets (e.g. when linkstatic=0), then this should change
        // to generate dwo files when cppConfiguration.useFission(),
        // and the dwp generating action for the shared library should
        // include all of the resulting dwo files.
        linkActionBuilder.setUseFissionForLTOBackendActions(false);
        CppLinkAction indexAction = linkActionBuilder.build();
        env.registerAction(indexAction);
        linkActionBuilder.setLTOIndexing(false);
    }
    CppLinkAction action = linkActionBuilder.build();
    env.registerAction(action);
    if (linkType == LinkTargetType.EXECUTABLE) {
        return result.build();
    }
    LibraryToLink dynamicLibrary = action.getOutputLibrary();
    LibraryToLink interfaceLibrary = action.getInterfaceOutputLibrary();
    if (interfaceLibrary == null) {
        interfaceLibrary = dynamicLibrary;
    }
    // mangled name only.
    if (neverLink) {
        result.addDynamicLibrary(interfaceLibrary);
        result.addExecutionDynamicLibrary(dynamicLibrary);
    } else {
        Artifact libraryLink = SolibSymlinkAction.getDynamicLibrarySymlink(ruleContext, interfaceLibrary.getArtifact(), false, false, ruleContext.getConfiguration());
        result.addDynamicLibrary(LinkerInputs.solibLibraryToLink(libraryLink, interfaceLibrary.getArtifact(), libraryIdentifier));
        Artifact implLibraryLink = SolibSymlinkAction.getDynamicLibrarySymlink(ruleContext, dynamicLibrary.getArtifact(), false, false, ruleContext.getConfiguration());
        result.addExecutionDynamicLibrary(LinkerInputs.solibLibraryToLink(implLibraryLink, dynamicLibrary.getArtifact(), libraryIdentifier));
    }
    return result.build();
}
Also used : Builder(com.google.devtools.build.lib.rules.cpp.CcCompilationOutputs.Builder) StringSequenceBuilder(com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.StringSequenceBuilder) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) 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) AnalysisEnvironment(com.google.devtools.build.lib.analysis.AnalysisEnvironment)

Example 28 with Artifact

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

the class CppModel method createCompileActionTemplate.

private Artifact createCompileActionTemplate(AnalysisEnvironment env, CppSource source, CppCompileActionBuilder builder, Iterable<ArtifactCategory> outputCategories) {
    Artifact sourceArtifact = source.getSource();
    Artifact outputFiles = CppHelper.getCompileOutputTreeArtifact(ruleContext, sourceArtifact);
    // TODO(rduan): Dotd file output is not supported yet.
    builder.setOutputs(outputFiles, null);
    setupCompileBuildVariables(builder, /* usePic=*/
    false, /*ccRelativeName=*/
    null, /*autoFdoImportPath=*/
    null, /*gcnoFile=*/
    null, /*dwoFile=*/
    null, builder.getContext().getCppModuleMap(), source.getBuildVariables());
    semantics.finalizeCompileActionBuilder(ruleContext, builder);
    CppCompileActionTemplate actionTemplate = new CppCompileActionTemplate(sourceArtifact, outputFiles, builder, cppConfiguration, outputCategories, ruleContext.getActionOwner());
    env.registerAction(actionTemplate);
    return outputFiles;
}
Also used : Artifact(com.google.devtools.build.lib.actions.Artifact)

Example 29 with Artifact

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

the class CppModel method createSourceAction.

private Collection<Artifact> createSourceAction(String outputName, CcCompilationOutputs.Builder result, AnalysisEnvironment env, Artifact sourceArtifact, CppCompileActionBuilder builder, ArtifactCategory outputCategory, CppModuleMap cppModuleMap, boolean addObject, boolean enableCoverage, boolean generateDwo, boolean generateDotd, Map<String, String> sourceSpecificBuildVariables) {
    ImmutableList.Builder<Artifact> directOutputs = new ImmutableList.Builder<>();
    PathFragment ccRelativeName = semantics.getEffectiveSourcePath(sourceArtifact);
    if (cppConfiguration.isLipoOptimization()) {
        // TODO(bazel-team): we shouldn't be needing this, merging context with the binary
        // is a superset of necessary information.
        LipoContextProvider lipoProvider = Preconditions.checkNotNull(CppHelper.getLipoContextProvider(ruleContext), outputName);
        builder.setContext(CppCompilationContext.mergeForLipo(lipoProvider.getLipoContext(), context));
    }
    boolean generatePicAction = getGeneratePicActions();
    boolean generateNoPicAction = getGenerateNoPicActions();
    Preconditions.checkState(generatePicAction || generateNoPicAction);
    if (fake) {
        boolean usePic = !generateNoPicAction;
        createFakeSourceAction(outputName, result, env, builder, outputCategory, addObject, ccRelativeName, sourceArtifact.getExecPath(), usePic, generateDotd);
    } else {
        // generate .pic.o, .pic.d, .pic.gcno instead of .o, .d, .gcno.)
        if (generatePicAction) {
            String picOutputBase = CppHelper.getArtifactNameForCategory(ruleContext, ccToolchain, ArtifactCategory.PIC_FILE, outputName);
            CppCompileActionBuilder picBuilder = copyAsPicBuilder(builder, picOutputBase, outputCategory, generateDotd);
            String gcnoFileName = CppHelper.getArtifactNameForCategory(ruleContext, ccToolchain, ArtifactCategory.COVERAGE_DATA_FILE, picOutputBase);
            Artifact gcnoFile = enableCoverage ? CppHelper.getCompileOutputArtifact(ruleContext, gcnoFileName, configuration) : null;
            Artifact dwoFile = generateDwo ? getDwoFile(picBuilder.getOutputFile()) : null;
            setupCompileBuildVariables(picBuilder, /*usePic=*/
            true, ccRelativeName, sourceArtifact.getExecPath(), gcnoFile, dwoFile, cppModuleMap, sourceSpecificBuildVariables);
            if (maySaveTemps) {
                result.addTemps(createTempsActions(sourceArtifact, outputName, picBuilder, /*usePic=*/
                true, /*generateDotd=*/
                generateDotd, ccRelativeName));
            }
            picBuilder.setGcnoFile(gcnoFile);
            picBuilder.setDwoFile(dwoFile);
            semantics.finalizeCompileActionBuilder(ruleContext, picBuilder);
            CppCompileAction picAction = picBuilder.buildAndValidate(ruleContext);
            env.registerAction(picAction);
            directOutputs.add(picAction.getOutputFile());
            if (addObject) {
                result.addPicObjectFile(picAction.getOutputFile());
                if (featureConfiguration.isEnabled(CppRuleClasses.THIN_LTO) && CppFileTypes.LTO_SOURCE.matches(sourceArtifact.getFilename())) {
                    result.addLTOBitcodeFile(picAction.getOutputFile());
                }
            }
            if (dwoFile != null) {
                // Host targets don't produce .dwo files.
                result.addPicDwoFile(dwoFile);
            }
            if (cppConfiguration.isLipoContextCollector() && !generateNoPicAction) {
                result.addLipoScannable(picAction);
            }
        }
        if (generateNoPicAction) {
            Artifact noPicOutputFile = CppHelper.getCompileOutputArtifact(ruleContext, CppHelper.getArtifactNameForCategory(ruleContext, ccToolchain, outputCategory, outputName), configuration);
            builder.setOutputs(ruleContext, outputCategory, outputName, generateDotd);
            String gcnoFileName = CppHelper.getArtifactNameForCategory(ruleContext, ccToolchain, ArtifactCategory.COVERAGE_DATA_FILE, outputName);
            // Create non-PIC compile actions
            Artifact gcnoFile = !cppConfiguration.isLipoOptimization() && enableCoverage ? CppHelper.getCompileOutputArtifact(ruleContext, gcnoFileName, configuration) : null;
            Artifact noPicDwoFile = generateDwo ? getDwoFile(noPicOutputFile) : null;
            setupCompileBuildVariables(builder, /*usePic=*/
            false, ccRelativeName, sourceArtifact.getExecPath(), gcnoFile, noPicDwoFile, cppModuleMap, sourceSpecificBuildVariables);
            if (maySaveTemps) {
                result.addTemps(createTempsActions(sourceArtifact, outputName, builder, /*usePic=*/
                false, /*generateDotd*/
                generateDotd, ccRelativeName));
            }
            builder.setGcnoFile(gcnoFile);
            builder.setDwoFile(noPicDwoFile);
            semantics.finalizeCompileActionBuilder(ruleContext, builder);
            CppCompileAction compileAction = builder.buildAndValidate(ruleContext);
            env.registerAction(compileAction);
            Artifact objectFile = compileAction.getOutputFile();
            directOutputs.add(objectFile);
            if (addObject) {
                result.addObjectFile(objectFile);
                if (featureConfiguration.isEnabled(CppRuleClasses.THIN_LTO) && CppFileTypes.LTO_SOURCE.matches(sourceArtifact.getFilename())) {
                    result.addLTOBitcodeFile(objectFile);
                }
            }
            if (noPicDwoFile != null) {
                // Host targets don't produce .dwo files.
                result.addDwoFile(noPicDwoFile);
            }
            if (cppConfiguration.isLipoContextCollector()) {
                result.addLipoScannable(compileAction);
            }
        }
    }
    return directOutputs.build();
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) Builder(com.google.devtools.build.lib.rules.cpp.CcCompilationOutputs.Builder) StringSequenceBuilder(com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.StringSequenceBuilder) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) Artifact(com.google.devtools.build.lib.actions.Artifact)

Example 30 with Artifact

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

the class CppModel method createCcCompileActions.

/**
   * Constructs the C++ compiler actions. It generally creates one action for every specified source
   * file. It takes into account LIPO, fake-ness, coverage, and PIC, in addition to using the
   * settings specified on the current object. This method should only be called once.
   */
public CcCompilationOutputs createCcCompileActions() {
    CcCompilationOutputs.Builder result = new CcCompilationOutputs.Builder();
    Preconditions.checkNotNull(context);
    AnalysisEnvironment env = ruleContext.getAnalysisEnvironment();
    if (shouldProvideHeaderModules()) {
        Collection<Artifact> modules = createModuleAction(result, context.getCppModuleMap());
        if (featureConfiguration.isEnabled(CppRuleClasses.HEADER_MODULE_CODEGEN)) {
            for (Artifact module : modules) {
                createModuleCodegenAction(result, module);
            }
        }
    } else if (context.getVerificationModuleMap() != null) {
        Collection<Artifact> modules = createModuleAction(result, context.getVerificationModuleMap());
        for (Artifact module : modules) {
            result.addHeaderTokenFile(module);
        }
    }
    for (CppSource source : sourceFiles) {
        Artifact sourceArtifact = source.getSource();
        Label sourceLabel = source.getLabel();
        String outputName = FileSystemUtils.removeExtension(semantics.getEffectiveSourcePath(sourceArtifact)).getPathString();
        CppCompileActionBuilder builder = initializeCompileAction(sourceArtifact, sourceLabel);
        builder.setSemantics(semantics);
        if (!sourceArtifact.isTreeArtifact()) {
            switch(source.getType()) {
                case HEADER:
                    createHeaderAction(outputName, result, env, builder, CppFileTypes.mustProduceDotdFile(sourceArtifact));
                    break;
                case CLIF_INPUT_PROTO:
                    createClifMatchAction(outputName, result, env, builder);
                    break;
                default:
                    boolean bitcodeOutput = featureConfiguration.isEnabled(CppRuleClasses.THIN_LTO) && CppFileTypes.LTO_SOURCE.matches(sourceArtifact.getFilename());
                    createSourceAction(outputName, result, env, sourceArtifact, builder, ArtifactCategory.OBJECT_FILE, context.getCppModuleMap(), /*addObject=*/
                    true, isCodeCoverageEnabled(), /*generateDwo=*/
                    cppConfiguration.useFission() && !bitcodeOutput, CppFileTypes.mustProduceDotdFile(sourceArtifact), source.getBuildVariables());
                    break;
            }
        } else {
            switch(source.getType()) {
                case HEADER:
                    Artifact headerTokenFile = createCompileActionTemplate(env, source, builder, ImmutableList.of(ArtifactCategory.GENERATED_HEADER, ArtifactCategory.PROCESSED_HEADER));
                    result.addHeaderTokenFile(headerTokenFile);
                    break;
                case SOURCE:
                    Artifact objectFile = createCompileActionTemplate(env, source, builder, ImmutableList.of(ArtifactCategory.OBJECT_FILE));
                    result.addObjectFile(objectFile);
                    break;
                default:
                    throw new IllegalStateException("Encountered invalid source types when creating CppCompileActionTemplates");
            }
        }
    }
    compilationOutputs = result.build();
    return compilationOutputs;
}
Also used : Builder(com.google.devtools.build.lib.rules.cpp.CcCompilationOutputs.Builder) StringSequenceBuilder(com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.StringSequenceBuilder) Label(com.google.devtools.build.lib.cmdline.Label) Builder(com.google.devtools.build.lib.rules.cpp.CcCompilationOutputs.Builder) Artifact(com.google.devtools.build.lib.actions.Artifact) AnalysisEnvironment(com.google.devtools.build.lib.analysis.AnalysisEnvironment) TransitiveInfoCollection(com.google.devtools.build.lib.analysis.TransitiveInfoCollection) Collection(java.util.Collection)

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