use of com.google.devtools.build.lib.analysis.BuildView.AnalysisResult in project bazel by bazelbuild.
the class BuildTool method buildTargets.
/**
* The crux of the build system. Builds the targets specified in the request using the specified
* Executor.
*
* <p>Performs loading, analysis and execution for the specified set of targets, honoring the
* configuration options in the BuildRequest. Returns normally iff successful, throws an exception
* otherwise.
*
* <p>Callers must ensure that {@link #stopRequest} is called after this method, even if it
* throws.
*
* <p>The caller is responsible for setting up and syncing the package cache.
*
* <p>During this function's execution, the actualTargets and successfulTargets
* fields of the request object are set.
*
* @param request the build request that this build tool is servicing, which specifies various
* options; during this method's execution, the actualTargets and successfulTargets fields
* of the request object are populated
* @param result the build result that is the mutable result of this build
* @param validator target validator
*/
public void buildTargets(BuildRequest request, BuildResult result, TargetValidator validator) throws BuildFailedException, InterruptedException, ViewCreationFailedException, TargetParsingException, LoadingFailedException, AbruptExitException, InvalidConfigurationException, TestExecException {
validateOptions(request);
BuildOptions buildOptions = runtime.createBuildOptions(request);
// Sync the package manager before sending the BuildStartingEvent in runLoadingPhase()
env.setupPackageCache(request, DefaultsPackage.getDefaultsPackageContent(buildOptions));
ExecutionTool executionTool = null;
boolean catastrophe = false;
try {
env.getEventBus().post(new BuildStartingEvent(env, request));
LOG.info("Build identifier: " + request.getId());
executionTool = new ExecutionTool(env, request);
if (needsExecutionPhase(request.getBuildOptions())) {
// Initialize the execution tool early if we need it. This hides the latency of setting up
// the execution backends.
executionTool.init();
}
// Error out early if multi_cpus is set, but we're not in build or test command.
if (!request.getMultiCpus().isEmpty()) {
getReporter().handle(Event.warn("The --experimental_multi_cpu option is _very_ experimental and only intended for " + "internal testing at this time. If you do not work on the build tool, then you " + "should stop now!"));
if (!"build".equals(request.getCommandName()) && !"test".equals(request.getCommandName())) {
throw new InvalidConfigurationException("The experimental setting to select multiple CPUs is only supported for 'build' and " + "'test' right now!");
}
}
// Exit if there are any pending exceptions from modules.
env.throwPendingException();
// Target pattern evaluation.
LoadingResult loadingResult = evaluateTargetPatterns(request, validator);
// Exit if there are any pending exceptions from modules.
env.throwPendingException();
// Configuration creation.
BuildConfigurationCollection configurations = env.getSkyframeExecutor().createConfigurations(env.getReporter(), runtime.getConfigurationFactory(), buildOptions, request.getMultiCpus(), request.getViewOptions().keepGoing);
env.throwPendingException();
if (configurations.getTargetConfigurations().size() == 1) {
// TODO(bazel-team): This is not optimal - we retain backwards compatibility in the case
// where there's only a single configuration, but we don't send an event in the multi-config
// case. Can we do better? [multi-config]
env.getEventBus().post(new MakeEnvironmentEvent(configurations.getTargetConfigurations().get(0).getMakeEnvironment()));
}
LOG.info("Configurations created");
if (request.getBuildOptions().performAnalysisPhase) {
AnalysisResult analysisResult = runAnalysisPhase(request, loadingResult, configurations);
result.setBuildConfigurationCollection(configurations);
result.setActualTargets(analysisResult.getTargetsToBuild());
result.setTestTargets(analysisResult.getTargetsToTest());
LoadedPackageProvider bridge = new LoadedPackageProvider(env.getPackageManager(), env.getReporter());
checkTargetEnvironmentRestrictions(analysisResult.getTargetsToBuild(), bridge);
reportTargets(analysisResult);
// Execution phase.
if (needsExecutionPhase(request.getBuildOptions())) {
executionTool.executeBuild(request.getId(), analysisResult, result, configurations, analysisResult.getPackageRoots(), request.getTopLevelArtifactContext());
}
String delayedErrorMsg = analysisResult.getError();
if (delayedErrorMsg != null) {
throw new BuildFailedException(delayedErrorMsg);
}
} else {
getReporter().handle(Event.progress("Loading complete."));
LOG.info("No analysis requested, so finished");
String errorMessage = BuildView.createErrorMessage(loadingResult, null);
if (errorMessage != null) {
throw new BuildFailedException(errorMessage);
}
// Return.
}
} catch (RuntimeException e) {
// Print an error message for unchecked runtime exceptions. This does not concern Error
// subclasses such as OutOfMemoryError.
request.getOutErr().printErrLn("Unhandled exception thrown during build; message: " + e.getMessage());
catastrophe = true;
throw e;
} catch (Error e) {
catastrophe = true;
throw e;
} catch (InvalidConfigurationException e) {
// TODO(gregce): With "global configurations" we cannot tie a configuration creation failure
// to a single target and have to halt the entire build. Once configurations are genuinely
// created as part of the analysis phase they should report their error on the level of the
// target(s) that triggered them.
catastrophe = true;
throw e;
} finally {
if (!catastrophe) {
// Delete dirty nodes to ensure that they do not accumulate indefinitely.
long versionWindow = request.getViewOptions().versionWindowForDirtyNodeGc;
if (versionWindow != -1) {
env.getSkyframeExecutor().deleteOldNodes(versionWindow);
}
if (executionTool != null) {
executionTool.shutdown();
}
// The workspace status actions will not run with certain flags, or if an error
// occurs early in the build. Tell a lie so that the event is not missing.
// If multiple build_info events are sent, only the first is kept, so this does not harm
// successful runs (which use the workspace status action).
env.getEventBus().post(new BuildInfoEvent(env.getBlazeWorkspace().getWorkspaceStatusActionFactory().createDummyWorkspaceStatus()));
}
}
}
use of com.google.devtools.build.lib.analysis.BuildView.AnalysisResult in project bazel by bazelbuild.
the class SkylarkAspectsTest method testMultipleExecutablesInTarget.
@Test
public void testMultipleExecutablesInTarget() throws Exception {
scratch.file("foo/extension.bzl", "def _aspect_impl(target, ctx):", " return struct()", "my_aspect = aspect(_aspect_impl)", "def _main_rule_impl(ctx):", " pass", "my_rule = rule(_main_rule_impl,", " attrs = { ", " 'exe1' : attr.label(executable = True, allow_files = True, cfg = 'host'),", " 'exe2' : attr.label(executable = True, allow_files = True, cfg = 'host'),", " },", ")");
scratch.file("foo/tool.sh", "#!/bin/bash");
scratch.file("foo/BUILD", "load('extension', 'my_rule')", "my_rule(name = 'main', exe1 = ':tool.sh', exe2 = ':tool.sh')");
AnalysisResult analysisResultOfRule = update(ImmutableList.<String>of(), "//foo:main");
assertThat(analysisResultOfRule.hasError()).isFalse();
AnalysisResult analysisResultOfAspect = update(ImmutableList.<String>of("/foo/extension.bzl%my_aspect"), "//foo:main");
assertThat(analysisResultOfAspect.hasError()).isFalse();
}
use of com.google.devtools.build.lib.analysis.BuildView.AnalysisResult in project bazel by bazelbuild.
the class SkylarkAspectsTest method aspectParametersOptionalOverride.
@Test
public void aspectParametersOptionalOverride() throws Exception {
scratch.file("test/aspect.bzl", "def _impl(target, ctx):", " if (ctx.attr.my_attr == 'a'):", " fail('Rule is not overriding default, still has value ' + ctx.attr.my_attr)", " return struct()", "def _rule_impl(ctx):", " return struct()", "MyAspectOptOverride = aspect(", " implementation=_impl,", " attrs = { 'my_attr' : attr.string(values=['a', 'b'], default='a') },", ")", "my_rule = rule(", " implementation=_rule_impl,", " attrs = { 'deps' : attr.label_list(aspects=[MyAspectOptOverride]),", " 'my_attr' : attr.string() },", ")");
scratch.file("test/BUILD", "load('//test:aspect.bzl', 'my_rule')", "my_rule(name = 'xxx', my_attr = 'b')");
AnalysisResult result = update(ImmutableList.<String>of(), "//test:xxx");
assertThat(result.hasError()).isFalse();
}
use of com.google.devtools.build.lib.analysis.BuildView.AnalysisResult in project bazel by bazelbuild.
the class SkylarkAspectsTest method aspectFailingReturnsNotAStruct.
@Test
public void aspectFailingReturnsNotAStruct() throws Exception {
scratch.file("test/aspect.bzl", "def _impl(target, ctx):", " return 0", "", "MyAspect = aspect(implementation=_impl)");
scratch.file("test/BUILD", "java_library(name = 'xxx',)");
reporter.removeHandler(failFastHandler);
try {
AnalysisResult result = update(ImmutableList.of("test/aspect.bzl%MyAspect"), "//test:xxx");
assertThat(keepGoing()).isTrue();
assertThat(result.hasError()).isTrue();
} catch (ViewCreationFailedException e) {
// expect to fail.
}
assertContainsEvent("Aspect implementation should return a struct or a list, but got int");
}
use of com.google.devtools.build.lib.analysis.BuildView.AnalysisResult in project bazel by bazelbuild.
the class SkylarkAspectsTest method labelKeyedStringDictAllowsAspects.
@Test
public void labelKeyedStringDictAllowsAspects() throws Exception {
scratch.file("test/aspect.bzl", "def _aspect_impl(target, ctx):", " return struct(aspect_data=target.label.name)", "", "def _rule_impl(ctx):", " return struct(", " data=','.join(['{}:{}'.format(dep.aspect_data, val)", " for dep, val in ctx.attr.attr.items()]))", "", "MyAspect = aspect(", " implementation=_aspect_impl,", ")", "my_rule = rule(", " implementation=_rule_impl,", " attrs = { 'attr' : ", " attr.label_keyed_string_dict(aspects = [MyAspect]) },", ")");
scratch.file("test/BUILD", "load('/test/aspect', 'my_rule')", "java_library(", " name = 'yyy',", ")", "my_rule(", " name = 'xxx',", " attr = {':yyy': 'zzz'},", ")");
AnalysisResult analysisResult = update("//test:xxx");
ConfiguredTarget target = analysisResult.getTargetsToBuild().iterator().next();
SkylarkProviders skylarkProviders = target.getProvider(SkylarkProviders.class);
Object value = skylarkProviders.getValue("data");
assertThat(value).isEqualTo("yyy:zzz");
}
Aggregations