blob: 914ec608af4d421ae4a1d263591a2108a76b7880 [file] [log] [blame]
// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.rules.cpp;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration.Options.MakeVariableSource;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.config.CompilationMode;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
import com.google.devtools.build.lib.analysis.config.PerLabelOptions;
import com.google.devtools.build.lib.analysis.skylark.annotations.SkylarkConfigurationField;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.rules.cpp.CppConfigurationLoader.CppConfigurationParameters;
import com.google.devtools.build.lib.rules.cpp.CrosstoolConfigurationLoader.CrosstoolFile;
import com.google.devtools.build.lib.rules.cpp.Link.LinkingMode;
import com.google.devtools.build.lib.skylarkbuildapi.cpp.CppConfigurationApi;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig;
import java.util.Map;
import javax.annotation.Nullable;
/**
* This class represents the C/C++ parts of the {@link BuildConfiguration}, including the host
* architecture, target architecture, compiler version, and a standard library version. It has
* information about the tools locations and the flags required for compiling.
*
* <p>Before {@link CppConfiguration} is created, two things need to be done:
*
* <ol>
* <li>choosing a {@link CcToolchainRule} label from {@code toolchains} map attribute of {@link
* CcToolchainSuiteRule}.
* <li>selection of a {@link
* com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CToolchain} from the
* CROSSTOOL file.
* </ol>
*
* <p>The process goes as follows:
*
* <p>Check for existence of {@link CcToolchainSuiteRule}.toolchains[<cpu>|<compiler>], if
* --compiler is specified, otherwise check for {@link CcToolchainSuiteRule}.toolchains[<cpu>].
*
* <ul>
* <li>if a value is found, load the {@link CcToolchainRule} rule and look for the {@code
* toolchain_identifier} attribute.
* <li>
* <ul>
* <li>if the attribute exists, loop through all the {@code CToolchain}s in CROSSTOOL and
* select the one with the matching toolchain identifier.
* <li>otherwise fall back to selecting the CToolchain from CROSSTOOL by matching the --cpu
* and --compiler values.
* </ul>
* <li>If a value is not found, select the CToolchain from CROSSTOOL by matching the --cpu and
* --compiler values, and construct the key as follows: <toolchain.cpu>|<toolchain.compiler>.
* </ul>
*/
@Immutable
public final class CppConfiguration extends BuildConfiguration.Fragment
implements CppConfigurationApi<InvalidConfigurationException> {
/**
* String indicating a Mac system, for example when used in a crosstool configuration's host or
* target system name.
*/
public static final String MAC_SYSTEM_NAME = "x86_64-apple-macosx";
/** String constant for CC_FLAGS make variable name */
public static final String CC_FLAGS_MAKE_VARIABLE_NAME = "CC_FLAGS";
/**
* An enumeration of all the tools that comprise a toolchain.
*/
public enum Tool {
AR("ar"),
CPP("cpp"),
GCC("gcc"),
GCOV("gcov"),
GCOVTOOL("gcov-tool"),
LD("ld"),
NM("nm"),
OBJCOPY("objcopy"),
OBJDUMP("objdump"),
STRIP("strip"),
DWP("dwp"),
LLVM_PROFDATA("llvm-profdata");
private final String namePart;
private Tool(String namePart) {
this.namePart = namePart;
}
public String getNamePart() {
return namePart;
}
}
/**
* Values for the --hdrs_check option. Note that Bazel only supports and will default to "strict".
*/
public enum HeadersCheckingMode {
/**
* Legacy behavior: Silently allow any source header file in any of the directories of the
* containing package to be included by sources in this rule and dependent rules.
*/
LOOSE,
/** Disallow undeclared headers. */
STRICT;
public static HeadersCheckingMode getValue(String value) {
if (value.equalsIgnoreCase("loose") || value.equalsIgnoreCase("warn")) {
return LOOSE;
}
if (value.equalsIgnoreCase("strict")) {
return STRICT;
}
throw new IllegalArgumentException();
}
}
/**
* --dynamic_mode parses to DynamicModeFlag, but AUTO will be translated based on platform,
* resulting in a DynamicMode value.
*/
public enum DynamicMode { OFF, DEFAULT, FULLY }
/**
* This enumeration is used for the --strip option.
*/
public enum StripMode {
ALWAYS("always"), // Always strip.
SOMETIMES("sometimes"), // Strip iff compilationMode == FASTBUILD.
NEVER("never"); // Never strip.
private final String mode;
private StripMode(String mode) {
this.mode = mode;
}
@Override
public String toString() {
return mode;
}
}
/**
* This macro will be passed as a command-line parameter (eg. -DBUILD_FDO_TYPE="AUTOFDO"). For
* possible values see {@code CppModel.getFdoBuildStamp()}.
*/
public static final String FDO_STAMP_MACRO = "BUILD_FDO_TYPE";
private final Label crosstoolTop;
private final CrosstoolFile crosstoolFile;
// TODO(lberki): desiredCpu *should* be always the same as targetCpu, except that we don't check
// that the CPU we get from the toolchain matches BuildConfiguration.Options.cpu . So we store
// it here so that the output directory doesn't depend on the CToolchain. When we will eventually
// verify that the two are the same, we can remove one of desiredCpu and targetCpu.
private final String desiredCpu;
private final PathFragment crosstoolTopPathFragment;
private final PathFragment fdoPath;
private final Label fdoOptimizeLabel;
// TODO(bazel-team): All these labels (except for ccCompilerRuleLabel) can be removed once the
// transition to the cc_compiler rule is complete.
private final Label ccToolchainLabel;
private final Label stlLabel;
// TODO(kmensah): This is temporary until all the Skylark functions that need this can be removed.
private final PathFragment nonConfiguredSysroot;
private final Label sysrootLabel;
private final ImmutableList<String> compilerFlags;
private final ImmutableList<String> cxxFlags;
private final ImmutableList<String> unfilteredCompilerFlags;
private final ImmutableList<String> conlyopts;
private final ImmutableList<String> mostlyStaticLinkFlags;
private final ImmutableList<String> mostlyStaticSharedLinkFlags;
private final ImmutableList<String> dynamicLinkFlags;
private final ImmutableList<String> copts;
private final ImmutableList<String> cxxopts;
private final ImmutableList<String> linkopts;
private final ImmutableList<String> ltoindexOptions;
private final ImmutableList<String> ltobackendOptions;
private final CppOptions cppOptions;
private final CpuTransformer cpuTransformerEnum;
// The dynamic mode for linking.
private final boolean stripBinaries;
private final CompilationMode compilationMode;
private final boolean shouldProvideMakeVariables;
private final CppToolchainInfo cppToolchainInfo;
static CppConfiguration create(CppConfigurationParameters params)
throws InvalidConfigurationException {
CppOptions cppOptions = params.cppOptions;
PathFragment crosstoolTopPathFragment =
params.crosstoolTop.getPackageIdentifier().getPathUnderExecRoot();
CppToolchainInfo cppToolchainInfo =
CppToolchainInfo.create(
crosstoolTopPathFragment,
params.ccToolchainLabel,
params.ccToolchainConfigInfo,
cppOptions.disableLegacyCrosstoolFields,
cppOptions.disableCompilationModeFlags,
cppOptions.disableLinkingModeFlags);
CompilationMode compilationMode = params.commonOptions.compilationMode;
ImmutableList.Builder<String> coptsBuilder =
ImmutableList.<String>builder()
.addAll(cppToolchainInfo.getCompilerFlags())
.addAll(cppToolchainInfo.getCFlagsByCompilationMode().get(compilationMode));
if (cppOptions.experimentalOmitfp) {
coptsBuilder.add("-fomit-frame-pointer");
coptsBuilder.add("-fasynchronous-unwind-tables");
coptsBuilder.add("-DNO_FRAME_POINTER");
}
coptsBuilder.addAll(cppOptions.coptList);
ImmutableList<String> cxxOpts =
ImmutableList.<String>builder()
.addAll(cppToolchainInfo.getCxxFlags())
.addAll(cppToolchainInfo.getCxxFlagsByCompilationMode().get(compilationMode))
.addAll(cppOptions.cxxoptList)
.build();
ImmutableList.Builder<String> linkoptsBuilder = ImmutableList.builder();
linkoptsBuilder.addAll(cppOptions.linkoptList);
if (cppOptions.experimentalOmitfp) {
linkoptsBuilder.add("-Wl,--eh-frame-hdr");
}
return new CppConfiguration(
params.crosstoolTop,
params.crosstoolFile,
Preconditions.checkNotNull(params.commonOptions.cpu),
crosstoolTopPathFragment,
params.fdoPath,
params.fdoOptimizeLabel,
params.ccToolchainLabel,
params.stlLabel,
params.sysrootLabel == null
? cppToolchainInfo.getDefaultSysroot()
: params.sysrootLabel.getPackageFragment(),
params.sysrootLabel,
coptsBuilder.build(),
cxxOpts,
cppToolchainInfo.getUnfilteredCompilerOptions(/* sysroot= */ null),
ImmutableList.copyOf(cppOptions.conlyoptList),
cppToolchainInfo.configureAllLegacyLinkOptions(compilationMode, LinkingMode.STATIC),
cppToolchainInfo.configureAllLegacyLinkOptions(
compilationMode, LinkingMode.LEGACY_MOSTLY_STATIC_LIBRARIES),
cppToolchainInfo.configureAllLegacyLinkOptions(compilationMode, LinkingMode.DYNAMIC),
ImmutableList.copyOf(cppOptions.coptList),
ImmutableList.copyOf(cppOptions.cxxoptList),
linkoptsBuilder.build(),
ImmutableList.copyOf(cppOptions.ltoindexoptList),
ImmutableList.copyOf(cppOptions.ltobackendoptList),
cppOptions,
params.cpuTransformer,
(cppOptions.stripBinaries == StripMode.ALWAYS
|| (cppOptions.stripBinaries == StripMode.SOMETIMES
&& compilationMode == CompilationMode.FASTBUILD)),
compilationMode,
params.commonOptions.makeVariableSource == MakeVariableSource.CONFIGURATION,
cppToolchainInfo);
}
private CppConfiguration(
Label crosstoolTop,
CrosstoolFile crosstoolFile,
String desiredCpu,
PathFragment crosstoolTopPathFragment,
PathFragment fdoPath,
Label fdoOptimizeLabel,
Label ccToolchainLabel,
Label stlLabel,
PathFragment nonConfiguredSysroot,
Label sysrootLabel,
ImmutableList<String> compilerFlags,
ImmutableList<String> cxxFlags,
ImmutableList<String> unfilteredCompilerFlags,
ImmutableList<String> conlyopts,
ImmutableList<String> mostlyStaticLinkFlags,
ImmutableList<String> mostlyStaticSharedLinkFlags,
ImmutableList<String> dynamicLinkFlags,
ImmutableList<String> copts,
ImmutableList<String> cxxopts,
ImmutableList<String> linkopts,
ImmutableList<String> ltoindexOptions,
ImmutableList<String> ltobackendOptions,
CppOptions cppOptions,
CpuTransformer cpuTransformerEnum,
boolean stripBinaries,
CompilationMode compilationMode,
boolean shouldProvideMakeVariables,
CppToolchainInfo cppToolchainInfo) {
this.crosstoolTop = crosstoolTop;
this.crosstoolFile = crosstoolFile;
this.desiredCpu = desiredCpu;
this.crosstoolTopPathFragment = crosstoolTopPathFragment;
this.fdoPath = fdoPath;
this.fdoOptimizeLabel = fdoOptimizeLabel;
this.ccToolchainLabel = ccToolchainLabel;
this.stlLabel = stlLabel;
this.nonConfiguredSysroot = nonConfiguredSysroot;
this.sysrootLabel = sysrootLabel;
this.compilerFlags = compilerFlags;
this.cxxFlags = cxxFlags;
this.unfilteredCompilerFlags = unfilteredCompilerFlags;
this.conlyopts = conlyopts;
this.mostlyStaticLinkFlags = mostlyStaticLinkFlags;
this.mostlyStaticSharedLinkFlags = mostlyStaticSharedLinkFlags;
this.dynamicLinkFlags = dynamicLinkFlags;
this.copts = copts;
this.cxxopts = cxxopts;
this.linkopts = linkopts;
this.ltoindexOptions = ltoindexOptions;
this.ltobackendOptions = ltobackendOptions;
this.cppOptions = cppOptions;
this.cpuTransformerEnum = cpuTransformerEnum;
this.stripBinaries = stripBinaries;
this.compilationMode = compilationMode;
this.shouldProvideMakeVariables = shouldProvideMakeVariables;
this.cppToolchainInfo = cppToolchainInfo;
}
@VisibleForTesting
static LinkingMode importLinkingMode(CrosstoolConfig.LinkingMode mode) {
switch (mode.name()) {
case "FULLY_STATIC":
return LinkingMode.LEGACY_FULLY_STATIC;
case "MOSTLY_STATIC_LIBRARIES":
return LinkingMode.LEGACY_MOSTLY_STATIC_LIBRARIES;
case "MOSTLY_STATIC":
return LinkingMode.STATIC;
case "DYNAMIC":
return LinkingMode.DYNAMIC;
default:
throw new IllegalArgumentException(
String.format("Linking mode '%s' not known.", mode.name()));
}
}
/** Returns the {@link CppToolchainInfo} used by this configuration. */
public CppToolchainInfo getCppToolchainInfo() {
return cppToolchainInfo;
}
/**
* Returns the toolchain identifier, which uniquely identifies the compiler version, target libc
* version, and target cpu.
*/
public String getToolchainIdentifier() {
return cppToolchainInfo.getToolchainIdentifier();
}
/** Returns the contents of the CROSSTOOL for this configuration. */
public CrosstoolFile getCrosstoolFile() {
return crosstoolFile;
}
/** Returns the label of the CROSSTOOL for this configuration. */
public Label getCrosstoolTop() {
return crosstoolTop;
}
/** Returns the transformer that should be applied to cpu names in toolchain selection. */
public Function<String, String> getCpuTransformer() {
return cpuTransformerEnum.getTransformer();
}
/**
* Returns the path of the crosstool.
*/
public PathFragment getCrosstoolTopPathFragment() {
return cppToolchainInfo.getCrosstoolTopPathFragment();
}
@Override
public String toString() {
return cppToolchainInfo.toString();
}
/**
* Returns the compiler version string (e.g. "gcc-4.1.1").
*
* <p>Deprecated: Use {@link CcToolchainProvider#getCompiler()}
*/
// TODO(b/68038647): Remove once make variables are no longer derived from CppConfiguration.
@Override
@Deprecated
public String getCompiler() throws EvalException {
checkForToolchainSkylarkApiAvailability();
return cppToolchainInfo.getCompiler();
}
/**
* Returns the libc version string (e.g. "glibc-2.2.2").
*
* <p>Deprecated: Use {@link CcToolchainProvider#getTargetLibc()}
*/
// TODO(b/68038647): Remove once make variables are no longer derived from CppConfiguration.
@Override
@Deprecated
public String getTargetLibc() throws EvalException {
checkForToolchainSkylarkApiAvailability();
return cppToolchainInfo.getTargetLibc();
}
/**
* Returns the target architecture using blaze-specific constants (e.g. "piii").
*
* <p>Deprecated: Use {@link CcToolchainProvider#getTargetCpu()}
*/
// TODO(b/68038647): Remove once skylark callers are migrated.
@Override
@Deprecated
public String getTargetCpu() throws EvalException {
checkForToolchainSkylarkApiAvailability();
return cppToolchainInfo.getTargetCpu();
}
/**
* Returns the path fragment that is either absolute or relative to the execution root that can be
* used to execute the given tool.
*
* <p>Deprecated: Use {@link CcToolchainProvider#getToolPathFragment(Tool)}
*/
@Deprecated
public PathFragment getToolPathFragment(CppConfiguration.Tool tool) {
return cppToolchainInfo.getToolPathFragment(tool);
}
/**
* Returns the label of the <code>cc_compiler</code> rule for the C++ configuration.
*/
@SkylarkConfigurationField(
name = "cc_toolchain",
doc = "The label of the target describing the C++ toolchain",
defaultLabel = "//tools/cpp:crosstool",
defaultInToolRepository = true
)
public Label getCcToolchainRuleLabel() {
return ccToolchainLabel;
}
/**
* Returns the configured features of the toolchain. Rules should not call this directly, but
* instead use {@code CcToolchainProvider.getFeatures}.
*/
public CcToolchainFeatures getFeatures() {
return cppToolchainInfo.getFeatures();
}
/**
* Returns the configured current compilation mode. Rules should not call this directly, but
* instead use {@code CcToolchainProvider.getCompilationMode}.
*/
public CompilationMode getCompilationMode() {
return compilationMode;
}
@Override
@Deprecated
public ImmutableList<String> getBuiltInIncludeDirectoriesForSkylark()
throws InvalidConfigurationException, EvalException {
checkForToolchainSkylarkApiAvailability();
return getBuiltInIncludeDirectories(nonConfiguredSysroot)
.stream()
.map(PathFragment::getPathString)
.collect(ImmutableList.toImmutableList());
}
/**
* Returns the built-in list of system include paths for the toolchain compiler. All paths in this
* list should be relative to the exec directory. They may be absolute if they are also installed
* on the remote build nodes or for local compilation.
*
* <p>TODO(b/64384912): Migrate skylark callers to
* CcToolchainProvider#getBuiltinIncludeDirectories and delete this method.
*/
private ImmutableList<PathFragment> getBuiltInIncludeDirectories(PathFragment sysroot)
throws InvalidConfigurationException {
ImmutableList.Builder<PathFragment> builtInIncludeDirectoriesBuilder = ImmutableList.builder();
for (String s : cppToolchainInfo.getRawBuiltInIncludeDirectories()) {
builtInIncludeDirectoriesBuilder.add(
CcToolchain.resolveIncludeDir(s, sysroot, crosstoolTopPathFragment));
}
return builtInIncludeDirectoriesBuilder.build();
}
/**
* Returns the sysroot to be used. If the toolchain compiler does not support
* different sysroots, or the sysroot is the same as the default sysroot, then
* this method returns <code>null</code>.
*/
@Override
@Deprecated
public String getSysroot() throws EvalException {
checkForToolchainSkylarkApiAvailability();
return nonConfiguredSysroot.getPathString();
}
public Label getSysrootLabel() {
return sysrootLabel;
}
/**
* Returns the default options to use for compiling C, C++, and assembler. This is just the
* options that should be used for all three languages. There may be additional C-specific or
* C++-specific options that should be used, in addition to the ones returned by this method.
*
* <p>Deprecated: Use {@link CcToolchainProvider#getLegacyCompileOptionsWithCopts()}
*/
// TODO(b/64384912): Migrate skylark callers and remove.
@Override
@Deprecated
public ImmutableList<String> getCompilerOptions(Iterable<String> featuresNotUsedAnymore)
throws EvalException {
checkForToolchainSkylarkApiAvailability();
checkForLegacyCompilationApiAvailability();
return compilerFlags;
}
/**
* Returns the list of additional C-specific options to use for compiling C. These should be go on
* the command line after the common options returned by {@link #getCompilerOptions}.
*/
// TODO(b/64384912): Migrate skylark callers and remove.
@Override
@Deprecated
public ImmutableList<String> getCOptionsForSkylark() throws EvalException {
checkForToolchainSkylarkApiAvailability();
checkForLegacyCompilationApiAvailability();
return getCOptions();
}
public ImmutableList<String> getCOptions() {
return conlyopts;
}
/**
* Returns the list of additional C++-specific options to use for compiling C++. These should be
* on the command line after the common options returned by {@link #getCompilerOptions}.
*
* <p>Deprecated: Use {@link CcToolchainProvider#getCxxOptionsWithCopts}
*/
// TODO(b/64384912): Migrate skylark callers and remove.
@Override
@Deprecated
public ImmutableList<String> getCxxOptions(Iterable<String> featuresNotUsedAnymore)
throws EvalException {
checkForToolchainSkylarkApiAvailability();
checkForLegacyCompilationApiAvailability();
return cxxFlags;
}
/**
* Returns the default list of options which cannot be filtered by BUILD rules. These should be
* appended to the command line after filtering.
*
* @deprecated since it uses nonconfigured sysroot. Use {@link
* CcToolchainProvider#getUnfilteredCompilerOptionsWithSysroot(Iterable)} if you *really* need
* to.
*/
// TODO(b/65401585): Migrate existing uses to cc_toolchain and cleanup here.
@Deprecated
@Override
public ImmutableList<String> getUnfilteredCompilerOptionsWithLegacySysroot(
Iterable<String> featuresNotUsedAnymore) throws EvalException {
checkForToolchainSkylarkApiAvailability();
checkForLegacyCompilationApiAvailability();
return getUnfilteredCompilerOptionsDoNotUse(nonConfiguredSysroot);
}
/**
* @deprecated since it hardcodes --sysroot flag. Use {@link
* com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration} instead.
*/
// TODO(b/65401585): Migrate existing uses to cc_toolchain and cleanup here.
@Deprecated
ImmutableList<String> getUnfilteredCompilerOptionsDoNotUse(@Nullable PathFragment sysroot)
throws EvalException {
checkForToolchainSkylarkApiAvailability();
if (sysroot == null) {
return unfilteredCompilerFlags;
}
return ImmutableList.<String>builder()
.add("--sysroot=" + sysroot)
.addAll(unfilteredCompilerFlags)
.build();
}
/**
* Returns the set of command-line linker options, including any flags inferred from the
* command-line options.
*
* @see Link
* @deprecated since it uses nonconfigured sysroot. Use
* {@link CcToolchainProvider#getLinkOptionsWithSysroot()} if you *really* need to.
*/
// TODO(b/65401585): Migrate existing uses to cc_toolchain and cleanup here.
@Deprecated
@Override
public ImmutableList<String> getLinkOptionsWithLegacySysroot() throws EvalException {
checkForToolchainSkylarkApiAvailability();
checkForLegacyLinkingApiAvailability();
return getLinkOptionsDoNotUse(nonConfiguredSysroot);
}
/**
* @deprecated since it hardcodes --sysroot flag. Use
* {@link com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration}
* instead.
*/
// TODO(b/65401585): Migrate existing uses to cc_toolchain and cleanup here.
@Deprecated
ImmutableList<String> getLinkOptionsDoNotUse(@Nullable PathFragment sysroot) {
if (sysroot == null) {
return linkopts;
} else {
return ImmutableList.<String>builder().addAll(linkopts).add("--sysroot=" + sysroot).build();
}
}
public boolean hasSharedLinkOption() {
return linkopts.contains("-shared");
}
/** Returns the set of command-line LTO indexing options. */
public ImmutableList<String> getLtoIndexOptions() {
return ltoindexOptions;
}
/** Returns the set of command-line LTO backend options. */
public ImmutableList<String> getLtoBackendOptions() {
return ltobackendOptions;
}
/**
* Returns the immutable list of linker options for fully statically linked outputs. Does not
* include command-line options passed via --linkopt or --linkopts.
*
* @param featuresNotUsedAnymore
* @param sharedLib true if the output is a shared lib, false if it's an executable
* <p>Deprecated: Use {@link CppHelper#getFullyStaticLinkOptions(CppConfiguration,
* CcToolchainProvider, boolean)}
*/
// TODO(b/64384912): Migrate skylark users to cc_common and remove.
@Override
@Deprecated
public ImmutableList<String> getFullyStaticLinkOptions(
Iterable<String> featuresNotUsedAnymore, Boolean sharedLib) throws EvalException {
checkForToolchainSkylarkApiAvailability();
checkForLegacyLinkingApiAvailability();
if (!sharedLib) {
throw new EvalException(
Location.BUILTIN, "fully_static_link_options is deprecated, new uses are not allowed.");
}
return getSharedLibraryLinkOptions(mostlyStaticLinkFlags);
}
/**
* Returns the immutable list of linker options for mostly statically linked outputs. Does not
* include command-line options passed via --linkopt or --linkopts.
*
* @param featuresNotUsedAnymore
* @param sharedLib true if the output is a shared lib, false if it's an executable
* <p>Deprecated: Use {@link CppHelper#getMostlyStaticLinkOptions( CppConfiguration,
* CcToolchainProvider, boolean, boolean)}
*/
// TODO(b/64384912): Migrate skylark users to cc_common and remove.
@Override
@Deprecated
public ImmutableList<String> getMostlyStaticLinkOptions(
Iterable<String> featuresNotUsedAnymore, Boolean sharedLib) throws EvalException {
checkForToolchainSkylarkApiAvailability();
checkForLegacyLinkingApiAvailability();
if (sharedLib) {
return getSharedLibraryLinkOptions(
cppToolchainInfo.supportsEmbeddedRuntimes()
? mostlyStaticSharedLinkFlags
: dynamicLinkFlags);
} else {
return mostlyStaticLinkFlags;
}
}
/**
* Returns the immutable list of linker options for artifacts that are not fully or mostly
* statically linked. Does not include command-line options passed via --linkopt or --linkopts.
*
* @param featuresNotUsedAnymore
* @param sharedLib true if the output is a shared lib, false if it's an executable
* <p>Deprecated: Use {@link CppHelper#getDynamicLinkOptions(CppConfiguration,
* CcToolchainProvider, Boolean)}
*/
// TODO(b/64384912): Migrate skylark users to cc_common and remove.
@Override
@Deprecated
public ImmutableList<String> getDynamicLinkOptions(
Iterable<String> featuresNotUsedAnymore, Boolean sharedLib) throws EvalException {
checkForToolchainSkylarkApiAvailability();
checkForLegacyLinkingApiAvailability();
if (sharedLib) {
return getSharedLibraryLinkOptions(dynamicLinkFlags);
} else {
return dynamicLinkFlags;
}
}
/**
* Returns link options for the specified flag list, combined with universal options for all
* shared libraries (regardless of link staticness).
*
* <p>Deprecated: Use {@link CcToolchainProvider#getSharedLibraryLinkOptions}
*/
// TODO(b/64384912): Migrate skylark dependants and delete.
private ImmutableList<String> getSharedLibraryLinkOptions(ImmutableList<String> flags) {
return cppToolchainInfo.getSharedLibraryLinkOptions(flags);
}
/**
* Returns a map of additional make variables for use by {@link
* BuildConfiguration}. These are to used to allow some build rules to
* avoid the limits on stack frame sizes and variable-length arrays.
*
* <p>The returned map must contain an entry for {@code STACK_FRAME_UNLIMITED},
* though the entry may be an empty string.
*/
public ImmutableMap<String, String> getAdditionalMakeVariables() {
return cppToolchainInfo.getAdditionalMakeVariables();
}
/**
* Returns the execution path to the linker binary to use for this build. Relative paths are
* relative to the execution root.
*/
@Override
@Deprecated
public String getLdExecutableForSkylark() throws EvalException {
checkForToolchainSkylarkApiAvailability();
PathFragment ldExecutable = getToolPathFragment(CppConfiguration.Tool.LD);
return ldExecutable != null ? ldExecutable.getPathString() : "";
}
@SkylarkCallable(
name = "minimum_os_version",
doc = "The minimum OS version for C/C++ compilation.")
public String getMinimumOsVersion() {
return cppOptions.minimumOsVersion;
}
/** Returns the value of the --dynamic_mode flag. */
public DynamicMode getDynamicModeFlag() {
return cppOptions.dynamicMode;
}
public boolean getLinkCompileOutputSeparately() {
return cppOptions.linkCompileOutputSeparately;
}
/**
* Returns the STL label if given on the command line. {@code null}
* otherwise.
*/
public Label getStl() {
return stlLabel;
}
@SkylarkConfigurationField(
name = "stl",
doc = "The label of the STL target",
defaultLabel = "//third_party/stl",
defaultInToolRepository = false
)
public Label getSkylarkStl() {
if (stlLabel == null) {
try {
return Label.parseAbsolute("//third_party/stl", ImmutableMap.of());
} catch (LabelSyntaxException e) {
throw new IllegalStateException("STL label not formatted correctly", e);
}
}
return stlLabel;
}
public boolean isFdo() {
return cppOptions.isFdo();
}
/**
* Returns whether or not to strip the binaries.
*/
public boolean shouldStripBinaries() {
return stripBinaries;
}
/**
* Returns the additional options to pass to strip when generating a
* {@code <name>.stripped} binary by this build.
*/
public ImmutableList<String> getStripOpts() {
return ImmutableList.copyOf(cppOptions.stripoptList);
}
/**
* Returns whether temporary outputs from gcc will be saved.
*/
public boolean getSaveTemps() {
return cppOptions.saveTemps;
}
/**
* Returns the {@link PerLabelOptions} to apply to the gcc command line, if
* the label of the compiled file matches the regular expression.
*/
public ImmutableList<PerLabelOptions> getPerFileCopts() {
return ImmutableList.copyOf(cppOptions.perFileCopts);
}
/**
* Returns the {@link PerLabelOptions} to apply to the LTO Backend command line, if the compiled
* object matches the regular expression.
*/
public ImmutableList<PerLabelOptions> getPerFileLtoBackendOpts() {
return ImmutableList.copyOf(cppOptions.perFileLtoBackendOpts);
}
/**
* Returns the custom malloc library label.
*/
public Label customMalloc() {
return cppOptions.customMalloc;
}
/**
* Returns whether we are processing headers in dependencies of built C++ targets.
*/
public boolean processHeadersInDependencies() {
return cppOptions.processHeadersInDependencies;
}
/** Returns true if --fission contains the current compilation mode. */
public boolean fissionIsActiveForCurrentCompilationMode() {
return cppOptions.fissionModes.contains(compilationMode);
}
/** Returns true if --build_test_dwp is set on this build. */
public boolean buildTestDwpIsActivated() {
return cppOptions.buildTestDwp;
}
/**
* Returns true if all C++ compilations should produce position-independent code, links should
* produce position-independent executables, and dependencies with equivalent pre-built pic and
* nopic versions should apply the pic versions. Returns false if default settings should be
* applied (i.e. make no special provisions for pic code).
*/
public boolean forcePic() {
return cppOptions.forcePic;
}
/** Returns true if --start_end_lib is set on this build. */
public boolean startEndLibIsRequested() {
return cppOptions.useStartEndLib;
}
public boolean legacyWholeArchive() {
return cppOptions.legacyWholeArchive;
}
public boolean getSymbolCounts() {
return cppOptions.symbolCounts;
}
public boolean getInmemoryDotdFiles() {
return cppOptions.inmemoryDotdFiles;
}
public boolean getPruneCppModules() {
return cppOptions.pruneCppModules;
}
public boolean getPruneCppInputDiscovery() {
return cppOptions.pruneCppInputDiscovery;
}
public boolean getNoDotdScanningWithModules() {
return cppOptions.noDotdScanningWithModules;
}
public boolean getParseHeadersVerifiesModules() {
return cppOptions.parseHeadersVerifiesModules;
}
public boolean getUseInterfaceSharedObjects() {
return cppOptions.useInterfaceSharedObjects;
}
/**
* Returns the path to the GNU binutils 'objcopy' binary to use for this build. (Corresponds to
* $(OBJCOPY) in make-dbg.) Relative paths are relative to the execution root.
*/
@Override
@Deprecated
public String getObjCopyExecutableForSkylark() throws EvalException {
checkForToolchainSkylarkApiAvailability();
PathFragment objCopyExecutable = getToolPathFragment(Tool.OBJCOPY);
return objCopyExecutable != null ? objCopyExecutable.getPathString() : "";
}
@Override
@Deprecated
public String getCppExecutableForSkylark() throws EvalException {
checkForToolchainSkylarkApiAvailability();
PathFragment cppExecutable = getToolPathFragment(Tool.GCC);
return cppExecutable != null ? cppExecutable.getPathString() : "";
}
@Override
@Deprecated
public String getCpreprocessorExecutableForSkylark() throws EvalException {
checkForToolchainSkylarkApiAvailability();
PathFragment cpreprocessorExecutable = getToolPathFragment(Tool.CPP);
return cpreprocessorExecutable != null ? cpreprocessorExecutable.getPathString() : "";
}
@Override
@Deprecated
public String getNmExecutableForSkylark() throws EvalException {
checkForToolchainSkylarkApiAvailability();
PathFragment nmExecutable = getToolPathFragment(Tool.NM);
return nmExecutable != null ? nmExecutable.getPathString() : "";
}
@Override
@Deprecated
public String getObjdumpExecutableForSkylark() throws EvalException {
checkForToolchainSkylarkApiAvailability();
PathFragment objdumpExecutable = getToolPathFragment(Tool.OBJDUMP);
return objdumpExecutable != null ? objdumpExecutable.getPathString() : "";
}
@Override
@Deprecated
public String getArExecutableForSkylark() throws EvalException {
checkForToolchainSkylarkApiAvailability();
PathFragment arExecutable = getToolPathFragment(Tool.AR);
return arExecutable != null ? arExecutable.getPathString() : "";
}
@Override
@Deprecated
public String getStripExecutableForSkylark() throws EvalException {
checkForToolchainSkylarkApiAvailability();
PathFragment stripExecutable = getToolPathFragment(Tool.STRIP);
return stripExecutable != null ? stripExecutable.getPathString() : "";
}
/**
* Returns the GNU System Name
*
*/
//TODO(b/70225490): Migrate skylark dependants to CcToolchainProvider and delete.
@Override
@Deprecated
public String getTargetGnuSystemName() throws EvalException {
checkForToolchainSkylarkApiAvailability();
return cppToolchainInfo.getTargetGnuSystemName();
}
/** Returns whether this configuration will use libunwind for stack unwinding. */
public boolean isOmitfp() {
return cppOptions.experimentalOmitfp;
}
/** Returns flags passed to Bazel by --copt option. */
@Override
public ImmutableList<String> getCopts() {
return copts;
}
/** Returns flags passed to Bazel by --cxxopt option. */
@Override
public ImmutableList<String> getCxxopts() {
return cxxopts;
}
/** Returns flags passed to Bazel by --conlyopt option. */
@Override
public ImmutableList<String> getConlyopts() {
return conlyopts;
}
/** Returns flags passed to Bazel by --linkopt option. */
@Override
public ImmutableList<String> getLinkopts() {
return linkopts;
}
@Override
public void reportInvalidOptions(EventHandler reporter, BuildOptions buildOptions) {
CppOptions cppOptions = buildOptions.get(CppOptions.class);
if (stripBinaries) {
boolean warn = cppOptions.coptList.contains("-g");
for (PerLabelOptions opt : cppOptions.perFileCopts) {
warn |= opt.getOptions().contains("-g");
}
if (warn) {
reporter.handle(
Event.warn(
"Stripping enabled, but '--copt=-g' (or --per_file_copt=...@-g) specified. "
+ "Debug information will be generated and then stripped away. This is "
+ "probably not what you want! Use '-c dbg' for debug mode, or use "
+ "'--strip=never' to disable stripping"));
}
}
// FDO
if (cppOptions.getFdoOptimize() != null && cppOptions.fdoProfileLabel != null) {
reporter.handle(Event.error("Both --fdo_optimize and --fdo_profile specified"));
}
if (cppOptions.fdoInstrumentForBuild != null) {
if (cppOptions.getFdoOptimize() != null || cppOptions.fdoProfileLabel != null) {
reporter.handle(
Event.error(
"Cannot instrument and optimize for FDO at the same time. Remove one of the "
+ "'--fdo_instrument' and '--fdo_optimize/--fdo_profile' options"));
}
if (!cppOptions.coptList.contains("-Wno-error")) {
// This is effectively impossible. --fdo_instrument adds this value, and only invocation
// policy could remove it.
reporter.handle(Event.error("Cannot instrument FDO without --copt including -Wno-error."));
}
}
// This is an assertion check vs. user error because users can't trigger this state.
Verify.verify(
!(buildOptions.get(BuildConfiguration.Options.class).isHost && cppOptions.isFdo()),
"FDO state should not propagate to the host configuration");
}
@Override
public void addGlobalMakeVariables(ImmutableMap.Builder<String, String> globalMakeEnvBuilder) {
if (cppOptions.disableMakeVariables || !cppOptions.enableMakeVariables) {
return;
}
if (!shouldProvideMakeVariables) {
return;
}
globalMakeEnvBuilder.putAll(
CcToolchainProvider.getCppBuildVariables(
this::getToolPathFragment,
cppToolchainInfo.getTargetLibc(),
cppToolchainInfo.getCompiler(),
desiredCpu,
crosstoolTopPathFragment,
cppToolchainInfo.getAbiGlibcVersion(),
cppToolchainInfo.getAbi(),
getAdditionalMakeVariables()));
}
@Override
public String getOutputDirectoryName() {
String toolchainPrefix = desiredCpu;
if (!cppOptions.outputDirectoryTag.isEmpty()) {
toolchainPrefix += "-" + cppOptions.outputDirectoryTag;
}
return toolchainPrefix;
}
/**
* Returns true if we should share identical native libraries between different targets.
*/
public boolean shareNativeDeps() {
return cppOptions.shareNativeDeps;
}
public boolean isStrictSystemIncludes() {
return cppOptions.strictSystemIncludes;
}
@Override
public Map<String, Object> lateBoundOptionDefaults() {
// --compiler initially defaults to null because its *actual* default isn't known
// until it's read from the CROSSTOOL. Feed the CROSSTOOL defaults in here.
return ImmutableMap.of("compiler", cppToolchainInfo.getCompiler());
}
public String getFdoInstrument() {
return cppOptions.fdoInstrumentForBuild;
}
public PathFragment getFdoPath() {
return fdoPath;
}
public Label getFdoOptimizeLabel() {
return fdoOptimizeLabel;
}
public Label getFdoPrefetchHintsLabel() {
return cppOptions.getFdoPrefetchHintsLabel();
}
public Label getFdoProfileLabel() {
return cppOptions.fdoProfileLabel;
}
public boolean isFdoAbsolutePathEnabled() {
return cppOptions.enableFdoProfileAbsolutePath;
}
public boolean useLLVMCoverageMapFormat() {
return cppOptions.useLLVMCoverageMapFormat;
}
public boolean disableLegacyCrosstoolFields() {
return cppOptions.disableLegacyCrosstoolFields;
}
public boolean disableCompilationModeFlags() {
return cppOptions.disableCompilationModeFlags;
}
public boolean disableLinkingModeFlags() {
return cppOptions.disableLinkingModeFlags;
}
public boolean disableMakeVariables() {
return cppOptions.disableMakeVariables || !cppOptions.enableMakeVariables;
}
public boolean enableLinkoptsInUserLinkFlags() {
return cppOptions.enableLinkoptsInUserLinkFlags;
}
public boolean disableEmittingStaticLibgcc() {
return cppOptions.disableEmittingStaticLibgcc;
}
public boolean disableDepsetInUserFlags() {
return cppOptions.disableDepsetInUserFlags;
}
private void checkForToolchainSkylarkApiAvailability() throws EvalException {
if (cppOptions.disableLegacyToolchainSkylarkApi
|| !cppOptions.enableLegacyToolchainSkylarkApi) {
throw new EvalException(null, "Information about the C++ toolchain API is not accessible "
+ "anymore through ctx.fragments.cpp . Use CcToolchainInfo instead.");
}
}
public void checkForLegacyCompilationApiAvailability() throws EvalException {
if (cppOptions.disableLegacyCompilationApi) {
throw new EvalException(
null,
"Skylark APIs accessing compilation flags has been removed. "
+ "Use the new API on cc_common.");
}
}
public void checkForLegacyLinkingApiAvailability() throws EvalException {
if (cppOptions.disableLegacyLinkingApi) {
throw new EvalException(
null,
"Skylark APIs accessing linking flags has been removed. Use the new API on cc_common.");
}
}
public static PathFragment computeDefaultSysroot(String builtInSysroot) {
if (builtInSysroot.isEmpty()) {
return null;
}
if (!PathFragment.isNormalized(builtInSysroot)) {
throw new IllegalArgumentException(
"The built-in sysroot '" + builtInSysroot + "' is not normalized.");
}
return PathFragment.create(builtInSysroot);
}
boolean enableCcToolchainConfigInfoFromSkylark() {
return cppOptions.enableCcToolchainConfigInfoFromSkylark;
}
/**
* Returns the value of the libc top-level directory (--grte_top) as specified on the command line
*/
public Label getLibcTopLabel() {
return cppOptions.libcTopLabel;
}
}