Add --toolchain_resolution_debug option to give more information about
toolchain selection.
Fixes #3431.
Change-Id: Ia38415575b6a121cbb6a028bfc0276691cd11b6d
PiperOrigin-RevId: 163196646
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/PlatformOptions.java b/src/main/java/com/google/devtools/build/lib/analysis/PlatformOptions.java
index 438d6f2..3376e96 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/PlatformOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/PlatformOptions.java
@@ -83,6 +83,17 @@
)
public List<ToolchainResolutionOverride> toolchainResolutionOverrides;
+ @Option(
+ name = "toolchain_resolution_debug",
+ defaultValue = "false",
+ documentationCategory = OptionDocumentationCategory.LOGGING,
+ effectTags = {OptionEffectTag.TERMINAL_OUTPUT},
+ help =
+ "Print debug information while finding toolchains for a rule. This might help developers "
+ + "of Bazel or Skylark rules with debugging failures due to missing toolchains."
+ )
+ public boolean toolchainResolutionDebug;
+
@Override
public PlatformOptions getHost(boolean fallback) {
PlatformOptions host = (PlatformOptions) getDefault();
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunction.java
index 28a6ebe..410578f 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunction.java
@@ -17,11 +17,14 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.PlatformConfiguration;
+import com.google.devtools.build.lib.analysis.PlatformOptions;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo;
import com.google.devtools.build.lib.analysis.platform.DeclaredToolchainInfo;
import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.events.Event;
+import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.packages.NoSuchThingException;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction.ConfiguredValueCreationException;
import com.google.devtools.build.lib.skyframe.RegisteredToolchainsFunction.InvalidTargetException;
@@ -74,12 +77,14 @@
}
// Find the right one.
+ boolean debug = configuration.getOptions().get(PlatformOptions.class).toolchainResolutionDebug;
DeclaredToolchainInfo toolchain =
resolveConstraints(
key.toolchainType(),
key.execPlatform(),
key.targetPlatform(),
- toolchains.registeredToolchains());
+ toolchains.registeredToolchains(),
+ debug ? env.getListener() : null);
if (toolchain == null) {
throw new ToolchainResolutionFunctionException(
@@ -93,35 +98,75 @@
Label toolchainType,
PlatformInfo execPlatform,
PlatformInfo targetPlatform,
- ImmutableList<DeclaredToolchainInfo> toolchains) {
+ ImmutableList<DeclaredToolchainInfo> toolchains,
+ @Nullable EventHandler eventHandler) {
+
+ debugMessage(eventHandler, "Looking for toolchain of type %s...", toolchainType);
for (DeclaredToolchainInfo toolchain : toolchains) {
// Make sure the type matches.
if (!toolchain.toolchainType().equals(toolchainType)) {
continue;
}
- if (!checkConstraints(toolchain.execConstraints(), execPlatform)) {
+ debugMessage(eventHandler, " Considering toolchain %s...", toolchain.toolchainLabel());
+ if (!checkConstraints(eventHandler, toolchain.execConstraints(), "execution", execPlatform)) {
+ debugMessage(
+ eventHandler,
+ " Rejected toolchain %s, because of execution platform mismatch",
+ toolchain.toolchainLabel());
continue;
}
- if (!checkConstraints(toolchain.targetConstraints(), targetPlatform)) {
+ if (!checkConstraints(
+ eventHandler, toolchain.targetConstraints(), "target", targetPlatform)) {
+ debugMessage(
+ eventHandler,
+ " Rejected toolchain %s, because of target platform mismatch",
+ toolchain.toolchainLabel());
continue;
}
+ debugMessage(eventHandler, " Selected toolchain %s", toolchain.toolchainLabel());
return toolchain;
}
+ debugMessage(eventHandler, " No toolchain found");
return null;
}
/**
+ * Helper method to print a debugging message, if the given {@link EventHandler} is not {@code
+ * null}.
+ */
+ private static void debugMessage(
+ @Nullable EventHandler eventHandler, String template, Object... args) {
+ if (eventHandler == null) {
+ return;
+ }
+
+ eventHandler.handle(Event.info("ToolchainResolution: " + String.format(template, args)));
+ }
+
+ /**
* Returns {@code true} iff all constraints set by the toolchain are present in the {@link
* PlatformInfo}.
*/
private static boolean checkConstraints(
- Iterable<ConstraintValueInfo> toolchainConstraints, PlatformInfo platform) {
+ @Nullable EventHandler eventHandler,
+ Iterable<ConstraintValueInfo> toolchainConstraints,
+ String platformType,
+ PlatformInfo platform) {
for (ConstraintValueInfo constraint : toolchainConstraints) {
ConstraintValueInfo found = platform.getConstraint(constraint.constraint());
if (!constraint.equals(found)) {
+ debugMessage(
+ eventHandler,
+ " Toolchain constraint %s has value %s, "
+ + "which does not match value %s from the %s platform %s",
+ constraint.constraint().label(),
+ constraint.label(),
+ found != null ? found.label() : "<missing>",
+ platformType,
+ platform.label());
return false;
}
}
diff --git a/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java b/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java
index e8b1f63..f0bc14a5 100644
--- a/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java
+++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java
@@ -368,11 +368,6 @@
public boolean apply(Event event) {
switch (event.getKind()) {
case INFO:
- throw new UnsupportedOperationException(
- "SkyFunctions should not display INFO messages: "
- + event.getLocation()
- + ": "
- + event.getMessage());
case PROGRESS:
return false;
default:
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunctionTest.java
index b98d572..d1b17bb 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunctionTest.java
@@ -203,7 +203,7 @@
DeclaredToolchainInfo resolvedToolchain =
ToolchainResolutionFunction.resolveConstraints(
- toolchainType, execPlatform, targetPlatform, toolchains);
+ toolchainType, execPlatform, targetPlatform, toolchains, null);
return assertThat(resolvedToolchain);
}
diff --git a/src/test/shell/bazel/toolchain_test.sh b/src/test/shell/bazel/toolchain_test.sh
index 62510c6..6490bf2 100755
--- a/src/test/shell/bazel/toolchain_test.sh
+++ b/src/test/shell/bazel/toolchain_test.sh
@@ -182,6 +182,29 @@
expect_log 'Using toolchain: rule message: "this is the rule", toolchain extra_str: "foo from 1"'
}
+function test_toolchain_debug_messages {
+ write_test_toolchain
+ write_test_rule
+ write_toolchains
+
+ mkdir -p demo
+ cat >> demo/BUILD <<EOF
+load('//toolchain:rule.bzl', 'use_toolchain')
+# Use the toolchain.
+use_toolchain(
+ name = 'use',
+ message = 'this is the rule')
+EOF
+
+ bazel build \
+ --toolchain_resolution_debug \
+ //demo:use &> $TEST_log || fail "Build failed"
+ expect_log 'ToolchainResolution: Looking for toolchain of type //toolchain:test_toolchain'
+ expect_log 'ToolchainResolution: Selected toolchain //:toolchain_impl_1'
+ expect_log 'Using toolchain: rule message: "this is the rule", toolchain extra_str: "foo from 1"'
+}
+
+
function test_toolchain_use_in_aspect {
write_test_toolchain
write_test_aspect