diff options
Diffstat (limited to 'src/main/java/com')
23 files changed, 389 insertions, 215 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisFailureEvent.java b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisFailureEvent.java index b39d826b19..cdc26efd30 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisFailureEvent.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisFailureEvent.java @@ -23,8 +23,10 @@ import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos; import com.google.devtools.build.lib.buildeventstream.GenericBuildEvent; import com.google.devtools.build.lib.buildeventstream.NullConfiguration; import com.google.devtools.build.lib.causes.Cause; +import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey; import java.util.Collection; +import javax.annotation.Nullable; /** * This event is fired during the build, when it becomes known that the analysis of a target cannot @@ -33,23 +35,37 @@ import java.util.Collection; public class AnalysisFailureEvent implements BuildEvent { private final ConfiguredTargetKey failedTarget; private final BuildEventId configuration; - private final Iterable<Cause> causes; + private final Iterable<Cause> rootCauses; public AnalysisFailureEvent( - ConfiguredTargetKey failedTarget, BuildEventId configuration, Iterable<Cause> causes) { + ConfiguredTargetKey failedTarget, BuildEventId configuration, Iterable<Cause> rootCauses) { this.failedTarget = failedTarget; if (configuration != null) { this.configuration = configuration; } else { this.configuration = NullConfiguration.INSTANCE.getEventId(); } - this.causes = causes; + this.rootCauses = rootCauses; } public ConfiguredTargetKey getFailedTarget() { return failedTarget; } + /** + * Returns the label of a single root cause. Use {@link #getRootCauses} to report all root causes. + */ + @Nullable public Label getLegacyFailureReason() { + if (!rootCauses.iterator().hasNext()) { + return null; + } + return rootCauses.iterator().next().getLabel(); + } + + public Iterable<Cause> getRootCauses() { + return rootCauses; + } + @Override public BuildEventId getEventId() { return BuildEventId.targetCompleted(failedTarget.getLabel(), configuration); @@ -57,7 +73,7 @@ public class AnalysisFailureEvent implements BuildEvent { @Override public Collection<BuildEventId> getChildrenEvents() { - return ImmutableList.copyOf(Iterables.transform(causes, BuildEventId::fromCause)); + return ImmutableList.copyOf(Iterables.transform(rootCauses, BuildEventId::fromCause)); } @Override diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AspectResolver.java b/src/main/java/com/google/devtools/build/lib/analysis/AspectResolver.java index da80785060..355fc21696 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/AspectResolver.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/AspectResolver.java @@ -16,6 +16,7 @@ package com.google.devtools.build.lib.analysis; import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.analysis.configuredtargets.MergedConfiguredTarget; +import com.google.devtools.build.lib.causes.LabelCause; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.packages.Aspect; import com.google.devtools.build.lib.packages.AspectDescriptor; @@ -81,7 +82,8 @@ public final class AspectResolver { "Evaluation of aspect %s on %s failed: %s", depAspect.getAspect().getAspectClass().getName(), dep.getLabel(), - e.toString())); + e.toString()), + new LabelCause(dep.getLabel(), e.getMessage())); } if (aspectValue == null) { diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java index ae3a500bd5..2651e65d82 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java @@ -52,6 +52,7 @@ import com.google.devtools.build.lib.analysis.constraints.TopLevelConstraintSema import com.google.devtools.build.lib.analysis.test.CoverageReportActionFactory; import com.google.devtools.build.lib.analysis.test.CoverageReportActionFactory.CoverageReportActionsWrapper; import com.google.devtools.build.lib.analysis.test.InstrumentedFilesProvider; +import com.google.devtools.build.lib.causes.Cause; 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; @@ -1053,7 +1054,7 @@ public class BuildView { } @Override - protected Target getTarget(Target from, Label label, NestedSetBuilder<Label> rootCauses) + protected Target getTarget(Target from, Label label, NestedSetBuilder<Cause> rootCauses) throws InterruptedException { try { return skyframeExecutor.getPackageManager().getTarget(eventHandler, label); diff --git a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java index 4a35e373e7..9ad8ba8a16 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java @@ -30,6 +30,7 @@ import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTr import com.google.devtools.build.lib.analysis.config.transitions.NullTransition; import com.google.devtools.build.lib.analysis.config.transitions.PatchTransition; import com.google.devtools.build.lib.analysis.config.transitions.SplitTransition; +import com.google.devtools.build.lib.causes.Cause; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.events.Location; @@ -108,7 +109,7 @@ public abstract class DependencyResolver { @Nullable RuleTransitionFactory trimmingTransitionFactory) throws EvalException, InvalidConfigurationException, InterruptedException, InconsistentAspectOrderException { - NestedSetBuilder<Label> rootCauses = NestedSetBuilder.<Label>stableOrder(); + NestedSetBuilder<Cause> rootCauses = NestedSetBuilder.stableOrder(); OrderedSetMultimap<Attribute, Dependency> outgoingEdges = dependentNodeMap( node, @@ -164,7 +165,7 @@ public abstract class DependencyResolver { Iterable<Aspect> aspects, ImmutableMap<Label, ConfigMatchingProvider> configConditions, ImmutableSet<Label> toolchainLabels, - NestedSetBuilder<Label> rootCauses, + NestedSetBuilder<Cause> rootCauses, BuildOptions defaultBuildOptions, @Nullable RuleTransitionFactory trimmingTransitionFactory) throws EvalException, InvalidConfigurationException, InterruptedException, @@ -207,7 +208,7 @@ public abstract class DependencyResolver { Iterable<Aspect> aspects, ImmutableMap<Label, ConfigMatchingProvider> configConditions, ImmutableSet<Label> toolchainLabels, - NestedSetBuilder<Label> rootCauses, + NestedSetBuilder<Cause> rootCauses, OrderedSetMultimap<Attribute, Dependency> outgoingEdges, BuildOptions defaultBuildOptions, @Nullable RuleTransitionFactory trimmingTransitionFactory) @@ -554,7 +555,7 @@ public abstract class DependencyResolver { public final Collection<Dependency> resolveRuleLabels( TargetAndConfiguration node, OrderedSetMultimap<Attribute, Label> depLabels, - NestedSetBuilder<Label> rootCauses, + NestedSetBuilder<Cause> rootCauses, @Nullable RuleTransitionFactory trimmingTransitionFactory) throws InterruptedException, InconsistentAspectOrderException { Preconditions.checkArgument(node.getTarget() instanceof Rule); @@ -581,7 +582,7 @@ public abstract class DependencyResolver { private void visitPackageGroup( TargetAndConfiguration node, PackageGroup packageGroup, - NestedSetBuilder<Label> rootCauses, + NestedSetBuilder<Cause> rootCauses, Collection<Dependency> outgoingEdges) throws InterruptedException { for (Label label : packageGroup.getIncludes()) { @@ -691,7 +692,7 @@ public abstract class DependencyResolver { private final BuildConfiguration ruleConfig; private final Iterable<Aspect> aspects; private final ConfiguredAttributeMapper attributeMap; - private final NestedSetBuilder<Label> rootCauses; + private final NestedSetBuilder<Cause> rootCauses; private final OrderedSetMultimap<Attribute, Dependency> outgoingEdges; @Nullable private final RuleTransitionFactory trimmingTransitionFactory; private final List<AttributeAndOwner> attributes; @@ -711,7 +712,7 @@ public abstract class DependencyResolver { BuildConfiguration ruleConfig, Iterable<Aspect> aspects, ConfiguredAttributeMapper attributeMap, - NestedSetBuilder<Label> rootCauses, + NestedSetBuilder<Cause> rootCauses, OrderedSetMultimap<Attribute, Dependency> outgoingEdges, @Nullable RuleTransitionFactory trimmingTransitionFactory) { this.rule = rule; @@ -839,7 +840,7 @@ public abstract class DependencyResolver { private void visitTargetVisibility( TargetAndConfiguration node, - NestedSetBuilder<Label> rootCauses, + NestedSetBuilder<Cause> rootCauses, Collection<Dependency> outgoingEdges) throws InterruptedException { Target target = node.getTarget(); @@ -899,7 +900,7 @@ public abstract class DependencyResolver { * dependencies. */ @Nullable - protected abstract Target getTarget(Target from, Label label, NestedSetBuilder<Label> rootCauses) + protected abstract Target getTarget(Target from, Label label, NestedSetBuilder<Cause> rootCauses) throws InterruptedException; /** diff --git a/src/main/java/com/google/devtools/build/lib/analysis/LegacyAnalysisFailureEvent.java b/src/main/java/com/google/devtools/build/lib/analysis/LegacyAnalysisFailureEvent.java deleted file mode 100644 index 26c23e29c8..0000000000 --- a/src/main/java/com/google/devtools/build/lib/analysis/LegacyAnalysisFailureEvent.java +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2014 The Bazel Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.devtools.build.lib.analysis; - -import com.google.devtools.build.lib.cmdline.Label; -import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey; - -/** - * This event is fired during the build, when it becomes known that the analysis of a target cannot - * be completed because of an error in one of its dependencies. - */ -public class LegacyAnalysisFailureEvent { - private final ConfiguredTargetKey failedTarget; - private final Label failureReason; - - public LegacyAnalysisFailureEvent(ConfiguredTargetKey failedTarget, Label failureReason) { - this.failedTarget = failedTarget; - this.failureReason = failureReason; - } - - public ConfiguredTargetKey getFailedTarget() { - return failedTarget; - } - - public Label getFailureReason() { - return failureReason; - } -} diff --git a/src/main/java/com/google/devtools/build/lib/analysis/TargetConfiguredEvent.java b/src/main/java/com/google/devtools/build/lib/analysis/TargetConfiguredEvent.java index dd015c7ad7..2dec44f617 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/TargetConfiguredEvent.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/TargetConfiguredEvent.java @@ -60,7 +60,7 @@ public class TargetConfiguredEvent implements BuildEventWithConfiguration { @Override public Collection<BuildEventId> getChildrenEvents() { - ImmutableList.Builder childrenBuilder = ImmutableList.builder(); + ImmutableList.Builder<BuildEventId> childrenBuilder = ImmutableList.builder(); for (BuildConfiguration config : configurations) { if (config != null) { childrenBuilder.add(BuildEventId.targetCompleted(target.getLabel(), config.getEventId())); diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ToolchainContext.java b/src/main/java/com/google/devtools/build/lib/analysis/ToolchainContext.java index a2e63b9755..a53b79950e 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/ToolchainContext.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/ToolchainContext.java @@ -42,6 +42,7 @@ import com.google.devtools.build.lib.syntax.SkylarkIndexable; import com.google.devtools.build.lib.util.OrderedSetMultimap; import java.util.Optional; import java.util.Set; +import java.util.stream.StreamSupport; import javax.annotation.Nullable; /** Contains toolchain-related information needed for a {@link RuleContext}. */ @@ -130,9 +131,8 @@ public class ToolchainContext { } /** Returns the {@link Label}s from the {@link NestedSet} that refer to toolchain dependencies. */ - public Set<Label> filterToolchainLabels(Set<Label> labels) { - return labels - .stream() + public Set<Label> filterToolchainLabels(Iterable<Label> labels) { + return StreamSupport.stream(labels.spliterator(), false) .filter(label -> resolvedToolchainLabels.isToolchainDependency(label)) .collect(ImmutableSet.toImmutableSet()); } diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/VisibilityErrorEvent.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/VisibilityErrorEvent.java index ebb0e4cc4f..9829ef459e 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/VisibilityErrorEvent.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/VisibilityErrorEvent.java @@ -39,8 +39,11 @@ public class VisibilityErrorEvent implements BuildEventWithConfiguration { @Override public BuildEventId getEventId() { - // TODO(aehlig): track the configuration as well - return BuildEventId.unconfiguredLabelId(label); + // This needs to match AnalysisFailedCause. + if (configuration == null) { + return BuildEventId.unconfiguredLabelId(label); + } + return BuildEventId.configuredLabelId(label, configuration.getEventId()); } @Override diff --git a/src/main/java/com/google/devtools/build/lib/causes/ActionFailed.java b/src/main/java/com/google/devtools/build/lib/causes/ActionFailed.java index 9200c18d0f..cc59d3c262 100644 --- a/src/main/java/com/google/devtools/build/lib/causes/ActionFailed.java +++ b/src/main/java/com/google/devtools/build/lib/causes/ActionFailed.java @@ -13,6 +13,7 @@ // limitations under the License. package com.google.devtools.build.lib.causes; +import com.google.common.base.MoreObjects; import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos; import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildEventId; import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildEventId.ActionCompletedId; @@ -23,7 +24,7 @@ import javax.annotation.Nullable; /** * Class describing a {@link Cause} that is associated with an action. It is uniquely determined by - * the path to the primary output. For reference, a Label is attached as well. + * the path to the primary output. For reference, a Label is attached as well if available. */ public class ActionFailed implements Cause { private final PathFragment execPath; @@ -38,7 +39,11 @@ public class ActionFailed implements Cause { @Override public String toString() { - return execPath.toString(); + return MoreObjects.toStringHelper(this) + .add("execPath", execPath) + .add("label", label) + .add("configurationChecksum", configurationChecksum) + .toString(); } @Override diff --git a/src/main/java/com/google/devtools/build/lib/causes/AnalysisFailedCause.java b/src/main/java/com/google/devtools/build/lib/causes/AnalysisFailedCause.java new file mode 100644 index 0000000000..9ff844cb10 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/causes/AnalysisFailedCause.java @@ -0,0 +1,94 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.devtools.build.lib.causes; + +import com.google.common.base.MoreObjects; +import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos; +import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildEventId.ConfigurationId; +import com.google.devtools.build.lib.cmdline.Label; +import java.util.Objects; +import javax.annotation.Nullable; + +/** + * Class describing a {@link Cause} that can uniquely be described by a {@link Label} and + * {@link com.google.devtools.build.lib.analysis.config.BuildConfiguration}. Note that the + * configuration may be null, in which case this generates an UnconfiguredLabel event. + */ +public class AnalysisFailedCause implements Cause { + private final Label label; + @Nullable private final ConfigurationId configuration; + private final String msg; + + public AnalysisFailedCause(Label label, @Nullable ConfigurationId configuration, String msg) { + this.label = label; + this.configuration = configuration; + this.msg = msg; + } + + public AnalysisFailedCause(Label label, @Nullable ConfigurationId configuration) { + this(label, configuration, null); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("label", label) + .add("configuration", configuration) + .add("msg", msg) + .toString(); + } + + @Override + public Label getLabel() { + return label; + } + + @Override + public BuildEventStreamProtos.BuildEventId getIdProto() { + // This needs to match VisibilityErrorEvent. + if (configuration == null) { + return BuildEventStreamProtos.BuildEventId.newBuilder() + .setUnconfiguredLabel( + BuildEventStreamProtos.BuildEventId.UnconfiguredLabelId.newBuilder() + .setLabel(label.toString()) + .build()) + .build(); + } + return BuildEventStreamProtos.BuildEventId.newBuilder() + .setConfiguredLabel( + BuildEventStreamProtos.BuildEventId.ConfiguredLabelId.newBuilder() + .setLabel(label.toString()) + .setConfiguration(configuration) + .build()) + .build(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } else if (!(o instanceof AnalysisFailedCause)) { + return false; + } + AnalysisFailedCause a = (AnalysisFailedCause) o; + return Objects.equals(label, a.label) + && Objects.equals(configuration, a.configuration) + && Objects.equals(msg, a.msg); + } + + @Override + public int hashCode() { + return Objects.hash(label, configuration, msg); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/causes/LabelCause.java b/src/main/java/com/google/devtools/build/lib/causes/LabelCause.java index b765c1516c..303f1ecd79 100644 --- a/src/main/java/com/google/devtools/build/lib/causes/LabelCause.java +++ b/src/main/java/com/google/devtools/build/lib/causes/LabelCause.java @@ -1,4 +1,4 @@ -// Copyright 2016 The Bazel Authors. All rights reserved. +// Copyright 2018 The Bazel Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,20 +13,27 @@ // limitations under the License. package com.google.devtools.build.lib.causes; +import com.google.common.base.MoreObjects; import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos; import com.google.devtools.build.lib.cmdline.Label; +import java.util.Objects; -/** Class describing a {@link Cause} that can uniquely be described by a {@link Label}. */ +/** Failure due to something associated with a label; also adds a message. */ public class LabelCause implements Cause { private final Label label; + private final String msg; - public LabelCause(Label label) { + public LabelCause(Label label, String msg) { this.label = label; + this.msg = msg; } @Override public String toString() { - return label.toString(); + return MoreObjects.toStringHelper(this) + .add("label", label) + .add("msg", msg) + .toString(); } @Override @@ -43,4 +50,20 @@ public class LabelCause implements Cause { .build()) .build(); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } else if (!(o instanceof LabelCause)) { + return false; + } + LabelCause a = (LabelCause) o; + return label.equals(a.label) && msg.equals(a.msg); + } + + @Override + public int hashCode() { + return Objects.hash(label, msg); + } } diff --git a/src/main/java/com/google/devtools/build/lib/causes/LoadingFailedCause.java b/src/main/java/com/google/devtools/build/lib/causes/LoadingFailedCause.java new file mode 100644 index 0000000000..84dbf6b4e0 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/causes/LoadingFailedCause.java @@ -0,0 +1,27 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.devtools.build.lib.causes; + +import com.google.devtools.build.lib.cmdline.Label; + +/** + * Failure due to something associated with a label; also adds a message. The difference between + * this class and {@link LabelCause} is that instances of this class get posted to the EventBus as + * {@link com.google.devtools.build.lib.pkgcache.LoadingFailureEvent}. + */ +public class LoadingFailedCause extends LabelCause { + public LoadingFailedCause(Label label, String msg) { + super(label, msg); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/pkgcache/LoadingFailureEvent.java b/src/main/java/com/google/devtools/build/lib/pkgcache/LoadingFailureEvent.java index 45305d2075..4ee722fcd4 100644 --- a/src/main/java/com/google/devtools/build/lib/pkgcache/LoadingFailureEvent.java +++ b/src/main/java/com/google/devtools/build/lib/pkgcache/LoadingFailureEvent.java @@ -13,7 +13,9 @@ // limitations under the License. package com.google.devtools.build.lib.pkgcache; +import com.google.common.base.MoreObjects; import com.google.devtools.build.lib.cmdline.Label; +import java.util.Objects; /** * This event is fired during the build, when it becomes known that the loading @@ -29,6 +31,14 @@ public class LoadingFailureEvent { this.failureReason = failureReason; } + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("failedTarget", failedTarget) + .add("failureReason", failureReason) + .toString(); + } + public Label getFailedTarget() { return failedTarget; } @@ -36,4 +46,21 @@ public class LoadingFailureEvent { public Label getFailureReason() { return failureReason; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } else if (!(o instanceof LoadingFailureEvent)) { + return false; + } + LoadingFailureEvent a = (LoadingFailureEvent) o; + return Objects.equals(failedTarget, a.failedTarget) + && Objects.equals(failureReason, a.failureReason); + } + + @Override + public int hashCode() { + return Objects.hash(failedTarget, failureReason); + } } diff --git a/src/main/java/com/google/devtools/build/lib/query2/BUILD b/src/main/java/com/google/devtools/build/lib/query2/BUILD index cb0dc139d8..b3ded139a2 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/BUILD +++ b/src/main/java/com/google/devtools/build/lib/query2/BUILD @@ -27,6 +27,7 @@ java_library( "//src/main/java/com/google/devtools/build/lib:packages-internal", "//src/main/java/com/google/devtools/build/lib:util", "//src/main/java/com/google/devtools/build/lib/actions", + "//src/main/java/com/google/devtools/build/lib/causes", "//src/main/java/com/google/devtools/build/lib/collect/compacthashset", "//src/main/java/com/google/devtools/build/lib/collect/nestedset", "//src/main/java/com/google/devtools/build/lib/concurrent", diff --git a/src/main/java/com/google/devtools/build/lib/query2/TransitionsOutputFormatterCallback.java b/src/main/java/com/google/devtools/build/lib/query2/TransitionsOutputFormatterCallback.java index 8da9e0f565..a84386b36a 100644 --- a/src/main/java/com/google/devtools/build/lib/query2/TransitionsOutputFormatterCallback.java +++ b/src/main/java/com/google/devtools/build/lib/query2/TransitionsOutputFormatterCallback.java @@ -35,6 +35,7 @@ import com.google.devtools.build.lib.analysis.config.InvalidConfigurationExcepti import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition; import com.google.devtools.build.lib.analysis.config.transitions.NoTransition; import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget; +import com.google.devtools.build.lib.causes.Cause; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.events.Event; @@ -240,7 +241,7 @@ public class TransitionsOutputFormatterCallback extends CqueryThreadsafeCallback } @Override - protected Target getTarget(Target from, Label label, NestedSetBuilder<Label> rootCauses) + protected Target getTarget(Target from, Label label, NestedSetBuilder<Cause> rootCauses) throws InterruptedException { return partialResultMap.get(label); } diff --git a/src/main/java/com/google/devtools/build/lib/runtime/AggregatingTestListener.java b/src/main/java/com/google/devtools/build/lib/runtime/AggregatingTestListener.java index 847ef2d457..e2a70d2afb 100644 --- a/src/main/java/com/google/devtools/build/lib/runtime/AggregatingTestListener.java +++ b/src/main/java/com/google/devtools/build/lib/runtime/AggregatingTestListener.java @@ -28,8 +28,8 @@ import com.google.common.eventbus.Subscribe; import com.google.devtools.build.lib.actions.ActionOwner; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.AliasProvider; +import com.google.devtools.build.lib.analysis.AnalysisFailureEvent; import com.google.devtools.build.lib.analysis.ConfiguredTarget; -import com.google.devtools.build.lib.analysis.LegacyAnalysisFailureEvent; import com.google.devtools.build.lib.analysis.TargetCompleteEvent; import com.google.devtools.build.lib.analysis.test.TestProvider; import com.google.devtools.build.lib.analysis.test.TestResult; @@ -207,7 +207,7 @@ public class AggregatingTestListener { } @Subscribe - public void analysisFailure(LegacyAnalysisFailureEvent event) { + public void analysisFailure(AnalysisFailureEvent event) { targetFailure(event.getFailedTarget()); } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java index f099d7635c..64e9b29681 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java @@ -703,7 +703,7 @@ public class ActionExecutionFunction implements SkyFunction, CompletionReceiver } catch (MissingInputFileException e) { missingCount++; if (input.getOwner() != null) { - rootCauses.add(new LabelCause(input.getOwner())); + rootCauses.add(new LabelCause(input.getOwner(), e.getMessage())); } } catch (ActionExecutionException e) { actionFailures++; diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java index 29ffee6abf..1e39c7693c 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java @@ -38,10 +38,13 @@ import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider; import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; import com.google.devtools.build.lib.analysis.configuredtargets.MergedConfiguredTarget; import com.google.devtools.build.lib.analysis.configuredtargets.MergedConfiguredTarget.DuplicateException; +import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildEventId.ConfigurationId; +import com.google.devtools.build.lib.causes.AnalysisFailedCause; +import com.google.devtools.build.lib.causes.Cause; +import com.google.devtools.build.lib.causes.LabelCause; 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.events.Event; import com.google.devtools.build.lib.events.StoredEventHandler; import com.google.devtools.build.lib.packages.Aspect; @@ -149,7 +152,8 @@ public final class AspectFunction implements SkyFunction { throw new AspectCreationException( String.format( "%s from %s is not a skylark-defined aspect", - skylarkValueName, extensionLabel.toString())); + skylarkValueName, extensionLabel.toString()), + extensionLabel); } else { return (SkylarkDefinedAspect) skylarkAspect; } @@ -202,7 +206,7 @@ public final class AspectFunction implements SkyFunction { | ConversionException | InconsistentFilesystemException e) { env.getListener().handle(Event.error(e.getMessage())); - throw new AspectCreationException(e.getMessage()); + throw new AspectCreationException(e.getMessage(), extensionLabel); } } @@ -211,7 +215,7 @@ public final class AspectFunction implements SkyFunction { public SkyValue compute(SkyKey skyKey, Environment env) throws AspectFunctionException, InterruptedException { SkyframeBuildView view = buildViewProvider.getSkyframeBuildView(); - NestedSetBuilder<Label> transitiveRootCauses = NestedSetBuilder.stableOrder(); + NestedSetBuilder<Cause> transitiveRootCauses = NestedSetBuilder.stableOrder(); AspectKey key = (AspectKey) skyKey.argument(); ConfiguredAspectFactory aspectFactory; Aspect aspect; @@ -274,7 +278,8 @@ public final class AspectFunction implements SkyFunction { baseConfiguredTargetValue = (ConfiguredTargetValue) baseAndAspectValues.get(key.getBaseConfiguredTargetKey()).get(); } catch (ConfiguredValueCreationException e) { - throw new AspectFunctionException(new AspectCreationException(e.getRootCauses())); + throw new AspectFunctionException( + new AspectCreationException(e.getMessage(), e.getRootCauses())); } if (aspectHasConfiguration) { @@ -364,7 +369,8 @@ public final class AspectFunction implements SkyFunction { associatedConfiguredTargetAndData.getTarget().getLocation(), e.getMessage())); throw new AspectFunctionException( - new AspectCreationException(e.getMessage(), associatedTarget.getLabel())); + new AspectCreationException( + e.getMessage(), associatedTarget.getLabel(), aspectConfiguration)); } } associatedConfiguredTargetAndData = @@ -416,7 +422,8 @@ public final class AspectFunction implements SkyFunction { key.getAspectConfigurationKey()); } catch (ToolchainContextException e) { // TODO(katre): better error handling - throw new AspectCreationException(e.getMessage()); + throw new AspectCreationException( + e.getMessage(), new LabelCause(key.getLabel(), e.getMessage())); } if (env.valuesMissing()) { return null; @@ -438,7 +445,7 @@ public final class AspectFunction implements SkyFunction { transitiveRootCauses, defaultBuildOptions); } catch (ConfiguredTargetFunctionException e) { - throw new AspectCreationException(e.getMessage()); + throw new AspectCreationException(e.getMessage(), key.getLabel(), aspectConfiguration); } if (depValueMap == null) { return null; @@ -463,17 +470,18 @@ public final class AspectFunction implements SkyFunction { } catch (DependencyEvaluationException e) { if (e.getCause() instanceof ConfiguredValueCreationException) { ConfiguredValueCreationException cause = (ConfiguredValueCreationException) e.getCause(); - throw new AspectFunctionException(new AspectCreationException( - cause.getMessage(), cause.getAnalysisRootCause())); + throw new AspectFunctionException( + new AspectCreationException(cause.getMessage(), cause.getRootCauses())); } else if (e.getCause() instanceof InconsistentAspectOrderException) { InconsistentAspectOrderException cause = (InconsistentAspectOrderException) e.getCause(); - throw new AspectFunctionException(new AspectCreationException( - cause.getMessage())); + throw new AspectFunctionException( + new AspectCreationException(cause.getMessage(), key.getLabel(), aspectConfiguration)); } else { // Cast to InvalidConfigurationException as a consistency check. If you add any // DependencyEvaluationException constructors, you may need to change this code, too. InvalidConfigurationException cause = (InvalidConfigurationException) e.getCause(); - throw new AspectFunctionException(new AspectCreationException(cause.getMessage())); + throw new AspectFunctionException( + new AspectCreationException(cause.getMessage(), key.getLabel(), aspectConfiguration)); } } catch (AspectCreationException e) { throw new AspectFunctionException(e); @@ -623,11 +631,11 @@ public final class AspectFunction implements SkyFunction { events.replayOn(env.getListener()); if (events.hasErrors()) { analysisEnvironment.disable(associatedTarget.getTarget()); + String msg = "Analysis of target '" + + associatedTarget.getTarget().getLabel() + + "' failed; build aborted"; throw new AspectFunctionException( - new AspectCreationException( - "Analysis of target '" - + associatedTarget.getTarget().getLabel() - + "' failed; build aborted")); + new AspectCreationException(msg, key.getLabel(), aspectConfiguration)); } Preconditions.checkState(!analysisEnvironment.hasErrors(), "Analysis environment hasError() but no errors reported"); @@ -672,41 +680,36 @@ public final class AspectFunction implements SkyFunction { * An exception indicating that there was a problem creating an aspect. */ public static final class AspectCreationException extends Exception { - /** Targets in the transitive closure that failed to load. May be empty. */ - private final NestedSet<Label> loadingRootCauses; - - /** - * The target for which analysis failed, if any. We can't represent aspects with labels, so if - * the aspect analysis fails, this will be {@code null}. - */ - @Nullable private final Label analysisRootCause; - - public AspectCreationException(String message, Label analysisRootCause) { - super(message); - this.loadingRootCauses = NestedSetBuilder.<Label>emptySet(Order.STABLE_ORDER); - this.analysisRootCause = analysisRootCause; + private static ConfigurationId toId(BuildConfiguration config) { + return config == null ? null : config.getEventId().asStreamProto().getConfiguration(); } - public AspectCreationException(String message, NestedSet<Label> loadingRootCauses) { + private final NestedSet<Cause> causes; + + public AspectCreationException(String message, NestedSet<Cause> causes) { super(message); - this.loadingRootCauses = loadingRootCauses; - this.analysisRootCause = null; + this.causes = causes; } - public AspectCreationException(NestedSet<Label> loadingRootCauses) { - this("Loading failed", loadingRootCauses); + public AspectCreationException( + String message, Label currentTarget, @Nullable BuildConfiguration configuration) { + this( + message, + NestedSetBuilder.<Cause>stableOrder() + .add(new AnalysisFailedCause(currentTarget, toId(configuration), message)) + .build()); } - public AspectCreationException(String message) { - this(message, (Label) null); + public AspectCreationException(String message, Label currentTarget) { + this(message, currentTarget, null); } - public NestedSet<Label> getRootCauses() { - return loadingRootCauses; + public AspectCreationException(String message, Cause cause) { + this(message, NestedSetBuilder.<Cause>stableOrder().add(cause).build()); } - @Nullable public Label getAnalysisRootCause() { - return analysisRootCause; + public NestedSet<Cause> getCauses() { + return causes; } } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/CompletionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/CompletionFunction.java index 05a4fbe1a3..83e879994f 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/CompletionFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/CompletionFunction.java @@ -322,7 +322,7 @@ public final class CompletionFunction<TValue extends SkyValue, TResult extends S missingCount++; final Label inputOwner = input.getOwner(); if (inputOwner != null) { - Cause cause = new LabelCause(inputOwner); + Cause cause = new LabelCause(inputOwner, e.getMessage()); rootCausesBuilder.add(cause); env.getListener().handle(completor.getRootCauseError(value, cause, env)); } 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 748451bbcb..a310fadf2b 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 @@ -41,11 +41,16 @@ import com.google.devtools.build.lib.analysis.config.InvalidConfigurationExcepti import com.google.devtools.build.lib.analysis.configuredtargets.MergedConfiguredTarget.DuplicateException; import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget; import com.google.devtools.build.lib.buildeventstream.BuildEventId; +import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildEventId.ConfigurationId; +import com.google.devtools.build.lib.causes.AnalysisFailedCause; +import com.google.devtools.build.lib.causes.Cause; +import com.google.devtools.build.lib.causes.LoadingFailedCause; 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.events.Event; +import com.google.devtools.build.lib.events.EventKind; import com.google.devtools.build.lib.events.StoredEventHandler; import com.google.devtools.build.lib.packages.Aspect; import com.google.devtools.build.lib.packages.Attribute; @@ -78,6 +83,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.Semaphore; +import java.util.stream.Collectors; import javax.annotation.Nullable; /** @@ -161,7 +167,7 @@ public final class ConfiguredTargetFunction implements SkyFunction { SkyframeBuildView view = buildViewProvider.getSkyframeBuildView(); NestedSetBuilder<Package> transitivePackagesForPackageRootResolution = storeTransitivePackagesForPackageRootResolution ? NestedSetBuilder.stableOrder() : null; - NestedSetBuilder<Label> transitiveLoadingRootCauses = NestedSetBuilder.stableOrder(); + NestedSetBuilder<Cause> transitiveRootCauses = NestedSetBuilder.stableOrder(); ConfiguredTargetKey configuredTargetKey = (ConfiguredTargetKey) key.argument(); Label label = configuredTargetKey.getLabel(); @@ -197,7 +203,8 @@ public final class ConfiguredTargetFunction implements SkyFunction { new ConfiguredValueCreationException(e.getMessage(), label, configuration)); } if (pkg.containsErrors()) { - transitiveLoadingRootCauses.add(label); + transitiveRootCauses.add( + new LoadingFailedCause(label, new NoSuchTargetException(target).getMessage())); } if (transitivePackagesForPackageRootResolution != null) { transitivePackagesForPackageRootResolution.add(pkg); @@ -241,7 +248,7 @@ public final class ConfiguredTargetFunction implements SkyFunction { resolver, ctgValue, transitivePackagesForPackageRootResolution, - transitiveLoadingRootCauses, + transitiveRootCauses, ((ConfiguredRuleClassProvider) ruleClassProvider).getTrimmingTransitionFactory()); if (env.valuesMissing()) { return null; @@ -253,9 +260,10 @@ public final class ConfiguredTargetFunction implements SkyFunction { // more root causes during computeDependencies. // Note that this doesn't apply to AspectFunction, because aspects can't have configurable // attributes. - if (!transitiveLoadingRootCauses.isEmpty() && configConditions != NO_CONFIG_CONDITIONS) { + if (!transitiveRootCauses.isEmpty() && configConditions != NO_CONFIG_CONDITIONS) { throw new ConfiguredTargetFunctionException( - new ConfiguredValueCreationException(transitiveLoadingRootCauses.build())); + new ConfiguredValueCreationException( + "Cannot compute config conditions", configuration, transitiveRootCauses.build())); } // Determine what toolchains are needed by this target. @@ -288,14 +296,15 @@ public final class ConfiguredTargetFunction implements SkyFunction { ruleClassProvider, view.getHostConfiguration(configuration), transitivePackagesForPackageRootResolution, - transitiveLoadingRootCauses, + transitiveRootCauses, defaultBuildOptions); if (env.valuesMissing()) { return null; } - if (!transitiveLoadingRootCauses.isEmpty()) { + if (!transitiveRootCauses.isEmpty()) { throw new ConfiguredTargetFunctionException( - new ConfiguredValueCreationException(transitiveLoadingRootCauses.build())); + new ConfiguredValueCreationException( + "Analysis failed", configuration, transitiveRootCauses.build())); } Preconditions.checkNotNull(depValueMap); ConfiguredTargetValue ans = @@ -315,21 +324,15 @@ public final class ConfiguredTargetFunction implements SkyFunction { // Check if this is caused by an unresolved toolchain, and report it as such. if (toolchainContext != null) { - ImmutableSet.Builder<Label> causes = new ImmutableSet.Builder<Label>(); - if (cvce.getAnalysisRootCause() != null) { - causes.add(cvce.getAnalysisRootCause()); - } - if (!cvce.getRootCauses().isEmpty()) { - causes.addAll(cvce.getRootCauses()); - } Set<Label> toolchainDependencyErrors = - toolchainContext.filterToolchainLabels(causes.build()); + toolchainContext.filterToolchainLabels( + Iterables.transform(cvce.getRootCauses(), Cause::getLabel)); if (!toolchainDependencyErrors.isEmpty()) { env.getListener() .handle( Event.error( String.format( - "While resolving toolchains for target %s: %s", + "XXX - While resolving toolchains for target %s: %s", target.getLabel(), e.getCause().getMessage()))); } } @@ -352,13 +355,11 @@ public final class ConfiguredTargetFunction implements SkyFunction { new ConfiguredValueCreationException(e.getMessage(), target.getLabel(), configuration)); } } catch (AspectCreationException e) { - // getAnalysisRootCause may be null if the analysis of the aspect itself failed. - Label analysisRootCause = target.getLabel(); - if (e.getAnalysisRootCause() != null) { - analysisRootCause = e.getAnalysisRootCause(); - } throw new ConfiguredTargetFunctionException( - new ConfiguredValueCreationException(e.getMessage(), analysisRootCause, configuration)); + new ConfiguredValueCreationException( + e.getMessage(), + configuration, + e.getCauses())); } catch (ToolchainContextException e) { // We need to throw a ConfiguredValueCreationException, so either find one or make one. ConfiguredValueCreationException cvce; @@ -415,7 +416,7 @@ public final class ConfiguredTargetFunction implements SkyFunction { RuleClassProvider ruleClassProvider, BuildConfiguration hostConfiguration, @Nullable NestedSetBuilder<Package> transitivePackagesForPackageRootResolution, - NestedSetBuilder<Label> transitiveLoadingRootCauses, + NestedSetBuilder<Cause> transitiveRootCauses, BuildOptions defaultBuildOptions) throws DependencyEvaluationException, ConfiguredTargetFunctionException, AspectCreationException, InterruptedException { @@ -431,14 +432,15 @@ public final class ConfiguredTargetFunction implements SkyFunction { toolchainContext == null ? ImmutableSet.of() : toolchainContext.getResolvedToolchainLabels(), - transitiveLoadingRootCauses, + transitiveRootCauses, defaultBuildOptions, ((ConfiguredRuleClassProvider) ruleClassProvider).getTrimmingTransitionFactory()); } 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())); throw new DependencyEvaluationException( - new ConfiguredValueCreationException(e.print(), ctgValue.getLabel())); + new ConfiguredValueCreationException( + e.print(), ctgValue.getLabel(), ctgValue.getConfiguration())); } catch (InvalidConfigurationException e) { throw new DependencyEvaluationException(e); } catch (InconsistentAspectOrderException e) { @@ -469,9 +471,10 @@ public final class ConfiguredTargetFunction implements SkyFunction { Map<SkyKey, ConfiguredTargetAndData> depValues = resolveConfiguredTargetDependencies( env, + ctgValue, depValueNames.values(), transitivePackagesForPackageRootResolution, - transitiveLoadingRootCauses); + transitiveRootCauses); if (depValues == null) { return null; } @@ -492,7 +495,8 @@ public final class ConfiguredTargetFunction implements SkyFunction { Event.error(ctgValue.getTarget().getLocation(), e.getMessage())); throw new ConfiguredTargetFunctionException( - new ConfiguredValueCreationException(e.getMessage(), ctgValue.getLabel())); + new ConfiguredValueCreationException( + e.getMessage(), ctgValue.getLabel(), ctgValue.getConfiguration())); } } @@ -510,7 +514,7 @@ public final class ConfiguredTargetFunction implements SkyFunction { SkyframeDependencyResolver resolver, TargetAndConfiguration ctgValue, @Nullable NestedSetBuilder<Package> transitivePackagesForPackageRootResolution, - NestedSetBuilder<Label> transitiveLoadingRootCauses, + NestedSetBuilder<Cause> transitiveRootCauses, @Nullable RuleTransitionFactory trimmingTransitionFactory) throws DependencyEvaluationException, InterruptedException { if (!(target instanceof Rule)) { @@ -538,7 +542,7 @@ public final class ConfiguredTargetFunction implements SkyFunction { Collection<Dependency> configValueNames; try { configValueNames = resolver.resolveRuleLabels( - ctgValue, configLabelMap, transitiveLoadingRootCauses, trimmingTransitionFactory); + ctgValue, configLabelMap, transitiveRootCauses, trimmingTransitionFactory); } catch (InconsistentAspectOrderException e) { throw new DependencyEvaluationException(e); } @@ -560,9 +564,10 @@ public final class ConfiguredTargetFunction implements SkyFunction { Map<SkyKey, ConfiguredTargetAndData> configValues = resolveConfiguredTargetDependencies( env, + ctgValue, configValueNames, transitivePackagesForPackageRootResolution, - transitiveLoadingRootCauses); + transitiveRootCauses); if (configValues == null) { return null; } @@ -580,8 +585,9 @@ public final class ConfiguredTargetFunction implements SkyFunction { String message = entry.getLabel() + " is not a valid configuration key for " + target.getLabel(); env.getListener().handle(Event.error(TargetUtils.getLocationMaybe(target), message)); - throw new DependencyEvaluationException(new ConfiguredValueCreationException( - message, target.getLabel())); + throw new DependencyEvaluationException( + new ConfiguredValueCreationException( + message, ctgValue.getLabel(), ctgValue.getConfiguration())); } } @@ -597,12 +603,13 @@ public final class ConfiguredTargetFunction implements SkyFunction { @Nullable private static Map<SkyKey, ConfiguredTargetAndData> resolveConfiguredTargetDependencies( Environment env, + TargetAndConfiguration ctgValue, Collection<Dependency> deps, @Nullable NestedSetBuilder<Package> transitivePackagesForPackageRootResolution, - NestedSetBuilder<Label> transitiveLoadingRootCauses) + NestedSetBuilder<Cause> transitiveRootCauses) throws DependencyEvaluationException, InterruptedException { boolean missedValues = env.valuesMissing(); - boolean failed = false; + String failWithMessage = null; // Naively we would like to just fetch all requested ConfiguredTargets, together with their // Packages. However, some ConfiguredTargets are AliasConfiguredTargets, which means that their // associated Targets (and therefore associated Packages) don't correspond to their own Labels. @@ -677,12 +684,8 @@ public final class ConfiguredTargetFunction implements SkyFunction { } } } catch (ConfiguredValueCreationException e) { - // 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; + transitiveRootCauses.addTransitive(e.rootCauses); + failWithMessage = e.getMessage(); } } if (aliasDepsToRedo.isEmpty()) { @@ -693,9 +696,10 @@ public final class ConfiguredTargetFunction implements SkyFunction { } if (missedValues) { return null; - } else if (failed) { + } else if (failWithMessage != null) { throw new DependencyEvaluationException( - new ConfiguredValueCreationException(transitiveLoadingRootCauses.build())); + new ConfiguredValueCreationException( + failWithMessage, ctgValue.getConfiguration(), transitiveRootCauses.build())); } else { return result; } @@ -753,11 +757,21 @@ public final class ConfiguredTargetFunction implements SkyFunction { events.replayOn(env.getListener()); if (events.hasErrors()) { analysisEnvironment.disable(target); + NestedSet<Cause> rootCauses = NestedSetBuilder.wrap( + Order.STABLE_ORDER, + events.getEvents().stream() + .filter((event) -> event.getKind() == EventKind.ERROR) + .map((event) -> + new AnalysisFailedCause( + target.getLabel(), + ConfiguredValueCreationException.toId(configuration), + event.getMessage())) + .collect(Collectors.toList())); throw new ConfiguredTargetFunctionException( new ConfiguredValueCreationException( "Analysis of target '" + target.getLabel() + "' failed; build aborted", - target.getLabel(), - configuration)); + configuration, + rootCauses)); } Preconditions.checkState(!analysisEnvironment.hasErrors(), "Analysis environment hasError() but no errors reported"); @@ -804,51 +818,41 @@ public final class ConfiguredTargetFunction implements SkyFunction { */ @AutoCodec public static final class ConfiguredValueCreationException extends Exception { - private final NestedSet<Label> loadingRootCauses; - // TODO(ulfjack): Collect all analysis root causes, not just the first one. - @Nullable private final Label analysisRootCause; - @Nullable private final BuildEventId configuration; - - private ConfiguredValueCreationException( - String message, Label currentTarget, BuildConfiguration configuration) { - this( - message, - Preconditions.checkNotNull(currentTarget), - NestedSetBuilder.<Label>emptySet(Order.STABLE_ORDER), - configuration == null ? null : configuration.getEventId()); + private static ConfigurationId toId(BuildConfiguration config) { + return config == null ? null : config.getEventId().asStreamProto().getConfiguration(); } + @Nullable private final BuildEventId configuration; + private final NestedSet<Cause> rootCauses; + @AutoCodec.VisibleForSerialization @AutoCodec.Instantiator ConfiguredValueCreationException( String message, - Label analysisRootCause, - NestedSet<Label> loadingRootCauses, - BuildEventId configuration) { + @Nullable BuildEventId configuration, + NestedSet<Cause> rootCauses) { super(message); - this.loadingRootCauses = loadingRootCauses; - this.analysisRootCause = analysisRootCause; + this.rootCauses = rootCauses; this.configuration = configuration; } - private ConfiguredValueCreationException(String message, Label currentTarget) { - this(message, currentTarget, /*configuration=*/ null); - } - - private ConfiguredValueCreationException(String message, NestedSet<Label> rootCauses) { - this(message, /*analysisRootCause=*/ null, rootCauses, /*configuration=*/ null); - } - - private ConfiguredValueCreationException(NestedSet<Label> rootCauses) { - this("Loading failed", rootCauses); + private ConfiguredValueCreationException( + String message, Label currentTarget, @Nullable BuildConfiguration configuration) { + this( + message, + configuration == null ? null : configuration.getEventId(), + NestedSetBuilder.<Cause>stableOrder() + .add(new AnalysisFailedCause(currentTarget, toId(configuration), message)) + .build()); } - public NestedSet<Label> getRootCauses() { - return loadingRootCauses; + private ConfiguredValueCreationException( + String message, @Nullable BuildConfiguration configuration, NestedSet<Cause> rootCauses) { + this(message, configuration == null ? null : configuration.getEventId(), rootCauses); } - @Nullable public Label getAnalysisRootCause() { - return analysisRootCause; + public NestedSet<Cause> getRootCauses() { + return rootCauses; } @Nullable public BuildEventId getConfiguration() { diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java index 9c36ba5daa..c4491ff6a0 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java @@ -34,12 +34,10 @@ import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictEx import com.google.devtools.build.lib.actions.PackageRoots; import com.google.devtools.build.lib.analysis.AnalysisFailureEvent; import com.google.devtools.build.lib.analysis.BlazeDirectories; -import com.google.devtools.build.lib.analysis.BuildView; import com.google.devtools.build.lib.analysis.CachingAnalysisEnvironment; import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider; import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.ConfiguredTargetFactory; -import com.google.devtools.build.lib.analysis.LegacyAnalysisFailureEvent; import com.google.devtools.build.lib.analysis.ToolchainContext; import com.google.devtools.build.lib.analysis.ViewCreationFailedException; import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory; @@ -51,6 +49,7 @@ import com.google.devtools.build.lib.analysis.config.FragmentClassSet; import com.google.devtools.build.lib.buildeventstream.BuildEventId; import com.google.devtools.build.lib.causes.Cause; import com.google.devtools.build.lib.causes.LabelCause; +import com.google.devtools.build.lib.causes.LoadingFailedCause; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.events.Event; @@ -78,10 +77,10 @@ import com.google.devtools.build.skyframe.SkyFunction.Environment; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; import java.util.Collection; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.logging.Logger; import javax.annotation.Nullable; /** @@ -90,8 +89,6 @@ import javax.annotation.Nullable; * <p>Covers enough functionality to work as a substitute for {@code BuildView#configureTargets}. */ public final class SkyframeBuildView { - private static final Logger logger = Logger.getLogger(BuildView.class.getName()); - private final ConfiguredTargetFactory factory; private final ArtifactFactory artifactFactory; private final SkyframeExecutor skyframeExecutor; @@ -332,26 +329,34 @@ public final class SkyframeBuildView { skyframeExecutor.getCyclesReporter().reportCycles(errorInfo.getCycleInfo(), errorKey, eventHandler); Exception cause = errorInfo.getException(); - Label analysisRootCause = null; BuildEventId configuration = null; Iterable<Cause> rootCauses; if (cause instanceof ConfiguredValueCreationException) { ConfiguredValueCreationException ctCause = (ConfiguredValueCreationException) cause; - for (Label rootCause : ctCause.getRootCauses()) { - hasLoadingError = true; - eventBus.post(new LoadingFailureEvent(topLevelLabel, rootCause)); + // Previously, the nested set was de-duplicating loading root cause labels. Now that we + // track Cause instances including a message, we get one event per label and message. In + // order to keep backwards compatibility, we de-duplicate root cause labels here. + // TODO(ulfjack): Remove this code once we've migrated to the BEP. + Set<Label> loadingRootCauses = new HashSet<>(); + for (Cause rootCause : ctCause.getRootCauses()) { + if (rootCause instanceof LoadingFailedCause) { + hasLoadingError = true; + loadingRootCauses.add(rootCause.getLabel()); + } } - analysisRootCause = ctCause.getAnalysisRootCause(); - rootCauses = analysisRootCause != null - ? ImmutableList.of(new LabelCause(analysisRootCause)) - : ImmutableList.copyOf(Iterables.transform(ctCause.getRootCauses(), LabelCause::new)); + for (Label loadingRootCause : loadingRootCauses) { + // This event is only for backwards compatibility with the old event protocol. Remove + // once we've migrated to the build event protocol. + eventBus.post(new LoadingFailureEvent(topLevelLabel, loadingRootCause)); + } + rootCauses = ctCause.getRootCauses(); configuration = ctCause.getConfiguration(); } else if (!Iterables.isEmpty(errorInfo.getCycleInfo())) { - analysisRootCause = maybeGetConfiguredTargetCycleCulprit( + Label analysisRootCause = maybeGetConfiguredTargetCycleCulprit( topLevelLabel, errorInfo.getCycleInfo()); - // TODO(ulfjack): Report the dependency cycle. rootCauses = analysisRootCause != null - ? ImmutableList.of(new LabelCause(analysisRootCause)) + ? ImmutableList.of(new LabelCause(analysisRootCause, "Dependency cycle")) + // TODO(ulfjack): We need to report the dependency cycle here. How? : ImmutableList.of(); } else if (cause instanceof ActionConflictException) { ((ActionConflictException) cause).reportTo(eventHandler); @@ -367,9 +372,6 @@ public final class SkyframeBuildView { ConfiguredTargetKey configuredTargetKey = ConfiguredTargetKey.of( topLevelLabel, label.getConfigurationKey(), label.isHostConfiguration()); - if (analysisRootCause != null) { - eventBus.post(new LegacyAnalysisFailureEvent(configuredTargetKey, analysisRootCause)); - } eventBus.post(new AnalysisFailureEvent(configuredTargetKey, configuration, rootCauses)); } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeDependencyResolver.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeDependencyResolver.java index f4940066c8..4d1b86bed2 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeDependencyResolver.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeDependencyResolver.java @@ -20,6 +20,8 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.BuildOptions; import com.google.devtools.build.lib.analysis.config.FragmentClassSet; import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; +import com.google.devtools.build.lib.causes.Cause; +import com.google.devtools.build.lib.causes.LoadingFailedCause; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.events.Event; @@ -86,14 +88,14 @@ public final class SkyframeDependencyResolver extends DependencyResolver { @Nullable @Override - protected Target getTarget(Target from, Label label, NestedSetBuilder<Label> rootCauses) + protected Target getTarget(Target from, Label label, NestedSetBuilder<Cause> rootCauses) throws InterruptedException { SkyKey key = PackageValue.key(label.getPackageIdentifier()); PackageValue packageValue; try { packageValue = (PackageValue) env.getValueOrThrow(key, NoSuchPackageException.class); } catch (NoSuchPackageException e) { - rootCauses.add(label); + rootCauses.add(new LoadingFailedCause(label, e.getMessage())); missingEdgeHook(from, label, e); return null; } @@ -107,7 +109,7 @@ public final class SkyframeDependencyResolver extends DependencyResolver { NoSuchTargetException e = new NoSuchTargetException(target); missingEdgeHook(from, label, e); if (target != null) { - rootCauses.add(label); + rootCauses.add(new LoadingFailedCause(label, e.getMessage())); return target; } else { return null; @@ -115,7 +117,7 @@ public final class SkyframeDependencyResolver extends DependencyResolver { } return target; } catch (NoSuchTargetException e) { - rootCauses.add(label); + rootCauses.add(new LoadingFailedCause(label, e.getMessage())); missingEdgeHook(from, label, e); return null; } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ToplevelSkylarkAspectFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ToplevelSkylarkAspectFunction.java index d2ce04f08e..ee2a30c37a 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/ToplevelSkylarkAspectFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/ToplevelSkylarkAspectFunction.java @@ -17,6 +17,7 @@ package com.google.devtools.build.lib.skyframe; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; +import com.google.devtools.build.lib.causes.LabelCause; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.events.Event; import com.google.devtools.build.lib.packages.SkylarkAspect; @@ -66,7 +67,7 @@ public class ToplevelSkylarkAspectFunction implements SkyFunction { } catch (SkylarkImportFailedException e) { env.getListener().handle(Event.error(e.getMessage())); throw new LoadSkylarkAspectFunctionException( - new AspectCreationException(e.getMessage())); + new AspectCreationException(e.getMessage(), Label.parseAbsoluteUnchecked("//:empty"))); } if (labelLookupMap == null) { return null; @@ -82,8 +83,9 @@ public class ToplevelSkylarkAspectFunction implements SkyFunction { return null; } if (!skylarkAspect.getParamAttributes().isEmpty()) { - throw new AspectCreationException("Cannot instantiate parameterized aspect " - + skylarkAspect.getName() + " at the top level.", extensionFileLabel); + String msg = "Cannot instantiate parameterized aspect " + skylarkAspect.getName() + + " at the top level."; + throw new AspectCreationException(msg, new LabelCause(extensionFileLabel, msg)); } } catch (AspectCreationException e) { throw new LoadSkylarkAspectFunctionException(e); |