Here are the examples of the java api com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.
56 Examples
19
View Complete Implementation : CppHelper.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Returns true if interface shared objects should be used in the build implied by the given
* cppConfiguration and toolchain.
*/
public static boolean useInterfaceSharedLibraries(CppConfiguration cppConfiguration, CcToolchainProvider toolchain, FeatureConfiguration featureConfiguration) {
return toolchain.supportsInterfaceSharedLibraries(featureConfiguration) && cppConfiguration.getUseInterfaceSharedLibraries();
}
19
View Complete Implementation : CppHelper.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Returns the FDO build subtype.
*/
public static String getFdoBuildStamp(CppConfiguration cppConfiguration, FdoContext fdoContext, FeatureConfiguration featureConfiguration) {
FdoContext.BranchFdoProfile branchFdoProfile = fdoContext.getBranchFdoProfile();
if (branchFdoProfile != null) {
if (branchFdoProfile.isAutoFdo()) {
return featureConfiguration.isEnabled(CppRuleClreplacedes.AUTOFDO) ? "AFDO" : null;
}
if (branchFdoProfile.isAutoXBinaryFdo()) {
return featureConfiguration.isEnabled(CppRuleClreplacedes.XBINARYFDO) ? "XFDO" : null;
}
}
if (cppConfiguration.isCSFdo()) {
return "CSFDO";
}
if (cppConfiguration.isFdo()) {
return "FDO";
}
return null;
}
19
View Complete Implementation : CcToolchainProvider.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Returns true if the featureConfiguration includes statically linking the cpp runtimes.
*
* @param featureConfiguration the relevant FeatureConfiguration.
*/
public boolean shouldStaticallyLinkCppRuntimes(FeatureConfiguration featureConfiguration) {
return featureConfiguration.isEnabled(CppRuleClreplacedes.STATIC_LINK_CPP_RUNTIMES);
}
19
View Complete Implementation : CcToolchainProvider.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Returns true if headers should be parsed in this build.
*
* <p>This means headers in 'srcs' and 'hdrs' will be "compiled" using {@link CppCompileAction}).
* It will run compiler's parser to ensure the header is self-contained. This is required for
* layering_check to work.
*/
public boolean shouldProcessHeaders(FeatureConfiguration featureConfiguration, CppConfiguration cppConfiguration) {
// If parse_headers_verifies_modules is switched on, we verify that headers are
// self-contained by building the module instead.
return !cppConfiguration.getParseHeadersVerifiesModules() && featureConfiguration.isEnabled(CppRuleClreplacedes.PARSE_HEADERS);
}
19
View Complete Implementation : CcToolchainTest.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
private boolean usePicForBinariesWithConfiguration(String... configuration) throws Exception {
useConfiguration(configuration);
ConfiguredTarget target = getConfiguredTarget("//a:b");
CcToolchainProvider toolchainProvider = (CcToolchainProvider) target.get(ToolchainInfo.PROVIDER);
CppConfiguration cppConfiguration = getRuleContext(target).getFragment(CppConfiguration.clreplaced);
FeatureConfiguration featureConfiguration = CcCommon.configureFeaturesOrThrowEvalException(/* requestedFeatures= */
ImmutableSet.of(), /* unsupportedFeatures= */
ImmutableSet.of(), toolchainProvider, cppConfiguration);
return CppHelper.usePicForBinaries(toolchainProvider, cppConfiguration, featureConfiguration);
}
19
View Complete Implementation : CcToolchainProvider.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Returns true if PER_OBJECT_DEBUG_INFO are specified and supported by the CROSSTOOL for the
* build implied by the given configuration, toolchain and feature configuration.
*/
public boolean shouldCreatePerObjectDebugInfo(FeatureConfiguration featureConfiguration, CppConfiguration cppConfiguration) {
return cppConfiguration.fissionIsActiveForCurrentCompilationMode() && featureConfiguration.isEnabled(CppRuleClreplacedes.PER_OBJECT_DEBUG_INFO);
}
19
View Complete Implementation : CppHelper.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Returns the type of archives being used by the build implied by the given config and toolchain.
*/
public static Link.ArchiveType getArchiveType(CppConfiguration config, CcToolchainProvider toolchain, FeatureConfiguration featureConfiguration) {
return useStartEndLib(config, toolchain, featureConfiguration) ? Link.ArchiveType.START_END_LIB : Link.ArchiveType.REGULAR;
}
19
View Complete Implementation : CppHelper.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
// TODO(bazel-team): figure out a way to merge these 2 methods. See the Todo in
// CcCommonConfiguredTarget.noCoptsMatches().
/**
* Returns whether binaries must be compiled with position independent code.
*/
public static boolean usePicForBinaries(CcToolchainProvider toolchain, CppConfiguration cppConfiguration, FeatureConfiguration featureConfiguration) {
return cppConfiguration.forcePic() || (toolchain.usePicForDynamicLibraries(cppConfiguration, featureConfiguration) && cppConfiguration.getCompilationMode() != CompilationMode.OPT);
}
19
View Complete Implementation : CppHelper.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Returns true if the build implied by the given config and toolchain uses --start-lib/--end-lib
* ld options.
*/
public static boolean useStartEndLib(CppConfiguration config, CcToolchainProvider toolchain, FeatureConfiguration featureConfiguration) {
return config.startEndLibIsRequested() && toolchain.supportsStartEndLib(featureConfiguration);
}
19
View Complete Implementation : CcToolchainProvider.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Returns the static runtime libraries.
*/
public NestedSet<Artifact> getStaticRuntimeLinkInputs(FeatureConfiguration featureConfiguration) throws EvalException {
if (shouldStaticallyLinkCppRuntimes(featureConfiguration)) {
if (staticRuntimeLinkInputs == null) {
throw new EvalException(Location.BUILTIN, "Toolchain supports embedded runtimes, but didn't " + "provide static_runtime_lib attribute.");
}
return staticRuntimeLinkInputs;
} else {
return NestedSetBuilder.emptySet(Order.STABLE_ORDER);
}
}
19
View Complete Implementation : CcToolchainProvider.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Returns the dynamic runtime libraries.
*/
public NestedSet<Artifact> getDynamicRuntimeLinkInputs(FeatureConfiguration featureConfiguration) throws EvalException {
if (shouldStaticallyLinkCppRuntimes(featureConfiguration)) {
if (dynamicRuntimeLinkInputs == null) {
throw new EvalException(Location.BUILTIN, "Toolchain supports embedded runtimes, but didn't " + "provide dynamic_runtime_lib attribute.");
}
return dynamicRuntimeLinkInputs;
} else {
return NestedSetBuilder.emptySet(Order.STABLE_ORDER);
}
}
19
View Complete Implementation : CppLinkActionTest.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
@Test
public void testToolchainFeatureFlags() throws Exception {
RuleContext ruleContext = createDummyRuleContext();
FeatureConfiguration featureConfiguration = CcToolchainFeaturesTest.buildFeatures(MockCcSupport.EMPTY_EXECUTABLE_ACTION_CONFIG, "feature {", " name: 'a'", " flag_set {", " action: '" + Link.LinkTargetType.EXECUTABLE.getActionName() + "'", " flag_group { flag: 'some_flag' }", " }", "}").getFeatureConfiguration(ImmutableSet.of("a", Link.LinkTargetType.EXECUTABLE.getActionName()));
CppLinkAction linkAction = createLinkBuilder(ruleContext, Link.LinkTargetType.EXECUTABLE, "dummyRuleContext/out", ImmutableList.<Artifact>of(), ImmutableList.<LibraryToLink>of(), featureConfiguration).build();
replacedertThat(linkAction.getArguments()).contains("some_flag");
}
19
View Complete Implementation : LinkBuildVariablesTestCase.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Returns the value of a given sequence variable in context of the given Variables instance.
*/
protected static List<String> getSequenceVariableValue(RuleContext ruleContext, CcToolchainVariables variables, String variable) throws Exception {
FeatureConfiguration mockFeatureConfiguration = buildFeatures(ruleContext, "feature {", " name: 'a'", " flag_set {", " action: 'foo'", " flag_group {", " iterate_over: '" + variable + "'", " flag: '%{" + variable + "}'", " }", " }", "}").getFeatureConfiguration(ImmutableSet.of("a"));
return mockFeatureConfiguration.getCommandLine("foo", variables);
}
19
View Complete Implementation : CcToolchainProvider.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Determines if we should apply -fPIC for this rule's C++ compilations. This determination is
* generally made by the global C++ configuration settings "needsPic" and "usePicForBinaries".
* However, an individual rule may override these settings by applying -fPIC" to its "nocopts"
* attribute. This allows incompatible rules to "opt out" of global PIC settings (see bug:
* "Provide a way to turn off -fPIC for targets that can't be built that way").
*
* @return true if this rule's compilations should apply -fPIC, false otherwise
*/
public boolean usePicForDynamicLibraries(CppConfiguration cppConfiguration, FeatureConfiguration featureConfiguration) {
return cppConfiguration.forcePic() || featureConfiguration.isEnabled(CppRuleClreplacedes.SUPPORTS_PIC);
}
19
View Complete Implementation : CcToolchainProvider.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Returns whether the toolchain supports dynamic linking.
*/
public boolean supportsDynamicLinker(FeatureConfiguration featureConfiguration) {
return featureConfiguration.isEnabled(CppRuleClreplacedes.SUPPORTS_DYNAMIC_LINKER);
}
19
View Complete Implementation : CppLinkActionTest.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
@Test
public void testToolchainFeatureEnv() throws Exception {
RuleContext ruleContext = createDummyRuleContext();
FeatureConfiguration featureConfiguration = CcToolchainFeaturesTest.buildFeatures(MockCcSupport.EMPTY_EXECUTABLE_ACTION_CONFIG, "feature {", " name: 'a'", " env_set {", " action: '" + Link.LinkTargetType.EXECUTABLE.getActionName() + "'", " env_entry { key: 'foo', value: 'bar' }", " }", "}").getFeatureConfiguration(ImmutableSet.of(Link.LinkTargetType.EXECUTABLE.getActionName(), "a"));
CppLinkAction linkAction = createLinkBuilder(ruleContext, Link.LinkTargetType.EXECUTABLE, "dummyRuleContext/out", ImmutableList.<Artifact>of(), ImmutableList.<LibraryToLink>of(), featureConfiguration).build();
replacedertThat(linkAction.getIncompleteEnvironmentForTesting()).containsEntry("foo", "bar");
}
18
View Complete Implementation : MockCppSemantics.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
@Override
public void finalizeCompileActionBuilder(BuildConfiguration configuration, FeatureConfiguration featureConfiguration, CppCompileActionBuilder actionBuilder) {
}
18
View Complete Implementation : CcToolchainProvider.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Returns whether the toolchain supports the --start-lib/--end-lib options.
*/
public boolean supportsStartEndLib(FeatureConfiguration featureConfiguration) {
return featureConfiguration.isEnabled(CppRuleClreplacedes.SUPPORTS_START_END_LIB);
}
18
View Complete Implementation : CcToolchainProvider.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Returns an aggregating middleman that represents the static runtime libraries.
*/
@Nullable
public Artifact getStaticRuntimeLinkMiddleman(RuleErrorConsumer ruleErrorConsumer, FeatureConfiguration featureConfiguration) throws RuleErrorException {
if (shouldStaticallyLinkCppRuntimes(featureConfiguration)) {
if (staticRuntimeLinkInputs == null) {
throw ruleErrorConsumer.throwWithRuleError("Toolchain supports embedded runtimes, but didn't " + "provide static_runtime_lib attribute.");
}
return staticRuntimeLinkMiddleman;
} else {
return null;
}
}
18
View Complete Implementation : CcToolchainProvider.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Returns an aggregating middleman that represents the dynamic runtime libraries.
*/
@Nullable
public Artifact getDynamicRuntimeLinkMiddleman(RuleErrorConsumer ruleContext, FeatureConfiguration featureConfiguration) throws RuleErrorException {
if (shouldStaticallyLinkCppRuntimes(featureConfiguration)) {
if (dynamicRuntimeLinkInputs == null) {
throw ruleContext.throwWithRuleError("Toolchain supports embedded runtimes, but didn't " + "provide dynamic_runtime_lib attribute.");
}
return dynamicRuntimeLinkMiddleman;
} else {
return null;
}
}
18
View Complete Implementation : CcToolchainProvider.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Returns whether this toolchain supports interface shared libraries.
*/
public boolean supportsInterfaceSharedLibraries(FeatureConfiguration featureConfiguration) {
return featureConfiguration.isEnabled(CppRuleClreplacedes.SUPPORTS_INTERFACE_SHARED_LIBRARIES);
}
18
View Complete Implementation : CppCompileActionBuilder.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Sets the feature configuration to be used for the action.
*/
public CppCompileActionBuilder setFeatureConfiguration(FeatureConfiguration featureConfiguration) {
Preconditions.checkNotNull(featureConfiguration);
this.featureConfiguration = featureConfiguration;
return this;
}
18
View Complete Implementation : CppHelper.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
public static ImmutableMap<String, String> getEnvironmentVariables(RuleErrorConsumer ruleErrorConsumer, FeatureConfiguration featureConfiguration, CcToolchainVariables variables, String actionName) throws RuleErrorException {
try {
return featureConfiguration.getEnvironmentVariables(actionName, variables);
} catch (ExpansionException e) {
throw ruleErrorConsumer.throwWithRuleError(e.getMessage());
}
}
18
View Complete Implementation : CppHelper.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Returns true when {@link CppRuleClreplacedes#WINDOWS_EXPORT_ALL_SYMBOLS} feature is enabled and
* {@link CppRuleClreplacedes#NO_WINDOWS_EXPORT_ALL_SYMBOLS} feature is not enabled and no custom DEF
* file is specified in win_def_file attribute.
*/
public static boolean shouldUseGeneratedDefFile(RuleContext ruleContext, FeatureConfiguration featureConfiguration) {
return featureConfiguration.isEnabled(CppRuleClreplacedes.WINDOWS_EXPORT_ALL_SYMBOLS) && !featureConfiguration.isEnabled(CppRuleClreplacedes.NO_WINDOWS_EXPORT_ALL_SYMBOLS) && ruleContext.getPrerequisiteArtifact("win_def_file", Mode.TARGET) == null;
}
18
View Complete Implementation : FeatureConfigurationForStarlark.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
public static FeatureConfigurationForStarlark from(FeatureConfiguration featureConfiguration, CppConfiguration cppConfiguration, BuildOptions buildOptions) {
return new FeatureConfigurationForStarlark(featureConfiguration, cppConfiguration, buildOptions);
}
18
View Complete Implementation : FeatureConfigurationForStarlark.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Wrapper for {@link FeatureConfiguration}, {@link CppConfiguration}, and {@link BuildOptions}.
*
* <p>Instances are created in Starlark by cc_common.configure_features(ctx, cc_toolchain), and
* preplaceded around pretending to be {@link FeatureConfiguration}. Then when the need arises, we get
* the {@link CppConfiguration} and {@link BuildOptions} from it and use it in times when
* configuration of cc_toolchain is different than configuration of the rule depending on it.
*/
// TODO(b/129045294): Remove once cc_toolchain has target configuration.
public clreplaced FeatureConfigurationForStarlark implements FeatureConfigurationApi {
private final FeatureConfiguration featureConfiguration;
private final CppConfiguration cppConfiguration;
private final BuildOptions buildOptions;
public static FeatureConfigurationForStarlark from(FeatureConfiguration featureConfiguration, CppConfiguration cppConfiguration, BuildOptions buildOptions) {
return new FeatureConfigurationForStarlark(featureConfiguration, cppConfiguration, buildOptions);
}
private FeatureConfigurationForStarlark(FeatureConfiguration featureConfiguration, CppConfiguration cppConfiguration, BuildOptions buildOptions) {
this.featureConfiguration = Preconditions.checkNotNull(featureConfiguration);
this.cppConfiguration = Preconditions.checkNotNull(cppConfiguration);
this.buildOptions = buildOptions;
}
public FeatureConfiguration getFeatureConfiguration() {
return featureConfiguration;
}
@Override
public void debugPrint(Printer printer) {
printer.append("<FeatureConfiguration(");
printer.append(Joiner.on(", ").join(featureConfiguration.getEnabledFeatureNames()));
printer.append(")>");
}
/**
* Get {@link CppConfiguration} that is threaded along with {@link FeatureConfiguration}. Do this
* only when you're completely aware of why this method was added and hlopko@ allowed you to.
*
* @deprecated will be removed soon by b/129045294.
*/
@Deprecated
CppConfiguration getCppConfigurationFromFeatureConfigurationCreatedForStarlark_andIKnowWhatImDoing() {
return cppConfiguration;
}
/**
* Get {@link BuildOptions} that is threaded along with {@link FeatureConfiguration}. Do this only
* when you're completely aware of why this method was added and hlopko@ allowed you to.
*
* @deprecated will be removed soon by b/129045294.
*/
@Deprecated
BuildOptions getBuildOptionsFromFeatureConfigurationCreatedForStarlark_andIKnowWhatImDoing() {
return buildOptions;
}
}
18
View Complete Implementation : LibrariesToLinkCollector.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Clreplaced that goes over linker inputs and produces {@link LibraryToLinkValue}s
*/
public clreplaced LibrariesToLinkCollector {
private final boolean isNativeDeps;
private final PathFragment toolchainLibrariesSolibDir;
private final CppConfiguration cppConfiguration;
private final CcToolchainProvider ccToolchainProvider;
private final Artifact outputArtifact;
private final boolean isLtoIndexing;
private final PathFragment solibDir;
private final Iterable<? extends LinkerInput> linkerInputs;
private final Iterable<LtoBackendArtifacts> allLtoArtifacts;
private final boolean allowLtoIndexing;
private final Artifact thinltoParamFile;
private final FeatureConfiguration featureConfiguration;
private final boolean needWholeArchive;
private final String rpathRoot;
private final boolean needToolchainLibrariesRpath;
private final Map<Artifact, Artifact> ltoMap;
public LibrariesToLinkCollector(boolean isNativeDeps, CppConfiguration cppConfiguration, CcToolchainProvider toolchain, PathFragment toolchainLibrariesSolibDir, LinkTargetType linkType, Link.LinkingMode linkingMode, Artifact output, PathFragment solibDir, boolean isLtoIndexing, Iterable<LtoBackendArtifacts> allLtoArtifacts, FeatureConfiguration featureConfiguration, Artifact thinltoParamFile, boolean allowLtoIndexing, Iterable<LinkerInput> linkerInputs, boolean needWholeArchive) {
this.isNativeDeps = isNativeDeps;
this.cppConfiguration = cppConfiguration;
this.ccToolchainProvider = toolchain;
this.toolchainLibrariesSolibDir = toolchainLibrariesSolibDir;
this.outputArtifact = output;
this.solibDir = solibDir;
this.isLtoIndexing = isLtoIndexing;
this.allLtoArtifacts = allLtoArtifacts;
this.featureConfiguration = featureConfiguration;
this.thinltoParamFile = thinltoParamFile;
this.allowLtoIndexing = allowLtoIndexing;
this.linkerInputs = linkerInputs;
this.needWholeArchive = needWholeArchive;
needToolchainLibrariesRpath = toolchainLibrariesSolibDir != null && (linkType.isDynamicLibrary() || (linkType == LinkTargetType.EXECUTABLE && linkingMode == LinkingMode.DYNAMIC));
// Calculate the correct relative value for the "-rpath" link option (which sets
// the search path for finding shared libraries).
if (isNativeDeps && cppConfiguration.shareNativeDeps()) {
// For shared native libraries, special symlinking is applied to ensure C++
// toolchain libraries are available under $ORIGIN/_solib_[arch]. So we set the RPATH to find
// them.
//
// Note that we have to do this because $ORIGIN points to different paths for
// different targets. In other words, blaze-bin/d1/d2/d3/a_shareddeps.so and
// blaze-bin/d4/b_shareddeps.so have different path depths. The first could
// reference a standard blaze-bin/_solib_[arch] via $ORIGIN/../../../_solib[arch],
// and the second could use $ORIGIN/../_solib_[arch]. But since this is a shared
// artifact, both are symlinks to the same place, so
// there's no *one* RPATH setting that fits all targets involved in the sharing.
rpathRoot = ccToolchainProvider.getSolibDirectory() + "/";
} else {
rpathRoot = Strings.repeat("../", outputArtifact.getRootRelativePath().segmentCount() - 1) + ccToolchainProvider.getSolibDirectory() + "/";
}
ltoMap = generateLtoMap();
}
/**
* Result of {@link LibrariesToLinkCollector#collectLibrariesToLink()}. Provides access to
* computed sequence of {@link LibraryToLinkValue}s and accompanying library search directories.
*/
public static clreplaced CollectedLibrariesToLink {
private final SequenceBuilder librariesToLink;
private final NestedSet<LinkerInput> expandedLinkerInputs;
private final NestedSet<String> librarySearchDirectories;
private final NestedSet<String> runtimeLibrarySearchDirectories;
private CollectedLibrariesToLink(SequenceBuilder librariesToLink, NestedSet<LinkerInput> expandedLinkerInputs, NestedSet<String> librarySearchDirectories, NestedSet<String> runtimeLibrarySearchDirectories) {
this.librariesToLink = librariesToLink;
this.expandedLinkerInputs = expandedLinkerInputs;
this.librarySearchDirectories = librarySearchDirectories;
this.runtimeLibrarySearchDirectories = runtimeLibrarySearchDirectories;
}
public SequenceBuilder getLibrariesToLink() {
return librariesToLink;
}
// TODO(b/78347840): Figure out how to make these Artifacts.
public NestedSet<LinkerInput> getExpandedLinkerInputs() {
return expandedLinkerInputs;
}
public NestedSet<String> getLibrarySearchDirectories() {
return librarySearchDirectories;
}
public NestedSet<String> getRuntimeLibrarySearchDirectories() {
return runtimeLibrarySearchDirectories;
}
}
/**
* When linking a shared library fully or mostly static then we need to link in *all* dependent
* files, not just what the shared library needs for its own code. This is done by wrapping all
* objects/libraries with -Wl,-whole-archive and -Wl,-no-whole-archive. For this case the
* globalNeedWholeArchive parameter must be set to true. Otherwise only library objects (.lo) need
* to be wrapped with -Wl,-whole-archive and -Wl,-no-whole-archive.
*
* <p>TODO: Factor out of the bazel binary into build variables for crosstool action_configs.
*/
public CollectedLibrariesToLink collectLibrariesToLink() {
NestedSetBuilder<String> librarySearchDirectories = NestedSetBuilder.linkOrder();
NestedSetBuilder<String> runtimeLibrarySearchDirectories = NestedSetBuilder.linkOrder();
ImmutableSet.Builder<String> rpathRootsForExplicitSoDeps = ImmutableSet.builder();
NestedSetBuilder<LinkerInput> expandedLinkerInputsBuilder = NestedSetBuilder.linkOrder();
// List of command line parameters that need to be placed *outside* of
// --whole-archive ... --no-whole-archive.
SequenceBuilder librariesToLink = new SequenceBuilder();
String toolchainLibrariesSolibName = toolchainLibrariesSolibDir != null ? toolchainLibrariesSolibDir.getBaseName() : null;
if (isNativeDeps && cppConfiguration.shareNativeDeps()) {
if (needToolchainLibrariesRpath) {
runtimeLibrarySearchDirectories.add("../" + toolchainLibrariesSolibName + "/");
}
} else {
// For all other links, calculate the relative path from the output file to _solib_[arch]
// (the directory where all shared libraries are stored, which resides under the blaze-bin
// directory. In other words, given blaze-bin/my/package/binary, rpathRoot would be
// "../../_solib_[arch]".
if (needToolchainLibrariesRpath) {
runtimeLibrarySearchDirectories.add(Strings.repeat("../", outputArtifact.getRootRelativePath().segmentCount() - 1) + toolchainLibrariesSolibName + "/");
}
if (isNativeDeps) {
// We also retain the $ORIGIN/ path to solibs that are in _solib_<arch>, as opposed to
// the package directory)
if (needToolchainLibrariesRpath) {
runtimeLibrarySearchDirectories.add("../" + toolchainLibrariesSolibName + "/");
}
}
}
if (needToolchainLibrariesRpath) {
if (isNativeDeps) {
runtimeLibrarySearchDirectories.add(".");
}
runtimeLibrarySearchDirectories.add(toolchainLibrariesSolibName + "/");
}
Pair<Boolean, Boolean> includeSolibsPair = addLinkerInputs(librarySearchDirectories, rpathRootsForExplicitSoDeps, librariesToLink, expandedLinkerInputsBuilder);
boolean includeSolibDir = includeSolibsPair.first;
boolean includeToolchainLibrariesSolibDir = includeSolibsPair.second;
Preconditions.checkState(ltoMap == null || ltoMap.isEmpty(), "Still have LTO objects left: %s", ltoMap);
NestedSetBuilder<String> allRuntimeLibrarySearchDirectories = NestedSetBuilder.linkOrder();
// rpath ordering matters for performance; first add the one where most libraries are found.
if (includeSolibDir) {
allRuntimeLibrarySearchDirectories.add(rpathRoot);
}
allRuntimeLibrarySearchDirectories.addAll(rpathRootsForExplicitSoDeps.build());
if (includeToolchainLibrariesSolibDir) {
allRuntimeLibrarySearchDirectories.addTransitive(runtimeLibrarySearchDirectories.build());
}
return new CollectedLibrariesToLink(librariesToLink, expandedLinkerInputsBuilder.build(), librarySearchDirectories.build(), allRuntimeLibrarySearchDirectories.build());
}
private Pair<Boolean, Boolean> addLinkerInputs(NestedSetBuilder<String> librarySearchDirectories, ImmutableSet.Builder<String> rpathEntries, SequenceBuilder librariesToLink, NestedSetBuilder<LinkerInput> expandedLinkerInputsBuilder) {
boolean includeSolibDir = false;
boolean includeToolchainLibrariesSolibDir = false;
for (LinkerInput input : linkerInputs) {
if (input.getArtifactCategory() == ArtifactCategory.DYNAMIC_LIBRARY || input.getArtifactCategory() == ArtifactCategory.INTERFACE_LIBRARY) {
PathFragment libDir = input.getArtifact().getExecPath().getParentDirectory();
// When COPY_DYNAMIC_LIBRARIES_TO_BINARY is enabled, dynamic libraries are not symlinked
// under solibDir, so don't check it and don't include solibDir.
if (!featureConfiguration.isEnabled(CppRuleClreplacedes.COPY_DYNAMIC_LIBRARIES_TO_BINARY)) {
Preconditions.checkState(libDir.startsWith(solibDir) || libDir.startsWith(toolchainLibrariesSolibDir), "Artifact '%s' is not under directory expected '%s'," + " neither it is in directory for toolchain libraries '%'.", input.getArtifact(), solibDir, toolchainLibrariesSolibDir);
if (libDir.equals(solibDir)) {
includeSolibDir = true;
}
if (libDir.equals(toolchainLibrariesSolibDir)) {
includeToolchainLibrariesSolibDir = true;
}
}
addDynamicInputLinkOptions(input, librariesToLink, expandedLinkerInputsBuilder, librarySearchDirectories, rpathEntries);
} else {
addStaticInputLinkOptions(input, librariesToLink, expandedLinkerInputsBuilder);
}
}
return Pair.of(includeSolibDir, includeToolchainLibrariesSolibDir);
}
/**
* Adds command-line options for a dynamic library input file into options and libOpts.
*
* @param librariesToLink - a collection that will be exposed as a build variable.
*/
private void addDynamicInputLinkOptions(LinkerInput input, SequenceBuilder librariesToLink, NestedSetBuilder<LinkerInput> expandedLinkerInputsBuilder, NestedSetBuilder<String> librarySearchDirectories, ImmutableSet.Builder<String> rpathRootsForExplicitSoDeps) {
Preconditions.checkState(input.getArtifactCategory() == ArtifactCategory.DYNAMIC_LIBRARY || input.getArtifactCategory() == ArtifactCategory.INTERFACE_LIBRARY);
Preconditions.checkState(!Link.useStartEndLib(input, CppHelper.getArchiveType(cppConfiguration, ccToolchainProvider, featureConfiguration)));
expandedLinkerInputsBuilder.add(input);
if (featureConfiguration.isEnabled(CppRuleClreplacedes.TARGETS_WINDOWS) && ccToolchainProvider.supportsInterfaceSharedLibraries(featureConfiguration)) {
// On Windows, dynamic library (dll) cannot be linked directly when using toolchains that
// support interface library (eg. MSVC). If the user is doing so, it is only to be referenced
// in other places (such as copy_dynamic_libraries_to_binary); skip adding it.
if (CppFileTypes.SHARED_LIBRARY.matches(input.getArtifact().getFilename())) {
return;
}
}
Artifact inputArtifact = input.getArtifact();
PathFragment libDir = inputArtifact.getExecPath().getParentDirectory();
if (!libDir.equals(solibDir) && (toolchainLibrariesSolibDir == null || !toolchainLibrariesSolibDir.equals(libDir))) {
String dotdots = "";
PathFragment commonParent = solibDir;
while (!libDir.startsWith(commonParent)) {
dotdots += "../";
commonParent = commonParent.getParentDirectory();
}
rpathRootsForExplicitSoDeps.add(rpathRoot + dotdots + libDir.relativeTo(commonParent).getPathString());
}
librarySearchDirectories.add(inputArtifact.getExecPath().getParentDirectory().getPathString());
String name = inputArtifact.getFilename();
if (CppFileTypes.SHARED_LIBRARY.matches(name)) {
// Use normal shared library resolution rules for shared libraries.
String libName = name.replaceAll("(^lib|\\.(so|dylib)$)", "");
librariesToLink.addValue(LibraryToLinkValue.forDynamicLibrary(libName));
} else if (CppFileTypes.VERSIONED_SHARED_LIBRARY.matches(name)) {
// Versioned shared libraries require the exact library filename, e.g.:
// -lfoo -> libfoo.so
// -l:libfoo.so.1 -> libfoo.so.1
librariesToLink.addValue(LibraryToLinkValue.forVersionedDynamicLibrary(name));
} else {
// Interface shared objects have a non-standard extension
// that the linker won't be able to find. So use the
// filename directly rather than a -l option. Since the
// library has an SONAME attribute, this will work fine.
librariesToLink.addValue(LibraryToLinkValue.forInterfaceLibrary(inputArtifact.getExecPathString()));
}
}
/**
* Get the effective path for the object artifact, being careful not to create new strings if
* possible.
*
* @param: objectFile - Artifact representing an object file.
* @param -inputIsFake - Is this object being used for a cc_fake_binary.
*/
private static String effectiveObjectFilePath(Artifact objectFile, boolean inputIsFake) {
// Avoid making new strings as much as possible! This called for every object file used in the
// build.
if (inputIsFake) {
return Link.FAKE_OBJECT_PREFIX + objectFile.getExecPathString();
}
return objectFile.getExecPathString();
}
/**
* Adds command-line options for a static library or non-library input into options.
*
* @param librariesToLink - a collection that will be exposed as a build variable.
*/
private void addStaticInputLinkOptions(LinkerInput input, SequenceBuilder librariesToLink, NestedSetBuilder<LinkerInput> expandedLinkerInputsBuilder) {
ArtifactCategory artifactCategory = input.getArtifactCategory();
Preconditions.checkArgument(artifactCategory.equals(ArtifactCategory.OBJECT_FILE) || artifactCategory.equals(ArtifactCategory.STATIC_LIBRARY) || artifactCategory.equals(ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY));
boolean isAlwaysLinkStaticLibrary = artifactCategory == ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY;
// input.disableWholeArchive() should only be true for libstdc++/libc++ etc.
boolean inputIsWholeArchive = !input.disableWholeArchive() && (isAlwaysLinkStaticLibrary || needWholeArchive);
// If we had any LTO artifacts, ltoMap whould be non-null. In that case,
// we should have created a thinltoParamFile which the LTO indexing
// step will populate with the exec paths that correspond to the LTO
// artifacts that the linker decided to include based on symbol resolution.
// Those files will be included directly in the link (and not wrapped
// in --start-lib/--end-lib) to ensure consistency between the two link
// steps.
Preconditions.checkState(ltoMap == null || thinltoParamFile != null || !allowLtoIndexing);
// start-lib/end-lib library: adds its input object files.
if (Link.useStartEndLib(input, CppHelper.getArchiveType(cppConfiguration, ccToolchainProvider, featureConfiguration))) {
Iterable<Artifact> archiveMembers = input.getObjectFiles();
if (!Iterables.isEmpty(archiveMembers)) {
ImmutableList.Builder<Artifact> nonLtoArchiveMembersBuilder = ImmutableList.builder();
for (Artifact member : archiveMembers) {
Artifact a;
if (ltoMap != null && (a = ltoMap.remove(member)) != null) {
// When ltoMap is non-null the backend artifact may be missing due to libraries that
// list .o files explicitly, or generate .o files from replacedembler.
if (handledByLtoIndexing(a, allowLtoIndexing)) {
// The LTO artifacts that should be included in the final link
// are listed in the thinltoParamFile, generated by the LTO indexing.
// Even if this object file is being skipped for exposure as a Build variable, it's
// still an input to this action.
expandedLinkerInputsBuilder.add(LinkerInputs.simpleLinkerInput(a, ArtifactCategory.OBJECT_FILE, /* disableWholeArchive= */
false));
continue;
}
// No LTO indexing step, so use the LTO backend's generated artifact directly
// instead of the bitcode object.
member = a;
}
nonLtoArchiveMembersBuilder.add(member);
expandedLinkerInputsBuilder.add(LinkerInputs.simpleLinkerInput(member, ArtifactCategory.OBJECT_FILE, /* disableWholeArchive = */
false));
}
ImmutableList<Artifact> nonLtoArchiveMembers = nonLtoArchiveMembersBuilder.build();
if (!nonLtoArchiveMembers.isEmpty()) {
if (inputIsWholeArchive) {
for (Artifact member : nonLtoArchiveMembers) {
if (member.isTreeArtifact()) {
// TODO(b/78189629): This object filegroup is expanded at action time but wrapped
// with --start/--end-lib. There's currently no way to force these objects to be
// linked in.
librariesToLink.addValue(LibraryToLinkValue.forObjectFileGroup(ImmutableList.<Artifact>of(member), /* isWholeArchive= */
true));
} else {
// TODO(b/78189629): These each need to be their own LibraryToLinkValue so they're
// not wrapped in --start/--end-lib (which lets the linker leave out objects with
// unreferenced code).
librariesToLink.addValue(LibraryToLinkValue.forObjectFile(effectiveObjectFilePath(member, input.isFake()), /* isWholeArchive= */
true));
}
}
} else {
librariesToLink.addValue(LibraryToLinkValue.forObjectFileGroup(nonLtoArchiveMembers, /* isWholeArchive= */
false));
}
}
}
} else {
Artifact inputArtifact = input.getArtifact();
Artifact a;
if (ltoMap != null && (a = ltoMap.remove(inputArtifact)) != null) {
if (handledByLtoIndexing(a, allowLtoIndexing)) {
// The LTO artifacts that should be included in the final link
// are listed in the thinltoParamFile, generated by the LTO indexing.
// Even if this object file is being skipped for exposure as a build variable, it's
// still an input to this action.
expandedLinkerInputsBuilder.add(LinkerInputs.simpleLinkerInput(a, ArtifactCategory.OBJECT_FILE, /* disableWholeArchive= */
false));
return;
}
// No LTO indexing step, so use the LTO backend's generated artifact directly
// instead of the bitcode object.
inputArtifact = a;
}
if (artifactCategory.equals(ArtifactCategory.OBJECT_FILE)) {
if (inputArtifact.isTreeArtifact()) {
librariesToLink.addValue(LibraryToLinkValue.forObjectFileGroup(ImmutableList.<Artifact>of(inputArtifact), inputIsWholeArchive));
} else {
librariesToLink.addValue(LibraryToLinkValue.forObjectFile(effectiveObjectFilePath(inputArtifact, input.isFake()), inputIsWholeArchive));
}
if (!input.isLinkstamp()) {
expandedLinkerInputsBuilder.add(input);
}
} else {
librariesToLink.addValue(LibraryToLinkValue.forStaticLibrary(effectiveObjectFilePath(inputArtifact, input.isFake()), inputIsWholeArchive));
expandedLinkerInputsBuilder.add(input);
}
}
}
/**
* Returns true if this artifact is produced from a bitcode file that will be input to the LTO
* indexing step, in which case that step will add it to the generated thinltoParamFile for
* inclusion in the final link step if the linker decides to include it.
*
* @param a is an artifact produced by an LTO backend.
* @param allowLtoIndexing
*/
private static boolean handledByLtoIndexing(Artifact a, boolean allowLtoIndexing) {
// If no LTO indexing is allowed for this link, then none are handled by LTO indexing.
// Otherwise, this may be from a linkstatic library that we decided not to include in
// LTO indexing because we are linking a test, to improve scalability when linking many tests.
return allowLtoIndexing && !a.getRootRelativePath().startsWith(PathFragment.create(CppLinkActionBuilder.SHARED_NONLTO_BACKEND_ROOT_PREFIX));
}
private Map<Artifact, Artifact> generateLtoMap() {
if (isLtoIndexing || allLtoArtifacts == null) {
return null;
}
// TODO(bazel-team): The LTO final link can only work if there are individual .o files on
// the command line. Rather than crashing, this should issue a nice error. We will get
// this by
// 1) moving supports_start_end_lib to a toolchain feature
// 2) having thin_lto require start_end_lib
// As a bonus, we can rephrase --nostart_end_lib as --features=-start_end_lib and get rid
// of a command line option.
Preconditions.checkState(CppHelper.useStartEndLib(cppConfiguration, ccToolchainProvider, featureConfiguration));
Map<Artifact, Artifact> ltoMap = new HashMap<>();
for (LtoBackendArtifacts l : allLtoArtifacts) {
ltoMap.put(l.getBitcodeFile(), l.getObjectFile());
}
return ltoMap;
}
}
18
View Complete Implementation : ObjcCppSemantics.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
@Override
public void finalizeCompileActionBuilder(BuildConfiguration configuration, FeatureConfiguration featureConfiguration, CppCompileActionBuilder actionBuilder) {
actionBuilder.addTransitiveMandatoryInputs(actionBuilder.getToolchain().getAllFilesMiddleman()).setShouldScanIncludes(includeProcessingType == INCLUDE_SCANNING);
if (includeProcessingType == NO_PROCESSING) {
// TODO(b/62060839): Identify the mechanism used to add generated headers in c++, and recycle
// it here.
actionBuilder.addTransitiveMandatoryInputs(objcProvider.getGeneratedHeaders());
}
}
18
View Complete Implementation : CppLinkActionTest.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
@Test
public void testSplitExecutableLinkCommandDynamicWithNoSplitting() throws Exception {
getreplacedysisMock().ccSupport().setupCcToolchainConfig(mockToolsConfig, CcToolchainConfig.builder().withFeatures(CppRuleClreplacedes.DO_NOT_SPLIT_LINKING_CMDLINE));
RuleContext ruleContext = createDummyRuleContext();
FeatureConfiguration featureConfiguration = getMockFeatureConfiguration(/* envVars= */
ImmutableMap.of());
CppLinkAction linkAction = createLinkBuilder(ruleContext, LinkTargetType.DYNAMIC_LIBRARY, "dummyRuleContext/out.so", ImmutableList.of(), ImmutableList.of(), featureConfiguration).setLibraryIdentifier("library").build();
Pair<List<String>, List<String>> result = linkAction.getLinkCommandLine().splitCommandline();
replacedertThat(result.first.stream().map(x -> removeOutDirectory(x)).collect(ImmutableList.toImmutableList())).containsExactly("crosstool/gcc_tool", "@/k8-fastbuild/bin/dummyRuleContext/out.so-2.params").inOrder();
replacedertThat(result.second.stream().map(x -> removeOutDirectory(x)).collect(ImmutableList.toImmutableList())).containsExactly("-shared", "-o", "/k8-fastbuild/bin/dummyRuleContext/out.so", "-Wl,-S", "--sysroot=/usr/grte/v1").inOrder();
}
18
View Complete Implementation : CppLinkActionTest.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
private CppLinkActionBuilder createLinkBuilder(RuleContext ruleContext, Link.LinkTargetType type, String outputPath, Iterable<Artifact> nonLibraryInputs, ImmutableList<LibraryToLink> libraryInputs, FeatureConfiguration featureConfiguration) {
CcToolchainProvider toolchain = CppHelper.getToolchainUsingDefaultCcToolchainAttribute(ruleContext);
CppLinkActionBuilder builder = new CppLinkActionBuilder(ruleContext, ruleContext, ruleContext.getLabel(), ActionsTestUtil.createArtifact(getTargetConfiguration().getBinDirectory(ruleContext.getRule().getRepository()), outputPath), ruleContext.getConfiguration(), toolchain, toolchain.getFdoContext(), featureConfiguration, MockCppSemantics.INSTANCE).addObjectFiles(nonLibraryInputs).addLibraries(libraryInputs).setLinkType(type).setLinkerFiles(NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER)).setLinkingMode(LinkingMode.STATIC);
return builder;
}
18
View Complete Implementation : CppLinkActionTest.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
@Test
public void testExecutionRequirementsFromCrosstool() throws Exception {
RuleContext ruleContext = createDummyRuleContext();
FeatureConfiguration featureConfiguration = CcToolchainFeaturesTest.buildFeatures("action_config {", " config_name: '" + LinkTargetType.EXECUTABLE.getActionName() + "'", " action_name: '" + LinkTargetType.EXECUTABLE.getActionName() + "'", " tool {", " tool_path: 'DUMMY_TOOL'", " execution_requirement: 'dummy-exec-requirement'", " }", "}").getFeatureConfiguration(ImmutableSet.of(LinkTargetType.EXECUTABLE.getActionName()));
CppLinkAction linkAction = createLinkBuilder(ruleContext, LinkTargetType.EXECUTABLE, "dummyRuleContext/out", ImmutableList.of(), ImmutableList.of(), featureConfiguration).build();
replacedertThat(linkAction.getExecutionInfo()).containsEntry("dummy-exec-requirement", "");
}
18
View Complete Implementation : LinkBuildVariablesTestCase.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Returns the value of a given string variable in context of the given Variables instance.
*/
protected static String getVariableValue(RuleContext ruleContext, CcToolchainVariables variables, String variable) throws Exception {
FeatureConfiguration mockFeatureConfiguration = buildFeatures(ruleContext, "feature {", " name: 'a'", " flag_set {", " action: 'foo'", " flag_group {", " flag: '%{" + variable + "}'", " }", " }", "}").getFeatureConfiguration(ImmutableSet.of("a"));
return Iterables.getOnlyElement(mockFeatureConfiguration.getCommandLine("foo", variables));
}
17
View Complete Implementation : BazelJavaSemantics.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
@Override
public Pair<Artifact, Artifact> getLauncher(RuleContext ruleContext, JavaCommon common, DeployArchiveBuilder deployArchiveBuilder, DeployArchiveBuilder unstrippedDeployArchiveBuilder, Builder runfilesBuilder, List<String> jvmFlags, JavaTargetAttributes.Builder attributesBuilder, boolean shouldStrip, CcToolchainProvider ccToolchain, FeatureConfiguration featureConfiguration) {
Artifact launcher = JavaHelper.launcherArtifactForTarget(this, ruleContext);
return new Pair<>(launcher, launcher);
}
17
View Complete Implementation : CompileCommandLine.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* The compile command line for the C++ compile action.
*/
@AutoCodec
public final clreplaced CompileCommandLine {
private final Artifact sourceFile;
private final CoptsFilter coptsFilter;
private final FeatureConfiguration featureConfiguration;
private final CcToolchainVariables variables;
private final String actionName;
private final Artifact dotdFile;
@AutoCodec.Instantiator
@VisibleForSerialization
CompileCommandLine(Artifact sourceFile, CoptsFilter coptsFilter, FeatureConfiguration featureConfiguration, CcToolchainVariables variables, String actionName, Artifact dotdFile) {
this.sourceFile = Preconditions.checkNotNull(sourceFile);
this.coptsFilter = coptsFilter;
this.featureConfiguration = Preconditions.checkNotNull(featureConfiguration);
this.variables = variables;
this.actionName = actionName;
this.dotdFile = isGenerateDotdFile(sourceFile) ? dotdFile : null;
}
/**
* Returns true if Dotd file should be generated.
*/
private boolean isGenerateDotdFile(Artifact sourceArtifact) {
return CppFileTypes.headerDiscoveryRequired(sourceArtifact) && !featureConfiguration.isEnabled(CppRuleClreplacedes.PARSE_SHOWINCLUDES);
}
/**
* Returns the environment variables that should be set for C++ compile actions.
*/
protected Map<String, String> getEnvironment() throws CommandLineExpansionException {
try {
return featureConfiguration.getEnvironmentVariables(actionName, variables);
} catch (ExpansionException e) {
throw new CommandLineExpansionException(e.getMessage());
}
}
/**
* Returns the tool path for the compilation based on the current feature configuration.
*/
@VisibleForTesting
public String getToolPath() {
Preconditions.checkArgument(featureConfiguration.actionIsConfigured(actionName), "Expected action_config for '%s' to be configured", actionName);
return featureConfiguration.getToolPathForAction(actionName);
}
/**
* @param overwrittenVariables: Variables that will overwrite original build variables. When null,
* unmodified original variables are used.
*/
protected List<String> getArguments(@Nullable PathFragment parameterFilePath, @Nullable CcToolchainVariables overwrittenVariables) throws CommandLineExpansionException {
List<String> commandLine = new ArrayList<>();
// first: The command name.
commandLine.add(getToolPath());
// second: The compiler options.
if (parameterFilePath != null) {
commandLine.add("@" + parameterFilePath.getSafePathString());
} else {
commandLine.addAll(getCompilerOptions(overwrittenVariables));
}
return commandLine;
}
/**
* Returns {@link CommandLine} instance that contains the exactly same command line as the {@link
* CppCompileAction}.
*
* @param cppCompileAction - {@link CppCompileAction} owning this {@link CompileCommandLine}.
*/
public CommandLine getFilteredFeatureConfigurationCommandLine(CppCompileAction cppCompileAction) {
return new CommandLine() {
@Override
public Iterable<String> arguments() throws CommandLineExpansionException {
CcToolchainVariables overwrittenVariables = cppCompileAction.getOverwrittenVariables();
List<String> compilerOptions = getCompilerOptions(overwrittenVariables);
return ImmutableList.<String>builder().add(getToolPath()).addAll(compilerOptions).build();
}
};
}
public List<String> getCompilerOptions(@Nullable CcToolchainVariables overwrittenVariables) throws CommandLineExpansionException {
try {
List<String> options = new ArrayList<>();
CcToolchainVariables updatedVariables = variables;
if (variables != null && overwrittenVariables != null) {
CcToolchainVariables.Builder variablesBuilder = CcToolchainVariables.builder(variables);
variablesBuilder.addAllNonTransitive(overwrittenVariables);
updatedVariables = variablesBuilder.build();
}
addFilteredOptions(options, featureConfiguration.getPerFeatureExpansions(actionName, updatedVariables));
return options;
} catch (ExpansionException e) {
throw new CommandLineExpansionException(e.getMessage());
}
}
// For each option in 'in', add it to 'out' unless it is matched by the 'coptsFilter' regexp.
private void addFilteredOptions(List<String> out, List<Pair<String, List<String>>> expandedFeatures) {
for (Pair<String, List<String>> pair : expandedFeatures) {
if (pair.getFirst().equals(CppRuleClreplacedes.UNFILTERED_COMPILE_FLAGS_FEATURE_NAME)) {
out.addAll(pair.getSecond());
continue;
}
// We do not uses Java's stream API here as it causes a substantial overhead compared to the
// very little work that this is actually doing.
for (String flag : pair.getSecond()) {
if (coptsFilter.preplacedesFilter(flag)) {
out.add(flag);
}
}
}
}
public Artifact getSourceFile() {
return sourceFile;
}
public Artifact getDotdFile() {
return dotdFile;
}
public CcToolchainVariables getVariables() {
return variables;
}
/**
* Returns all user provided copts flags.
*
* TODO(b/64108724): Get rid of this method when we don't need to parse copts to collect include
* directories anymore (meaning there is a way of specifying include directories using an
* explicit attribute, not using platform-dependent garbage bag that copts is).
*/
public ImmutableList<String> getCopts() {
if (variables.isAvailable(CompileBuildVariables.USER_COMPILE_FLAGS.getVariableName())) {
try {
return CcToolchainVariables.toStringList(variables, CompileBuildVariables.USER_COMPILE_FLAGS.getVariableName());
} catch (ExpansionException e) {
throw new IllegalStateException("Should not happen - 'user_compile_flags' should be a string list, but wasn't.");
}
} else {
return ImmutableList.of();
}
}
public static Builder builder(Artifact sourceFile, CoptsFilter coptsFilter, String actionName, Artifact dotdFile) {
return new Builder(sourceFile, coptsFilter, actionName, dotdFile);
}
/**
* A builder for a {@link CompileCommandLine}.
*/
public static final clreplaced Builder {
private final Artifact sourceFile;
private CoptsFilter coptsFilter;
private FeatureConfiguration featureConfiguration;
private CcToolchainVariables variables = CcToolchainVariables.EMPTY;
private final String actionName;
@Nullable
private final Artifact dotdFile;
public CompileCommandLine build() {
return new CompileCommandLine(Preconditions.checkNotNull(sourceFile), Preconditions.checkNotNull(coptsFilter), Preconditions.checkNotNull(featureConfiguration), Preconditions.checkNotNull(variables), Preconditions.checkNotNull(actionName), dotdFile);
}
private Builder(Artifact sourceFile, CoptsFilter coptsFilter, String actionName, Artifact dotdFile) {
this.sourceFile = sourceFile;
this.coptsFilter = coptsFilter;
this.actionName = actionName;
this.dotdFile = dotdFile;
}
/**
* Sets the feature configuration for this compile action.
*/
public Builder setFeatureConfiguration(FeatureConfiguration featureConfiguration) {
this.featureConfiguration = featureConfiguration;
return this;
}
public Builder setVariables(CcToolchainVariables variables) {
this.variables = variables;
return this;
}
@VisibleForTesting
Builder setCoptsFilter(CoptsFilter filter) {
this.coptsFilter = Preconditions.checkNotNull(filter);
return this;
}
}
}
17
View Complete Implementation : CppHelper.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Convenience function for finding the static runtime inputs for the current toolchain. Useful
* for non C++ rules that link against the C++ runtime.
*/
public static NestedSet<Artifact> getDefaultCcToolchainStaticRuntimeInputs(RuleContext ruleContext) throws RuleErrorException {
CcToolchainProvider defaultToolchain = getToolchainUsingDefaultCcToolchainAttribute(ruleContext);
if (defaultToolchain == null) {
return NestedSetBuilder.emptySet(Order.STABLE_ORDER);
}
FeatureConfiguration featureConfiguration = CcCommon.configureFeaturesOrReportRuleError(ruleContext, defaultToolchain);
try {
return defaultToolchain.getStaticRuntimeLinkInputs(featureConfiguration);
} catch (EvalException e) {
throw ruleContext.throwWithRuleError(e.getMessage());
}
}
17
View Complete Implementation : CppHelper.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Decide which DEF file should be used for the linking action.
*
* @return The artifact of the DEF file that should be used for the linking action.
*/
public static Artifact getWindowsDefFileForLinking(RuleContext ruleContext, Artifact customDefFile, Artifact generatedDefFile, FeatureConfiguration featureConfiguration) {
// 1. If a custom DEF file is specified in win_def_file attribute, use it.
// 2. If a generated DEF file is available and should be used, use it.
// 3. Otherwise, we use an empty DEF file to ensure the import library will be generated.
if (customDefFile != null) {
return customDefFile;
} else if (generatedDefFile != null && CppHelper.shouldUseGeneratedDefFile(ruleContext, featureConfiguration)) {
return generatedDefFile;
} else {
return createEmptyDefFileAction(ruleContext);
}
}
17
View Complete Implementation : CppHelper.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Convenience function for finding the dynamic runtime inputs for the current toolchain. Useful
* for Starlark-defined rules that link against the C++ runtime.
*
* <p>This uses the default feature configuration. Do *not* use this method in rules that use a
* non-default feature configuration, or risk a mismatch.
*/
public static NestedSet<Artifact> getDefaultCcToolchainDynamicRuntimeInputsFromStarlark(RuleContext ruleContext) throws EvalException {
CcToolchainProvider defaultToolchain = getToolchainUsingDefaultCcToolchainAttribute(ruleContext);
if (defaultToolchain == null) {
return NestedSetBuilder.emptySet(Order.STABLE_ORDER);
}
FeatureConfiguration featureConfiguration = CcCommon.configureFeaturesOrReportRuleError(ruleContext, defaultToolchain);
return defaultToolchain.getDynamicRuntimeLinkInputs(featureConfiguration);
}
17
View Complete Implementation : CppLinkActionTest.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
@Test
public void testInterfaceOutputForDynamicLibraryLegacy() throws Exception {
RuleContext ruleContext = createDummyRuleContext();
FeatureConfiguration featureConfiguration = CcToolchainFeaturesTest.buildFeatures(MockCcSupport.SUPPORTS_INTERFACE_SHARED_LIBRARIES_FEATURE, "feature {", " name: 'build_interface_libraries'", " flag_set {", " action: '" + LinkTargetType.NODEPS_DYNAMIC_LIBRARY.getActionName() + "',", " flag_group {", " flag: '%{generate_interface_library}'", " flag: '%{interface_library_builder_path}'", " flag: '%{interface_library_input_path}'", " flag: '%{interface_library_output_path}'", " }", " }", "}", "feature {", " name: 'dynamic_library_linker_tool'", " flag_set {", " action: 'c++-link-nodeps-dynamic-library'", " flag_group {", " flag: 'dynamic_library_linker_tool'", " }", " }", "}", "feature {", " name: 'has_configured_linker_path'", "}", "action_config {", " config_name: '" + LinkTargetType.NODEPS_DYNAMIC_LIBRARY.getActionName() + "'", " action_name: '" + LinkTargetType.NODEPS_DYNAMIC_LIBRARY.getActionName() + "'", " tool {", " tool_path: 'custom/crosstool/scripts/link_dynamic_library.sh'", " }", " implies: 'has_configured_linker_path'", " implies: 'build_interface_libraries'", " implies: 'dynamic_library_linker_tool'", "}").getFeatureConfiguration(ImmutableSet.of("build_interface_libraries", "dynamic_library_linker_tool", LinkTargetType.NODEPS_DYNAMIC_LIBRARY.getActionName()));
CppLinkActionBuilder builder = createLinkBuilder(ruleContext, LinkTargetType.NODEPS_DYNAMIC_LIBRARY, "foo.so", ImmutableList.<Artifact>of(), ImmutableList.<LibraryToLink>of(), featureConfiguration).setLibraryIdentifier("foo").setInterfaceOutput(scratchArtifact("FakeInterfaceOutput.ifso"));
List<String> commandLine = builder.build().getCommandLine(null);
replacedertThat(commandLine).hreplacedize(6);
replacedertThat(commandLine.get(0)).endsWith("custom/crosstool/scripts/link_dynamic_library.sh");
replacedertThat(commandLine.get(1)).isEqualTo("yes");
replacedertThat(commandLine.get(2)).endsWith("tools/cpp/build_interface_so");
replacedertThat(commandLine.get(3)).endsWith("foo.so");
replacedertThat(commandLine.get(4)).isEqualTo("out/FakeInterfaceOutput.ifso");
replacedertThat(commandLine.get(5)).isEqualTo("dynamic_library_linker_tool");
}
16
View Complete Implementation : CcLibrary.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Adds linker output artifacts to the given map, to be registered on the configured target as
* output groups.
*/
private static Map<String, NestedSet<Artifact>> addLinkerOutputArtifacts(RuleContext ruleContext, CcToolchainProvider ccToolchain, CppConfiguration cppConfiguration, BuildConfiguration configuration, CcCompilationOutputs ccCompilationOutputs, FeatureConfiguration featureConfiguration) throws RuleErrorException {
NestedSetBuilder<Artifact> archiveFile = new NestedSetBuilder<>(Order.STABLE_ORDER);
NestedSetBuilder<Artifact> dynamicLibrary = new NestedSetBuilder<>(Order.STABLE_ORDER);
ImmutableSortedMap.Builder<String, NestedSet<Artifact>> outputGroups = ImmutableSortedMap.naturalOrder();
if (!ruleContext.attributes().has("alwayslink", Type.BOOLEAN) || !ruleContext.attributes().has("linkstatic", Type.BOOLEAN)) {
return outputGroups.build();
}
if (ruleContext.attributes().get("alwayslink", Type.BOOLEAN)) {
archiveFile.add(CppHelper.getLinkedArtifact(ruleContext, ccToolchain, configuration, Link.LinkTargetType.ALWAYS_LINK_STATIC_LIBRARY, /* linkedArtifactNameSuffix= */
""));
} else {
archiveFile.add(CppHelper.getLinkedArtifact(ruleContext, ccToolchain, configuration, Link.LinkTargetType.STATIC_LIBRARY, /* linkedArtifactNameSuffix= */
""));
}
if (!ruleContext.attributes().get("linkstatic", Type.BOOLEAN) && !ccCompilationOutputs.isEmpty()) {
dynamicLibrary.add(CppHelper.getLinkedArtifact(ruleContext, ccToolchain, configuration, Link.LinkTargetType.NODEPS_DYNAMIC_LIBRARY, /* linkedArtifactNameSuffix= */
""));
if (CppHelper.useInterfaceSharedLibraries(cppConfiguration, ccToolchain, featureConfiguration)) {
dynamicLibrary.add(CppHelper.getLinkedArtifact(ruleContext, ccToolchain, configuration, LinkTargetType.INTERFACE_DYNAMIC_LIBRARY, /* linkedArtifactNameSuffix= */
""));
}
}
outputGroups.put(ARCHIVE_LIBRARY_OUTPUT_GROUP_NAME, archiveFile.build());
outputGroups.put(DYNAMIC_LIBRARY_OUTPUT_GROUP_NAME, dynamicLibrary.build());
return outputGroups.build();
}
16
View Complete Implementation : CcLibrary.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
private static NestedSet<Artifact> collectHiddenTopLevelArtifacts(RuleContext ruleContext, CcToolchainProvider toolchain, CcCompilationOutputs ccCompilationOutputs, FeatureConfiguration featureConfiguration) {
// Ensure that we build all the dependencies, otherwise users may get confused.
NestedSetBuilder<Artifact> artifactsToForceBuilder = NestedSetBuilder.stableOrder();
CppConfiguration cppConfiguration = ruleContext.getFragment(CppConfiguration.clreplaced);
boolean processHeadersInDependencies = cppConfiguration.processHeadersInDependencies();
boolean usePic = toolchain.usePicForDynamicLibraries(cppConfiguration, featureConfiguration);
artifactsToForceBuilder.addTransitive(ccCompilationOutputs.getFilesToCompile(processHeadersInDependencies, usePic));
for (OutputGroupInfo dep : ruleContext.getPrerequisites("deps", Mode.TARGET, OutputGroupInfo.SKYLARK_CONSTRUCTOR)) {
artifactsToForceBuilder.addTransitive(dep.getOutputGroup(OutputGroupInfo.HIDDEN_TOP_LEVEL));
}
return artifactsToForceBuilder.build();
}
16
View Complete Implementation : CppHelper.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
public static ImmutableList<String> getCommandLine(RuleErrorConsumer ruleErrorConsumer, FeatureConfiguration featureConfiguration, CcToolchainVariables variables, String actionName) throws RuleErrorException {
try {
return ImmutableList.copyOf(featureConfiguration.getCommandLine(actionName, variables));
} catch (ExpansionException e) {
throw ruleErrorConsumer.throwWithRuleError(e.getMessage());
}
}
16
View Complete Implementation : LtoBackendArtifacts.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Adds the AFDO profile path to the variable builder and the profile tothe inputs of the action.
*/
@ThreadSafe
private static void addProfileForLtoBackend(LtoBackendAction.Builder builder, FdoContext fdoContext, FeatureConfiguration featureConfiguration, CcToolchainVariables.Builder buildVariables) {
Artifact prefetch = fdoContext.getPrefetchHintsArtifact();
if (prefetch != null) {
buildVariables.addStringVariable("fdo_prefetch_hints_path", prefetch.getExecPathString());
builder.addInput(fdoContext.getPrefetchHintsArtifact());
}
if (!featureConfiguration.isEnabled(CppRuleClreplacedes.AUTOFDO) && !featureConfiguration.isEnabled(CppRuleClreplacedes.CS_FDO_OPTIMIZE) && !featureConfiguration.isEnabled(CppRuleClreplacedes.XBINARYFDO)) {
return;
}
FdoContext.BranchFdoProfile branchFdoProfile = Preconditions.checkNotNull(fdoContext.getBranchFdoProfile());
Artifact profile = branchFdoProfile.getProfileArtifact();
buildVariables.addStringVariable("fdo_profile_path", profile.getExecPathString());
builder.addInput(branchFdoProfile.getProfileArtifact());
}
15
View Complete Implementation : BazelCppSemantics.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
@Override
public void finalizeCompileActionBuilder(BuildConfiguration configuration, FeatureConfiguration featureConfiguration, CppCompileActionBuilder actionBuilder) {
CcToolchainProvider toolchain = actionBuilder.getToolchain();
actionBuilder.addTransitiveMandatoryInputs(configuration.getFragment(CppConfiguration.clreplaced).useSpecificToolFiles() ? (actionBuilder.getActionName().equals(CppActionNames.replacedEMBLE) ? toolchain.getAsFiles() : toolchain.getCompilerFiles()) : toolchain.getAllFiles()).setShouldScanIncludes(false);
}
15
View Complete Implementation : CcCommon.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
private static List<String> computeCcFlagsFromFeatureConfig(RuleContext ruleContext, CcToolchainProvider toolchainProvider) throws RuleErrorException {
FeatureConfiguration featureConfiguration = null;
CppConfiguration cppConfiguration;
if (toolchainProvider.requireCtxInConfigureFeatures()) {
// When --incompatible_require_ctx_in_configure_features is flipped, this whole method will go
// away. But I'm keeping it there so we can experiment with flags before they are flipped.
cppConfiguration = ruleContext.getFragment(CppConfiguration.clreplaced);
} else {
cppConfiguration = toolchainProvider.getCppConfigurationEvenThoughItCanBeDifferentThanWhatTargetHas();
}
try {
featureConfiguration = configureFeaturesOrThrowEvalException(ruleContext.getFeatures(), ruleContext.getDisabledFeatures(), toolchainProvider, cppConfiguration);
} catch (EvalException e) {
ruleContext.ruleError(e.getMessage());
}
if (featureConfiguration.actionIsConfigured(CppActionNames.CC_FLAGS_MAKE_VARIABLE)) {
CcToolchainVariables buildVariables = toolchainProvider.getBuildVariables(ruleContext.getConfiguration().getOptions(), cppConfiguration);
return CppHelper.getCommandLine(ruleContext, featureConfiguration, buildVariables, CppActionNames.CC_FLAGS_MAKE_VARIABLE);
}
return ImmutableList.of();
}
14
View Complete Implementation : CppLinkstampCompileHelper.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Creates {@link CppCompileAction} to compile linkstamp source
*
* @param inputsForInvalidation: see {@link CppCompileAction#inputsForInvalidation}
*/
public static CppCompileAction createLinkstampCompileAction(RuleErrorConsumer ruleErrorConsumer, ActionConstructionContext actionConstructionContext, @Nullable Artifact grepIncludes, BuildConfiguration configuration, Artifact sourceFile, Artifact outputFile, NestedSet<Artifact> compilationInputs, NestedSet<Artifact> nonCodeInputs, NestedSet<Artifact> inputsForInvalidation, ImmutableList<Artifact> buildInfoHeaderArtifacts, Iterable<String> additionalLinkstampDefines, CcToolchainProvider ccToolchainProvider, boolean codeCoverageEnabled, CppConfiguration cppConfiguration, String fdoBuildStamp, FeatureConfiguration featureConfiguration, boolean needsPic, String labelReplacement, String outputReplacement, CppSemantics semantics) {
CppCompileActionBuilder builder = new CppCompileActionBuilder(actionConstructionContext, grepIncludes, ccToolchainProvider, configuration).addMandatoryInputs(compilationInputs).setVariables(getVariables(ruleErrorConsumer, sourceFile, outputFile, labelReplacement, outputReplacement, additionalLinkstampDefines, buildInfoHeaderArtifacts, featureConfiguration, configuration.getOptions(), cppConfiguration, ccToolchainProvider, needsPic, fdoBuildStamp, codeCoverageEnabled)).setFeatureConfiguration(featureConfiguration).setSourceFile(sourceFile).setSemantics(semantics).setOutputs(outputFile, null).setInputsForInvalidation(inputsForInvalidation).setBuiltinIncludeFiles(buildInfoHeaderArtifacts).addMandatoryInputs(nonCodeInputs).setShareable(true).setShouldScanIncludes(false).setActionName(CppActionNames.LINKSTAMP_COMPILE);
semantics.finalizeCompileActionBuilder(configuration, featureConfiguration, builder);
return builder.buildOrThrowIllegalStateException();
}
14
View Complete Implementation : LinkCommandLine.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Represents the command line of a linker invocation. It supports executables and dynamic libraries
* as well as static libraries.
*/
@AutoCodec
@Immutable
public final clreplaced LinkCommandLine extends CommandLine {
private final String actionName;
private final String forcedToolPath;
private final CcToolchainVariables variables;
// The feature config can be null for tests.
@Nullable
private final FeatureConfiguration featureConfiguration;
private final ImmutableList<Artifact> buildInfoHeaderArtifacts;
private final NestedSet<Artifact> linkerInputArtifacts;
private final LinkTargetType linkTargetType;
private final Link.LinkingMode linkingMode;
@Nullable
private final PathFragment toolchainLibrariesSolibDir;
private final boolean nativeDeps;
private final boolean useTestOnlyFlags;
private final boolean doNotSplitLinkingCmdLine;
@Nullable
private final Artifact paramFile;
@VisibleForSerialization
LinkCommandLine(String actionName, String forcedToolPath, ImmutableList<Artifact> buildInfoHeaderArtifacts, NestedSet<Artifact> linkerInputArtifacts, LinkTargetType linkTargetType, Link.LinkingMode linkingMode, @Nullable PathFragment toolchainLibrariesSolibDir, boolean nativeDeps, boolean useTestOnlyFlags, @Nullable Artifact paramFile, CcToolchainVariables variables, @Nullable FeatureConfiguration featureConfiguration, boolean doNotSplitLinkingCmdLine) {
this.actionName = actionName;
this.forcedToolPath = forcedToolPath;
this.variables = variables;
this.featureConfiguration = featureConfiguration;
this.buildInfoHeaderArtifacts = Preconditions.checkNotNull(buildInfoHeaderArtifacts);
this.linkerInputArtifacts = Preconditions.checkNotNull(linkerInputArtifacts);
this.linkTargetType = Preconditions.checkNotNull(linkTargetType);
this.linkingMode = Preconditions.checkNotNull(linkingMode);
this.toolchainLibrariesSolibDir = toolchainLibrariesSolibDir;
this.nativeDeps = nativeDeps;
this.useTestOnlyFlags = useTestOnlyFlags;
this.paramFile = paramFile;
this.doNotSplitLinkingCmdLine = doNotSplitLinkingCmdLine;
}
@Nullable
public Artifact getParamFile() {
return paramFile;
}
/**
* See {@link CppLinkAction#getBuildInfoHeaderArtifacts()}
*/
public ImmutableList<Artifact> getBuildInfoHeaderArtifacts() {
return buildInfoHeaderArtifacts;
}
/**
* Returns the (ordered, immutable) list of paths to the linker's input files.
*/
public NestedSet<Artifact> getLinkerInputArtifacts() {
return linkerInputArtifacts;
}
@Nullable
@VisibleForTesting
public FeatureConfiguration getFeatureConfiguration() {
return featureConfiguration;
}
public String getActionName() {
return actionName;
}
/**
* Returns the current type of link target set.
*/
public LinkTargetType getLinkTargetType() {
return linkTargetType;
}
/**
* Returns the "staticness" of the link.
*/
public Link.LinkingMode getLinkingMode() {
return linkingMode;
}
/**
* Returns the path to the linker.
*/
public String getLinkerPathString() {
return featureConfiguration.getToolPathForAction(linkTargetType.getActionName());
}
/**
* Returns the location of the C++ runtime solib symlinks. If null, the C++ dynamic runtime
* libraries either do not exist (because they do not come from the depot) or they are in the
* regular solib directory.
*/
@Nullable
public PathFragment getToolchainLibrariesSolibDir() {
return toolchainLibrariesSolibDir;
}
/**
* Returns true for libraries linked as native dependencies for other languages.
*/
public boolean isNativeDeps() {
return nativeDeps;
}
/**
* Returns true if this link should use test-specific flags (e.g. $EXEC_ORIGIN as the root for
* finding shared libraries or lazy binding); false by default. See bug "Please use $EXEC_ORIGIN
* instead of $ORIGIN when linking cc_tests" for further context.
*/
public boolean useTestOnlyFlags() {
return useTestOnlyFlags;
}
/**
* Returns the build variables used to template the crosstool for this linker invocation.
*/
@VisibleForTesting
public CcToolchainVariables getBuildVariables() {
return this.variables;
}
/**
* Splits the link command-line into a part to be written to a parameter file, and the remaining
* actual command line to be executed (which references the parameter file). Should only be used
* if getParamFile() is not null.
*/
@VisibleForTesting
final Pair<List<String>, List<String>> splitCommandline() throws CommandLineExpansionException {
return splitCommandline(paramFile, getRawLinkArgv(null), linkTargetType, doNotSplitLinkingCmdLine);
}
@VisibleForTesting
final Pair<List<String>, List<String>> splitCommandline(@Nullable ArtifactExpander expander) throws CommandLineExpansionException {
return splitCommandline(paramFile, getRawLinkArgv(expander), linkTargetType, doNotSplitLinkingCmdLine);
}
private static Pair<List<String>, List<String>> splitCommandline(Artifact paramFile, List<String> args, LinkTargetType linkTargetType, boolean doNotSplitLinkingCmdline) {
Preconditions.checkNotNull(paramFile);
if (linkTargetType.linkerOrArchiver() == LinkerOrArchiver.ARCHIVER) {
// Ar link commands can also generate huge command lines.
List<String> paramFileArgs = new ArrayList<>();
List<String> commandlineArgs = new ArrayList<>();
extractArgumentsForStaticLinkParamFile(args, commandlineArgs, paramFileArgs);
return Pair.of(commandlineArgs, paramFileArgs);
} else {
// Gcc link commands tend to generate humongous commandlines for some targets, which may
// not fit on some remote execution machines. To work around this we will employ the help of
// a parameter file and preplaced any linker options through it.
List<String> paramFileArgs = new ArrayList<>();
List<String> commandlineArgs = new ArrayList<>();
extractArgumentsForDynamicLinkParamFile(args, commandlineArgs, paramFileArgs, doNotSplitLinkingCmdline);
return Pair.of(commandlineArgs, paramFileArgs);
}
}
public CommandLine getCommandLineForStarlark() {
return new CommandLine() {
@Override
public Iterable<String> arguments() throws CommandLineExpansionException {
return arguments(/* artifactExpander= */
null);
}
@Override
public Iterable<String> arguments(ArtifactExpander artifactExpander) throws CommandLineExpansionException {
if (paramFile == null) {
return ImmutableList.copyOf(getRawLinkArgv(artifactExpander));
} else {
return ImmutableList.<String>builder().add(getLinkerPathString()).addAll(splitCommandline(artifactExpander).getSecond()).build();
}
}
};
}
/**
* A {@link CommandLine} implementation that returns the command line args pertaining to the
* .params file.
*/
@AutoCodec
@VisibleForSerialization
static clreplaced ParamFileCommandLine extends CommandLine {
private final Artifact paramsFile;
private final LinkTargetType linkTargetType;
private final String forcedToolPath;
private final FeatureConfiguration featureConfiguration;
private final String actionName;
private final CcToolchainVariables variables;
private final boolean doNotSplitLinkingCmdLine;
public ParamFileCommandLine(Artifact paramsFile, LinkTargetType linkTargetType, String forcedToolPath, FeatureConfiguration featureConfiguration, String actionName, CcToolchainVariables variables, boolean doNotSplitLinkingCmdLine) {
this.paramsFile = paramsFile;
this.linkTargetType = linkTargetType;
this.forcedToolPath = forcedToolPath;
this.featureConfiguration = featureConfiguration;
this.actionName = actionName;
this.variables = variables;
this.doNotSplitLinkingCmdLine = doNotSplitLinkingCmdLine;
}
@Override
public Iterable<String> arguments() throws CommandLineExpansionException {
List<String> argv = getRawLinkArgv(null, forcedToolPath, featureConfiguration, actionName, linkTargetType, variables);
return splitCommandline(paramsFile, argv, linkTargetType, doNotSplitLinkingCmdLine).getSecond();
}
@Override
public Iterable<String> arguments(ArtifactExpander expander) throws CommandLineExpansionException {
List<String> argv = getRawLinkArgv(expander, forcedToolPath, featureConfiguration, actionName, linkTargetType, variables);
return splitCommandline(paramsFile, argv, linkTargetType, doNotSplitLinkingCmdLine).getSecond();
}
}
/**
* Returns just the .params file portion of the command-line as a {@link CommandLine}.
*/
CommandLine paramCmdLine() {
Preconditions.checkNotNull(paramFile);
return new ParamFileCommandLine(paramFile, linkTargetType, forcedToolPath, featureConfiguration, actionName, variables, doNotSplitLinkingCmdLine);
}
public static void extractArgumentsForStaticLinkParamFile(List<String> args, List<String> commandlineArgs, List<String> paramFileArgs) {
// ar command, must not be moved!
commandlineArgs.add(args.get(0));
int argsSize = args.size();
for (int i = 1; i < argsSize; i++) {
String arg = args.get(i);
if (arg.startsWith("@")) {
// params file, keep it in the command line
commandlineArgs.add(arg);
} else {
// the rest goes to the params file
paramFileArgs.add(arg);
}
}
}
public static void extractArgumentsForDynamicLinkParamFile(List<String> args, List<String> commandlineArgs, List<String> paramFileArgs, boolean doNotSplitLinkingCmdline) {
// Note, that it is not important that all linker arguments are extracted so that
// they can be moved into a parameter file, but the vast majority should.
// gcc command, must not be moved!
commandlineArgs.add(args.get(0));
int argsSize = args.size();
if (doNotSplitLinkingCmdline) {
for (int i = 1; i < argsSize; i++) {
String arg = args.get(i);
if (arg.startsWith("@")) {
// params file, keep it in the command line
commandlineArgs.add(arg);
} else {
// the rest goes to the params file
paramFileArgs.add(arg);
}
}
} else {
for (int i = 1; i < argsSize; i++) {
String arg = args.get(i);
if (arg.isEmpty()) {
continue;
}
if (arg.equals("-Wl,-no-whole-archive")) {
paramFileArgs.add("-no-whole-archive");
} else if (arg.equals("-Wl,-whole-archive")) {
paramFileArgs.add("-whole-archive");
} else if (arg.equals("-Wl,--start-group")) {
paramFileArgs.add("--start-group");
} else if (arg.equals("-Wl,--end-group")) {
paramFileArgs.add("--end-group");
} else if (arg.equals("-Wl,--start-lib")) {
paramFileArgs.add("--start-lib");
} else if (arg.equals("-Wl,--end-lib")) {
paramFileArgs.add("--end-lib");
} else if (arg.charAt(0) == '-') {
if (arg.startsWith("-l")) {
paramFileArgs.add(arg);
} else {
// Anything else starting with a '-' can stay on the commandline.
commandlineArgs.add(arg);
if (arg.equals("-o")) {
// Special case for '-o': add the following argument as well - it is the output file!
commandlineArgs.add(args.get(++i));
}
}
} else if (CppFileTypes.OBJECT_FILE.apply(arg) || CppFileTypes.PIC_OBJECT_FILE.apply(arg) || CppFileTypes.ARCHIVE.apply(arg) || CppFileTypes.PIC_ARCHIVE.apply(arg) || CppFileTypes.ALWAYS_LINK_LIBRARY.apply(arg) || CppFileTypes.ALWAYS_LINK_PIC_LIBRARY.apply(arg) || CppFileTypes.SHARED_LIBRARY.apply(arg) || CppFileTypes.INTERFACE_SHARED_LIBRARY.apply(arg) || CppFileTypes.VERSIONED_SHARED_LIBRARY.apply(arg)) {
// All objects of any kind go into the linker parameters.
paramFileArgs.add(arg);
} else {
// Everything that's left stays conservatively on the commandline.
commandlineArgs.add(arg);
}
}
}
}
/**
* Returns a raw link command for the given link invocation, including both command and arguments
* (argv). The version that uses the expander is preferred, but that one can't be used during
* replacedysis.
*
* @return raw link command line.
*/
public List<String> getRawLinkArgv() throws CommandLineExpansionException {
return getRawLinkArgv(null);
}
/**
* Returns a raw link command for the given link invocation, including both command and arguments
* (argv).
*
* @param expander ArtifactExpander for expanding TreeArtifacts.
* @return raw link command line.
*/
public List<String> getRawLinkArgv(@Nullable ArtifactExpander expander) throws CommandLineExpansionException {
return getRawLinkArgv(expander, forcedToolPath, featureConfiguration, actionName, linkTargetType, variables);
}
private static List<String> getRawLinkArgv(@Nullable ArtifactExpander expander, String forcedToolPath, FeatureConfiguration featureConfiguration, String actionName, LinkTargetType linkTargetType, CcToolchainVariables variables) throws CommandLineExpansionException {
List<String> argv = new ArrayList<>();
if (forcedToolPath != null) {
argv.add(forcedToolPath);
} else {
Preconditions.checkArgument(featureConfiguration.actionIsConfigured(actionName), String.format("Expected action_config for '%s' to be configured", actionName));
argv.add(featureConfiguration.getToolPathForAction(linkTargetType.getActionName()));
}
try {
argv.addAll(featureConfiguration.getCommandLine(actionName, variables, expander));
} catch (ExpansionException e) {
throw new CommandLineExpansionException(e.getMessage());
}
return argv;
}
List<String> getCommandLine(@Nullable ArtifactExpander expander) throws CommandLineExpansionException {
// Try to shorten the command line by use of a parameter file.
// This makes the output with --subcommands (et al) more readable.
if (paramFile != null) {
Pair<List<String>, List<String>> split = splitCommandline(expander);
return split.first;
} else {
return getRawLinkArgv(expander);
}
}
@Override
public List<String> arguments() throws CommandLineExpansionException {
return getRawLinkArgv(null);
}
@Override
public Iterable<String> arguments(ArtifactExpander artifactExpander) throws CommandLineExpansionException {
return getRawLinkArgv(artifactExpander);
}
/**
* A builder for a {@link LinkCommandLine}.
*/
public static final clreplaced Builder {
private String forcedToolPath;
private ImmutableList<Artifact> buildInfoHeaderArtifacts = ImmutableList.of();
private NestedSet<Artifact> linkerInputArtifacts = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
@Nullable
private LinkTargetType linkTargetType;
private Link.LinkingMode linkingMode = Link.LinkingMode.STATIC;
@Nullable
private PathFragment toolchainLibrariesSolibDir;
private boolean nativeDeps;
private boolean useTestOnlyFlags;
@Nullable
private Artifact paramFile;
private CcToolchainVariables variables;
private FeatureConfiguration featureConfiguration;
private boolean doNotSplitLinkingCmdLine;
private String actionName;
public LinkCommandLine build() {
if (linkTargetType.linkerOrArchiver() == LinkerOrArchiver.ARCHIVER) {
Preconditions.checkArgument(buildInfoHeaderArtifacts.isEmpty(), "build info headers may only be present on dynamic library or executable links");
}
if (variables == null) {
variables = CcToolchainVariables.EMPTY;
}
return new LinkCommandLine(actionName, forcedToolPath, buildInfoHeaderArtifacts, linkerInputArtifacts, linkTargetType, linkingMode, toolchainLibrariesSolibDir, nativeDeps, useTestOnlyFlags, paramFile, variables, featureConfiguration, doNotSplitLinkingCmdLine);
}
/**
* Use given tool path instead of the one from feature configuration
*/
public Builder forceToolPath(String forcedToolPath) {
this.forcedToolPath = forcedToolPath;
return this;
}
/**
* Sets the feature configuration for this link action.
*/
public Builder setFeatureConfiguration(FeatureConfiguration featureConfiguration) {
this.featureConfiguration = featureConfiguration;
return this;
}
/**
* Sets the type of the link. It is an error to try to set this to {@link
* LinkTargetType#INTERFACE_DYNAMIC_LIBRARY}. Note that all the static target types (see {@link
* LinkTargetType#linkerOrArchiver}) are equivalent, and there is no check that the output
* artifact matches the target type extension.
*/
public Builder setLinkTargetType(LinkTargetType linkTargetType) {
Preconditions.checkArgument(linkTargetType != LinkTargetType.INTERFACE_DYNAMIC_LIBRARY);
this.linkTargetType = linkTargetType;
return this;
}
/**
* Sets a list of linker input artifacts. These get turned into linker options depending on the
* staticness and the target type. This call makes an immutable copy of the inputs, if the
* provided Iterable isn't already immutable (see {@link CollectionUtils#makeImmutable}).
*/
public Builder setLinkerInputArtifacts(NestedSet<Artifact> linkerInputArtifacts) {
this.linkerInputArtifacts = linkerInputArtifacts;
return this;
}
/**
* Sets how static the link is supposed to be. For static target types (see {@link
* LinkTargetType#linkerOrArchiver()}}), the {@link #build} method throws an exception if this
* is not {@link LinkingMode#STATIC}. The default setting is {@link LinkingMode#STATIC}.
*/
public Builder setLinkingMode(Link.LinkingMode linkingMode) {
this.linkingMode = linkingMode;
return this;
}
/**
* The build info header artifacts are generated header files that are used for link stamping.
* The {@link #build} method throws an exception if the build info header artifacts are
* non-empty for a static link (see {@link LinkTargetType#linkerOrArchiver()}}).
*/
public Builder setBuildInfoHeaderArtifacts(ImmutableList<Artifact> buildInfoHeaderArtifacts) {
this.buildInfoHeaderArtifacts = buildInfoHeaderArtifacts;
return this;
}
/**
* Whether the resulting library is intended to be used as a native library from another
* programming language. This influences the rpath. The {@link #build} method throws an
* exception if this is true for a static link (see {@link LinkTargetType#linkerOrArchiver()}}).
*/
public Builder setNativeDeps(boolean nativeDeps) {
this.nativeDeps = nativeDeps;
return this;
}
/**
* Sets whether to use test-specific linker flags, e.g. {@code $EXEC_ORIGIN} instead of {@code
* $ORIGIN} in the rpath or lazy binding.
*/
public Builder setUseTestOnlyFlags(boolean useTestOnlyFlags) {
this.useTestOnlyFlags = useTestOnlyFlags;
return this;
}
public Builder setParamFile(Artifact paramFile) {
this.paramFile = paramFile;
return this;
}
public Builder setBuildVariables(CcToolchainVariables variables) {
this.variables = variables;
return this;
}
public Builder setToolchainLibrariesSolibDir(PathFragment toolchainLibrariesSolibDir) {
this.toolchainLibrariesSolibDir = toolchainLibrariesSolibDir;
return this;
}
public Builder doNotSplitLinkingCmdLine() {
this.doNotSplitLinkingCmdLine = true;
return this;
}
public Builder setActionName(String actionName) {
this.actionName = actionName;
return this;
}
}
}
13
View Complete Implementation : CcCommon.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Returns artifacts that help debug the state of C++ features for the given ruleContext.
*/
public static Map<String, NestedSet<Artifact>> createSaveFeatureStateArtifacts(CppConfiguration cppConfiguration, FeatureConfiguration featureConfiguration, RuleContext ruleContext) {
ImmutableMap.Builder<String, NestedSet<Artifact>> outputGroupsBuilder = ImmutableMap.builder();
if (cppConfiguration.saveFeatureState()) {
Artifact enabledFeaturesFile = ruleContext.getUniqueDirectoryArtifact("feature_debug", "enabled_features.txt");
ruleContext.registerAction(FileWriteAction.create(ruleContext, enabledFeaturesFile, featureConfiguration.getEnabledFeatureNames().toString(), /* makeExecutable= */
false));
Artifact requestedFeaturesFile = ruleContext.getUniqueDirectoryArtifact("feature_debug", "requested_features.txt");
ruleContext.registerAction(FileWriteAction.create(ruleContext, requestedFeaturesFile, featureConfiguration.getRequestedFeatures().toString(), /* makeExecutable= */
false));
outputGroupsBuilder.put(OutputGroupInfo.DEFAULT, NestedSetBuilder.<Artifact>stableOrder().add(enabledFeaturesFile).add(requestedFeaturesFile).build());
}
return outputGroupsBuilder.build();
}
13
View Complete Implementation : LinkCommandLine.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
private static List<String> getRawLinkArgv(@Nullable ArtifactExpander expander, String forcedToolPath, FeatureConfiguration featureConfiguration, String actionName, LinkTargetType linkTargetType, CcToolchainVariables variables) throws CommandLineExpansionException {
List<String> argv = new ArrayList<>();
if (forcedToolPath != null) {
argv.add(forcedToolPath);
} else {
Preconditions.checkArgument(featureConfiguration.actionIsConfigured(actionName), String.format("Expected action_config for '%s' to be configured", actionName));
argv.add(featureConfiguration.getToolPathForAction(linkTargetType.getActionName()));
}
try {
argv.addAll(featureConfiguration.getCommandLine(actionName, variables, expander));
} catch (ExpansionException e) {
throw new CommandLineExpansionException(e.getMessage());
}
return argv;
}
13
View Complete Implementation : CppLinkstampCompileHelperTest.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
/**
* Regression test for b/73447914: Linkstamps were not re-built when only volatile data changed,
* i.e. when we modified cc_binary source, linkstamp was not recompiled so we got old timestamps.
* The proper behavior is to recompile linkstamp whenever any input to cc_binary action changes.
* And the current implementation solves this by adding all linking inputs as
* inputsForInvalidation to linkstamp compile action.
*/
@Test
public void testLinkstampCompileDependsOnAllCcBinaryLinkingInputs() throws Exception {
scratch.file("x/BUILD", "cc_binary(", " name = 'foo',", " deps = ['bar'],", " srcs = [ 'main.cc' ],", ")", "cc_library(", " name = 'bar',", " srcs = [ 'bar.cc' ],", " linkstamp = 'ls.cc',", ")");
useConfiguration();
ConfiguredTarget target = getConfiguredTarget("//x:foo");
Artifact executable = getExecutable(target);
CcToolchainProvider toolchain = CppHelper.getToolchainUsingDefaultCcToolchainAttribute(getRuleContext(target));
CppConfiguration cppConfiguration = getRuleContext(target).getFragment(CppConfiguration.clreplaced);
FeatureConfiguration featureConfiguration = CcCommon.configureFeaturesOrThrowEvalException(/* requestedFeatures= */
ImmutableSet.of(), /* unsupportedFeatures= */
ImmutableSet.of(), toolchain, cppConfiguration);
boolean usePic = CppHelper.usePicForBinaries(toolchain, cppConfiguration, featureConfiguration);
CppLinkAction generatingAction = (CppLinkAction) getGeneratingAction(executable);
Artifact compiledLinkstamp = ActionsTestUtil.getFirstArtifactEndingWith(generatingAction.getInputs(), "ls.o");
CppCompileAction linkstampCompileAction = (CppCompileAction) getGeneratingAction(compiledLinkstamp);
Artifact mainObject = ActionsTestUtil.getFirstArtifactEndingWith(generatingAction.getInputs(), usePic ? "main.pic.o" : "main.o");
Artifact bar = generatingAction.getInputs().toList().stream().filter(a -> a.getExecPath().getBaseName().contains("bar")).findFirst().get();
ImmutableList<Artifact> linkstampInputs = linkstampCompileAction.getInputs().toList();
replacedertThat(linkstampInputs).containsAtLeast(mainObject, bar);
}
11
View Complete Implementation : LtoBackendArtifacts.java
Copyright Apache License 2.0
Author : bazelbuild
Copyright Apache License 2.0
Author : bazelbuild
private void scheduleLtoBackendAction(RuleErrorConsumer ruleErrorConsumer, BuildOptions buildOptions, CppConfiguration cppConfiguration, ActionConstructionContext actionConstructionContext, RepositoryName repositoryName, FeatureConfiguration featureConfiguration, CcToolchainProvider ccToolchain, FdoContext fdoContext, boolean usePic, boolean generateDwo, BuildConfiguration configuration, LinkArtifactFactory linkArtifactFactory, List<String> userCompileFlags, @Nullable BitcodeFiles bitcodeFiles) throws RuleErrorException {
LtoBackendAction.Builder builder = new LtoBackendAction.Builder();
builder.addInput(bitcodeFile);
Preconditions.checkState((index == null) == (imports == null), "Either both or neither index and imports files should be null");
if (imports != null) {
builder.addImportsInfo(bitcodeFiles, imports);
// Although the imports file is not used by the LTOBackendAction while the action is
// executing, it is needed during the input discovery phase, and we must list it as an input
// to the action in order for it to be preserved under --discard_orphaned_artifacts.
builder.addInput(imports);
}
if (index != null) {
builder.addInput(index);
}
builder.addTransitiveInputs(ccToolchain.getCompilerFiles());
builder.addOutput(objectFile);
builder.setProgressMessage("LTO Backend Compile %s", objectFile.getExecPath());
builder.setMnemonic("CcLtoBackendCompile");
CcToolchainVariables.Builder buildVariablesBuilder = CcToolchainVariables.builder(ccToolchain.getBuildVariables(buildOptions, cppConfiguration));
if (index != null) {
buildVariablesBuilder.addStringVariable("thinlto_index", index.getExecPath().toString());
} else {
// An empty input indicates not to perform cross-module optimization.
buildVariablesBuilder.addStringVariable("thinlto_index", "/dev/null");
}
// The output from the LTO backend step is a native object file.
buildVariablesBuilder.addStringVariable("thinlto_output_object_file", objectFile.getExecPath().toString());
// The input to the LTO backend step is the bitcode file.
buildVariablesBuilder.addStringVariable("thinlto_input_bitcode_file", bitcodeFile.getExecPath().toString());
addProfileForLtoBackend(builder, fdoContext, featureConfiguration, buildVariablesBuilder);
// Add the context sensitive instrument path to the backend.
if (featureConfiguration.isEnabled(CppRuleClreplacedes.CS_FDO_INSTRUMENT)) {
buildVariablesBuilder.addStringVariable(CompileBuildVariables.CS_FDO_INSTRUMENT_PATH.getVariableName(), ccToolchain.getCSFdoInstrument());
}
if (generateDwo) {
dwoFile = linkArtifactFactory.create(actionConstructionContext, repositoryName, configuration, FileSystemUtils.replaceExtension(objectFile.getRootRelativePath(), ".dwo"));
builder.addOutput(dwoFile);
buildVariablesBuilder.addStringVariable(CompileBuildVariables.PER_OBJECT_DEBUG_INFO_FILE.getVariableName(), dwoFile.getExecPathString());
buildVariablesBuilder.addStringVariable(CompileBuildVariables.IS_USING_FISSION.getVariableName(), "");
}
buildVariablesBuilder.addStringSequenceVariable(CompileBuildVariables.USER_COMPILE_FLAGS.getVariableName(), userCompileFlags);
CcToolchainVariables buildVariables = buildVariablesBuilder.build();
if (cppConfiguration.useStandaloneLtoIndexingCommandLines()) {
if (!featureConfiguration.actionIsConfigured(CppActionNames.LTO_BACKEND)) {
throw ruleErrorConsumer.throwWithRuleError("Thinlto build is requested, but the C++ toolchain doesn't define an action_config for" + " 'lto-backend' action.");
}
PathFragment compiler = PathFragment.create(featureConfiguration.getToolPathForAction(CppActionNames.LTO_BACKEND));
builder.setExecutable(compiler);
} else {
PathFragment compiler = ccToolchain.getToolPathFragment(Tool.GCC, ruleErrorConsumer);
builder.setExecutable(compiler);
}
CommandLine ltoCommandLine = new CommandLine() {
@Override
public Iterable<String> arguments() throws CommandLineExpansionException {
return arguments(/* artifactExpander= */
null);
}
@Override
public Iterable<String> arguments(ArtifactExpander artifactExpander) throws CommandLineExpansionException {
ImmutableList.Builder<String> args = ImmutableList.builder();
try {
args.addAll(featureConfiguration.getCommandLine(CppActionNames.LTO_BACKEND, buildVariables, artifactExpander));
} catch (ExpansionException e) {
throw new CommandLineExpansionException(e.getMessage());
}
// If this is a PIC compile (set based on the CppConfiguration), the PIC
// option should be added after the rest of the command line so that it
// cannot be overridden. This is consistent with the ordering in the
// CppCompileAction's compiler options.
if (usePic) {
args.add("-fPIC");
}
return args.build();
}
};
builder.addCommandLine(ltoCommandLine);
actionConstructionContext.registerAction(builder.build(actionConstructionContext));
}