use of com.google.devtools.build.lib.analysis.FilesToRunProvider 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.analysis.FilesToRunProvider in project bazel by bazelbuild.
the class ReleaseBundlingSupport method registerPostProcessAndSigningActions.
/**
* Registers all actions necessary to create a processed and signed IPA from the initial merged
* IPA.
*
* <p>Includes user-provided actions to process IPA contents (via {@code ipa_post_processor}),
* and signing actions if the IPA is being built for device architectures. If signing is necessary
* also includes entitlements generation and processing actions.
*
* <p>Note that multiple "actions" on the IPA contents may be run in a single blaze action to
* avoid excessive zipping/unzipping of IPA contents.
*/
private void registerPostProcessAndSigningActions() {
Artifact processedIpa = releaseBundling.getIpaArtifact();
Artifact unprocessedIpa = intermediateArtifacts.unprocessedIpa();
NestedSetBuilder<Artifact> inputs = NestedSetBuilder.<Artifact>stableOrder().add(unprocessedIpa);
String actionCommandLine = "set -e && " + "t=$(mktemp -d \"${TMPDIR:-/tmp}/signing_intermediate.XXXXXX\") && " + "trap \"rm -rf ${t}\" EXIT && " + // Get an absolute path since we need to cd into the temp directory for zip.
"signed_ipa=${PWD}/" + processedIpa.getShellEscapedExecPathString() + " && " + "/usr/bin/unzip -qq " + unprocessedIpa.getShellEscapedExecPathString() + " -d ${t} && ";
FilesToRunProvider processor = attributes.ipaPostProcessor();
if (processor != null) {
actionCommandLine += processor.getExecutable().getShellEscapedExecPathString() + " ${t} && ";
}
if (platform.isDevice()) {
actionCommandLine += deviceSigningCommandLine();
registerEntitlementsActions();
inputs.add(releaseBundling.getProvisioningProfile()).add(intermediateArtifacts.entitlements());
} else {
actionCommandLine += simulatorSigningCommandLine();
}
actionCommandLine += "cd ${t} && /usr/bin/zip -q -r \"${signed_ipa}\" .";
AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class);
SpawnAction.Builder processAction = ObjcRuleClasses.spawnBashOnDarwinActionBuilder(actionCommandLine).setEnvironment(ObjcRuleClasses.appleToolchainEnvironment(appleConfiguration, platform)).setMnemonic("ObjcProcessIpa").setProgressMessage("Processing iOS IPA: " + ruleContext.getLabel()).disableSandboxing().addTransitiveInputs(inputs.build()).addOutput(processedIpa);
if (processor != null) {
processAction.addTool(processor);
}
ruleContext.registerAction(processAction.build(ruleContext));
}
use of com.google.devtools.build.lib.analysis.FilesToRunProvider in project bazel by bazelbuild.
the class ProguardHelper method applyProguardIfRequested.
/**
* Creates an action to run Proguard to <i>output</i> the given {@code deployJar} artifact if
* --java_optimization_mode calls for it from an assumed input artifact {@link
* JavaSemantics#JAVA_BINARY_MERGED_JAR}. Returns the artifacts that Proguard will generate or
* {@code null} if Proguard isn't used.
*
* <p>If this method returns artifacts then {@link
* com.google.devtools.build.lib.rules.java.DeployArchiveBuilder} needs to write the assumed input
* artifact (instead of the conventional deploy.jar, which now Proguard writes). Do not use this
* method for binary rules that themselves declare {@link #PROGUARD_SPECS} attributes, which as of
* includes 1/2016 {@code android_binary} and {@code android_test}.
*/
@Nullable
public ProguardOutput applyProguardIfRequested(RuleContext ruleContext, Artifact deployJar, ImmutableList<Artifact> bootclasspath, String mainClassName, JavaSemantics semantics) throws InterruptedException {
JavaOptimizationMode optMode = getJavaOptimizationMode(ruleContext);
if (optMode == JavaOptimizationMode.NOOP || optMode == JavaOptimizationMode.LEGACY) {
// For simplicity do nothing in LEGACY mode
return null;
}
Preconditions.checkArgument(!bootclasspath.isEmpty(), "Bootclasspath should not be empty");
FilesToRunProvider proguard = findProguard(ruleContext);
if (proguard == null) {
ruleContext.ruleError("--proguard_top required for --java_optimization_mode=" + optMode);
return null;
}
ImmutableList<Artifact> proguardSpecs = collectProguardSpecs(ruleContext, bootclasspath, mainClassName);
Artifact singleJar = ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_BINARY_MERGED_JAR);
// TODO(bazel-team): Verify that proguard spec files don't contain -printmapping directions
// which this -printmapping command line flag will override.
Artifact proguardOutputMap = null;
if (genProguardMapping(ruleContext.attributes()) || optMode.alwaysGenerateOutputMapping()) {
proguardOutputMap = ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_BINARY_PROGUARD_MAP);
}
return createProguardAction(ruleContext, proguard, singleJar, proguardSpecs, /* proguardSeeds */
(Artifact) null, /* proguardUsage */
(Artifact) null, /* proguardMapping */
(Artifact) null, bootclasspath, deployJar, semantics, /* optimizationPases */
3, proguardOutputMap, /* useSingleJarForProguardLibraryJars */
false);
}
use of com.google.devtools.build.lib.analysis.FilesToRunProvider in project bazel by bazelbuild.
the class ProguardLibrary method collectProguardSpecs.
/**
* Collects the validated proguard specs exported by this rule and its dependencies through the
* given attributes.
*/
public NestedSet<Artifact> collectProguardSpecs(Multimap<Mode, String> attributes) {
NestedSetBuilder<Artifact> specsBuilder = NestedSetBuilder.naiveLinkOrder();
for (Entry<Mode, String> attribute : attributes.entries()) {
specsBuilder.addTransitive(collectProguardSpecsFromAttribute(attribute.getValue(), attribute.getKey()));
}
Collection<Artifact> localSpecs = collectLocalProguardSpecs();
if (!localSpecs.isEmpty()) {
// Pass our local proguard configs through the validator, which checks a whitelist.
FilesToRunProvider proguardWhitelister = ruleContext.getExecutablePrerequisite("$proguard_whitelister", Mode.HOST);
for (Artifact specToValidate : localSpecs) {
specsBuilder.add(validateProguardSpec(proguardWhitelister, specToValidate));
}
}
return specsBuilder.build();
}
use of com.google.devtools.build.lib.analysis.FilesToRunProvider in project bazel by bazelbuild.
the class PopulateTreeArtifactActionTest method createPopulateTreeArtifactAction.
private PopulateTreeArtifactAction createPopulateTreeArtifactAction() throws Exception {
Artifact archive = getSourceArtifact("myArchive.zip");
Artifact treeArtifactToPopulate = createTreeArtifact("test/archive_member");
Artifact archiveManifest = getSourceArtifact("archiveManifest.txt");
FilesToRunProvider unzip = FilesToRunProvider.fromSingleExecutableArtifact(getSourceArtifact("unzipBinary"));
scratch.file("archiveManifest.txt", "archive_members/1.class", "archive_members/2.class", "archive_members/txt/text.txt");
return new PopulateTreeArtifactAction(ActionsTestUtil.NULL_ACTION_OWNER, archive, archiveManifest, treeArtifactToPopulate, unzip);
}
Aggregations