use of com.google.devtools.build.skyframe.ErrorInfo in project bazel by bazelbuild.
the class SkyframeBuildView method configureTargets.
/**
* Analyzes the specified targets using Skyframe as the driving framework.
*
* @return the configured targets that should be built along with a WalkableGraph of the analysis.
*/
public SkyframeAnalysisResult configureTargets(ExtendedEventHandler eventHandler, List<ConfiguredTargetKey> values, List<AspectValueKey> aspectKeys, EventBus eventBus, boolean keepGoing, int numThreads) throws InterruptedException, ViewCreationFailedException {
enableAnalysis(true);
EvaluationResult<ActionLookupValue> result;
try {
result = skyframeExecutor.configureTargets(eventHandler, values, aspectKeys, keepGoing, numThreads);
} finally {
enableAnalysis(false);
}
ImmutableMap<ActionAnalysisMetadata, ConflictException> badActions = skyframeExecutor.findArtifactConflicts();
Collection<AspectValue> goodAspects = Lists.newArrayListWithCapacity(values.size());
NestedSetBuilder<Package> packages = NestedSetBuilder.stableOrder();
for (AspectValueKey aspectKey : aspectKeys) {
AspectValue value = (AspectValue) result.get(aspectKey.getSkyKey());
if (value == null) {
// Skip aspects that couldn't be applied to targets.
continue;
}
goodAspects.add(value);
packages.addTransitive(value.getTransitivePackages());
}
// Filter out all CTs that have a bad action and convert to a list of configured targets. This
// code ensures that the resulting list of configured targets has the same order as the incoming
// list of values, i.e., that the order is deterministic.
Collection<ConfiguredTarget> goodCts = Lists.newArrayListWithCapacity(values.size());
for (ConfiguredTargetKey value : values) {
ConfiguredTargetValue ctValue = (ConfiguredTargetValue) result.get(ConfiguredTargetValue.key(value));
if (ctValue == null) {
continue;
}
goodCts.add(ctValue.getConfiguredTarget());
packages.addTransitive(ctValue.getTransitivePackages());
}
ImmutableMap<PackageIdentifier, Path> packageRoots = LoadingPhaseRunner.collectPackageRoots(packages.build().toCollection());
if (!result.hasError() && badActions.isEmpty()) {
return new SkyframeAnalysisResult(/*hasLoadingError=*/
false, /*hasAnalysisError=*/
false, ImmutableList.copyOf(goodCts), result.getWalkableGraph(), ImmutableList.copyOf(goodAspects), packageRoots);
}
// for keeping this code in parity with legacy we just report the first error for now.
if (!keepGoing) {
for (Map.Entry<ActionAnalysisMetadata, ConflictException> bad : badActions.entrySet()) {
ConflictException ex = bad.getValue();
try {
ex.rethrowTyped();
} catch (MutableActionGraph.ActionConflictException ace) {
ace.reportTo(eventHandler);
String errorMsg = "Analysis of target '" + bad.getKey().getOwner().getLabel() + "' failed; build aborted";
throw new ViewCreationFailedException(errorMsg);
} catch (ArtifactPrefixConflictException apce) {
eventHandler.handle(Event.error(apce.getMessage()));
}
throw new ViewCreationFailedException(ex.getMessage());
}
Map.Entry<SkyKey, ErrorInfo> error = result.errorMap().entrySet().iterator().next();
SkyKey topLevel = error.getKey();
ErrorInfo errorInfo = error.getValue();
assertSaneAnalysisError(errorInfo, topLevel);
skyframeExecutor.getCyclesReporter().reportCycles(errorInfo.getCycleInfo(), topLevel, eventHandler);
Throwable cause = errorInfo.getException();
Preconditions.checkState(cause != null || !Iterables.isEmpty(errorInfo.getCycleInfo()), errorInfo);
String errorMsg = null;
if (topLevel.argument() instanceof ConfiguredTargetKey) {
errorMsg = "Analysis of target '" + ConfiguredTargetValue.extractLabel(topLevel) + "' failed; build aborted";
} else if (topLevel.argument() instanceof AspectValueKey) {
AspectValueKey aspectKey = (AspectValueKey) topLevel.argument();
errorMsg = "Analysis of aspect '" + aspectKey.getDescription() + "' failed; build aborted";
} else {
assert false;
}
if (cause instanceof ActionConflictException) {
((ActionConflictException) cause).reportTo(eventHandler);
}
throw new ViewCreationFailedException(errorMsg);
}
boolean hasLoadingError = false;
// --keep_going : We notify the error and return a ConfiguredTargetValue
for (Map.Entry<SkyKey, ErrorInfo> errorEntry : result.errorMap().entrySet()) {
// TODO(ulfjack): this is quadratic - if there are a lot of CTs, this could be rather slow.
if (!values.contains(errorEntry.getKey().argument())) {
continue;
}
SkyKey errorKey = errorEntry.getKey();
ConfiguredTargetKey label = (ConfiguredTargetKey) errorKey.argument();
Label topLevelLabel = label.getLabel();
ErrorInfo errorInfo = errorEntry.getValue();
assertSaneAnalysisError(errorInfo, errorKey);
skyframeExecutor.getCyclesReporter().reportCycles(errorInfo.getCycleInfo(), errorKey, eventHandler);
Exception cause = errorInfo.getException();
Label analysisRootCause = null;
if (cause instanceof ConfiguredValueCreationException) {
ConfiguredValueCreationException ctCause = (ConfiguredValueCreationException) cause;
for (Label rootCause : ctCause.getRootCauses()) {
hasLoadingError = true;
eventBus.post(new LoadingFailureEvent(topLevelLabel, rootCause));
}
analysisRootCause = ctCause.getAnalysisRootCause();
} else if (!Iterables.isEmpty(errorInfo.getCycleInfo())) {
analysisRootCause = maybeGetConfiguredTargetCycleCulprit(topLevelLabel, errorInfo.getCycleInfo());
} else if (cause instanceof ActionConflictException) {
((ActionConflictException) cause).reportTo(eventHandler);
}
eventHandler.handle(Event.warn("errors encountered while analyzing target '" + topLevelLabel + "': it will not be built"));
if (analysisRootCause != null) {
eventBus.post(new AnalysisFailureEvent(LabelAndConfiguration.of(topLevelLabel, label.getConfiguration()), analysisRootCause));
}
}
Collection<Exception> reportedExceptions = Sets.newHashSet();
for (Map.Entry<ActionAnalysisMetadata, ConflictException> bad : badActions.entrySet()) {
ConflictException ex = bad.getValue();
try {
ex.rethrowTyped();
} catch (MutableActionGraph.ActionConflictException ace) {
ace.reportTo(eventHandler);
eventHandler.handle(Event.warn("errors encountered while analyzing target '" + bad.getKey().getOwner().getLabel() + "': it will not be built"));
} catch (ArtifactPrefixConflictException apce) {
if (reportedExceptions.add(apce)) {
eventHandler.handle(Event.error(apce.getMessage()));
}
}
}
if (!badActions.isEmpty()) {
// In order to determine the set of configured targets transitively error free from action
// conflict issues, we run a post-processing update() that uses the bad action map.
EvaluationResult<PostConfiguredTargetValue> actionConflictResult = skyframeExecutor.postConfigureTargets(eventHandler, values, keepGoing, badActions);
goodCts = Lists.newArrayListWithCapacity(values.size());
for (ConfiguredTargetKey value : values) {
PostConfiguredTargetValue postCt = actionConflictResult.get(PostConfiguredTargetValue.key(value));
if (postCt != null) {
goodCts.add(postCt.getCt());
}
}
}
return new SkyframeAnalysisResult(hasLoadingError, result.hasError() || !badActions.isEmpty(), ImmutableList.copyOf(goodCts), result.getWalkableGraph(), ImmutableList.copyOf(goodAspects), packageRoots);
}
use of com.google.devtools.build.skyframe.ErrorInfo in project bazel by bazelbuild.
the class SkyframeExecutor method getConfigurations.
/**
* Retrieves the configurations needed for the given deps. If {@link
* BuildConfiguration.Options#trimConfigurations()} is true, trims their fragments to only those
* needed by their transitive closures. Else unconditionally includes all fragments.
*
* <p>Skips targets with loading phase errors.
*/
public Multimap<Dependency, BuildConfiguration> getConfigurations(ExtendedEventHandler eventHandler, BuildOptions fromOptions, Iterable<Dependency> keys) {
Multimap<Dependency, BuildConfiguration> builder = ArrayListMultimap.<Dependency, BuildConfiguration>create();
Set<Dependency> depsToEvaluate = new HashSet<>();
// Check: if !Configuration.useDynamicConfigs then just return the original configs.
Set<Class<? extends BuildConfiguration.Fragment>> allFragments = null;
if (useUntrimmedDynamicConfigs(fromOptions)) {
allFragments = ((ConfiguredRuleClassProvider) ruleClassProvider).getAllFragments();
}
// Get the fragments needed for dynamic configuration nodes.
final List<SkyKey> transitiveFragmentSkyKeys = new ArrayList<>();
Map<Label, Set<Class<? extends BuildConfiguration.Fragment>>> fragmentsMap = new HashMap<>();
Set<Label> labelsWithErrors = new HashSet<>();
for (Dependency key : keys) {
if (key.hasStaticConfiguration()) {
builder.put(key, key.getConfiguration());
} else if (useUntrimmedDynamicConfigs(fromOptions)) {
fragmentsMap.put(key.getLabel(), allFragments);
} else {
depsToEvaluate.add(key);
transitiveFragmentSkyKeys.add(TransitiveTargetValue.key(key.getLabel()));
}
}
EvaluationResult<SkyValue> fragmentsResult = evaluateSkyKeys(eventHandler, transitiveFragmentSkyKeys, /*keepGoing=*/
true);
for (Map.Entry<SkyKey, ErrorInfo> entry : fragmentsResult.errorMap().entrySet()) {
reportCycles(eventHandler, entry.getValue().getCycleInfo(), entry.getKey());
}
for (Dependency key : keys) {
if (!depsToEvaluate.contains(key)) {
// No fragments to compute here.
} else if (fragmentsResult.getError(TransitiveTargetValue.key(key.getLabel())) != null) {
labelsWithErrors.add(key.getLabel());
} else {
TransitiveTargetValue ttv = (TransitiveTargetValue) fragmentsResult.get(TransitiveTargetValue.key(key.getLabel()));
fragmentsMap.put(key.getLabel(), ttv.getTransitiveConfigFragments().toSet());
}
}
// Now get the configurations.
final List<SkyKey> configSkyKeys = new ArrayList<>();
for (Dependency key : keys) {
if (labelsWithErrors.contains(key.getLabel()) || key.hasStaticConfiguration()) {
continue;
}
Set<Class<? extends BuildConfiguration.Fragment>> depFragments = fragmentsMap.get(key.getLabel());
if (depFragments != null) {
for (BuildOptions toOptions : ConfiguredTargetFunction.getDynamicTransitionOptions(fromOptions, key.getTransition(), depFragments, ruleClassProvider, true)) {
configSkyKeys.add(BuildConfigurationValue.key(depFragments, toOptions));
}
}
}
EvaluationResult<SkyValue> configsResult = evaluateSkyKeys(eventHandler, configSkyKeys, /*keepGoing=*/
true);
for (Dependency key : keys) {
if (labelsWithErrors.contains(key.getLabel()) || key.hasStaticConfiguration()) {
continue;
}
Set<Class<? extends BuildConfiguration.Fragment>> depFragments = fragmentsMap.get(key.getLabel());
if (depFragments != null) {
for (BuildOptions toOptions : ConfiguredTargetFunction.getDynamicTransitionOptions(fromOptions, key.getTransition(), depFragments, ruleClassProvider, true)) {
SkyKey configKey = BuildConfigurationValue.key(depFragments, toOptions);
builder.put(key, ((BuildConfigurationValue) configsResult.get(configKey)).getConfiguration());
}
}
}
return builder;
}
use of com.google.devtools.build.skyframe.ErrorInfo in project bazel by bazelbuild.
the class SkyframeExecutor method evaluateSkyKeyForExecutionSetup.
/**
* This method exists only to allow a module to make a top-level Skyframe call during the
* transition to making it fully Skyframe-compatible. Do not add additional callers!
*/
public SkyValue evaluateSkyKeyForExecutionSetup(final ExtendedEventHandler eventHandler, final SkyKey key) throws EnvironmentalExecException, InterruptedException {
synchronized (valueLookupLock) {
// We evaluate in keepGoing mode because in the case that the graph does not store its
// edges, nokeepGoing builds are not allowed, whereas keepGoing builds are always
// permitted.
EvaluationResult<SkyValue> result = buildDriver.evaluate(ImmutableList.of(key), true, ResourceUsage.getAvailableProcessors(), eventHandler);
if (!result.hasError()) {
return Preconditions.checkNotNull(result.get(key), "%s %s", result, key);
}
ErrorInfo errorInfo = Preconditions.checkNotNull(result.getError(key), "%s %s", key, result);
Throwables.propagateIfPossible(errorInfo.getException(), EnvironmentalExecException.class);
if (errorInfo.getException() != null) {
throw new IllegalStateException(errorInfo.getException());
}
throw new IllegalStateException(errorInfo.toString());
}
}
use of com.google.devtools.build.skyframe.ErrorInfo in project bazel by bazelbuild.
the class SkyframeLabelVisitor method sync.
// The only remaining non-test caller of this code is BlazeQueryEnvironment.
@Override
public boolean sync(ExtendedEventHandler eventHandler, Set<Label> labelsToVisit, boolean keepGoing, int parallelThreads) throws InterruptedException {
EvaluationResult<TransitiveTargetValue> result = transitivePackageLoader.loadTransitiveTargets(eventHandler, labelsToVisit, keepGoing, parallelThreads);
if (!hasErrors(result)) {
return true;
}
Set<Entry<SkyKey, ErrorInfo>> errors = result.errorMap().entrySet();
if (!keepGoing) {
// We may have multiple errors, but in non keep_going builds, we're obligated to print only
// one of them.
Preconditions.checkState(!errors.isEmpty(), result);
Entry<SkyKey, ErrorInfo> error = errors.iterator().next();
ErrorInfo errorInfo = error.getValue();
SkyKey topLevel = error.getKey();
Label topLevelLabel = (Label) topLevel.argument();
if (!Iterables.isEmpty(errorInfo.getCycleInfo())) {
skyframeCyclesReporter.get().reportCycles(errorInfo.getCycleInfo(), topLevel, eventHandler);
errorAboutLoadingFailure(topLevelLabel, null, eventHandler);
} else if (isDirectErrorFromTopLevelLabel(topLevelLabel, labelsToVisit, errorInfo)) {
// An error caused by a non-top-level label has already been reported during error
// bubbling but an error caused by the top-level non-target label itself hasn't been
// reported yet. Note that errors from top-level targets have already been reported
// during target parsing.
errorAboutLoadingFailure(topLevelLabel, errorInfo.getException(), eventHandler);
}
return false;
}
for (Entry<SkyKey, ErrorInfo> errorEntry : errors) {
SkyKey key = errorEntry.getKey();
ErrorInfo errorInfo = errorEntry.getValue();
Preconditions.checkState(key.functionName().equals(SkyFunctions.TRANSITIVE_TARGET), errorEntry);
Label topLevelLabel = (Label) key.argument();
if (!Iterables.isEmpty(errorInfo.getCycleInfo())) {
skyframeCyclesReporter.get().reportCycles(errorInfo.getCycleInfo(), key, eventHandler);
}
if (isDirectErrorFromTopLevelLabel(topLevelLabel, labelsToVisit, errorInfo)) {
// Unlike top-level targets, which have already gone through target parsing,
// errors directly coming from top-level labels have not been reported yet.
//
// See the note in the --nokeep_going case above.
eventHandler.handle(Event.error(errorInfo.getException().getMessage()));
}
warnAboutLoadingFailure(topLevelLabel, eventHandler);
}
for (Label topLevelLabel : result.<Label>keyNames()) {
SkyKey topLevelTransitiveTargetKey = TransitiveTargetValue.key(topLevelLabel);
TransitiveTargetValue topLevelTransitiveTargetValue = result.get(topLevelTransitiveTargetKey);
if (topLevelTransitiveTargetValue.getTransitiveRootCauses() != null) {
warnAboutLoadingFailure(topLevelLabel, eventHandler);
}
}
return false;
}
use of com.google.devtools.build.skyframe.ErrorInfo in project bazel by bazelbuild.
the class SkyframeExecutor method getConfiguredTargetMap.
/**
* Returns a map from {@link Dependency} inputs to the {@link ConfiguredTarget}s corresponding to
* those dependencies.
*
* <p>For use for legacy support and tests calling through {@code BuildView} only.
*
* <p>If a requested configured target is in error, the corresponding value is omitted from the
* returned list.
*/
@ThreadSafety.ThreadSafe
public ImmutableMultimap<Dependency, ConfiguredTarget> getConfiguredTargetMap(ExtendedEventHandler eventHandler, BuildConfiguration originalConfig, Iterable<Dependency> keys, boolean useOriginalConfig) {
checkActive();
Multimap<Dependency, BuildConfiguration> configs;
if (originalConfig != null) {
if (useOriginalConfig) {
// This flag is used because of some unfortunate complexity in the configuration machinery:
// Most callers of this method pass a <Label, Configuration> pair to directly create a
// ConfiguredTarget from, but happen to use the Dependency data structure to pass that
// info (even though the data has nothing to do with dependencies). If this configuration
// includes a split transition, a dynamic configuration created from it will *not*
// include that transition (because dynamic configurations don't embed transitions to
// other configurations. In that case, we need to preserve the original configuration.
// TODO(bazel-team); make this unnecessary once split transition logic is properly ported
// out of configurations.
configs = ArrayListMultimap.<Dependency, BuildConfiguration>create();
configs.put(Iterables.getOnlyElement(keys), originalConfig);
} else {
configs = getConfigurations(eventHandler, originalConfig.getOptions(), keys);
}
} else {
configs = ArrayListMultimap.<Dependency, BuildConfiguration>create();
for (Dependency key : keys) {
configs.put(key, null);
}
}
final List<SkyKey> skyKeys = new ArrayList<>();
for (Dependency key : keys) {
if (!configs.containsKey(key)) {
// it couldn't be loaded). Exclude it from the results.
continue;
}
for (BuildConfiguration depConfig : configs.get(key)) {
skyKeys.add(ConfiguredTargetValue.key(key.getLabel(), depConfig));
for (AspectDescriptor aspectDescriptor : key.getAspects().getAllAspects()) {
skyKeys.add(ActionLookupValue.key(AspectValue.createAspectKey(key.getLabel(), depConfig, aspectDescriptor, depConfig)));
}
}
}
EvaluationResult<SkyValue> result = evaluateSkyKeys(eventHandler, skyKeys);
for (Map.Entry<SkyKey, ErrorInfo> entry : result.errorMap().entrySet()) {
reportCycles(eventHandler, entry.getValue().getCycleInfo(), entry.getKey());
}
ImmutableMultimap.Builder<Dependency, ConfiguredTarget> cts = ImmutableMultimap.<Dependency, ConfiguredTarget>builder();
DependentNodeLoop: for (Dependency key : keys) {
if (!configs.containsKey(key)) {
// it couldn't be loaded). Exclude it from the results.
continue;
}
for (BuildConfiguration depConfig : configs.get(key)) {
SkyKey configuredTargetKey = ConfiguredTargetValue.key(key.getLabel(), depConfig);
if (result.get(configuredTargetKey) == null) {
continue;
}
ConfiguredTarget configuredTarget = ((ConfiguredTargetValue) result.get(configuredTargetKey)).getConfiguredTarget();
List<ConfiguredAspect> configuredAspects = new ArrayList<>();
for (AspectDescriptor aspectDescriptor : key.getAspects().getAllAspects()) {
SkyKey aspectKey = ActionLookupValue.key(AspectValue.createAspectKey(key.getLabel(), depConfig, aspectDescriptor, depConfig));
if (result.get(aspectKey) == null) {
continue DependentNodeLoop;
}
configuredAspects.add(((AspectValue) result.get(aspectKey)).getConfiguredAspect());
}
try {
cts.put(key, MergedConfiguredTarget.of(configuredTarget, configuredAspects));
} catch (DuplicateException e) {
throw new IllegalStateException(String.format("Error creating %s", configuredTarget.getTarget().getLabel()), e);
}
}
}
return cts.build();
}
Aggregations