use of com.google.devtools.build.lib.buildtool.BuildResult in project bazel by bazelbuild.
the class RunCommand method exec.
@Override
public ExitCode exec(CommandEnvironment env, OptionsProvider options) {
RunOptions runOptions = options.getOptions(RunOptions.class);
// This list should look like: ["//executable:target", "arg1", "arg2"]
List<String> targetAndArgs = options.getResidue();
// The user must at the least specify an executable target.
if (targetAndArgs.isEmpty()) {
env.getReporter().handle(Event.error("Must specify a target to run"));
return ExitCode.COMMAND_LINE_ERROR;
}
String targetString = targetAndArgs.get(0);
List<String> runTargetArgs = targetAndArgs.subList(1, targetAndArgs.size());
RunUnder runUnder = options.getOptions(BuildConfiguration.Options.class).runUnder;
OutErr outErr = env.getReporter().getOutErr();
List<String> targets = (runUnder != null) && (runUnder.getLabel() != null) ? ImmutableList.of(targetString, runUnder.getLabel().toString()) : ImmutableList.of(targetString);
BuildRequest request = BuildRequest.create(this.getClass().getAnnotation(Command.class).name(), options, env.getRuntime().getStartupOptionsProvider(), targets, outErr, env.getCommandId(), env.getCommandStartTime());
currentRunUnder = runUnder;
BuildResult result;
try {
result = processRequest(env, request);
} finally {
currentRunUnder = null;
}
if (!result.getSuccess()) {
env.getReporter().handle(Event.error("Build failed. Not running target"));
return result.getExitCondition();
}
// Make sure that we have exactly 1 built target (excluding --run_under),
// and that it is executable.
// These checks should only fail if keepGoing is true, because we already did
// validation before the build began. See {@link #validateTargets()}.
Collection<ConfiguredTarget> targetsBuilt = result.getSuccessfulTargets();
ConfiguredTarget targetToRun = null;
ConfiguredTarget runUnderTarget = null;
if (targetsBuilt != null) {
int maxTargets = runUnder != null && runUnder.getLabel() != null ? 2 : 1;
if (targetsBuilt.size() > maxTargets) {
env.getReporter().handle(Event.error(SINGLE_TARGET_MESSAGE));
return ExitCode.COMMAND_LINE_ERROR;
}
for (ConfiguredTarget target : targetsBuilt) {
ExitCode targetValidation = fullyValidateTarget(env, target);
if (!targetValidation.equals(ExitCode.SUCCESS)) {
return targetValidation;
}
if (runUnder != null && target.getLabel().equals(runUnder.getLabel())) {
if (runUnderTarget != null) {
env.getReporter().handle(Event.error(null, "Can't identify the run_under target from multiple options?"));
return ExitCode.COMMAND_LINE_ERROR;
}
runUnderTarget = target;
} else if (targetToRun == null) {
targetToRun = target;
} else {
env.getReporter().handle(Event.error(SINGLE_TARGET_MESSAGE));
return ExitCode.COMMAND_LINE_ERROR;
}
}
}
// Handle target & run_under referring to the same target.
if ((targetToRun == null) && (runUnderTarget != null)) {
targetToRun = runUnderTarget;
}
if (targetToRun == null) {
env.getReporter().handle(Event.error(NO_TARGET_MESSAGE));
return ExitCode.COMMAND_LINE_ERROR;
}
Path executablePath = Preconditions.checkNotNull(targetToRun.getProvider(FilesToRunProvider.class).getExecutable().getPath());
BuildConfiguration configuration = targetToRun.getConfiguration();
if (configuration == null) {
// The target may be an input file, which doesn't have a configuration. In that case, we
// choose any target configuration.
configuration = result.getBuildConfigurationCollection().getTargetConfigurations().get(0);
}
Path workingDir;
try {
workingDir = ensureRunfilesBuilt(env, targetToRun);
} catch (CommandException e) {
env.getReporter().handle(Event.error("Error creating runfiles: " + e.getMessage()));
return ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
}
List<String> args = runTargetArgs;
FilesToRunProvider provider = targetToRun.getProvider(FilesToRunProvider.class);
RunfilesSupport runfilesSupport = provider == null ? null : provider.getRunfilesSupport();
if (runfilesSupport != null && runfilesSupport.getArgs() != null) {
List<String> targetArgs = runfilesSupport.getArgs();
if (!targetArgs.isEmpty()) {
args = Lists.newArrayListWithCapacity(targetArgs.size() + runTargetArgs.size());
args.addAll(targetArgs);
args.addAll(runTargetArgs);
}
}
String productName = env.getRuntime().getProductName();
//
// We now have a unique executable ready to be run.
//
// We build up two different versions of the command to run: one with an absolute path, which
// we'll actually run, and a prettier one with the long absolute path to the executable
// replaced with a shorter relative path that uses the symlinks in the workspace.
PathFragment prettyExecutablePath = OutputDirectoryLinksUtils.getPrettyPath(executablePath, env.getWorkspaceName(), env.getWorkspace(), options.getOptions(BuildRequestOptions.class).getSymlinkPrefix(productName), productName);
List<String> cmdLine = new ArrayList<>();
if (runOptions.scriptPath == null) {
PathFragment processWrapperPath = env.getBlazeWorkspace().getBinTools().getExecPath(PROCESS_WRAPPER);
Preconditions.checkNotNull(processWrapperPath, PROCESS_WRAPPER + " not found in embedded tools");
cmdLine.add(env.getExecRoot().getRelative(processWrapperPath).getPathString());
cmdLine.add("-1");
cmdLine.add("15");
cmdLine.add("-");
cmdLine.add("-");
}
List<String> prettyCmdLine = new ArrayList<>();
// at the start of the command line.
if (runUnder != null) {
String runUnderValue = runUnder.getValue();
if (runUnderTarget != null) {
// --run_under specifies a target. Get the corresponding executable.
// This must be an absolute path, because the run_under target is only
// in the runfiles of test targets.
runUnderValue = runUnderTarget.getProvider(FilesToRunProvider.class).getExecutable().getPath().getPathString();
// If the run_under command contains any options, make sure to add them
// to the command line as well.
List<String> opts = runUnder.getOptions();
if (!opts.isEmpty()) {
runUnderValue += " " + ShellEscaper.escapeJoinAll(opts);
}
}
cmdLine.add(configuration.getShellExecutable().getPathString());
cmdLine.add("-c");
cmdLine.add(runUnderValue + " " + executablePath.getPathString() + " " + ShellEscaper.escapeJoinAll(args));
prettyCmdLine.add(configuration.getShellExecutable().getPathString());
prettyCmdLine.add("-c");
prettyCmdLine.add(runUnderValue + " " + prettyExecutablePath.getPathString() + " " + ShellEscaper.escapeJoinAll(args));
} else {
cmdLine.add(executablePath.getPathString());
cmdLine.addAll(args);
prettyCmdLine.add(prettyExecutablePath.getPathString());
prettyCmdLine.addAll(args);
}
// Add a newline between the blaze output and the binary's output.
outErr.printErrLn("");
if (runOptions.scriptPath != null) {
String unisolatedCommand = CommandFailureUtils.describeCommand(CommandDescriptionForm.COMPLETE_UNISOLATED, cmdLine, null, workingDir.getPathString());
if (writeScript(env, runOptions.scriptPath, unisolatedCommand)) {
return ExitCode.SUCCESS;
} else {
return ExitCode.RUN_FAILURE;
}
}
env.getReporter().handle(Event.info(null, "Running command line: " + ShellEscaper.escapeJoinAll(prettyCmdLine)));
com.google.devtools.build.lib.shell.Command command = new CommandBuilder().addArgs(cmdLine).setEnv(env.getClientEnv()).setWorkingDir(workingDir).build();
try {
// Restore a raw EventHandler if it is registered. This allows for blaze run to produce the
// actual output of the command being run even if --color=no is specified.
env.getReporter().switchToAnsiAllowingHandler();
// The command API is a little strange in that the following statement
// will return normally only if the program exits with exit code 0.
// If it ends with any other code, we have to catch BadExitStatusException.
command.execute(com.google.devtools.build.lib.shell.Command.NO_INPUT, com.google.devtools.build.lib.shell.Command.NO_OBSERVER, outErr.getOutputStream(), outErr.getErrorStream(), true).getTerminationStatus().getExitCode();
return ExitCode.SUCCESS;
} catch (BadExitStatusException e) {
String message = "Non-zero return code '" + e.getResult().getTerminationStatus().getExitCode() + "' from command: " + e.getMessage();
env.getReporter().handle(Event.error(message));
return ExitCode.RUN_FAILURE;
} catch (AbnormalTerminationException e) {
// The process was likely terminated by a signal in this case.
return ExitCode.INTERRUPTED;
} catch (CommandException e) {
env.getReporter().handle(Event.error("Error running program: " + e.getMessage()));
return ExitCode.RUN_FAILURE;
}
}
use of com.google.devtools.build.lib.buildtool.BuildResult in project bazel by bazelbuild.
the class TestCommand method doTest.
private ExitCode doTest(CommandEnvironment env, OptionsProvider options, AggregatingTestListener testListener) {
BlazeRuntime runtime = env.getRuntime();
// Run simultaneous build and test.
List<String> targets = ProjectFileSupport.getTargets(runtime, options);
BuildRequest request = BuildRequest.create(getClass().getAnnotation(Command.class).name(), options, runtime.getStartupOptionsProvider(), targets, env.getReporter().getOutErr(), env.getCommandId(), env.getCommandStartTime());
request.setRunTests();
BuildResult buildResult = new BuildTool(env).processRequest(request, null);
Collection<ConfiguredTarget> testTargets = buildResult.getTestTargets();
// TODO(bazel-team): don't handle isEmpty here or fix up a bunch of tests
if (buildResult.getSuccessfulTargets() == null) {
// This can happen if there were errors in the target parsing or loading phase
// (original exitcode=BUILD_FAILURE) or if there weren't but --noanalyze was given
// (original exitcode=SUCCESS).
env.getReporter().handle(Event.error("Couldn't start the build. Unable to run tests"));
return buildResult.getSuccess() ? ExitCode.PARSING_FAILURE : buildResult.getExitCondition();
}
// more tests
if (testTargets.isEmpty()) {
env.getReporter().handle(Event.error(null, "No test targets were found, yet testing was requested"));
return buildResult.getSuccess() ? ExitCode.NO_TESTS_FOUND : buildResult.getExitCondition();
}
boolean buildSuccess = buildResult.getSuccess();
boolean testSuccess = analyzeTestResults(testTargets, testListener, options);
if (testSuccess && !buildSuccess) {
// If all tests run successfully, test summary should include warning if
// there were build errors not associated with the test targets.
printer.printLn(AnsiTerminalPrinter.Mode.ERROR + "All tests passed but there were other errors during the build.\n" + AnsiTerminalPrinter.Mode.DEFAULT);
}
return buildSuccess ? (testSuccess ? ExitCode.SUCCESS : ExitCode.TESTS_FAILED) : buildResult.getExitCondition();
}
use of com.google.devtools.build.lib.buildtool.BuildResult in project bazel by bazelbuild.
the class BuildEventStreamerTest method testMissingPrerequisits.
@Test
public void testMissingPrerequisits() {
// Verify that an event where the prerequisite is never coming till the end of
// the build still gets posted, with the prerequisite aborted.
RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
BuildEventStreamer streamer = new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport));
BuildEventId expectedId = testId("the target");
BuildEvent startEvent = new GenericBuildEvent(testId("Initial"), ImmutableSet.<BuildEventId>of(ProgressEvent.INITIAL_PROGRESS_UPDATE, expectedId, BuildEventId.buildFinished()));
BuildEventId rootCauseId = testId("failure event");
BuildEvent failedTarget = new GenericOrderEvent(expectedId, ImmutableSet.<BuildEventId>of(rootCauseId));
streamer.buildEvent(startEvent);
streamer.buildEvent(failedTarget);
streamer.buildEvent(new BuildCompleteEvent(new BuildResult(0)));
List<BuildEvent> allEventsSeen = transport.getEvents();
assertThat(allEventsSeen).hasSize(6);
assertEquals(startEvent.getEventId(), allEventsSeen.get(0).getEventId());
assertEquals(BuildEventId.buildFinished(), allEventsSeen.get(1).getEventId());
BuildEvent linkEvent = allEventsSeen.get(2);
assertEquals(ProgressEvent.INITIAL_PROGRESS_UPDATE, linkEvent.getEventId());
assertEquals(rootCauseId, allEventsSeen.get(3).getEventId());
assertEquals(failedTarget.getEventId(), allEventsSeen.get(4).getEventId());
}
use of com.google.devtools.build.lib.buildtool.BuildResult in project bazel by bazelbuild.
the class AggregatingTestListener method buildCompleteEvent.
@Subscribe
public void buildCompleteEvent(BuildCompleteEvent event) {
BuildResult result = event.getResult();
if (result.wasCatastrophe()) {
blazeHalted = true;
}
buildComplete(result.getActualTargets(), result.getSuccessfulTargets());
}
use of com.google.devtools.build.lib.buildtool.BuildResult in project bazel by bazelbuild.
the class BuildEventStreamerTest method testReferPastEvent.
@Test
public void testReferPastEvent() {
// Verify that, if an event is refers to a previously done event, that duplicated
// late-referenced event is not expected again.
RecordingBuildEventTransport transport = new RecordingBuildEventTransport();
BuildEventStreamer streamer = new BuildEventStreamer(ImmutableSet.<BuildEventTransport>of(transport));
BuildEvent startEvent = new GenericBuildEvent(testId("Initial"), ImmutableSet.<BuildEventId>of(ProgressEvent.INITIAL_PROGRESS_UPDATE, BuildEventId.buildFinished()));
BuildEvent earlyEvent = new GenericBuildEvent(testId("unexpected"), ImmutableSet.<BuildEventId>of());
BuildEvent lateReference = new GenericBuildEvent(testId("late reference"), ImmutableSet.of(earlyEvent.getEventId()));
streamer.buildEvent(startEvent);
streamer.buildEvent(earlyEvent);
streamer.buildEvent(lateReference);
streamer.buildEvent(new BuildCompleteEvent(new BuildResult(0)));
List<BuildEvent> eventsSeen = transport.getEvents();
int earlyEventCount = 0;
for (BuildEvent event : eventsSeen) {
if (event.getEventId().equals(earlyEvent.getEventId())) {
earlyEventCount++;
}
}
// The early event should be reported precisely once.
assertEquals(1, earlyEventCount);
}
Aggregations