use of com.google.devtools.build.lib.actions.ActionExecutionException in project bazel by bazelbuild.
the class SkyframeBuilder method processResult.
/**
* Process the Skyframe update, taking into account the keepGoing setting.
*
* <p>Returns optional {@link ExitCode} based on following conditions: 1. null, if result had no
* errors. 2. Optional.absent(), if result had errors but none of the errors specified an exit
* code. 3. Optional.of(e), if result had errors and one of them specified exit code 'e'. Throws
* on fail-fast failures.
*/
@Nullable
private static Optional<ExitCode> processResult(ExtendedEventHandler eventHandler, EvaluationResult<?> result, boolean keepGoing, SkyframeExecutor skyframeExecutor) throws BuildFailedException, TestExecException {
if (result.hasError()) {
for (Map.Entry<SkyKey, ErrorInfo> entry : result.errorMap().entrySet()) {
Iterable<CycleInfo> cycles = entry.getValue().getCycleInfo();
skyframeExecutor.reportCycles(eventHandler, cycles, entry.getKey());
}
if (result.getCatastrophe() != null) {
rethrow(result.getCatastrophe());
}
if (keepGoing) {
// If build fails and keepGoing is true, an exit code is assigned using reported errors
// in the following order:
// 1. First infrastructure error with non-null exit code
// 2. First non-infrastructure error with non-null exit code
// 3. Null (later default to 1)
ExitCode exitCode = null;
for (Map.Entry<SkyKey, ErrorInfo> error : result.errorMap().entrySet()) {
Throwable cause = error.getValue().getException();
if (cause instanceof ActionExecutionException) {
ActionExecutionException actionExecutionCause = (ActionExecutionException) cause;
ExitCode code = actionExecutionCause.getExitCode();
// a lower 'reporting' priority.
if (ExitCodeComparator.INSTANCE.compare(code, exitCode) > 0) {
exitCode = code;
}
}
}
return Optional.fromNullable(exitCode);
}
ErrorInfo errorInfo = Preconditions.checkNotNull(result.getError(), result);
Exception exception = errorInfo.getException();
if (exception == null) {
Preconditions.checkState(!Iterables.isEmpty(errorInfo.getCycleInfo()), errorInfo);
// cycles above.
throw new BuildFailedException(null, /*hasCatastrophe=*/
false);
} else {
rethrow(exception);
}
}
return null;
}
use of com.google.devtools.build.lib.actions.ActionExecutionException in project bazel by bazelbuild.
the class CppLinkAction method executeFake.
// Don't forget to update FAKE_LINK_GUID if you modify this method.
@ThreadCompatible
private void executeFake() throws ActionExecutionException {
// The uses of getLinkConfiguration in this method may not be consistent with the computed key.
// I.e., this may be incrementally incorrect.
final Collection<Artifact> linkstampOutputs = getLinkCommandLine().getLinkstamps().values();
// Prefix all fake output files in the command line with $TEST_TMPDIR/.
final String outputPrefix = "$TEST_TMPDIR/";
List<String> escapedLinkArgv = escapeLinkArgv(linkCommandLine.getRawLinkArgv(), linkstampOutputs, outputPrefix);
// Write the commands needed to build the real target to the fake target
// file.
StringBuilder s = new StringBuilder();
Joiner.on('\n').appendTo(s, "# This is a fake target file, automatically generated.", "# Do not edit by hand!", "echo $0 is a fake target file and not meant to be executed.", "exit 0", "EOS", "", "makefile_dir=.", "");
try {
// Concatenate all the (fake) .o files into the result.
for (LinkerInput linkerInput : getLinkCommandLine().getLinkerInputs()) {
Artifact objectFile = linkerInput.getArtifact();
if ((CppFileTypes.OBJECT_FILE.matches(objectFile.getFilename()) || CppFileTypes.PIC_OBJECT_FILE.matches(objectFile.getFilename())) && linkerInput.isFake()) {
// (IOException)
s.append(FileSystemUtils.readContentAsLatin1(objectFile.getPath()));
}
}
s.append(getOutputFile().getBaseName()).append(": ");
for (Artifact linkstamp : linkstampOutputs) {
s.append("mkdir -p " + outputPrefix + linkstamp.getExecPath().getParentDirectory() + " && ");
}
Joiner.on(' ').appendTo(s, ShellEscaper.escapeAll(linkCommandLine.finalizeAlreadyEscapedWithLinkstampCommands(escapedLinkArgv, outputPrefix)));
s.append('\n');
if (getOutputFile().exists()) {
// (IOException)
getOutputFile().setWritable(true);
}
FileSystemUtils.writeContent(getOutputFile(), ISO_8859_1, s.toString());
// (IOException)
getOutputFile().setExecutable(true);
for (Artifact linkstamp : linkstampOutputs) {
FileSystemUtils.touchFile(linkstamp.getPath());
}
} catch (IOException e) {
throw new ActionExecutionException("failed to create fake link command for rule '" + getOwner().getLabel() + ": " + e.getMessage(), this, false);
}
}
use of com.google.devtools.build.lib.actions.ActionExecutionException in project bazel by bazelbuild.
the class CppCompileAction method processDepset.
public DependencySet processDepset(Path execRoot, Reply reply) throws ActionExecutionException {
try {
DotdFile dotdFile = getDotdFile();
Preconditions.checkNotNull(dotdFile);
DependencySet depSet = new DependencySet(execRoot);
// Perhaps we produced the file locally.
if (dotdFile.artifact() != null || reply == null) {
return depSet.read(dotdFile.getPath());
} else {
// This is an in-memory .d file.
return depSet.process(reply.getContents());
}
} catch (IOException e) {
// Some kind of IO or parse exception--wrap & rethrow it to stop the build.
throw new ActionExecutionException("error while parsing .d file", e, this, false);
}
}
use of com.google.devtools.build.lib.actions.ActionExecutionException in project bazel by bazelbuild.
the class FakeCppCompileAction method execute.
@Override
@ThreadCompatible
public void execute(ActionExecutionContext actionExecutionContext) throws ActionExecutionException, InterruptedException {
setModuleFileFlags();
Executor executor = actionExecutionContext.getExecutor();
// First, do a normal compilation, to generate the ".d" file. The generated object file is built
// to a temporary location (tempOutputFile) and ignored afterwards.
LOG.info("Generating " + getDotdFile());
CppCompileActionContext context = executor.getContext(actionContext);
CppCompileActionContext.Reply reply = null;
try {
// We delegate stdout/stderr to nowhere, i.e. same as redirecting to /dev/null.
reply = context.execWithReply(this, actionExecutionContext.withFileOutErr(new FileOutErr()));
} catch (ExecException e) {
// We ignore failures here (other than capturing the Distributor reply).
// The compilation may well fail (that's the whole point of negative compilation tests).
// We execute it here just for the side effect of generating the ".d" file.
reply = context.getReplyFromException(e, this);
if (reply == null) {
// This can only happen if the ExecException does not come from remote execution.
throw e.toActionExecutionException("Fake C++ Compilation of rule '" + getOwner().getLabel() + "'", executor.getVerboseFailures(), this);
}
}
IncludeScanningContext scanningContext = executor.getContext(IncludeScanningContext.class);
Path execRoot = executor.getExecRoot();
NestedSet<Artifact> discoveredInputs;
if (getDotdFile() == null) {
discoveredInputs = NestedSetBuilder.<Artifact>stableOrder().build();
} else {
HeaderDiscovery.Builder discoveryBuilder = new HeaderDiscovery.Builder().setAction(this).setDotdFile(getDotdFile()).setSourceFile(getSourceFile()).setSpecialInputsHandler(specialInputsHandler).setDependencySet(processDepset(execRoot, reply)).setPermittedSystemIncludePrefixes(getPermittedSystemIncludePrefixes(execRoot)).setAllowedDerivedinputsMap(getAllowedDerivedInputsMap());
if (cppSemantics.needsIncludeValidation()) {
discoveryBuilder.shouldValidateInclusions();
}
discoveredInputs = discoveryBuilder.build().discoverInputsFromDotdFiles(execRoot, scanningContext.getArtifactResolver());
}
// Clear in-memory .d files early.
reply = null;
// depends on.
try {
validateInclusions(discoveredInputs, actionExecutionContext.getArtifactExpander(), executor.getEventHandler());
} catch (ActionExecutionException e) {
// TODO(bazel-team): (2009) make this into an error, once most of the current warnings
// are fixed.
executor.getEventHandler().handle(Event.warn(getOwner().getLocation(), e.getMessage() + ";\n this warning may eventually become an error"));
}
updateActionInputs(discoveredInputs);
// Generate a fake ".o" file containing the command line needed to generate
// the real object file.
LOG.info("Generating " + outputFile);
// A cc_fake_binary rule generates fake .o files and a fake target file,
// which merely contain instructions on building the real target. We need to
// be careful to use a new set of output file names in the instructions, as
// to not overwrite the fake output files when someone tries to follow the
// instructions. As the real compilation is executed by the test from its
// runfiles directory (where writing is forbidden), we patch the command
// line to write to $TEST_TMPDIR instead.
final String outputPrefix = "$TEST_TMPDIR/";
String argv = Joiner.on(' ').join(Iterables.transform(getArgv(outputFile.getExecPath()), new Function<String, String>() {
@Override
public String apply(String input) {
String result = ShellEscaper.escapeString(input);
// -c <tempOutputFile>, but here it has to be outputFile, so we replace it.
if (input.equals(tempOutputFile.getPathString())) {
result = outputPrefix + ShellEscaper.escapeString(outputFile.getExecPathString());
}
if (input.equals(outputFile.getExecPathString()) || input.equals(getDotdFile().getSafeExecPath().getPathString())) {
result = outputPrefix + ShellEscaper.escapeString(input);
}
return result;
}
}));
// the compilation would fail.
try {
// Ensure that the .d file and .o file are siblings, so that the "mkdir" below works for
// both.
Preconditions.checkState(outputFile.getExecPath().getParentDirectory().equals(getDotdFile().getSafeExecPath().getParentDirectory()));
FileSystemUtils.writeContent(outputFile.getPath(), ISO_8859_1, outputFile.getPath().getBaseName() + ": " + "mkdir -p " + outputPrefix + "$(dirname " + outputFile.getExecPath() + ")" + " && " + argv + "\n");
} catch (IOException e) {
throw new ActionExecutionException("failed to create fake compile command for rule '" + getOwner().getLabel() + ": " + e.getMessage(), this, false);
}
}
use of com.google.devtools.build.lib.actions.ActionExecutionException in project bazel by bazelbuild.
the class TreeArtifactBuildTest method testDigestInjection.
// This is more a smoke test than anything, because it turns out that:
// 1) there is no easy way to turn fast digests on/off for these test cases, and
// 2) injectDigest() doesn't really complain if you inject bad digests or digests
// for nonexistent files. Instead some weird error shows up down the line.
// In fact, there are no tests for injectDigest anywhere in the codebase.
// So all we're really testing here is that injectDigest() doesn't throw a weird exception.
// TODO(bazel-team): write real tests for injectDigest, here and elsewhere.
@Test
public void testDigestInjection() throws Exception {
TreeArtifactTestAction action = new TreeArtifactTestAction(outOne) {
@Override
public void execute(ActionExecutionContext actionExecutionContext) throws ActionExecutionException {
try {
writeFile(outOneFileOne, "one");
writeFile(outOneFileTwo, "two");
MetadataHandler md = actionExecutionContext.getMetadataHandler();
FileStatus stat = outOneFileOne.getPath().stat(Symlinks.NOFOLLOW);
md.injectDigest(outOneFileOne, new InjectedStat(stat.getLastModifiedTime(), stat.getSize(), stat.getNodeId()), Hashing.md5().hashString("one", Charset.forName("UTF-8")).asBytes());
stat = outOneFileTwo.getPath().stat(Symlinks.NOFOLLOW);
md.injectDigest(outOneFileTwo, new InjectedStat(stat.getLastModifiedTime(), stat.getSize(), stat.getNodeId()), Hashing.md5().hashString("two", Charset.forName("UTF-8")).asBytes());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
registerAction(action);
buildArtifact(action.getSoleOutput());
}
Aggregations