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; +}