Encode additional environmental execution failures with FailureDetails
Ninja, dynamic execution, include scanning.
RELNOTES: None.
PiperOrigin-RevId: 315825179
diff --git a/src/main/java/com/google/devtools/build/lib/actions/EnvironmentalExecException.java b/src/main/java/com/google/devtools/build/lib/actions/EnvironmentalExecException.java
index 55a60d1..82a64ed 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/EnvironmentalExecException.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/EnvironmentalExecException.java
@@ -56,9 +56,9 @@
failureDetail = null;
}
- public EnvironmentalExecException(String message) {
- super(message);
- failureDetail = null;
+ public EnvironmentalExecException(FailureDetail failureDetail) {
+ super(failureDetail.getMessage());
+ this.failureDetail = failureDetail;
}
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/BUILD b/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/BUILD
index e9fa09a..a368f0c 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/BUILD
@@ -44,6 +44,7 @@
"//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
"//src/main/java/com/google/devtools/build/skyframe",
"//src/main/java/com/google/devtools/build/skyframe:skyframe-objects",
+ "//src/main/protobuf:failure_details_java_proto",
"//third_party:guava",
"//third_party:jsr305",
],
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaAction.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaAction.java
index 453bfbc..06a8fd2 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaAction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaAction.java
@@ -38,6 +38,9 @@
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.packages.StarlarkSemanticsOptions;
import com.google.devtools.build.lib.rules.cpp.CppIncludeExtractionContext;
+import com.google.devtools.build.lib.server.FailureDetails;
+import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
+import com.google.devtools.build.lib.server.FailureDetails.NinjaAction.Code;
import com.google.devtools.build.lib.skyframe.TrackSourceDirectoriesFlag;
import com.google.devtools.build.lib.util.DependencySet;
import com.google.devtools.build.lib.vfs.Path;
@@ -187,10 +190,12 @@
if (inputArtifact == null) {
throw new EnvironmentalExecException(
- String.format(
- "depfile-declared dependency '%s' is invalid: it must either be "
- + "a source input, or a pre-declared generated input",
- execRelativePath));
+ createFailureDetail(
+ String.format(
+ "depfile-declared dependency '%s' is invalid: it must either be "
+ + "a source input, or a pre-declared generated input",
+ execRelativePath),
+ Code.INVALID_DEPFILE_DECLARED_DEPENDENCY));
}
inputsBuilder.add(inputArtifact);
@@ -198,7 +203,9 @@
updateInputs(inputsBuilder.build());
} catch (IOException e) {
// Some kind of IO or parse exception--wrap & rethrow it to stop the build.
- throw new EnvironmentalExecException("error while parsing .d file: " + e.getMessage(), e);
+ String message = "error while parsing .d file: " + e.getMessage();
+ throw new EnvironmentalExecException(
+ e, createFailureDetail(message, Code.D_FILE_PARSE_FAILURE));
}
}
@@ -222,4 +229,11 @@
updateInputs(inputs);
return inputs;
}
+
+ private static FailureDetail createFailureDetail(String message, Code detailedCode) {
+ return FailureDetail.newBuilder()
+ .setMessage(message)
+ .setNinjaAction(FailureDetails.NinjaAction.newBuilder().setCode(detailedCode))
+ .build();
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/dynamic/LegacyDynamicSpawnStrategy.java b/src/main/java/com/google/devtools/build/lib/dynamic/LegacyDynamicSpawnStrategy.java
index 550755a..6f919ac 100644
--- a/src/main/java/com/google/devtools/build/lib/dynamic/LegacyDynamicSpawnStrategy.java
+++ b/src/main/java/com/google/devtools/build/lib/dynamic/LegacyDynamicSpawnStrategy.java
@@ -35,6 +35,9 @@
import com.google.devtools.build.lib.actions.UserExecException;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.exec.ExecutionPolicy;
+import com.google.devtools.build.lib.server.FailureDetails.DynamicExecution;
+import com.google.devtools.build.lib.server.FailureDetails.DynamicExecution.Code;
+import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.util.io.FileOutErr;
import com.google.devtools.build.lib.vfs.Path;
import java.io.IOException;
@@ -142,7 +145,7 @@
&& !options.availabilityInfoExempt.contains(spawn.getMnemonic())) {
if (spawn.getExecutionInfo().containsKey(ExecutionRequirements.REQUIRES_DARWIN)
&& !spawn.getExecutionInfo().containsKey(ExecutionRequirements.REQUIREMENTS_SET)) {
- throw new EnvironmentalExecException(
+ String message =
String.format(
"The following spawn was missing Xcode-related execution requirements. Please"
+ " let the Bazel team know if you encounter this issue. You can work around"
@@ -156,7 +159,9 @@
spawn.getMnemonic(),
spawn.getToolFiles(),
spawn.getExecutionPlatform(),
- spawn.getExecutionInfo()));
+ spawn.getExecutionInfo());
+ throw new EnvironmentalExecException(
+ createFailureDetail(message, Code.XCODE_RELATED_PREREQ_UNMET));
}
}
ExecutionPolicy executionPolicy = getExecutionPolicy.apply(spawn);
@@ -403,6 +408,13 @@
"executorCreated not yet called or no default dynamic_remote_strategy set");
}
+ private static FailureDetail createFailureDetail(String message, Code detailedCode) {
+ return FailureDetail.newBuilder()
+ .setMessage(message)
+ .setDynamicExecution(DynamicExecution.newBuilder().setCode(detailedCode))
+ .build();
+ }
+
private abstract static class DynamicExecutionCallable
implements Callable<DynamicExecutionResult> {
private final Phaser taskFinished;
diff --git a/src/main/java/com/google/devtools/build/lib/includescanning/IncludeHintsFunction.java b/src/main/java/com/google/devtools/build/lib/includescanning/IncludeHintsFunction.java
index 076bf91..63bcfdd 100644
--- a/src/main/java/com/google/devtools/build/lib/includescanning/IncludeHintsFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/includescanning/IncludeHintsFunction.java
@@ -18,6 +18,9 @@
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.includescanning.IncludeParser.Hints;
import com.google.devtools.build.lib.packages.BuildFileNotFoundException;
+import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
+import com.google.devtools.build.lib.server.FailureDetails.IncludeScanning;
+import com.google.devtools.build.lib.server.FailureDetails.IncludeScanning.Code;
import com.google.devtools.build.lib.skyframe.ContainingPackageLookupValue;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -61,14 +64,14 @@
}
if (!hintsLookupValue.hasContainingPackage()) {
String reasonForNoContainingPackage = hintsLookupValue.getReasonForNoContainingPackage();
+ String message =
+ String.format(
+ "INCLUDE_HINTS file %s was not in a package%s",
+ hintsFile,
+ reasonForNoContainingPackage != null ? ": " + reasonForNoContainingPackage : "");
throw new IncludeHintsFunctionException(
new EnvironmentalExecException(
- "INCLUDE_HINTS file "
- + hintsFile
- + " was not in a package"
- + (reasonForNoContainingPackage != null
- ? ": " + reasonForNoContainingPackage
- : "")));
+ createFailureDetail(message, Code.INCLUDE_HINTS_FILE_NOT_IN_PACKAGE)));
}
hintsPackageRoot = hintsLookupValue.getContainingPackageRoot();
env.getValueOrThrow(FileValue.key(RootedPath.toRootedPath(hintsPackageRoot, hintsFile)),
@@ -94,6 +97,13 @@
return null;
}
+ private static FailureDetail createFailureDetail(String message, Code detailedCode) {
+ return FailureDetail.newBuilder()
+ .setMessage(message)
+ .setIncludeScanning(IncludeScanning.newBuilder().setCode(detailedCode))
+ .build();
+ }
+
/**
* Used to declare the exception type that can be wrapped in the exception thrown by
* {@link IncludeHintsFunction#compute}.
diff --git a/src/main/protobuf/failure_details.proto b/src/main/protobuf/failure_details.proto
index afac067..69f1477 100644
--- a/src/main/protobuf/failure_details.proto
+++ b/src/main/protobuf/failure_details.proto
@@ -133,6 +133,8 @@
ActionRewinding action_rewinding = 160;
CppCompile cpp_compile = 161;
StarlarkAction starlark_action = 162;
+ NinjaAction ninja_action = 163;
+ DynamicExecution dynamic_execution = 164;
}
reserved 102; // For internal use
@@ -603,6 +605,7 @@
INCLUDE_SCANNING_UNKNOWN = 0 [(metadata) = { exit_code: 37 }];
INITIALIZE_INCLUDE_HINTS_ERROR = 1 [(metadata) = { exit_code: 36 }];
SCANNING_IO_EXCEPTION = 2 [(metadata) = { exit_code: 36 }];
+ INCLUDE_HINTS_FILE_NOT_IN_PACKAGE = 3 [(metadata) = { exit_code: 36 }];
}
Code code = 1;
@@ -838,3 +841,22 @@
Code code = 1;
}
+
+message NinjaAction {
+ enum Code {
+ NINJA_ACTION_UNKNOWN = 0 [(metadata) = { exit_code: 37 }];
+ INVALID_DEPFILE_DECLARED_DEPENDENCY = 1 [(metadata) = { exit_code: 36 }];
+ D_FILE_PARSE_FAILURE = 2 [(metadata) = { exit_code: 36 }];
+ }
+
+ Code code = 1;
+}
+
+message DynamicExecution {
+ enum Code {
+ DYNAMIC_EXECUTION_UNKNOWN = 0 [(metadata) = { exit_code: 37 }];
+ XCODE_RELATED_PREREQ_UNMET = 1 [(metadata) = { exit_code: 36 }];
+ }
+
+ Code code = 1;
+}