aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
diff options
context:
space:
mode:
authorGravatar Ulf Adams <ulfjack@google.com>2016-01-28 15:05:16 +0000
committerGravatar Kristina Chodorow <kchodorow@google.com>2016-01-28 15:30:46 +0000
commit849017381db007108b3a9e25b1dbf07b7587d31c (patch)
treebb1b03a339fedb20d87b9a80e3af8d74b8a8b4f7 /src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
parentb6fbab7115c1567705e7bddc7b79bdee6313fce3 (diff)
Refactor DependencyResolver to collect and return loading errors.
This should never be triggered in production, where we always run a loading phase first and only analyze targets that load successfully. I.e., this is just plumbing which will be hooked up in a subsequent change. -- MOS_MIGRATED_REVID=113258593
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java125
1 files changed, 84 insertions, 41 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
index f4a74460bd..dba5155f25 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
@@ -42,7 +42,9 @@ import com.google.devtools.build.lib.analysis.config.HostTransition;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
import com.google.devtools.build.lib.analysis.config.PatchTransition;
import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.StoredEventHandler;
@@ -68,7 +70,7 @@ import com.google.devtools.build.skyframe.SkyFunctionException;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.build.skyframe.ValueOrException;
-import com.google.devtools.build.skyframe.ValueOrException3;
+import com.google.devtools.build.skyframe.ValueOrException2;
import java.util.Collection;
import java.util.HashMap;
@@ -124,6 +126,7 @@ final class ConfiguredTargetFunction implements SkyFunction {
InterruptedException {
SkyframeBuildView view = buildViewProvider.getSkyframeBuildView();
NestedSetBuilder<Package> transitivePackages = NestedSetBuilder.stableOrder();
+ NestedSetBuilder<Label> transitiveLoadingRootCauses = NestedSetBuilder.stableOrder();
ConfiguredTargetKey configuredTargetKey = (ConfiguredTargetKey) key.argument();
LabelAndConfiguration lc = LabelAndConfiguration.of(
configuredTargetKey.getLabel(), configuredTargetKey.getConfiguration());
@@ -162,8 +165,9 @@ final class ConfiguredTargetFunction implements SkyFunction {
new TargetAndConfiguration(target, configuration);
try {
// Get the configuration targets that trigger this rule's configurable attributes.
- Set<ConfigMatchingProvider> configConditions =
- getConfigConditions(ctgValue.getTarget(), env, resolver, ctgValue, transitivePackages);
+ Set<ConfigMatchingProvider> configConditions = getConfigConditions(
+ ctgValue.getTarget(), env, resolver, ctgValue, transitivePackages,
+ transitiveLoadingRootCauses);
if (env.valuesMissing()) {
return null;
}
@@ -177,7 +181,16 @@ final class ConfiguredTargetFunction implements SkyFunction {
configConditions,
ruleClassProvider,
view.getHostConfiguration(configuration),
- transitivePackages);
+ transitivePackages,
+ transitiveLoadingRootCauses);
+ if (env.valuesMissing()) {
+ return null;
+ }
+ if (!transitiveLoadingRootCauses.isEmpty()) {
+ throw new ConfiguredTargetFunctionException(
+ new ConfiguredValueCreationException(transitiveLoadingRootCauses.build()));
+ }
+ Preconditions.checkNotNull(depValueMap);
ConfiguredTargetValue ans = createConfiguredTarget(
view, env, target, configuration, depValueMap, configConditions, transitivePackages);
return ans;
@@ -194,12 +207,12 @@ final class ConfiguredTargetFunction implements SkyFunction {
}
} catch (AspectCreationException e) {
// getAnalysisRootCause may be null if the analysis of the aspect itself failed.
- Label rootCause = target.getLabel();
+ Label analysisRootCause = target.getLabel();
if (e.getAnalysisRootCause() != null) {
- rootCause = e.getAnalysisRootCause();
+ analysisRootCause = e.getAnalysisRootCause();
}
throw new ConfiguredTargetFunctionException(
- new ConfiguredValueCreationException(e.getMessage(), rootCause));
+ new ConfiguredValueCreationException(e.getMessage(), analysisRootCause));
}
}
@@ -229,13 +242,14 @@ final class ConfiguredTargetFunction implements SkyFunction {
Set<ConfigMatchingProvider> configConditions,
RuleClassProvider ruleClassProvider,
BuildConfiguration hostConfiguration,
- NestedSetBuilder<Package> transitivePackages)
+ NestedSetBuilder<Package> transitivePackages,
+ NestedSetBuilder<Label> transitiveLoadingRootCauses)
throws DependencyEvaluationException, AspectCreationException, InterruptedException {
// Create the map from attributes to list of (target, configuration) pairs.
ListMultimap<Attribute, Dependency> depValueNames;
try {
- depValueNames =
- resolver.dependentNodeMap(ctgValue, hostConfiguration, aspect, configConditions);
+ depValueNames = resolver.dependentNodeMap(
+ ctgValue, hostConfiguration, aspect, configConditions, transitiveLoadingRootCauses);
} catch (EvalException e) {
// EvalException can only be thrown by computed Skylark attributes in the current rule.
env.getListener().handle(Event.error(e.getLocation(), e.getMessage()));
@@ -256,14 +270,14 @@ final class ConfiguredTargetFunction implements SkyFunction {
// Resolve configured target dependencies and handle errors.
Map<SkyKey, ConfiguredTarget> depValues = resolveConfiguredTargetDependencies(env,
- depValueNames.values(), transitivePackages);
+ depValueNames.values(), transitivePackages, transitiveLoadingRootCauses);
if (depValues == null) {
return null;
}
// Resolve required aspects.
- ListMultimap<SkyKey, ConfiguredAspect> depAspects =
- resolveAspectDependencies(env, depValues, depValueNames.values(), transitivePackages);
+ ListMultimap<SkyKey, ConfiguredAspect> depAspects = resolveAspectDependencies(
+ env, depValues, depValueNames.values(), transitivePackages);
if (depAspects == null) {
return null;
}
@@ -566,10 +580,8 @@ final class ConfiguredTargetFunction implements SkyFunction {
}
}
- Map<SkyKey, ValueOrException3<
- AspectCreationException, NoSuchThingException, ConfiguredValueCreationException>>
- depAspects = env.getValuesOrThrow(aspectKeys, AspectCreationException.class,
- NoSuchThingException.class, ConfiguredValueCreationException.class);
+ Map<SkyKey, ValueOrException2<AspectCreationException, NoSuchThingException>> depAspects =
+ env.getValuesOrThrow(aspectKeys, AspectCreationException.class, NoSuchThingException.class);
for (Dependency dep : deps) {
SkyKey depKey = TO_KEYS.apply(dep);
@@ -587,10 +599,9 @@ final class ConfiguredTargetFunction implements SkyFunction {
SkyKey aspectKey = createAspectKey(dep.getLabel(), dep.getConfiguration(), depAspect);
AspectValue aspectValue = null;
try {
+ // TODO(ulfjack): Catch all thrown AspectCreationException and NoSuchThingException
+ // instances and merge them into a single Exception to get full root cause data.
aspectValue = (AspectValue) depAspects.get(aspectKey).get();
- } catch (ConfiguredValueCreationException e) {
- // The configured target should have been created in resolveConfiguredTargetDependencies()
- throw new IllegalStateException(e);
} catch (NoSuchThingException e) {
throw new AspectCreationException(
String.format(
@@ -639,7 +650,8 @@ final class ConfiguredTargetFunction implements SkyFunction {
@Nullable
static Set<ConfigMatchingProvider> getConfigConditions(Target target, Environment env,
SkyframeDependencyResolver resolver, TargetAndConfiguration ctgValue,
- NestedSetBuilder<Package> transitivePackages)
+ NestedSetBuilder<Package> transitivePackages,
+ NestedSetBuilder<Label> transitiveLoadingRootCauses)
throws DependencyEvaluationException {
if (!(target instanceof Rule)) {
return ImmutableSet.of();
@@ -665,7 +677,8 @@ final class ConfiguredTargetFunction implements SkyFunction {
// Collect the corresponding Skyframe configured target values. Abort early if they haven't
// been computed yet.
- Collection<Dependency> configValueNames = resolver.resolveRuleLabels(ctgValue, configLabelMap);
+ Collection<Dependency> configValueNames = resolver.resolveRuleLabels(
+ ctgValue, configLabelMap, transitiveLoadingRootCauses);
// No need to get new configs from Skyframe - config_setting rules always use the current
// target's config.
@@ -682,7 +695,7 @@ final class ConfiguredTargetFunction implements SkyFunction {
}
Map<SkyKey, ConfiguredTarget> configValues = resolveConfiguredTargetDependencies(
- env, configValueNames, transitivePackages);
+ env, configValueNames, transitivePackages, transitiveLoadingRootCauses);
if (configValues == null) {
return null;
}
@@ -714,30 +727,39 @@ final class ConfiguredTargetFunction implements SkyFunction {
*/
@Nullable
private static Map<SkyKey, ConfiguredTarget> resolveConfiguredTargetDependencies(
- Environment env, Collection<Dependency> deps, NestedSetBuilder<Package> transitivePackages)
- throws DependencyEvaluationException {
- boolean ok = !env.valuesMissing();
+ Environment env, Collection<Dependency> deps, NestedSetBuilder<Package> transitivePackages,
+ NestedSetBuilder<Label> transitiveLoadingRootCauses) throws DependencyEvaluationException {
+ boolean missedValues = env.valuesMissing();
+ boolean failed = false;
Iterable<SkyKey> depKeys = Iterables.transform(deps, TO_KEYS);
- Map<SkyKey, ValueOrException<ConfiguredValueCreationException>> depValues =
+ Map<SkyKey, ValueOrException<ConfiguredValueCreationException>> depValuesOrExceptions =
env.getValuesOrThrow(depKeys, ConfiguredValueCreationException.class);
- Map<SkyKey, ConfiguredTarget> result = Maps.newHashMapWithExpectedSize(depValues.size());
- for (Map.Entry<SkyKey, ValueOrException<ConfiguredValueCreationException>> entry :
- depValues.entrySet()) {
- ConfiguredTargetValue depValue;
+ Map<SkyKey, ConfiguredTarget> result =
+ Maps.newHashMapWithExpectedSize(depValuesOrExceptions.size());
+ for (Map.Entry<SkyKey, ValueOrException<ConfiguredValueCreationException>> entry
+ : depValuesOrExceptions.entrySet()) {
try {
- depValue = (ConfiguredTargetValue) entry.getValue().get();
+ ConfiguredTargetValue depValue = (ConfiguredTargetValue) entry.getValue().get();
+ if (depValue == null) {
+ missedValues = true;
+ } else {
+ result.put(entry.getKey(), depValue.getConfiguredTarget());
+ transitivePackages.addTransitive(depValue.getTransitivePackages());
+ }
} catch (ConfiguredValueCreationException e) {
- throw new DependencyEvaluationException(e);
- }
- if (depValue == null) {
- ok = false;
- } else {
- result.put(entry.getKey(), depValue.getConfiguredTarget());
- transitivePackages.addTransitive(depValue.getTransitivePackages());
+ // TODO(ulfjack): If there is an analysis root cause, we drop all loading root causes.
+ if (e.getAnalysisRootCause() != null) {
+ throw new DependencyEvaluationException(e);
+ }
+ transitiveLoadingRootCauses.addTransitive(e.loadingRootCauses);
+ failed = true;
}
}
- if (!ok) {
+ if (missedValues) {
return null;
+ } else if (failed) {
+ throw new DependencyEvaluationException(
+ new ConfiguredValueCreationException(transitiveLoadingRootCauses.build()));
} else {
return result;
}
@@ -766,6 +788,7 @@ final class ConfiguredTargetFunction implements SkyFunction {
return null;
}
+ Preconditions.checkNotNull(depValueMap);
ConfiguredTarget configuredTarget = view.createConfiguredTarget(target, configuration,
analysisEnvironment, depValueMap, configConditions);
@@ -817,14 +840,34 @@ final class ConfiguredTargetFunction implements SkyFunction {
* a ConfiguredTargetValue.
*/
public static final class ConfiguredValueCreationException extends Exception {
+ private final NestedSet<Label> loadingRootCauses;
// TODO(ulfjack): Collect all analysis root causes, not just the first one.
- private final Label analysisRootCause;
+ @Nullable private final Label analysisRootCause;
public ConfiguredValueCreationException(String message, Label currentTarget) {
super(message);
+ this.loadingRootCauses = NestedSetBuilder.<Label>emptySet(Order.STABLE_ORDER);
this.analysisRootCause = Preconditions.checkNotNull(currentTarget);
}
+ public ConfiguredValueCreationException(String message, NestedSet<Label> rootCauses) {
+ super(message);
+ this.loadingRootCauses = rootCauses;
+ this.analysisRootCause = null;
+ }
+
+ public ConfiguredValueCreationException(NestedSet<Label> rootCauses) {
+ this("Loading failed", rootCauses);
+ }
+
+ public ConfiguredValueCreationException(String message) {
+ this(message, NestedSetBuilder.<Label>emptySet(Order.STABLE_ORDER));
+ }
+
+ public NestedSet<Label> getRootCauses() {
+ return loadingRootCauses;
+ }
+
public Label getAnalysisRootCause() {
return analysisRootCause;
}