Migrate more tests to use Starlark cc_toolchain configuration

Issue #5380

RELNOTES: None.
PiperOrigin-RevId: 239568494
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/mock/cc_toolchain_config.bzl b/src/test/java/com/google/devtools/build/lib/analysis/mock/cc_toolchain_config.bzl
index 153a857..c266971 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/mock/cc_toolchain_config.bzl
+++ b/src/test/java/com/google/devtools/build/lib/analysis/mock/cc_toolchain_config.bzl
@@ -95,8 +95,11 @@
     uses_ifso_variables = "uses_ifso_variables",
     def_feature = "def",
     strip_debug_symbols = "strip_debug_symbols",
+    disable_pbh = "disable_pbh",
 )
 
+_disable_pbh_feature = feature(name = _FEATURE_NAMES.disable_pbh)
+
 _no_legacy_features_feature = feature(name = _FEATURE_NAMES.no_legacy_features)
 
 _do_not_split_linking_cmdline_feature = feature(name = _FEATURE_NAMES.do_not_split_linking_cmdline)
@@ -181,6 +184,16 @@
     ],
 )
 
+_simple_header_modules_feature = feature(
+    name = _FEATURE_NAMES.header_modules,
+    flag_sets = [
+        flag_set(
+            actions = [ACTION_NAMES.cpp_module_compile],
+            flag_groups = [flag_group(flags = ["<flag>"])],
+        ),
+    ],
+)
+
 _header_modules_feature = feature(
     name = _FEATURE_NAMES.header_modules,
     implies = ["use_header_modules", "header_module_compile"],
@@ -334,6 +347,23 @@
     ],
 )
 
+_simple_module_maps_feature = feature(
+    name = _FEATURE_NAMES.module_maps,
+    enabled = True,
+    flag_sets = [
+        flag_set(
+            actions = [
+                ACTION_NAMES.cpp_compile,
+            ],
+            flag_groups = [
+                flag_group(
+                    flags = ["<flag>"],
+                ),
+            ],
+        ),
+    ],
+)
+
 _env_var_feature_configuration = [
     _env_feature,
     _static_env_feature,
@@ -975,6 +1005,20 @@
     ],
 )
 
+_portable_overrides_configuration = [
+    feature(name = "proto_force_lite_runtime", implies = ["proto_disable_services"]),
+    feature(name = "proto_disable_services"),
+    feature(name = "proto_one_output_per_message", implies = ["proto_force_lite_runtime"]),
+    feature(
+        name = "proto_enable_portable_overrides",
+        implies = [
+            "proto_force_lite_runtime",
+            "proto_disable_services",
+            "proto_one_output_per_message",
+        ],
+    ),
+]
+
 _feature_name_to_feature = {
     _FEATURE_NAMES.no_legacy_features: _no_legacy_features_feature,
     _FEATURE_NAMES.do_not_split_linking_cmdline: _do_not_split_linking_cmdline_feature,
@@ -1028,12 +1072,16 @@
     _FEATURE_NAMES.uses_ifso_variables: _uses_ifso_variables_feature,
     _FEATURE_NAMES.def_feature: _def_feature,
     _FEATURE_NAMES.strip_debug_symbols: _strip_debug_symbols_feature,
+    _FEATURE_NAMES.disable_pbh: _disable_pbh_feature,
     "header_modules_feature_configuration": _header_modules_feature_configuration,
     "env_var_feature_configuration": _env_var_feature_configuration,
     "host_and_nonhost_configuration": _host_and_nonhost_configuration,
     "simple_layering_check": _simple_layering_check_feature,
     "compilation_mode_features": _compilation_mode_features,
     "compile_header_modules": _compile_header_modules_feature_configuration,
+    "simple_module_maps": _simple_module_maps_feature,
+    "simple_header_modules": _simple_header_modules_feature,
+    "portable_overrides_configuration": _portable_overrides_configuration,
 }
 
 _tool_for_action_config = {
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/Crosstool.java b/src/test/java/com/google/devtools/build/lib/packages/util/Crosstool.java
index 9482dd2..708bce4 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/util/Crosstool.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/Crosstool.java
@@ -206,7 +206,7 @@
       return getCcToolchainConfigForCpu("k8");
     }
 
-    String getCcToolchainConfigRule() {
+    public String getCcToolchainConfigRule() {
       ImmutableList<String> featuresList =
           features.stream()
               .map(feature -> "'" + feature + "'")
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderTest.java
index ae86a79..84fa685 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainProviderTest.java
@@ -24,6 +24,9 @@
 import com.google.devtools.build.lib.analysis.util.AnalysisMock;
 import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
 import com.google.devtools.build.lib.packages.util.Crosstool.CcToolchainConfig;
+import com.google.devtools.build.lib.packages.util.MockCcSupport;
+import com.google.devtools.build.lib.packages.util.ResourceLoader;
+import com.google.devtools.build.lib.util.Pair;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -82,6 +85,7 @@
   public void testRemoveCpuAndCompiler() throws Exception {
     scratch.file(
         "a/BUILD",
+        "load(':cc_toolchain_config.bzl', 'cc_toolchain_config')",
         "filegroup(name = 'empty')",
         "cc_toolchain_suite(",
         "    name = 'a_suite',",
@@ -106,16 +110,9 @@
         "    linker_files = ':empty',",
         "    strip_files = ':empty',",
         "    objcopy_files = ':empty',",
-        "    proto = \"\"\"",
-        "      toolchain_identifier: \"a\"",
-        "      host_system_name: \"a\"",
-        "      target_system_name: \"a\"",
-        "      target_cpu: \"a\"",
-        "      target_libc: \"a\"",
-        "      compiler: \"a\"",
-        "      abi_version: \"a\"",
-        "      abi_libc_version: \"a\"",
-        "\"\"\")",
+        "    toolchain_identifier = 'banana',",
+        "    toolchain_config = ':banana_config',",
+        ")",
         "cc_toolchain(",
         "    name = 'b',",
         "    compiler = 'banana',",
@@ -127,16 +124,9 @@
         "    linker_files = ':empty',",
         "    strip_files = ':empty',",
         "    objcopy_files = ':empty',",
-        "    proto = \"\"\"",
-        "      toolchain_identifier: \"a\"",
-        "      host_system_name: \"a\"",
-        "      target_system_name: \"a\"",
-        "      target_cpu: \"a\"",
-        "      target_libc: \"a\"",
-        "      compiler: \"a\"",
-        "      abi_version: \"a\"",
-        "      abi_libc_version: \"a\"",
-        "\"\"\")",
+        "    toolchain_identifier = 'banana',",
+        "    toolchain_config = ':banana_config',",
+        ")",
         "cc_toolchain(",
         "    name = 'c',",
         "    all_files = ':empty',",
@@ -147,16 +137,13 @@
         "    linker_files = ':empty',",
         "    strip_files = ':empty',",
         "    objcopy_files = ':empty',",
-        "    proto = \"\"\"",
-        "      toolchain_identifier: \"a\"",
-        "      host_system_name: \"a\"",
-        "      target_system_name: \"a\"",
-        "      target_cpu: \"a\"",
-        "      target_libc: \"a\"",
-        "      compiler: \"a\"",
-        "      abi_version: \"a\"",
-        "      abi_libc_version: \"a\"",
-        "\"\"\")");
+        "    toolchain_identifier = 'banana',",
+        "    toolchain_config = ':banana_config',",
+        ")",
+        "cc_toolchain_config(name = 'banana_config')");
+
+    scratch.file("a/cc_toolchain_config.bzl", MockCcSupport.EMPTY_CC_TOOLCHAIN);
+
     reporter.removeHandler(failFastHandler);
     useConfiguration(
         "--crosstool_top=//a:a_suite",
@@ -199,7 +186,11 @@
             "compilation_mode_flags { mode: OPT linker_flag: '-baz_from_compilation_mode' }");
     scratch.file("a/BUILD", "cc_library(name='a', srcs=['a.cc'])");
 
-    useConfiguration("-c", "opt", "--noincompatible_disable_legacy_crosstool_fields");
+    useConfiguration(
+        "-c",
+        "opt",
+        "--noincompatible_disable_legacy_crosstool_fields",
+        "--noincompatible_disable_crosstool_file");
     CcToolchainProvider ccToolchainProvider = getCcToolchainProvider();
     assertThat(ccToolchainProvider.getLegacyCompileOptionsWithCopts())
         .contains("-foo_from_compilation_mode");
@@ -207,7 +198,11 @@
     assertThat(ccToolchainProvider.getLegacyMostlyStaticLinkFlags(CompilationMode.OPT))
         .contains("-baz_from_compilation_mode");
 
-    useConfiguration("-c", "opt", "--incompatible_disable_legacy_crosstool_fields");
+    useConfiguration(
+        "-c",
+        "opt",
+        "--incompatible_disable_legacy_crosstool_fields",
+        "--noincompatible_disable_crosstool_file");
     getConfiguredTarget("//a");
     assertContainsEvent(
         "compilation_mode_flags is disabled by "
@@ -237,7 +232,9 @@
     assertThat(ccToolchainProvider.getLegacyMostlyStaticLinkFlags(CompilationMode.OPT))
         .contains("-foo_from_linking_mode");
 
-    useConfiguration("--incompatible_disable_legacy_crosstool_fields");
+    useConfiguration(
+        "--incompatible_disable_legacy_crosstool_fields",
+        "--noincompatible_disable_crosstool_file");
     getConfiguredTarget("//a");
     assertContainsEvent(
         "linking_mode_flags is disabled by "
@@ -252,11 +249,15 @@
         .setupCrosstool(mockToolsConfig, "compiler_flag: '-foo_compiler_flag'");
     scratch.file("a/BUILD", "cc_library(name='a', srcs=['a.cc'])");
 
-    useConfiguration("--noincompatible_disable_legacy_crosstool_fields");
+    useConfiguration(
+        "--noincompatible_disable_legacy_crosstool_fields",
+        "--noincompatible_disable_crosstool_file");
     CcToolchainProvider ccToolchainProvider = getCcToolchainProvider();
     assertThat(ccToolchainProvider.getLegacyCompileOptions()).contains("-foo_compiler_flag");
 
-    useConfiguration("--incompatible_disable_legacy_crosstool_fields");
+    useConfiguration(
+        "--incompatible_disable_legacy_crosstool_fields",
+        "--noincompatible_disable_crosstool_file");
     getConfiguredTarget("//a");
 
     assertContainsEvent(
@@ -278,11 +279,15 @@
 
     scratch.file("a/BUILD", "cc_library(name='a', srcs=['a.cc'])");
 
-    useConfiguration("--noincompatible_disable_expand_if_all_available_in_flag_set");
+    useConfiguration(
+        "--noincompatible_disable_expand_if_all_available_in_flag_set",
+        "--noincompatible_disable_crosstool_file");
     getConfiguredTarget("//a");
     assertNoEvents();
 
-    useConfiguration("--incompatible_disable_expand_if_all_available_in_flag_set");
+    useConfiguration(
+        "--incompatible_disable_expand_if_all_available_in_flag_set",
+        "--noincompatible_disable_crosstool_file");
     getConfiguredTarget("//a");
 
     assertContainsEvent(
@@ -295,10 +300,11 @@
    * should also add a make variable.
    */
   @Test
-  public void testOptionalGcovTool() throws Exception {
-    // Crosstool without gcov-tool
+  public void testGcovToolNotDefined() throws Exception {
+    // Crosstool with gcov-tool
     scratch.file(
         "a/BUILD",
+        "load(':cc_toolchain_config.bzl', 'cc_toolchain_config')",
         "filegroup(",
         "   name='empty')",
         "cc_toolchain_suite(",
@@ -316,37 +322,40 @@
         "    linker_files = ':empty',",
         "    strip_files = ':empty',",
         "    objcopy_files = ':empty',",
-        "    dynamic_runtime_lib = ':empty',",
-        "    static_runtime_lib = ':empty',",
-        "    proto=\"\"\"",
-        "      feature { name: 'no_legacy_features' }",
-        "      tool_path { name: 'gcc' path: 'path-to-gcc-tool' }",
-        "      tool_path { name: 'ar' path: 'ar' }",
-        "      tool_path { name: 'cpp' path: 'cpp' }",
-        "      tool_path { name: 'gcov' path: 'gcov' }",
-        "      tool_path { name: 'ld' path: 'ld' }",
-        "      tool_path { name: 'nm' path: 'nm' }",
-        "      tool_path { name: 'objdump' path: 'objdump' }",
-        "      tool_path { name: 'strip' path: 'strip' }",
-        "      toolchain_identifier: \"banana\"",
-        "      abi_version: \"banana\"",
-        "      abi_libc_version: \"banana\"",
-        "      compiler: \"banana\"",
-        "      host_system_name: \"banana\"",
-        "      target_system_name: \"banana\"",
-        "      target_cpu: \"banana\"",
-        "      target_libc: \"banana\"",
-        "    \"\"\")");
+        "    toolchain_identifier = 'banana',",
+        "    toolchain_config = ':k8-compiler_config',",
+        ")",
+        CcToolchainConfig.builder()
+            .withToolPaths(
+                Pair.of("gcc", "path-to-gcc-tool"),
+                Pair.of("ar", "ar"),
+                Pair.of("cpp", "cpp"),
+                Pair.of("gcov", "gcov"),
+                Pair.of("ld", "ld"),
+                Pair.of("nm", "nm"),
+                Pair.of("objdump", "objdump"),
+                Pair.of("strip", "strip"))
+            .build()
+            .getCcToolchainConfigRule());
+    analysisMock.ccSupport().setupCcToolchainConfig(mockToolsConfig, CcToolchainConfig.builder());
+    mockToolsConfig.create(
+        "a/cc_toolchain_config.bzl",
+        ResourceLoader.readFromResources(
+            "com/google/devtools/build/lib/analysis/mock/cc_toolchain_config.bzl"));
     useConfiguration("--cpu=k8", "--host_cpu=k8");
     CcToolchainProvider ccToolchainProvider =
         (CcToolchainProvider) getConfiguredTarget("//a:a").get(ToolchainInfo.PROVIDER);
     ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
     ccToolchainProvider.addGlobalMakeVariables(builder);
     assertThat(builder.build().get("GCOVTOOL")).isNull();
+  }
 
+  @Test
+  public void testGcovToolDefined() throws Exception {
     // Crosstool with gcov-tool
     scratch.file(
-        "b/BUILD",
+        "a/BUILD",
+        "load(':cc_toolchain_config.bzl', 'cc_toolchain_config')",
         "filegroup(",
         "   name='empty')",
         "cc_toolchain_suite(",
@@ -364,30 +373,31 @@
         "    linker_files = ':empty',",
         "    strip_files = ':empty',",
         "    objcopy_files = ':empty',",
-        "    proto=\"\"\"",
-        "      feature { name: 'no_legacy_features' }",
-        "      tool_path { name: 'gcc' path: 'path-to-gcc-tool' }",
-        "      tool_path { name: 'gcov-tool' path: 'path-to-gcov-tool' }",
-        "      tool_path { name: 'ar' path: 'ar' }",
-        "      tool_path { name: 'cpp' path: 'cpp' }",
-        "      tool_path { name: 'gcov' path: 'gcov' }",
-        "      tool_path { name: 'ld' path: 'ld' }",
-        "      tool_path { name: 'nm' path: 'nm' }",
-        "      tool_path { name: 'objdump' path: 'objdump' }",
-        "      tool_path { name: 'strip' path: 'strip' }",
-        "      toolchain_identifier: \"banana\"",
-        "      abi_version: \"banana\"",
-        "      abi_libc_version: \"banana\"",
-        "      compiler: \"banana\"",
-        "      host_system_name: \"banana\"",
-        "      target_system_name: \"banana\"",
-        "      target_cpu: \"banana\"",
-        "      target_libc: \"banana\"",
-        "    \"\"\")");
+        "    toolchain_identifier = 'banana',",
+        "    toolchain_config = ':k8-compiler_config',",
+        ")",
+        CcToolchainConfig.builder()
+            .withToolPaths(
+                Pair.of("gcc", "path-to-gcc-tool"),
+                Pair.of("gcov-tool", "path-to-gcov-tool"),
+                Pair.of("ar", "ar"),
+                Pair.of("cpp", "cpp"),
+                Pair.of("gcov", "gcov"),
+                Pair.of("ld", "ld"),
+                Pair.of("nm", "nm"),
+                Pair.of("objdump", "objdump"),
+                Pair.of("strip", "strip"))
+            .build()
+            .getCcToolchainConfigRule());
+    analysisMock.ccSupport().setupCcToolchainConfig(mockToolsConfig, CcToolchainConfig.builder());
+    mockToolsConfig.create(
+        "a/cc_toolchain_config.bzl",
+        ResourceLoader.readFromResources(
+            "com/google/devtools/build/lib/analysis/mock/cc_toolchain_config.bzl"));
     useConfiguration("--cpu=k8", "--host_cpu=k8");
-    ccToolchainProvider =
-        (CcToolchainProvider) getConfiguredTarget("//b:a").get(ToolchainInfo.PROVIDER);
-    builder = ImmutableMap.builder();
+    CcToolchainProvider ccToolchainProvider =
+        (CcToolchainProvider) getConfiguredTarget("//a:a").get(ToolchainInfo.PROVIDER);
+    ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
     ccToolchainProvider.addGlobalMakeVariables(builder);
     assertThat(builder.build().get("GCOVTOOL")).isNotNull();
   }
@@ -396,7 +406,8 @@
   public void testUnsupportedSysrootErrorMessage() throws Exception {
     scratch.file(
         "a/BUILD",
-        "filegroup(name='empty') ",
+        "load(':cc_toolchain_config.bzl', 'cc_toolchain_config')",
+        "filegroup(name='empty')",
         "filegroup(name='everything')",
         "cc_toolchain_suite(",
         "    name = 'a',",
@@ -413,17 +424,16 @@
         "    linker_files = ':empty',",
         "    strip_files = ':empty',",
         "    objcopy_files = ':empty',",
-        "    proto = \"\"\"",
-        "      toolchain_identifier: \"a\"",
-        "      host_system_name: \"a\"",
-        "      target_system_name: \"a\"",
-        "      target_cpu: \"a\"",
-        "      target_libc: \"a\"",
-        "      compiler: \"a\"",
-        "      abi_version: \"a\"",
-        "      abi_libc_version: \"a\"",
-        // Not specifying `builtin_sysroot` means the toolchain doesn't support --grte_top,
-        "\"\"\")");
+        "    toolchain_identifier = 'banana',",
+        "    toolchain_config = ':k8-compiler_config',",
+        ")",
+        // Not specifying `builtin_sysroot` means the toolchain doesn't support --grte_top.
+        CcToolchainConfig.builder().withSysroot("").build().getCcToolchainConfigRule());
+    analysisMock.ccSupport().setupCcToolchainConfig(mockToolsConfig, CcToolchainConfig.builder());
+    mockToolsConfig.create(
+        "a/cc_toolchain_config.bzl",
+        ResourceLoader.readFromResources(
+            "com/google/devtools/build/lib/analysis/mock/cc_toolchain_config.bzl"));
     reporter.removeHandler(failFastHandler);
     useConfiguration("--grte_top=//a", "--cpu=k8", "--host_cpu=k8");
     getConfiguredTarget("//a:a");
@@ -434,7 +444,9 @@
   public void testConfigWithMissingToolDefs() throws Exception {
     scratch.file(
         "a/BUILD",
-        "filegroup(name='empty') ",
+        "load(':cc_toolchain_config.bzl', 'cc_toolchain_config')",
+        "filegroup(",
+        "   name='empty')",
         "cc_toolchain_suite(",
         "    name = 'a',",
         "    toolchains = { 'k8': ':b' },",
@@ -450,24 +462,27 @@
         "    linker_files = ':empty',",
         "    strip_files = ':empty',",
         "    objcopy_files = ':empty',",
-        "    proto = \"\"\"",
-        "      toolchain_identifier: \"a\"",
-        "      host_system_name: \"a\"",
-        "      target_system_name: \"a\"",
-        "      target_cpu: \"a\"",
-        "      target_libc: \"a\"",
-        "      compiler: \"a\"",
-        "      abi_version: \"a\"",
-        "      abi_libc_version: \"a\"",
-        "      tool_path { name: 'gcc' path: 'path-to-gcc-tool' }",
-        "      tool_path { name: 'ar' path: 'ar' }",
-        "      tool_path { name: 'cpp' path: 'cpp' }",
-        "      tool_path { name: 'gcov' path: 'gcov' }",
-        "      tool_path { name: 'ld' path: 'ld' }",
-        "      tool_path { name: 'nm' path: 'nm' }",
-        "      tool_path { name: 'objdump' path: 'objdump' }",
-        // "      tool_path { name: 'strip' path: 'strip' }",
-        "\"\"\")");
+        "    toolchain_identifier = 'banana',",
+        "    toolchain_config = ':k8-compiler_config',",
+        ")",
+        CcToolchainConfig.builder()
+            .withToolPaths(
+                Pair.of("gcc", "path-to-gcc-tool"),
+                Pair.of("ar", "ar"),
+                Pair.of("cpp", "cpp"),
+                Pair.of("gcov", "gcov"),
+                Pair.of("ld", "ld"),
+                Pair.of("nm", "nm"),
+                Pair.of("objdump", "objdump")
+                // Pair.of("strip", "strip")
+                )
+            .build()
+            .getCcToolchainConfigRule());
+    analysisMock.ccSupport().setupCcToolchainConfig(mockToolsConfig, CcToolchainConfig.builder());
+    mockToolsConfig.create(
+        "a/cc_toolchain_config.bzl",
+        ResourceLoader.readFromResources(
+            "com/google/devtools/build/lib/analysis/mock/cc_toolchain_config.bzl"));
     reporter.removeHandler(failFastHandler);
     useConfiguration("--cpu=k8", "--host_cpu=k8");
     getConfiguredTarget("//a:a");
@@ -515,7 +530,8 @@
         "      tool_path { name: 'strip' path: 'strip' }",
         "\"\"\")");
     reporter.removeHandler(failFastHandler);
-    useConfiguration("--cpu=k8", "--host_cpu=k8");
+    analysisMock.ccSupport().setupCrosstool(mockToolsConfig);
+    useConfiguration("--cpu=k8", "--host_cpu=k8", "--noincompatible_disable_crosstool_file");
     getConfiguredTarget("//a:a");
     assertContainsEvent("Tool path for 'dwp' is missing");
   }
@@ -524,6 +540,7 @@
   public void testRuntimeLibsAttributesAreNotObligatory() throws Exception {
     scratch.file(
         "a/BUILD",
+        "load(':cc_toolchain_config.bzl', 'cc_toolchain_config')",
         "filegroup(name='empty') ",
         "cc_toolchain_suite(",
         "    name = 'a',",
@@ -540,16 +557,12 @@
         "    linker_files = ':empty',",
         "    strip_files = ':empty',",
         "    objcopy_files = ':empty',",
-        "    proto = \"\"\"",
-        "      toolchain_identifier: \"a\"",
-        "      host_system_name: \"a\"",
-        "      target_system_name: \"a\"",
-        "      target_cpu: \"a\"",
-        "      target_libc: \"a\"",
-        "      compiler: \"a\"",
-        "      abi_version: \"a\"",
-        "      abi_libc_version: \"a\"",
-        "\"\"\")");
+        "    toolchain_identifier = 'banana',",
+        "    toolchain_config = ':banana_config',",
+        ")",
+        "cc_toolchain_config(name = 'banana_config')");
+    scratch.file("a/cc_toolchain_config.bzl", MockCcSupport.EMPTY_CC_TOOLCHAIN);
+    analysisMock.ccSupport().setupCcToolchainConfig(mockToolsConfig, CcToolchainConfig.builder());
     reporter.removeHandler(failFastHandler);
     useConfiguration("--cpu=k8", "--host_cpu=k8");
     getConfiguredTarget("//a:a");
@@ -557,16 +570,17 @@
   }
 
   @Test
-  public void testWhenRuntimeLibsAttributesMandatoryWhenSupportsEmbeddedRuntimes()
+  public void testWhenStaticRuntimeLibAttributeMandatoryWhenSupportsEmbeddedRuntimes()
       throws Exception {
     scratch.file(
         "a/BUILD",
+        "load(':cc_toolchain_config.bzl', 'cc_toolchain_config')",
         "filegroup(name = 'empty')",
         "cc_binary(name = 'main', srcs = [ 'main.cc' ],)",
         "cc_binary(name = 'test', linkstatic = 0, srcs = [ 'test.cc' ],)",
         "cc_toolchain_suite(",
         "    name = 'a',",
-        "    toolchains = { 'k8': ':b', 'k9': ':c' },",
+        "    toolchains = { 'k8': ':b'},",
         ")",
         "cc_toolchain(",
         "    name = 'b',",
@@ -579,19 +593,44 @@
         "    linker_files = ':empty',",
         "    strip_files = ':empty',",
         "    objcopy_files = ':empty',",
-        "    proto = \"\"\"",
-        "      toolchain_identifier: \"a\"",
-        "      host_system_name: \"a\"",
-        "      target_system_name: \"a\"",
-        "      target_cpu: \"a\"",
-        "      target_libc: \"a\"",
-        "      compiler: \"a\"",
-        "      abi_version: \"a\"",
-        "      abi_libc_version: \"a\"",
-        "      feature { name: 'static_link_cpp_runtimes' enabled: true }",
-        "\"\"\")",
+        "    toolchain_identifier = 'banana',",
+        "    toolchain_config = ':k8-compiler_config',",
+        ")",
+        CcToolchainConfig.builder()
+            .withFeatures(CppRuleClasses.STATIC_LINK_CPP_RUNTIMES)
+            .build()
+            .getCcToolchainConfigRule());
+    analysisMock.ccSupport().setupCcToolchainConfig(mockToolsConfig, CcToolchainConfig.builder());
+    mockToolsConfig.create(
+        "a/cc_toolchain_config.bzl",
+        ResourceLoader.readFromResources(
+            "com/google/devtools/build/lib/analysis/mock/cc_toolchain_config.bzl"));
+    reporter.removeHandler(failFastHandler);
+    useConfiguration(
+        "--crosstool_top=//a:a",
+        "--cpu=k8",
+        "--host_cpu=k8",
+        "--experimental_disable_legacy_crosstool_fields");
+    assertThat(getConfiguredTarget("//a:main")).isNull();
+    assertContainsEvent(
+        "Toolchain supports embedded runtimes, but didn't provide static_runtime_lib attribute.");
+  }
+
+  @Test
+  public void testWhenDynamicRuntimeLibAttributeMandatoryWhenSupportsEmbeddedRuntimes()
+      throws Exception {
+    scratch.file(
+        "a/BUILD",
+        "load(':cc_toolchain_config.bzl', 'cc_toolchain_config')",
+        "filegroup(name = 'empty')",
+        "cc_binary(name = 'main', srcs = [ 'main.cc' ],)",
+        "cc_binary(name = 'test', linkstatic = 0, srcs = [ 'test.cc' ],)",
+        "cc_toolchain_suite(",
+        "    name = 'a',",
+        "    toolchains = { 'k8': ':b'},",
+        ")",
         "cc_toolchain(",
-        "    name = 'c',",
+        "    name = 'b',",
         "    cpu = 'banana',",
         "    all_files = ':empty',",
         "    ar_files = ':empty',",
@@ -602,33 +641,24 @@
         "    strip_files = ':empty',",
         "    objcopy_files = ':empty',",
         "    static_runtime_lib = ':empty',",
-        "    proto = \"\"\"",
-        "      toolchain_identifier: \"a\"",
-        "      host_system_name: \"a\"",
-        "      target_system_name: \"a\"",
-        "      target_cpu: \"a\"",
-        "      target_libc: \"a\"",
-        "      compiler: \"a\"",
-        "      abi_version: \"a\"",
-        "      abi_libc_version: \"a\"",
-        "      feature { name: 'supports_dynamic_linker' enabled: true }",
-        "      feature { name: 'static_link_cpp_runtimes' enabled: true }",
-        "\"\"\")");
+        "    toolchain_identifier = 'banana',",
+        "    toolchain_config = ':k8-compiler_config',",
+        ")",
+        CcToolchainConfig.builder()
+            .withFeatures(
+                CppRuleClasses.STATIC_LINK_CPP_RUNTIMES, CppRuleClasses.SUPPORTS_DYNAMIC_LINKER)
+            .build()
+            .getCcToolchainConfigRule());
+    analysisMock.ccSupport().setupCcToolchainConfig(mockToolsConfig, CcToolchainConfig.builder());
+    mockToolsConfig.create(
+        "a/cc_toolchain_config.bzl",
+        ResourceLoader.readFromResources(
+            "com/google/devtools/build/lib/analysis/mock/cc_toolchain_config.bzl"));
     reporter.removeHandler(failFastHandler);
     useConfiguration(
         "--crosstool_top=//a:a",
         "--cpu=k8",
         "--host_cpu=k8",
-        "--experimental_disable_legacy_crosstool_fields");
-    assertThat(getConfiguredTarget("//a:main")).isNull();
-    assertContainsEvent(
-        "Toolchain supports embedded runtimes, but didn't provide static_runtime_lib attribute.");
-    eventCollector.clear();
-
-    useConfiguration(
-        "--crosstool_top=//a:a",
-        "--cpu=k9",
-        "--host_cpu=k9",
         "--dynamic_mode=fully",
         "--experimental_disable_legacy_crosstool_fields");
     assertThat(getConfiguredTarget("//a:test")).isNull();
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CppLinkstampCompileHelperTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CppLinkstampCompileHelperTest.java
index cc98fba..3fdde9b 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CppLinkstampCompileHelperTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CppLinkstampCompileHelperTest.java
@@ -25,7 +25,7 @@
 import com.google.devtools.build.lib.analysis.platform.ToolchainInfo;
 import com.google.devtools.build.lib.analysis.util.AnalysisMock;
 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.Crosstool.CcToolchainConfig;
 import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
 import java.util.List;
 import org.junit.Test;
@@ -41,7 +41,8 @@
   public void testLinkstampCompileOptionsForExecutable() throws Exception {
     AnalysisMock.get()
         .ccSupport()
-        .setupCrosstool(mockToolsConfig, "builtin_sysroot: '/usr/local/custom-sysroot'");
+        .setupCcToolchainConfig(
+            mockToolsConfig, CcToolchainConfig.builder().withSysroot("/usr/local/custom-sysroot"));
     useConfiguration();
     scratch.file(
         "x/BUILD",
@@ -100,7 +101,8 @@
   public void testLinkstampCompileOptionsForSharedLibrary() throws Exception {
     AnalysisMock.get()
         .ccSupport()
-        .setupCrosstool(mockToolsConfig, "builtin_sysroot: '/usr/local/custom-sysroot'");
+        .setupCcToolchainConfig(
+            mockToolsConfig, CcToolchainConfig.builder().withSysroot("/usr/local/custom-sysroot"));
     useConfiguration();
     scratch.file(
         "x/BUILD",
@@ -142,8 +144,10 @@
   public void testLinkstampRespectsPicnessFromConfiguration() throws Exception {
     getAnalysisMock()
         .ccSupport()
-        .setupCrosstool(
-            mockToolsConfig, MockCcSupport.SUPPORTS_PIC_FEATURE, MockCcSupport.PIC_FEATURE);
+        .setupCcToolchainConfig(
+            mockToolsConfig,
+            CcToolchainConfig.builder()
+                .withFeatures(CppRuleClasses.SUPPORTS_PIC, CppRuleClasses.PIC));
 
     useConfiguration("--force_pic");
     scratch.file(
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/LibraryLinkingTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/LibraryLinkingTest.java
index eaad325..4dcb3db 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/LibraryLinkingTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/LibraryLinkingTest.java
@@ -21,7 +21,7 @@
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.FileProvider;
 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.Crosstool.CcToolchainConfig;
 import java.util.List;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -50,7 +50,9 @@
   public void testGeneratedLib() throws Exception {
     getAnalysisMock()
         .ccSupport()
-        .setupCrosstool(mockToolsConfig, MockCcSupport.SUPPORTS_DYNAMIC_LINKER_FEATURE);
+        .setupCcToolchainConfig(
+            mockToolsConfig,
+            CcToolchainConfig.builder().withFeatures(CppRuleClasses.SUPPORTS_DYNAMIC_LINKER));
 
     useConfiguration("--cpu=k8");
     ConfiguredTarget genlib =
@@ -87,7 +89,9 @@
   public void testCcLibraryLinkopts() throws Exception {
     getAnalysisMock()
         .ccSupport()
-        .setupCrosstool(mockToolsConfig, MockCcSupport.SUPPORTS_DYNAMIC_LINKER_FEATURE);
+        .setupCcToolchainConfig(
+            mockToolsConfig,
+            CcToolchainConfig.builder().withFeatures(CppRuleClasses.SUPPORTS_DYNAMIC_LINKER));
 
     scratch.overwriteFile(
         "custom_malloc/BUILD",
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariablesTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariablesTest.java
index 03eaebc..ecef4ba 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariablesTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/LinkBuildVariablesTest.java
@@ -23,6 +23,7 @@
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.analysis.RuleContext;
 import com.google.devtools.build.lib.analysis.util.AnalysisMock;
+import com.google.devtools.build.lib.packages.util.Crosstool.CcToolchainConfig;
 import com.google.devtools.build.lib.packages.util.MockCcSupport;
 import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.LibraryToLinkValue;
 import com.google.devtools.build.lib.rules.cpp.CcToolchainVariables.VariableValue;
@@ -57,7 +58,8 @@
   public void testForcePicBuildVariable() throws Exception {
     AnalysisMock.get()
         .ccSupport()
-        .setupCrosstool(mockToolsConfig, MockCcSupport.SUPPORTS_PIC_FEATURE);
+        .setupCcToolchainConfig(
+            mockToolsConfig, CcToolchainConfig.builder().withFeatures(CppRuleClasses.SUPPORTS_PIC));
     useConfiguration("--force_pic");
     scratch.file("x/BUILD", "cc_binary(name = 'bin', srcs = ['a.cc'])");
     scratch.file("x/a.cc");
@@ -74,7 +76,9 @@
   public void testLibrariesToLinkAreExported() throws Exception {
     AnalysisMock.get()
         .ccSupport()
-        .setupCrosstool(mockToolsConfig, MockCcSupport.SUPPORTS_DYNAMIC_LINKER_FEATURE);
+        .setupCcToolchainConfig(
+            mockToolsConfig,
+            CcToolchainConfig.builder().withFeatures(CppRuleClasses.SUPPORTS_DYNAMIC_LINKER));
     useConfiguration();
 
     scratch.file("x/BUILD", "cc_library(name = 'foo', srcs = ['a.cc'])");
@@ -104,7 +108,6 @@
 
   @Test
   public void testLibrarySearchDirectoriesAreExported() throws Exception {
-    AnalysisMock.get().ccSupport().setupCrosstool(mockToolsConfig);
     useConfiguration();
 
     scratch.file("x/BUILD", "cc_binary(name = 'bin', srcs = ['some-dir/bar.so'])");
@@ -122,7 +125,6 @@
 
   @Test
   public void testLinkerParamFileIsExported() throws Exception {
-    AnalysisMock.get().ccSupport().setupCrosstool(mockToolsConfig);
     useConfiguration();
 
     scratch.file("x/BUILD", "cc_binary(name = 'bin', srcs = ['some-dir/bar.so'])");
@@ -140,10 +142,12 @@
   public void testInterfaceLibraryBuildingVariablesWhenLegacyGenerationPossible() throws Exception {
     AnalysisMock.get()
         .ccSupport()
-        .setupCrosstool(
+        .setupCcToolchainConfig(
             mockToolsConfig,
-            MockCcSupport.SUPPORTS_INTERFACE_SHARED_LIBRARIES_FEATURE,
-            MockCcSupport.SUPPORTS_DYNAMIC_LINKER_FEATURE);
+            CcToolchainConfig.builder()
+                .withFeatures(
+                    CppRuleClasses.SUPPORTS_INTERFACE_SHARED_LIBRARIES,
+                    CppRuleClasses.SUPPORTS_DYNAMIC_LINKER));
     useConfiguration();
 
     verifyIfsoVariables();
@@ -153,10 +157,12 @@
   public void testInterfaceLibraryBuildingVariablesWhenGenerationPossible() throws Exception {
     AnalysisMock.get()
         .ccSupport()
-        .setupCrosstool(
+        .setupCcToolchainConfig(
             mockToolsConfig,
-            MockCcSupport.SUPPORTS_DYNAMIC_LINKER_FEATURE,
-            MockCcSupport.SUPPORTS_INTERFACE_SHARED_LIBRARIES_FEATURE);
+            CcToolchainConfig.builder()
+                .withFeatures(
+                    CppRuleClasses.SUPPORTS_DYNAMIC_LINKER,
+                    CppRuleClasses.SUPPORTS_INTERFACE_SHARED_LIBRARIES));
     useConfiguration();
 
     verifyIfsoVariables();
@@ -204,14 +210,16 @@
     invalidatePackages(true);
     AnalysisMock.get()
         .ccSupport()
-        .setupCrosstool(
+        .setupCcToolchainConfig(
             mockToolsConfig,
-            MockCcSupport.THIN_LTO_CONFIGURATION,
-            MockCcSupport.SUPPORTS_PIC_FEATURE,
-            MockCcSupport.HOST_AND_NONHOST_CONFIGURATION,
-            MockCcSupport.SUPPORTS_INTERFACE_SHARED_LIBRARIES_FEATURE,
-            MockCcSupport.SUPPORTS_DYNAMIC_LINKER_FEATURE,
-            MockCcSupport.SUPPORTS_START_END_LIB_FEATURE);
+            CcToolchainConfig.builder()
+                .withFeatures(
+                    CppRuleClasses.THIN_LTO,
+                    CppRuleClasses.SUPPORTS_PIC,
+                    MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
+                    CppRuleClasses.SUPPORTS_INTERFACE_SHARED_LIBRARIES,
+                    CppRuleClasses.SUPPORTS_DYNAMIC_LINKER,
+                    CppRuleClasses.SUPPORTS_START_END_LIB));
     useConfiguration("--features=thin_lto");
 
     scratch.file("x/BUILD", "cc_library(name = 'foo', srcs = ['a.cc'])");
@@ -264,7 +272,10 @@
     // (which it is not by default for some windows toolchains)
     AnalysisMock.get()
         .ccSupport()
-        .setupCrosstool(mockToolsConfig, MockCcSupport.SUPPORTS_INTERFACE_SHARED_LIBRARIES_FEATURE);
+        .setupCcToolchainConfig(
+            mockToolsConfig,
+            CcToolchainConfig.builder()
+                .withFeatures(CppRuleClasses.SUPPORTS_INTERFACE_SHARED_LIBRARIES));
     useConfiguration();
 
     scratch.file("x/BUILD", "cc_library(name = 'foo', srcs = ['a.cc'])");
@@ -304,7 +315,9 @@
   public void testOutputExecpath() throws Exception {
     AnalysisMock.get()
         .ccSupport()
-        .setupCrosstool(mockToolsConfig, MockCcSupport.SUPPORTS_DYNAMIC_LINKER_FEATURE);
+        .setupCcToolchainConfig(
+            mockToolsConfig,
+            CcToolchainConfig.builder().withFeatures(CppRuleClasses.SUPPORTS_DYNAMIC_LINKER));
     // Make sure the interface shared object generation is enabled in the configuration
     // (which it is not by default for some windows toolchains)
     scratch.file("x/BUILD", "cc_library(name = 'foo', srcs = ['a.cc'])");
@@ -324,14 +337,16 @@
   public void testOutputExecpathIsNotExposedWhenThinLtoIndexing() throws Exception {
     AnalysisMock.get()
         .ccSupport()
-        .setupCrosstool(
+        .setupCcToolchainConfig(
             mockToolsConfig,
-            MockCcSupport.THIN_LTO_CONFIGURATION,
-            MockCcSupport.HOST_AND_NONHOST_CONFIGURATION,
-            MockCcSupport.SUPPORTS_DYNAMIC_LINKER_FEATURE,
-            MockCcSupport.SUPPORTS_PIC_FEATURE,
-            MockCcSupport.SUPPORTS_INTERFACE_SHARED_LIBRARIES_FEATURE,
-            MockCcSupport.SUPPORTS_START_END_LIB_FEATURE);
+            CcToolchainConfig.builder()
+                .withFeatures(
+                    CppRuleClasses.THIN_LTO,
+                    MockCcSupport.HOST_AND_NONHOST_CONFIGURATION_FEATURES,
+                    CppRuleClasses.SUPPORTS_DYNAMIC_LINKER,
+                    CppRuleClasses.SUPPORTS_PIC,
+                    CppRuleClasses.SUPPORTS_INTERFACE_SHARED_LIBRARIES,
+                    CppRuleClasses.SUPPORTS_START_END_LIB));
     useConfiguration("--features=thin_lto");
 
     scratch.file("x/BUILD", "cc_library(name = 'foo', srcs = ['a.cc'])");
@@ -412,7 +427,9 @@
 
     AnalysisMock.get()
         .ccSupport()
-        .setupCrosstool(mockToolsConfig, MockCcSupport.PER_OBJECT_DEBUG_INFO_CONFIGURATION);
+        .setupCcToolchainConfig(
+            mockToolsConfig,
+            CcToolchainConfig.builder().withFeatures(CppRuleClasses.PER_OBJECT_DEBUG_INFO));
 
     useConfiguration("--fission=no");
     ConfiguredTarget target = getConfiguredTarget("//x:foo");
@@ -435,7 +452,9 @@
 
     AnalysisMock.get()
         .ccSupport()
-        .setupCrosstool(mockToolsConfig, MockCcSupport.PER_OBJECT_DEBUG_INFO_CONFIGURATION);
+        .setupCcToolchainConfig(
+            mockToolsConfig,
+            CcToolchainConfig.builder().withFeatures(CppRuleClasses.PER_OBJECT_DEBUG_INFO));
 
     useConfiguration("--fission=no");
     ConfiguredTarget target = getConfiguredTarget("//x:foo");
@@ -455,7 +474,8 @@
   public void testSysrootVariable() throws Exception {
     AnalysisMock.get()
         .ccSupport()
-        .setupCrosstool(mockToolsConfig, "builtin_sysroot: '/usr/local/custom-sysroot'");
+        .setupCcToolchainConfig(
+            mockToolsConfig, CcToolchainConfig.builder().withSysroot("/usr/local/custom-sysroot"));
     useConfiguration();
 
     scratch.file("x/BUILD", "cc_binary(name = 'foo', srcs = ['a.cc'])");