Add all available toolchains to the FileProvider of cc_toolchain_suite.

This is necessary because we don't have a replacement for saying "this genrule needs the C++ toolchain" and I'd prefer this to do it in a backward-compatible way; burned myself here by trying to be principled, so let's now do the pragmatic thing.

--
MOS_MIGRATED_REVID=127317024
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index dc6064c..85b2be3 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -648,6 +648,28 @@
   }
 
   /**
+   * Returns the dependencies through a {@code LABEL_DICT_UNARY} attribute as a map from
+   * a string to a {@link TransitiveInfoCollection}.
+   */
+  public Map<String, TransitiveInfoCollection> getPrerequisiteMap(String attributeName) {
+    Attribute attributeDefinition = getAttribute(attributeName);
+    Preconditions.checkState(attributeDefinition.getType() == BuildType.LABEL_DICT_UNARY);
+
+    ImmutableMap.Builder<String, TransitiveInfoCollection> result = ImmutableMap.builder();
+    Map<String, Label> dict = attributes().get(attributeName, BuildType.LABEL_DICT_UNARY);
+    Map<Label, ConfiguredTarget> labelToDep = new HashMap<>();
+    for (ConfiguredTarget dep : targetMap.get(attributeName)) {
+      labelToDep.put(dep.getLabel(), dep);
+    }
+
+    for (Map.Entry<String, Label> entry : dict.entrySet()) {
+      result.put(entry.getKey(), Preconditions.checkNotNull(labelToDep.get(entry.getValue())));
+    }
+
+    return result.build();
+  }
+
+  /**
    * Returns the list of transitive info collections that feed into this target through the
    * specified attribute. Note that you need to specify the correct mode for the attribute,
    * otherwise an assertion will be raised.
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuite.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuite.java
index 637d86a..83aa0fd 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuite.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuite.java
@@ -18,9 +18,8 @@
 import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
 import com.google.devtools.build.lib.analysis.RuleContext;
 import com.google.devtools.build.lib.analysis.RunfilesProvider;
+import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
-import com.google.devtools.build.lib.collect.nestedset.Order;
-import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
 import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
 
 /**
@@ -35,8 +34,16 @@
   @Override
   public ConfiguredTarget create(RuleContext ruleContext)
       throws InterruptedException, RuleErrorException {
+    NestedSetBuilder<Artifact> filesToBuild = NestedSetBuilder.stableOrder();
+    for (TransitiveInfoCollection dep : ruleContext.getPrerequisiteMap("toolchains").values()) {
+      CcToolchainProvider provider = dep.getProvider(CcToolchainProvider.class);
+      if (provider != null) {
+        filesToBuild.addTransitive(provider.getCrosstool());
+      }
+    }
+
     return new RuleConfiguredTargetBuilder(ruleContext)
-        .setFilesToBuild(NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER))
+        .setFilesToBuild(filesToBuild.build())
         .add(RunfilesProvider.class, RunfilesProvider.EMPTY)
         .build();
   }
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuiteTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuiteTest.java
index 45b1556..3101ff1 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuiteTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcToolchainSuiteTest.java
@@ -16,7 +16,11 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
 import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,6 +32,119 @@
 @RunWith(JUnit4.class)
 public class CcToolchainSuiteTest extends BuildViewTestCase {
   @Test
+  public void testFilesToBuild() throws Exception {
+    scratch.file(
+        "cc/BUILD",
+        "cc_toolchain_suite(",
+        "    name = 'suite',",
+        "    toolchains = { ",
+        "       'k8|k8-compiler': ':k8-toolchain',",
+        "       'darwin|darwin-compiler': ':darwin-toolchain',",
+        "    },",
+        "    proto = \"\"\"",
+        "major_version: 'v1'",
+        "minor_version: '0'",
+        "default_target_cpu: 'k8'",
+        "default_toolchain {",
+        "  cpu: 'k8'",
+        "  toolchain_identifier: 'k8-toolchain'",
+        "}",
+        "default_toolchain {",
+        "  cpu: 'darwin'",
+        "  toolchain_identifier: 'darwin-toolchain'",
+        "}",
+        "toolchain {",
+        "  compiler: 'k8-compiler'",
+        "  target_cpu: 'k8'",
+        "  toolchain_identifier: 'k8-toolchain'",
+        "  host_system_name: 'linux'",
+        "  target_system_name: 'linux'",
+        "  abi_version: 'cpu-abi'",
+        "  abi_libc_version: ''",
+        "  target_libc: ''",
+        "  builtin_sysroot: 'sysroot'",
+        "  default_grte_top: '//cc:grtetop'",
+        "  tool_path { name: 'cpu-compiler', path: 'k8/compiler' }",
+        "  tool_path { name: 'ar', path: 'k8/ar' }",
+        "  tool_path { name: 'cpp', path: 'k8/cpp' }",
+        "  tool_path { name: 'gcc', path: 'k8/gcc' }",
+        "  tool_path { name: 'gcov', path: 'k8/gcov' }",
+        "  tool_path { name: 'ld', path: 'k8/ld' }",
+        "  tool_path { name: 'nm', path: 'k8/nm' }",
+        "  tool_path { name: 'objcopy', path: 'k8/objcopy' }",
+        "  tool_path { name: 'objdump', path: 'k8/objdump' }",
+        "  tool_path { name: 'strip', path: 'k8/strip' }",
+        "}",
+        "toolchain {",
+        "  compiler: 'darwin-compiler'",
+        "  target_cpu: 'darwin'",
+        "  toolchain_identifier: 'darwin-toolchain'",
+        "  host_system_name: 'linux'",
+        "  target_system_name: 'linux'",
+        "  abi_version: ''",
+        "  abi_libc_version: ''",
+        "  target_libc: ''",
+        "  builtin_sysroot: 'sysroot'",
+        "  default_grte_top: '//cc:grtetop'",
+        "  tool_path { name: 'darwin-compiler', path: 'darwin/compiler' }",
+        "  tool_path { name: 'ar', path: 'darwin/ar' }",
+        "  tool_path { name: 'cpp', path: 'darwin/cpp' }",
+        "  tool_path { name: 'gcc', path: 'darwin/gcc' }",
+        "  tool_path { name: 'gcov', path: 'darwin/gcov' }",
+        "  tool_path { name: 'ld', path: 'darwin/ld' }",
+        "  tool_path { name: 'nm', path: 'darwin/nm' }",
+        "  tool_path { name: 'objcopy', path: 'darwin/objcopy' }",
+        "  tool_path { name: 'objdump', path: 'darwin/objdump' }",
+        "  tool_path { name: 'strip', path: 'darwin/strip' }",
+        "}",
+        "\"\"\")",
+        "cc_toolchain(",
+        "    name = 'k8-toolchain',",
+        "    module_map = 'map',",
+        "    cpu = 'cpu',",
+        "    compiler_files = 'compile',",
+        "    dwp_files = 'dwp',",
+        "    linker_files = 'link',",
+        "    strip_files = ':strip',",
+        "    objcopy_files = 'objcopy',",
+        "    all_files = ':k8-files',",
+        "    dynamic_runtime_libs = ['k8-dynamic-runtime-libs'],",
+        "    static_runtime_libs = ['k8-static-runtime-libs'])",
+        "filegroup(",
+        "    name = 'k8-files',",
+        "    srcs = ['k8-marker', 'everything'])",
+        "",
+        "cc_toolchain(",
+        "    name = 'darwin-toolchain',",
+        "    module_map = 'map',",
+        "    cpu = 'cpu',",
+        "    compiler_files = 'compile',",
+        "    dwp_files = 'dwp',",
+        "    linker_files = 'link',",
+        "    strip_files = ':strip',",
+        "    objcopy_files = 'objcopy',",
+        "    all_files = ':darwin-files',",
+        "    dynamic_runtime_libs = ['darwin-dynamic-runtime-libs'],",
+        "    static_runtime_libs = ['darwin-static-runtime-libs'])",
+        "filegroup(",
+        "    name = 'darwin-files',",
+        "    srcs = ['darwin-marker', 'everything'])");
+
+    scratch.file("a/BUILD",
+        "genrule(name='a', srcs=[], outs=['ao'], tools=['//tools/defaults:crosstool'], cmd='x')");
+
+    invalidatePackages();
+    useConfiguration("--crosstool_top=//cc:suite");
+    Action action = getGeneratingAction(getConfiguredTarget("//a:a"), "a/ao");
+    assertThat(ActionsTestUtil.baseArtifactNames(action.getInputs()))
+        .containsAllOf("k8-marker", "darwin-marker");
+
+    NestedSet<Artifact> suiteFiles = getFilesToBuild(getConfiguredTarget("//cc:suite"));
+    assertThat(ActionsTestUtil.baseArtifactNames(suiteFiles))
+        .containsAllOf("k8-marker", "darwin-marker");
+  }
+
+  @Test
   public void testSmoke() throws Exception {
     scratch.file(
         "cc/BUILD",