Supply the C++ toolchain files to genrules using them directly using the
middleman.
RELNOTES: None.
PiperOrigin-RevId: 213451420
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/CommandHelper.java b/src/main/java/com/google/devtools/build/lib/analysis/CommandHelper.java
index 08cebe5..07d5e00 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/CommandHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/CommandHelper.java
@@ -165,11 +165,24 @@
for (Iterable<? extends TransitiveInfoCollection> tools : toolsList) {
for (TransitiveInfoCollection dep : tools) { // (Note: host configuration)
Label label = AliasProvider.getDependencyLabel(dep);
+ MiddlemanProvider toolMiddleman = dep.getProvider(MiddlemanProvider.class);
+ if (toolMiddleman != null) {
+ resolvedToolsBuilder.addAll(toolMiddleman.getMiddlemanArtifact());
+ // It is not obviously correct to skip potentially adding getFilesToRun of the
+ // FilesToRunProvider. However, for all tools that we know of that provide a middleman,
+ // the middleman is equivalent to the list of files coming out of getFilesToRun().
+ // Just adding all the files creates a substantial performance bottleneck. E.g. a C++
+ // toolchain might consist of thousands of files and tracking them one by one for each
+ // action that uses them is inefficient.
+ continue;
+ }
+
FilesToRunProvider tool = dep.getProvider(FilesToRunProvider.class);
if (tool == null) {
continue;
}
+ // TODO(djasper): This is flattening the NestedSet coming out of getFilesToRun(). Don't.
Iterable<Artifact> files = tool.getFilesToRun();
resolvedToolsBuilder.addAll(files);
Artifact executableArtifact = tool.getExecutable();
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 6f5de1d..d8bd700 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
@@ -629,7 +629,8 @@
.addNativeDeclaredProvider(ccProvider)
.addNativeDeclaredProvider(templateVariableInfo)
.setFilesToBuild(crosstool)
- .addProvider(RunfilesProvider.simple(Runfiles.EMPTY));
+ .addProvider(RunfilesProvider.simple(Runfiles.EMPTY))
+ .addProvider(new MiddlemanProvider(crosstoolMiddleman));
// If output_license is specified on the cc_toolchain rule, override the transitive licenses
// with that one. This is necessary because cc_toolchain is used in the target configuration,
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 eed04b1..1f9d0c3 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
@@ -243,7 +243,8 @@
useConfiguration(
"--crosstool_top=//cc:suite", "--cpu=ppc", "--host_cpu=ppc", "--compiler=compiler");
Action action = getGeneratingAction(getConfiguredTarget("//a:a"), "a/ao");
- assertThat(ActionsTestUtil.baseArtifactNames(action.getInputs())).contains("linux-marker");
+ assertThat(ActionsTestUtil.baseArtifactNames(action.getInputs()))
+ .contains("tools_Scpp_Ccrosstool");
NestedSet<Artifact> suiteFiles = getFilesToBuild(getConfiguredTarget("//cc:suite"));
assertThat(ActionsTestUtil.baseArtifactNames(suiteFiles))