[7.0.0] Add more details to the warning message in --keep_going mode (#20450)
The current message is too generic and not helpful for the user.
```
Before:
WARNING: errors encountered while analyzing target '//:bin': it will not be built
---
After:
WARNING: errors encountered while analyzing target '//:bin', it will not be built.
Target //:bin is incompatible and cannot be built, but was explicitly requested.
Dependency chain:
//:bin (8250b5) <-- target platform (@@local_config_platform//:host) didn't satisfy constraint @@platforms//:incompatible
```
Fixes https://github.com/bazelbuild/bazel/issues/20443
Commit
https://github.com/bazelbuild/bazel/commit/c5493b9557502fe6ec48e78b0b5f06f4c1d75238
PiperOrigin-RevId: 588363260
Change-Id: I70e151cd9baa6a0dd7b307b7ddeb9f43ee30b526
Co-authored-by: Googler <leba@google.com>
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeErrorProcessor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeErrorProcessor.java
index b138996..5c51881 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeErrorProcessor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeErrorProcessor.java
@@ -270,8 +270,9 @@
} else {
assertValidAnalysisException(errorInfo, errorKey, result.getWalkableGraph(), keepEdges);
}
- Exception cause = errorInfo.getException();
- Preconditions.checkState(cause != null || !errorInfo.getCycleInfo().isEmpty(), errorInfo);
+ Exception nullableCause = errorInfo.getException();
+ Preconditions.checkState(
+ nullableCause != null || !errorInfo.getCycleInfo().isEmpty(), errorInfo);
if (inBuildViewTest && !isValidErrorKeyType(errorKey.argument())) {
// This means that we are in a BuildViewTestCase.
@@ -308,15 +309,15 @@
label,
individualErrorProcessingResult);
- boolean isExecutionException = isExecutionException(cause);
+ boolean isExecutionException = isExecutionException(nullableCause);
if (keepGoing) {
aggregatingResultBuilder.aggregateSingleResult(individualErrorProcessingResult);
- logOrPrintWarnings(isExecutionException, label, eventHandler, cause);
+ logOrPrintWarningsKeepGoing(isExecutionException, label, eventHandler, nullableCause);
} else {
noKeepGoingAnalysisExceptionAspect =
throwOrReturnAspectAnalysisException(
result,
- cause,
+ nullableCause,
bugReporter,
errorKey,
isExecutionException,
@@ -391,7 +392,7 @@
*/
private static ViewCreationFailedException throwOrReturnAspectAnalysisException(
EvaluationResult<? extends SkyValue> result,
- Exception cause,
+ @Nullable Exception cause,
BugReporter bugReporter,
SkyKey errorKey,
boolean isExecutionException,
@@ -399,6 +400,8 @@
throws BuildFailedException, TestExecException, ViewCreationFailedException {
// If the error is execution-related: straightaway rethrow. No further steps required.
if (isExecutionException) {
+ // cause is not null for execution exceptions.
+ Preconditions.checkNotNull(cause);
rethrow(cause, bugReporter, result);
}
// If a --nokeep_going build found a cycle, that means there were no other errors thrown
@@ -569,11 +572,11 @@
return createDetailedExecutionExitCode(message, UNKNOWN_EXECUTION);
}
- private static void logOrPrintWarnings(
+ private static void logOrPrintWarningsKeepGoing(
boolean isExecutionException,
@Nullable Label topLevelLabel,
ExtendedEventHandler eventHandler,
- Exception cause) {
+ @Nullable Exception cause) {
// For execution exceptions, we don't print any extra warning.
if (isExecutionException) {
if (isExecutionCauseWorthLogging(cause)) {
@@ -582,11 +585,13 @@
}
return;
}
- eventHandler.handle(
- Event.warn(
- String.format(
- "errors encountered while analyzing target '%s': it will not be built",
- topLevelLabel)));
+ var message =
+ String.format(
+ "errors encountered while analyzing target '%s', it will not be built.", topLevelLabel);
+ if (cause != null) {
+ message += String.format("\n%s", cause.getMessage());
+ }
+ eventHandler.handle(Event.warn(message));
}
private static boolean isExecutionCauseWorthLogging(Throwable cause) {
@@ -777,7 +782,7 @@
return null;
}
- private static boolean isExecutionException(Throwable cause) {
+ private static boolean isExecutionException(@Nullable Throwable cause) {
return cause instanceof ActionExecutionException
|| cause instanceof InputFileErrorException
|| cause instanceof TestExecException
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/BuildViewTest.java b/src/test/java/com/google/devtools/build/lib/analysis/BuildViewTest.java
index 47feb01..e8058f8 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/BuildViewTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/BuildViewTest.java
@@ -1066,9 +1066,9 @@
assertContainsEvent("in cc_library rule //cycle:foo: cycle in dependency graph:");
assertContainsEvent("in cc_library rule //cycle:bas: cycle in dependency graph:");
assertContainsEvent(
- "errors encountered while analyzing target '//cycle:foo': it will not be built");
+ "errors encountered while analyzing target '//cycle:foo', it will not be built");
assertContainsEvent(
- "errors encountered while analyzing target '//cycle:bat': it will not be built");
+ "errors encountered while analyzing target '//cycle:bat', it will not be built");
// With interleaved loading and analysis, we can no longer distinguish loading-phase cycles
// and analysis-phase cycles. This was previously reported as a loading-phase cycle, as it
// happens with any configuration (cycle is hard-coded in the BUILD files). Also see the
diff --git a/src/test/java/com/google/devtools/build/lib/buildtool/SkymeldBuildIntegrationTest.java b/src/test/java/com/google/devtools/build/lib/buildtool/SkymeldBuildIntegrationTest.java
index e8dae66..2aead5d 100644
--- a/src/test/java/com/google/devtools/build/lib/buildtool/SkymeldBuildIntegrationTest.java
+++ b/src/test/java/com/google/devtools/build/lib/buildtool/SkymeldBuildIntegrationTest.java
@@ -302,6 +302,30 @@
events.assertContainsError("rule '//foo:missing' does not exist");
}
+ // Regression test for https://github.com/bazelbuild/bazel/issues/20443
+ @Test
+ public void testKeepGoingWarningContainsDetails() throws Exception {
+ addOptions("--keep_going");
+ write(
+ "foo/BUILD",
+ "constraint_setting(name = 'incompatible_setting')",
+ "constraint_value(",
+ " name = 'incompatible',",
+ " constraint_setting = ':incompatible_setting',",
+ " visibility = ['//visibility:public']",
+ ")",
+ "cc_library(",
+ " name = 'foo',",
+ " srcs = ['foo.cc'],",
+ " target_compatible_with = ['//foo:incompatible']",
+ ")");
+ assertThrows(BuildFailedException.class, () -> buildTarget("//foo:foo"));
+ events.assertContainsWarning(
+ "errors encountered while analyzing target '//foo:foo', it will not be built.");
+ // The details.
+ events.assertContainsWarning("Dependency chain:");
+ }
+
@Test
public void analysisAndExecutionFailure_keepGoing_bothReported() throws Exception {
addOptions("--keep_going");