Skip to content

Commit

Permalink
Add a helper class to simplify printing of single toolchain resolutio…
Browse files Browse the repository at this point in the history
…n debug messages.

PiperOrigin-RevId: 699130634
Change-Id: I9b0311386ab331bdc7e687bd155354103818db06
  • Loading branch information
katre authored and copybara-github committed Nov 22, 2024
1 parent 8a5e70c commit b8320e9
Show file tree
Hide file tree
Showing 3 changed files with 323 additions and 164 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,10 @@ java_library(

java_library(
name = "single_toolchain_resolution_function",
srcs = ["SingleToolchainResolutionFunction.java"],
srcs = [
"SingleToolchainResolutionDebugPrinter.java",
"SingleToolchainResolutionFunction.java",
],
deps = [
":platform_lookup_util",
":registered_toolchains_function",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
// Copyright 2024 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.skyframe.toolchains;

import static java.util.stream.Collectors.joining;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.analysis.platform.ConstraintCollection;
import com.google.devtools.build.lib.analysis.platform.ConstraintSettingInfo;
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.ExtendedEventHandler;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
import com.google.errorprone.annotations.FormatMethod;
import com.google.errorprone.annotations.FormatString;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/** A helper interface for printing debug messages from single toolchain resolution. */
public sealed interface SingleToolchainResolutionDebugPrinter {
static SingleToolchainResolutionDebugPrinter create(
boolean debug, ExtendedEventHandler eventHandler) {
if (debug) {
return new EventHandlerImpl(eventHandler);
}
return new NoopPrinter();
}

void finishDebugging();

void describeRejectedToolchains(ImmutableMap<Label, String> rejectedToolchains);

void startToolchainResolution(Label toolchainType, Label targetPlatform);

void reportCompatibleTargetPlatform(Label toolchainLabel);

void reportSkippedExecutionPlatformSeen(Label executionPlatform);

void reportSkippedExecutionPlatformDisallowed(Label executionPlatform, Label toolchainType);

void reportCompatibleExecutionPlatform(Label executionPlatform);

void reportResolvedToolchains(
ImmutableMap<ConfiguredTargetKey, Label> resolvedToolchains,
Label targetPlatform,
Label toolchainType);

void reportMismatchedSettings(
ConstraintCollection toolchainConstraints,
boolean isTargetPlatform,
PlatformInfo platform,
Label toolchainLabel,
ImmutableSet<ConstraintSettingInfo> mismatchSettingsWithDefault);

void reportDone(Label toolchainType);

/** A do-nothing implementation for when debug messages are suppressed. */
final class NoopPrinter implements SingleToolchainResolutionDebugPrinter {

private NoopPrinter() {}

@Override
public void finishDebugging() {}

@Override
public void describeRejectedToolchains(ImmutableMap<Label, String> rejectedToolchains) {}

@Override
public void startToolchainResolution(Label toolchainType, Label targetPlatform) {}

@Override
public void reportCompatibleTargetPlatform(Label toolchainLabel) {}

@Override
public void reportSkippedExecutionPlatformSeen(Label executionPlatform) {}

@Override
public void reportSkippedExecutionPlatformDisallowed(
Label executionPlatform, Label toolchainType) {}

@Override
public void reportCompatibleExecutionPlatform(Label executionPlatform) {}

@Override
public void reportResolvedToolchains(
ImmutableMap<ConfiguredTargetKey, Label> resolvedToolchains,
Label targetPlatform,
Label toolchainType) {}

@Override
public void reportMismatchedSettings(
ConstraintCollection toolchainConstraints,
boolean isTargetPlatform,
PlatformInfo platform,
Label toolchainLabel,
ImmutableSet<ConstraintSettingInfo> mismatchSettingsWithDefault) {}

@Override
public void reportDone(Label toolchainType) {}
}

/** Implement debug printing using the {@link ExtendedEventHandler}. */
final class EventHandlerImpl implements SingleToolchainResolutionDebugPrinter {
/** Helper enum to define the three indentation levels used in {@code debugMessage}. */
private enum IndentLevel {
TARGET_PLATFORM_LEVEL(""),
TOOLCHAIN_LEVEL(" "),
EXECUTION_PLATFORM_LEVEL(" ");

final String value;

IndentLevel(String value) {
this.value = value;
}

public String indent() {
return value;
}
}

private final ExtendedEventHandler eventHandler;
private final List<String> resolutionTrace = new ArrayList<>();

private EventHandlerImpl(ExtendedEventHandler eventHandler) {
this.eventHandler = eventHandler;
}

@FormatMethod
private void debugMessage(IndentLevel indent, @FormatString String template, Object... args) {
String padding = resolutionTrace.isEmpty() ? "" : " ".repeat("INFO: ".length());
resolutionTrace.add(
padding + "ToolchainResolution: " + indent.indent() + String.format(template, args));
}

@Override
public void finishDebugging() {
eventHandler.handle(Event.info(String.join("\n", resolutionTrace)));
}

@Override
public void describeRejectedToolchains(ImmutableMap<Label, String> rejectedToolchains) {
if (!rejectedToolchains.isEmpty()) {
for (Map.Entry<Label, String> entry : rejectedToolchains.entrySet()) {
Label toolchainLabel = entry.getKey();
String message = entry.getValue();
debugMessage(
IndentLevel.TOOLCHAIN_LEVEL, "Rejected toolchain %s; %s", toolchainLabel, message);
}
}
}

@Override
public void startToolchainResolution(Label toolchainType, Label targetPlatform) {
debugMessage(
IndentLevel.TARGET_PLATFORM_LEVEL,
"Performing resolution of %s for target platform %s",
toolchainType,
targetPlatform);
}

@Override
public void reportCompatibleTargetPlatform(Label toolchainLabel) {
debugMessage(
IndentLevel.TOOLCHAIN_LEVEL,
"Toolchain %s is compatible with target platform, searching for execution platforms:",
toolchainLabel);
}

@Override
public void reportSkippedExecutionPlatformSeen(Label executionPlatform) {
debugMessage(
IndentLevel.EXECUTION_PLATFORM_LEVEL,
"Skipping execution platform %s; it has already selected a toolchain",
executionPlatform);
}

@Override
public void reportSkippedExecutionPlatformDisallowed(
Label executionPlatform, Label toolchainType) {
debugMessage(
IndentLevel.EXECUTION_PLATFORM_LEVEL,
"Skipping execution platform %s; its allowed toolchain types does not contain the"
+ " current toolchain type %s",
executionPlatform,
toolchainType);
}

@Override
public void reportCompatibleExecutionPlatform(Label executionPlatform) {
debugMessage(
IndentLevel.EXECUTION_PLATFORM_LEVEL,
"Compatible execution platform %s",
executionPlatform);
}

@Override
public void reportResolvedToolchains(
ImmutableMap<ConfiguredTargetKey, Label> resolvedToolchains,
Label targetPlatform,
Label toolchainType) {
if (resolvedToolchains.isEmpty()) {
debugMessage(
IndentLevel.TARGET_PLATFORM_LEVEL,
"No %s toolchain found for target platform %s.",
toolchainType,
targetPlatform);
} else {
debugMessage(
IndentLevel.TARGET_PLATFORM_LEVEL,
"Recap of selected %s toolchains for target platform %s:",
toolchainType,
targetPlatform);
resolvedToolchains.forEach(
(executionPlatformKey, toolchainLabel) ->
debugMessage(
IndentLevel.TOOLCHAIN_LEVEL,
"Selected %s to run on execution platform %s",
toolchainLabel,
executionPlatformKey.getLabel()));
}
}

@Override
public void reportMismatchedSettings(
ConstraintCollection toolchainConstraints,
boolean isTargetPlatform,
PlatformInfo platform,
Label toolchainLabel,
ImmutableSet<ConstraintSettingInfo> mismatchSettingsWithDefault) {
if (!mismatchSettingsWithDefault.isEmpty()) {
String mismatchValues =
mismatchSettingsWithDefault.stream()
.filter(toolchainConstraints::has)
.map(s -> toolchainConstraints.get(s).label().getName())
.collect(joining(", "));
if (!mismatchValues.isEmpty()) {
mismatchValues = "; mismatching values: " + mismatchValues;
}

String missingSettings =
mismatchSettingsWithDefault.stream()
.filter(s -> !toolchainConstraints.has(s))
.map(s -> s.label().getName())
.collect(joining(", "));
if (!missingSettings.isEmpty()) {
missingSettings = "; missing: " + missingSettings;
}
if (isTargetPlatform) {
debugMessage(
IndentLevel.TOOLCHAIN_LEVEL,
"Rejected toolchain %s%s",
toolchainLabel,
mismatchValues + missingSettings);
} else {
debugMessage(
IndentLevel.EXECUTION_PLATFORM_LEVEL,
"Incompatible execution platform %s%s",
platform.label(),
mismatchValues + missingSettings);
}
}
}

@Override
public void reportDone(Label toolchainType) {
debugMessage(
IndentLevel.TOOLCHAIN_LEVEL,
"All execution platforms have been assigned a %s toolchain, stopping",
toolchainType);
}
}
}
Loading

0 comments on commit b8320e9

Please sign in to comment.