Add 'toolchain_config' attribute to cc_toolchain to enable replacing CROSSTOOL with a skylark rule
Work towards issue #5380.
RELNOTES: None.
PiperOrigin-RevId: 211793570
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
index be06a5d..7318467 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
@@ -1918,4 +1918,9 @@
public ImmutableSet<String> getReservedActionMnemonics() {
return reservedActionMnemonics;
}
+
+ public boolean disableLateBoundOptionDefaults() {
+ return options.incompatibleDisableLateBoundOptionDefaults
+ || !options.useLateBoundOptionDefaults;
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java
index 8fbb804..15bd164 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java
@@ -847,6 +847,13 @@
if (!config.enableCcToolchainConfigInfoFromSkylark()) {
throw new InvalidConfigurationException("Creating a CcToolchainConfigInfo is not enabled.");
}
+ if (!skylarkRuleContext.getConfiguration().disableLateBoundOptionDefaults()
+ || !config.disableMakeVariables()) {
+ throw new InvalidConfigurationException(
+ "--incompatible_disable_late_bound_option_defaults and "
+ + "--incompatible_disable_cc_configuration_make_variables must be set to true in "
+ + "order to configure the C++ toolchain from Starlark.");
+ }
ImmutableList.Builder<Feature> featureBuilder = ImmutableList.builder();
for (Object feature : features) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java
index b6eae3c..e03c69d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java
@@ -52,6 +52,7 @@
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.License;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration.Tool;
import com.google.devtools.build.lib.rules.cpp.FdoProvider.FdoMode;
@@ -630,6 +631,36 @@
private CppToolchainInfo getCppToolchainInfo(
RuleContext ruleContext, CppConfiguration cppConfiguration) throws RuleErrorException {
+ if (cppConfiguration.enableCcToolchainConfigInfoFromSkylark()) {
+ // Attempt to obtain CppToolchainInfo from the 'toolchain_config' attribute of cc_toolchain.
+ CcToolchainConfigInfo configInfo =
+ ruleContext.getPrerequisite(
+ CcToolchainRule.TOOLCHAIN_CONFIG_ATTR, Mode.TARGET, CcToolchainConfigInfo.PROVIDER);
+ if (configInfo != null) {
+ try {
+ return CppToolchainInfo.create(
+ ruleContext.getRepository().getPathUnderExecRoot(),
+ ruleContext.getLabel(),
+ configInfo,
+ cppConfiguration.disableLegacyCrosstoolFields(),
+ cppConfiguration.disableCompilationModeFlags(),
+ cppConfiguration.disableLinkingModeFlags());
+ } catch (InvalidConfigurationException e) {
+ throw ruleContext.throwWithRuleError(e.getMessage());
+ }
+ } else {
+ ruleContext.attributeError(
+ CcToolchainRule.TOOLCHAIN_CONFIG_ATTR,
+ String.format(
+ "The target '%s' from '%s' attribute does not provide "
+ + "a CcToolchainConfigInfo provider",
+ CcToolchainRule.TOOLCHAIN_CONFIG_ATTR,
+ ruleContext
+ .attributes()
+ .get(CcToolchainRule.TOOLCHAIN_CONFIG_ATTR, BuildType.LABEL)));
+ }
+ }
+
// Attempt to find a toolchain based on the target attributes, not the configuration.
CToolchain toolchain = getToolchainFromAttributes(ruleContext, cppConfiguration);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainConfigInfo.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainConfigInfo.java
index 1213ee9..e08940e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainConfigInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainConfigInfo.java
@@ -535,55 +535,64 @@
// TODO(b/65151735): Remove once this field is migrated to features.
@Deprecated
public ImmutableList<String> getOptCompilationModeCompilerFlags() {
- return compilationModeCompilerFlags.get(CompilationMode.OPT);
+ ImmutableList<String> flags = compilationModeCompilerFlags.get(CompilationMode.OPT);
+ return flags == null ? ImmutableList.of() : flags;
}
// TODO(b/65151735): Remove once this field is migrated to features.
@Deprecated
public ImmutableList<String> getOptCompilationModeCxxFlags() {
- return compilationModeCxxFlags.get(CompilationMode.OPT);
+ ImmutableList<String> flags = compilationModeCxxFlags.get(CompilationMode.OPT);
+ return flags == null ? ImmutableList.of() : flags;
}
// TODO(b/65151735): Remove once this field is migrated to features.
@Deprecated
public ImmutableList<String> getOptCompilationModeLinkerFlags() {
- return compilationModeLinkerFlags.get(CompilationMode.OPT);
+ ImmutableList<String> flags = compilationModeLinkerFlags.get(CompilationMode.OPT);
+ return flags == null ? ImmutableList.of() : flags;
}
// TODO(b/65151735): Remove once this field is migrated to features.
@Deprecated
public ImmutableList<String> getDbgCompilationModeCompilerFlags() {
- return compilationModeCompilerFlags.get(CompilationMode.DBG);
+ ImmutableList<String> flags = compilationModeCompilerFlags.get(CompilationMode.DBG);
+ return flags == null ? ImmutableList.of() : flags;
}
// TODO(b/65151735): Remove once this field is migrated to features.
@Deprecated
public ImmutableList<String> getDbgCompilationModeCxxFlags() {
- return compilationModeCxxFlags.get(CompilationMode.DBG);
+ ImmutableList<String> flags = compilationModeCxxFlags.get(CompilationMode.DBG);
+ return flags == null ? ImmutableList.of() : flags;
}
// TODO(b/65151735): Remove once this field is migrated to features.
@Deprecated
public ImmutableList<String> getDbgCompilationModeLinkerFlags() {
- return compilationModeLinkerFlags.get(CompilationMode.DBG);
+ ImmutableList<String> flags = compilationModeLinkerFlags.get(CompilationMode.DBG);
+ return flags == null ? ImmutableList.of() : flags;
}
// TODO(b/65151735): Remove once this field is migrated to features.
@Deprecated
public ImmutableList<String> getFastbuildCompilationModeCompilerFlags() {
- return compilationModeCompilerFlags.get(CompilationMode.FASTBUILD);
+ ImmutableList<String> flags = compilationModeCompilerFlags.get(CompilationMode.FASTBUILD);
+ return flags == null ? ImmutableList.of() : flags;
}
// TODO(b/65151735): Remove once this field is migrated to features.
@Deprecated
public ImmutableList<String> getFastbuildCompilationModeCxxFlags() {
- return compilationModeCxxFlags.get(CompilationMode.FASTBUILD);
+ ImmutableList<String> flags = compilationModeCxxFlags.get(CompilationMode.FASTBUILD);
+ return flags == null ? ImmutableList.of() : flags;
}
// TODO(b/65151735): Remove once this field is migrated to features.
@Deprecated
public ImmutableList<String> getFastbuildCompilationModeLinkerFlags() {
- return compilationModeLinkerFlags.get(CompilationMode.FASTBUILD);
+ ImmutableList<String> flags = compilationModeLinkerFlags.get(CompilationMode.FASTBUILD);
+ return flags == null ? ImmutableList.of() : flags;
}
// TODO(b/65151735): Remove once this field is migrated to features.
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java
index aa13189..1f2d8ae 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java
@@ -44,6 +44,7 @@
public static final String LIBC_TOP_ATTR = ":libc_top";
public static final String FDO_OPTIMIZE_ATTR = ":fdo_optimize";
public static final String FDO_PROFILE_ATTR = ":fdo_profile";
+ public static final String TOOLCHAIN_CONFIG_ATTR = "toolchain_config";
/**
* Determines if the given target is a cc_toolchain or one of its subclasses. New subclasses
@@ -191,6 +192,10 @@
attr("toolchain_identifier", Type.STRING)
.nonconfigurable("Used in configuration creation")
.value(""))
+ .add(
+ attr(TOOLCHAIN_CONFIG_ATTR, LABEL)
+ .allowedFileTypes()
+ .mandatoryProviders(CcToolchainConfigInfo.PROVIDER.id()))
.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
index a019a33..e3bb2ff 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java
@@ -1166,6 +1166,10 @@
return cppOptions.disableLinkingModeFlags;
}
+ public boolean disableMakeVariables() {
+ return cppOptions.disableMakeVariables || !cppOptions.enableMakeVariables;
+ }
+
public boolean enableLinkoptsInUserLinkFlags() {
return cppOptions.enableLinkoptsInUserLinkFlags;
}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainTest.java
index 8f0e8ec..ffa4fc8 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainTest.java
@@ -25,6 +25,7 @@
import com.google.devtools.build.lib.analysis.platform.ToolchainInfo;
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
import com.google.devtools.build.lib.packages.util.MockCcSupport;
+import com.google.devtools.build.lib.packages.util.ResourceLoader;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration.DynamicMode;
import com.google.devtools.build.lib.testutil.TestConstants;
@@ -778,6 +779,192 @@
assertThat(toolchainProvider.getAbi()).isEqualTo("banana");
}
+ private void loadCcToolchainConfigLib() throws IOException {
+ scratch.appendFile("tools/cpp/BUILD", "");
+ scratch.file(
+ "tools/cpp/cc_toolchain_config_lib.bzl",
+ ResourceLoader.readFromResources(
+ TestConstants.BAZEL_REPO_PATH + "tools/cpp/cc_toolchain_config_lib.bzl"));
+ }
+
+ @Test
+ public void testToolchainFromSkylarkRule() throws Exception {
+ loadCcToolchainConfigLib();
+ scratch.file(
+ "a/BUILD",
+ "load(':crosstool_rule.bzl', 'cc_toolchain_config_rule')",
+ "cc_toolchain_config_rule(name = 'toolchain_config')",
+ "filegroup(",
+ " name='empty')",
+ "cc_toolchain(",
+ " name = 'b',",
+ " cpu = 'banana',",
+ " all_files = ':empty',",
+ " ar_files = ':empty',",
+ " as_files = ':empty',",
+ " compiler_files = ':empty',",
+ " dwp_files = ':empty',",
+ " linker_files = ':empty',",
+ " strip_files = ':empty',",
+ " objcopy_files = ':empty',",
+ " dynamic_runtime_libs = [':empty'],",
+ " static_runtime_libs = [':empty'],",
+ " toolchain_config = ':toolchain_config')");
+
+ scratch.file(
+ "a/crosstool_rule.bzl",
+ "load('//tools/cpp:cc_toolchain_config_lib.bzl',",
+ " 'feature',",
+ " 'action_config',",
+ " 'artifact_name_pattern',",
+ " 'env_entry',",
+ " 'variable_with_value',",
+ " 'make_variable',",
+ " 'feature_set',",
+ " 'with_feature_set',",
+ " 'env_set',",
+ " 'flag_group',",
+ " 'flag_set',",
+ " 'tool_path',",
+ " 'tool')",
+ "",
+ "def _impl(ctx):",
+ " return cc_common.create_cc_toolchain_config_info(",
+ " ctx = ctx,",
+ " features = [feature(name = 'simple_feature')],",
+ " action_configs = [",
+ " action_config(action_name = 'simple_action', enabled=True)",
+ " ],",
+ " artifact_name_patterns = [artifact_name_pattern(",
+ " category_name = 'static_library',",
+ " prefix = 'prefix',",
+ " extension = '.a')],",
+ " cxx_builtin_include_directories = ['dir1', 'dir2', 'dir3'],",
+ " toolchain_identifier = 'toolchain',",
+ " host_system_name = 'host',",
+ " target_system_name = 'target',",
+ " target_cpu = 'cpu',",
+ " target_libc = 'libc',",
+ " default_libc_top = 'libc_top',",
+ " compiler = 'compiler',",
+ " abi_libc_version = 'abi_libc',",
+ " abi_version = 'banana',",
+ " supports_gold_linker = True,",
+ " supports_start_end_lib = True,",
+ " tool_paths = [",
+ " tool_path(name = 'ar', path = '/some/path'),",
+ " tool_path(name = 'cpp', path = '/some/path'),",
+ " tool_path(name = 'gcc', path = '/some/path'),",
+ " tool_path(name = 'gcov', path = '/some/path'),",
+ " tool_path(name = 'gcovtool', path = '/some/path'),",
+ " tool_path(name = 'ld', path = '/some/path'),",
+ " tool_path(name = 'nm', path = '/some/path'),",
+ " tool_path(name = 'objcopy', path = '/some/path'),",
+ " tool_path(name = 'objdump', path = '/some/path'),",
+ " tool_path(name = 'strip', path = '/some/path'),",
+ " tool_path(name = 'dwp', path = '/some/path'),",
+ " tool_path(name = 'llvm_profdata', path = '/some/path'),",
+ " ],",
+ " cc_target_os = 'os',",
+ " compiler_flags = ['flag1', 'flag2', 'flag3'],",
+ " linker_flags = ['flag1'],",
+ " compilation_mode_compiler_flags = {",
+ " 'OPT' : ['flagopt'], 'FASTBUILD' : ['flagfast'] ",
+ " },",
+ " objcopy_embed_flags = ['flag1'],",
+ " needs_pic = True,",
+ " builtin_sysroot = 'sysroot')",
+ "cc_toolchain_config_rule = rule(",
+ " implementation = _impl,",
+ " attrs = {},",
+ " provides = [CcToolchainConfigInfo],",
+ " fragments = ['cpp']",
+ ")");
+
+ getAnalysisMock()
+ .ccSupport()
+ .setupCrosstool(
+ mockToolsConfig,
+ CrosstoolConfig.CToolchain.newBuilder().setAbiVersion("orange").buildPartial());
+
+ useConfiguration(
+ "--experimental_enable_cc_toolchain_config_info",
+ "--incompatible_disable_late_bound_option_defaults",
+ "--incompatible_disable_cc_configuration_make_variables");
+
+ ConfiguredTarget target = getConfiguredTarget("//a:b");
+ CcToolchainProvider toolchainProvider =
+ (CcToolchainProvider) target.get(ToolchainInfo.PROVIDER);
+
+ assertThat(toolchainProvider.getAbi()).isEqualTo("banana");
+ assertThat(toolchainProvider.getCcToolchainLabel().toString()).isEqualTo("//a:b");
+ assertThat(toolchainProvider.getFeatures().getActivatableNames())
+ .containsExactly("simple_action", "simple_feature");
+ }
+
+ @Test
+ public void testToolchainFromSkylarkRuleWithoutIncompatibleFlagsFlipped() throws Exception {
+ scratch.file(
+ "a/BUILD",
+ "load(':crosstool_rule.bzl', 'cc_toolchain_config_rule')",
+ "cc_toolchain_config_rule(name = 'toolchain_config')",
+ "filegroup(",
+ " name='empty')",
+ "cc_toolchain(",
+ " name = 'b',",
+ " cpu = 'banana',",
+ " all_files = ':empty',",
+ " ar_files = ':empty',",
+ " as_files = ':empty',",
+ " compiler_files = ':empty',",
+ " dwp_files = ':empty',",
+ " linker_files = ':empty',",
+ " strip_files = ':empty',",
+ " objcopy_files = ':empty',",
+ " dynamic_runtime_libs = [':empty'],",
+ " static_runtime_libs = [':empty'],",
+ " toolchain_config = ':toolchain_config')");
+
+ scratch.file(
+ "a/crosstool_rule.bzl",
+ "def _impl(ctx):",
+ " return cc_common.create_cc_toolchain_config_info(",
+ " ctx = ctx,",
+ " toolchain_identifier = 'toolchain',",
+ " host_system_name = 'host',",
+ " target_system_name = 'target',",
+ " target_cpu = 'cpu',",
+ " target_libc = 'libc',",
+ " compiler = 'compiler',",
+ " abi_libc_version = 'abi_libc',",
+ " abi_version = 'banana',",
+ " )",
+ "cc_toolchain_config_rule = rule(",
+ " implementation = _impl,",
+ " attrs = {},",
+ " provides = [CcToolchainConfigInfo],",
+ " fragments = ['cpp']",
+ ")");
+
+ getAnalysisMock()
+ .ccSupport()
+ .setupCrosstool(
+ mockToolsConfig,
+ CrosstoolConfig.CToolchain.newBuilder().setAbiVersion("orange").buildPartial());
+
+ useConfiguration("--experimental_enable_cc_toolchain_config_info");
+ try {
+ getConfiguredTarget("//a:b");
+ } catch (AssertionError e) {
+ assertThat(e)
+ .hasMessageThat()
+ .contains(
+ "--incompatible_disable_late_bound_option_defaults and "
+ + "--incompatible_disable_cc_configuration_make_variables must be set to true in "
+ + "order to configure the C++ toolchain from Starlark.");
+ }
+ }
+
@Test
public void testSupportsDynamicLinkerCheckFeatures() throws Exception {
writeDummyCcToolchain();
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcCommonTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcCommonTest.java
index 7e30cc0..e5f4ccd 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcCommonTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/SkylarkCcCommonTest.java
@@ -3971,7 +3971,10 @@
"load(':crosstool.bzl', 'cc_toolchain_config_rule')",
"cc_toolchain_alias(name='alias')",
"cc_toolchain_config_rule(name='r')");
- useConfiguration("--experimental_enable_cc_toolchain_config_info");
+ useConfiguration(
+ "--experimental_enable_cc_toolchain_config_info",
+ "--incompatible_disable_late_bound_option_defaults",
+ "--incompatible_disable_cc_configuration_make_variables");
ConfiguredTarget target = getConfiguredTarget("//foo:r");
assertThat(target).isNotNull();
CcToolchainConfigInfo ccToolchainConfigInfo =
@@ -4044,7 +4047,10 @@
@Test
public void testCcToolchainInfoFromSkylarkAllRequiredStringsPresent() throws Exception {
setupSkylarkRuleForStringFieldsTesting("");
- useConfiguration("--experimental_enable_cc_toolchain_config_info");
+ useConfiguration(
+ "--experimental_enable_cc_toolchain_config_info",
+ "--incompatible_disable_late_bound_option_defaults",
+ "--incompatible_disable_cc_configuration_make_variables");
ConfiguredTarget target = getConfiguredTarget("//foo:r");
assertThat(target).isNotNull();
CcToolchainConfigInfo ccToolchainConfigInfo =