Search in sources :

Example 1 with Variables

use of com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables in project bazel by bazelbuild.

the class CppLinkActionBuilder method build.

/** Builds the Action as configured and returns it. */
public CppLinkAction build() throws InterruptedException {
    // Executable links do not have library identifiers.
    boolean hasIdentifier = (libraryIdentifier != null);
    boolean isExecutable = linkType.isExecutable();
    Preconditions.checkState(hasIdentifier != isExecutable);
    if (interfaceOutput != null && (fake || linkType != LinkTargetType.DYNAMIC_LIBRARY)) {
        throw new RuntimeException("Interface output can only be used " + "with non-fake DYNAMIC_LIBRARY targets");
    }
    final ImmutableList<Artifact> buildInfoHeaderArtifacts = !linkstamps.isEmpty() ? analysisEnvironment.getBuildInfo(ruleContext, CppBuildInfo.KEY, configuration) : ImmutableList.<Artifact>of();
    boolean needWholeArchive = wholeArchive || needWholeArchive(linkStaticness, linkType, linkopts, isNativeDeps, cppConfiguration);
    NestedSet<LibraryToLink> uniqueLibraries = libraries.build();
    final Iterable<Artifact> objectArtifacts = LinkerInputs.toLibraryArtifacts(objectFiles);
    final Iterable<LinkerInput> linkerInputs = IterablesChain.<LinkerInput>builder().add(ImmutableList.copyOf(objectFiles)).add(ImmutableIterable.from(Link.mergeInputsCmdLine(uniqueLibraries, needWholeArchive, cppConfiguration.archiveType()))).build();
    // ruleContext can only be null during testing. This is kind of ugly.
    final ImmutableSet<String> features = (ruleContext == null) ? ImmutableSet.<String>of() : ruleContext.getFeatures();
    // instantiated without a feature configuration.
    if (featureConfiguration == null) {
        if (toolchain != null) {
            featureConfiguration = CcCommon.configureFeatures(ruleContext, toolchain, CcLibraryHelper.SourceCategory.CC);
        } else {
            featureConfiguration = CcCommon.configureFeatures(ruleContext, toolchain);
        }
    }
    final LibraryToLink outputLibrary = linkType.isExecutable() ? null : LinkerInputs.newInputLibrary(output, linkType.getLinkerOutput(), libraryIdentifier, objectArtifacts, this.ltoBitcodeFiles);
    final LibraryToLink interfaceOutputLibrary = (interfaceOutput == null) ? null : LinkerInputs.newInputLibrary(interfaceOutput, ArtifactCategory.DYNAMIC_LIBRARY, libraryIdentifier, objectArtifacts, this.ltoBitcodeFiles);
    final ImmutableMap<Artifact, Artifact> linkstampMap = mapLinkstampsToOutputs(linkstamps, ruleContext, configuration, output, linkArtifactFactory);
    PathFragment ltoOutputRootPrefix = null;
    if (isLTOIndexing && allLTOArtifacts == null) {
        ltoOutputRootPrefix = FileSystemUtils.appendExtension(output.getRootRelativePath(), ".lto");
        allLTOArtifacts = createLTOArtifacts(ltoOutputRootPrefix, uniqueLibraries);
    }
    PathFragment linkerParamFileRootPath = null;
    @Nullable Artifact thinltoParamFile = null;
    if (allLTOArtifacts != null) {
        // Create artifact for the file that the LTO indexing step will emit
        // object file names into for any that were included in the link as
        // determined by the linker's symbol resolution. It will be used to
        // provide the inputs for the subsequent final native object link.
        // Note that the paths emitted into this file will have their prefixes
        // replaced with the final output directory, so they will be the paths
        // of the native object files not the input bitcode files.
        linkerParamFileRootPath = ParameterFile.derivePath(output.getRootRelativePath(), "lto-final");
        thinltoParamFile = linkArtifactFactory.create(ruleContext, configuration, linkerParamFileRootPath);
    }
    final ImmutableList<Artifact> actionOutputs;
    if (isLTOIndexing) {
        ImmutableList.Builder<Artifact> builder = ImmutableList.builder();
        for (LTOBackendArtifacts ltoA : allLTOArtifacts) {
            ltoA.addIndexingOutputs(builder);
        }
        if (thinltoParamFile != null) {
            builder.add(thinltoParamFile);
        }
        actionOutputs = builder.build();
    } else {
        actionOutputs = constructOutputs(output, linkstampMap.values(), interfaceOutputLibrary == null ? null : interfaceOutputLibrary.getArtifact(), symbolCounts);
    }
    ImmutableList<LinkerInput> runtimeLinkerInputs = ImmutableList.copyOf(LinkerInputs.simpleLinkerInputs(runtimeInputs, runtimeType));
    PathFragment paramRootPath = ParameterFile.derivePath(output.getRootRelativePath(), (isLTOIndexing) ? "lto-index" : "2");
    @Nullable final Artifact paramFile = canSplitCommandLine() ? linkArtifactFactory.create(ruleContext, configuration, paramRootPath) : null;
    // Add build variables necessary to template link args into the crosstool.
    Variables.Builder buildVariablesBuilder = new Variables.Builder();
    CppLinkVariablesExtension variablesExtension = isLTOIndexing ? new CppLinkVariablesExtension(configuration, ImmutableMap.<Artifact, Artifact>of(), needWholeArchive, linkerInputs, runtimeLinkerInputs, null, paramFile, thinltoParamFile, ltoOutputRootPrefix, null, null) : new CppLinkVariablesExtension(configuration, linkstampMap, needWholeArchive, linkerInputs, runtimeLinkerInputs, output, paramFile, thinltoParamFile, PathFragment.EMPTY_FRAGMENT, toolchain.getInterfaceSoBuilder(), interfaceOutput);
    variablesExtension.addVariables(buildVariablesBuilder);
    for (VariablesExtension extraVariablesExtension : variablesExtensions) {
        extraVariablesExtension.addVariables(buildVariablesBuilder);
    }
    Variables buildVariables = buildVariablesBuilder.build();
    Preconditions.checkArgument(linkType != LinkTargetType.INTERFACE_DYNAMIC_LIBRARY, "you can't link an interface dynamic library directly");
    if (linkType != LinkTargetType.DYNAMIC_LIBRARY) {
        Preconditions.checkArgument(interfaceOutput == null, "interface output may only be non-null for dynamic library links");
    }
    if (linkType.staticness() == Staticness.STATIC) {
        // solib dir must be null for static links
        runtimeSolibDir = null;
        Preconditions.checkArgument(linkStaticness == LinkStaticness.FULLY_STATIC, "static library link must be static");
        Preconditions.checkArgument(symbolCounts == null, "the symbol counts output must be null for static links");
        Preconditions.checkArgument(!isNativeDeps, "the native deps flag must be false for static links");
        Preconditions.checkArgument(!needWholeArchive, "the need whole archive flag must be false for static links");
    }
    LinkCommandLine.Builder linkCommandLineBuilder = new LinkCommandLine.Builder(configuration, getOwner(), ruleContext).setLinkerInputs(linkerInputs).setRuntimeInputs(runtimeLinkerInputs).setLinkTargetType(linkType).setLinkStaticness(linkStaticness).setFeatures(features).setRuntimeSolibDir(linkType.staticness() == Staticness.STATIC ? null : runtimeSolibDir).setNativeDeps(isNativeDeps).setUseTestOnlyFlags(useTestOnlyFlags).setParamFile(paramFile).setToolchain(toolchain).setFdoSupport(fdoSupport.getFdoSupport()).setBuildVariables(buildVariables).setToolPath(getToolPath()).setFeatureConfiguration(featureConfiguration);
    if (!isLTOIndexing) {
        linkCommandLineBuilder.setOutput(output).setBuildInfoHeaderArtifacts(buildInfoHeaderArtifacts).setLinkstamps(linkstampMap).setLinkopts(ImmutableList.copyOf(linkopts)).addLinkstampCompileOptions(linkstampOptions);
    } else {
        List<String> opts = new ArrayList<>(linkopts);
        opts.addAll(featureConfiguration.getCommandLine("lto-indexing", buildVariables));
        opts.addAll(cppConfiguration.getLTOIndexOptions());
        linkCommandLineBuilder.setLinkopts(ImmutableList.copyOf(opts));
    }
    LinkCommandLine linkCommandLine = linkCommandLineBuilder.build();
    // Compute the set of inputs - we only need stable order here.
    NestedSetBuilder<Artifact> dependencyInputsBuilder = NestedSetBuilder.stableOrder();
    dependencyInputsBuilder.addTransitive(crosstoolInputs);
    dependencyInputsBuilder.add(toolchain.getLinkDynamicLibraryTool());
    dependencyInputsBuilder.addTransitive(linkActionInputs.build());
    if (runtimeMiddleman != null) {
        dependencyInputsBuilder.add(runtimeMiddleman);
    }
    if (!isLTOIndexing) {
        dependencyInputsBuilder.addAll(buildInfoHeaderArtifacts);
        dependencyInputsBuilder.addAll(linkstamps);
        dependencyInputsBuilder.addTransitive(compilationInputs.build());
    }
    Iterable<Artifact> expandedInputs = LinkerInputs.toLibraryArtifacts(Link.mergeInputsDependencies(uniqueLibraries, needWholeArchive, cppConfiguration.archiveType()));
    Iterable<Artifact> expandedNonLibraryInputs = LinkerInputs.toLibraryArtifacts(objectFiles);
    if (!isLTOIndexing && allLTOArtifacts != null) {
        // We are doing LTO, and this is the real link, so substitute
        // the LTO bitcode files with the real object files they were translated into.
        Map<Artifact, Artifact> ltoMapping = new HashMap<>();
        for (LTOBackendArtifacts a : allLTOArtifacts) {
            ltoMapping.put(a.getBitcodeFile(), a.getObjectFile());
        }
        // Handle libraries.
        List<Artifact> renamedInputs = new ArrayList<>();
        for (Artifact a : expandedInputs) {
            Artifact renamed = ltoMapping.get(a);
            renamedInputs.add(renamed == null ? a : renamed);
        }
        expandedInputs = renamedInputs;
        // Handle non-libraries.
        List<Artifact> renamedNonLibraryInputs = new ArrayList<>();
        for (Artifact a : expandedNonLibraryInputs) {
            Artifact renamed = ltoMapping.get(a);
            renamedNonLibraryInputs.add(renamed == null ? a : renamed);
        }
        expandedNonLibraryInputs = renamedNonLibraryInputs;
    } else if (isLTOIndexing && allLTOArtifacts != null) {
        for (LTOBackendArtifacts a : allLTOArtifacts) {
            List<String> argv = new ArrayList<>();
            argv.addAll(cppConfiguration.getLinkOptions());
            argv.addAll(cppConfiguration.getCompilerOptions(features));
            a.setCommandLine(argv);
            a.scheduleLTOBackendAction(ruleContext, featureConfiguration, toolchain, fdoSupport, usePicForLTOBackendActions, useFissionForLTOBackendActions);
        }
    }
    // getPrimaryInput returns the first element, and that is a public interface - therefore the
    // order here is important.
    IterablesChain.Builder<Artifact> inputsBuilder = IterablesChain.<Artifact>builder().add(ImmutableList.copyOf(expandedNonLibraryInputs)).add(ImmutableList.copyOf(nonCodeInputs)).add(dependencyInputsBuilder.build()).add(ImmutableIterable.from(expandedInputs));
    if (thinltoParamFile != null && !isLTOIndexing) {
        inputsBuilder.add(ImmutableList.of(thinltoParamFile));
    }
    if (linkCommandLine.getParamFile() != null) {
        inputsBuilder.add(ImmutableList.of(linkCommandLine.getParamFile()));
        Action parameterFileWriteAction = new ParameterFileWriteAction(getOwner(), paramFile, linkCommandLine.paramCmdLine(), ParameterFile.ParameterFileType.UNQUOTED, ISO_8859_1);
        analysisEnvironment.registerAction(parameterFileWriteAction);
    }
    ImmutableMap<String, String> toolchainEnv = featureConfiguration.getEnvironmentVariables(getActionName(), buildVariables);
    // If the crosstool uses action_configs to configure cc compilation, collect execution info
    // from there, otherwise, use no execution info.
    // TODO(b/27903698): Assert that the crosstool has an action_config for this action.
    ImmutableSet.Builder<String> executionRequirements = ImmutableSet.<String>builder();
    if (featureConfiguration.actionIsConfigured(getActionName())) {
        executionRequirements.addAll(featureConfiguration.getToolForAction(getActionName()).getExecutionRequirements());
    }
    return new CppLinkAction(getOwner(), mnemonic, inputsBuilder.deduplicate().build(), actionOutputs, cppConfiguration, outputLibrary, output, interfaceOutputLibrary, fake, isLTOIndexing, allLTOArtifacts, linkCommandLine, configuration.getVariableShellEnvironment(), configuration.getLocalShellEnvironment(), toolchainEnv, executionRequirements.build());
}
Also used : Action(com.google.devtools.build.lib.actions.Action) ParameterFileWriteAction(com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction) HashMap(java.util.HashMap) ImmutableList(com.google.common.collect.ImmutableList) SequenceBuilder(com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.SequenceBuilder) Builder(com.google.common.collect.ImmutableSet.Builder) NestedSetBuilder(com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) ArrayList(java.util.ArrayList) Variables(com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables) ParameterFileWriteAction(com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction) ImmutableSet(com.google.common.collect.ImmutableSet) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) IterablesChain(com.google.devtools.build.lib.collect.IterablesChain) Artifact(com.google.devtools.build.lib.actions.Artifact) LibraryToLink(com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink) VariablesExtension(com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.VariablesExtension) Nullable(javax.annotation.Nullable)

Example 2 with Variables

use of com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables in project bazel by bazelbuild.

the class LinkBuildVariablesTest method testLinkstampBuildVariable.

@Test
public void testLinkstampBuildVariable() throws Exception {
    scratch.file("x/BUILD", "cc_binary(", "   name = 'bin',", "   srcs = ['a.cc'],", "   deps = [':lib'],", ")", "cc_library(", "   name = 'lib',", "   srcs = ['b.cc'],", "   linkstamp = 'c.cc',", ")");
    scratch.file("x/a.cc");
    scratch.file("x/b.cc");
    scratch.file("x/c.cc");
    ConfiguredTarget target = getConfiguredTarget("//x:bin");
    Variables variables = getLinkBuildVariables(target, Link.LinkTargetType.EXECUTABLE);
    List<String> variableValue = getVariableValue(variables, CppLinkActionBuilder.LINKSTAMP_PATHS_VARIABLE);
    assertThat(Iterables.getOnlyElement(variableValue)).contains("c.o");
}
Also used : Variables(com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables) ConfiguredTarget(com.google.devtools.build.lib.analysis.ConfiguredTarget) Test(org.junit.Test)

Example 3 with Variables

use of com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables in project bazel by bazelbuild.

the class LinkBuildVariablesTest method testInterfaceLibraryBuildingVariablesWhenGenerationPossible.

@Test
public void testInterfaceLibraryBuildingVariablesWhenGenerationPossible() throws Exception {
    // Make sure the interface shared object generation is enabled in the configuration
    // (which it is not by default for some windows toolchains)
    AnalysisMock.get().ccSupport().setupCrosstool(mockToolsConfig, "supports_interface_shared_objects: true");
    useConfiguration();
    scratch.file("x/BUILD", "cc_library(name = 'foo', srcs = ['a.cc'])");
    scratch.file("x/a.cc");
    ConfiguredTarget target = getConfiguredTarget("//x:foo");
    Variables variables = getLinkBuildVariables(target, LinkTargetType.DYNAMIC_LIBRARY);
    String interfaceLibraryBuilder = Iterables.getOnlyElement(getVariableValue(variables, CppLinkActionBuilder.INTERFACE_LIBRARY_BUILDER_VARIABLE));
    String interfaceLibraryInput = Iterables.getOnlyElement(getVariableValue(variables, CppLinkActionBuilder.INTERFACE_LIBRARY_INPUT_VARIABLE));
    String interfaceLibraryOutput = Iterables.getOnlyElement(getVariableValue(variables, CppLinkActionBuilder.INTERFACE_LIBRARY_OUTPUT_VARIABLE));
    String generateInterfaceLibrary = Iterables.getOnlyElement(getVariableValue(variables, CppLinkActionBuilder.GENERATE_INTERFACE_LIBRARY_VARIABLE));
    assertThat(generateInterfaceLibrary).isEqualTo("yes");
    assertThat(interfaceLibraryInput).endsWith("libfoo.so");
    assertThat(interfaceLibraryOutput).endsWith("libfoo.ifso");
    assertThat(interfaceLibraryBuilder).endsWith("build_interface_so");
}
Also used : Variables(com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables) ConfiguredTarget(com.google.devtools.build.lib.analysis.ConfiguredTarget) Test(org.junit.Test)

Example 4 with Variables

use of com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables in project bazel by bazelbuild.

the class LinkBuildVariablesTest method testLibrariesToLinkAreExported.

@Test
public void testLibrariesToLinkAreExported() throws Exception {
    AnalysisMock.get().ccSupport().setupCrosstool(mockToolsConfig);
    useConfiguration();
    scratch.file("x/BUILD", "cc_library(name = 'foo', srcs = ['a.cc'])");
    scratch.file("x/a.cc");
    ConfiguredTarget target = getConfiguredTarget("//x:foo");
    Variables variables = getLinkBuildVariables(target, LinkTargetType.DYNAMIC_LIBRARY);
    VariableValue librariesToLinkSequence = variables.getVariable(CppLinkActionBuilder.LIBRARIES_TO_LINK_VARIABLE);
    assertThat(librariesToLinkSequence).isNotNull();
    Iterable<? extends VariableValue> librariesToLink = librariesToLinkSequence.getSequenceValue(CppLinkActionBuilder.LIBRARIES_TO_LINK_VARIABLE);
    assertThat(librariesToLink).hasSize(1);
    VariableValue nameValue = librariesToLink.iterator().next().getFieldValue(CppLinkActionBuilder.LIBRARIES_TO_LINK_VARIABLE, LibraryToLinkValue.NAME_FIELD_NAME);
    assertThat(nameValue).isNotNull();
    String name = nameValue.getStringValue(LibraryToLinkValue.NAME_FIELD_NAME);
    assertThat(name).matches(".*a\\..*o");
}
Also used : Variables(com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables) VariableValue(com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.VariableValue) ConfiguredTarget(com.google.devtools.build.lib.analysis.ConfiguredTarget) Test(org.junit.Test)

Example 5 with Variables

use of com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables in project bazel by bazelbuild.

the class LinkBuildVariablesTest method testInterfaceLibraryBuildingVariablesWhenGenerationNotAllowed.

@Test
public void testInterfaceLibraryBuildingVariablesWhenGenerationNotAllowed() throws Exception {
    // Make sure the interface shared object generation is enabled in the configuration
    // (which it is not by default for some windows toolchains)
    AnalysisMock.get().ccSupport().setupCrosstool(mockToolsConfig, "supports_interface_shared_objects: true");
    useConfiguration();
    scratch.file("x/BUILD", "cc_library(name = 'foo', srcs = ['a.cc'])");
    scratch.file("x/a.cc");
    ConfiguredTarget target = getConfiguredTarget("//x:foo");
    Variables variables = getLinkBuildVariables(target, LinkTargetType.STATIC_LIBRARY);
    String interfaceLibraryBuilder = Iterables.getOnlyElement(getVariableValue(variables, CppLinkActionBuilder.INTERFACE_LIBRARY_BUILDER_VARIABLE));
    String interfaceLibraryInput = Iterables.getOnlyElement(getVariableValue(variables, CppLinkActionBuilder.INTERFACE_LIBRARY_INPUT_VARIABLE));
    String interfaceLibraryOutput = Iterables.getOnlyElement(getVariableValue(variables, CppLinkActionBuilder.INTERFACE_LIBRARY_OUTPUT_VARIABLE));
    String generateInterfaceLibrary = Iterables.getOnlyElement(getVariableValue(variables, CppLinkActionBuilder.GENERATE_INTERFACE_LIBRARY_VARIABLE));
    assertThat(generateInterfaceLibrary).isEqualTo("no");
    assertThat(interfaceLibraryInput).endsWith("ignored");
    assertThat(interfaceLibraryOutput).endsWith("ignored");
    assertThat(interfaceLibraryBuilder).endsWith("ignored");
}
Also used : Variables(com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables) ConfiguredTarget(com.google.devtools.build.lib.analysis.ConfiguredTarget) Test(org.junit.Test)

Aggregations

Variables (com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables)11 ConfiguredTarget (com.google.devtools.build.lib.analysis.ConfiguredTarget)9 Test (org.junit.Test)8 Artifact (com.google.devtools.build.lib.actions.Artifact)2 PathFragment (com.google.devtools.build.lib.vfs.PathFragment)2 ArrayList (java.util.ArrayList)2 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 Builder (com.google.common.collect.ImmutableSet.Builder)1 Action (com.google.devtools.build.lib.actions.Action)1 ParameterFileWriteAction (com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction)1 IterablesChain (com.google.devtools.build.lib.collect.IterablesChain)1 NestedSetBuilder (com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder)1 SequenceBuilder (com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.SequenceBuilder)1 VariableValue (com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.VariableValue)1 VariablesExtension (com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.VariablesExtension)1 LibraryToLink (com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink)1 HashMap (java.util.HashMap)1 List (java.util.List)1 Nullable (javax.annotation.Nullable)1