When --experimental_extra_action_top_level_only, Bazel to report extra-actions for actions registered by Aspects injected by a top-level rule.
Because we can't know whether an aspect was injected by a top-level target or one of its children, we approximate it by only reporting extra-actions from Aspects that the top-level target could have injected.
RELNOTES: When --experimental_extra_action_top_level_only, Bazel reports extra-actions for actions registered by Aspects injected by a top-level rule (approximately).
--
MOS_MIGRATED_REVID=138570606
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 6376fd5..239fd93 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
@@ -14,6 +14,8 @@
package com.google.devtools.build.lib.analysis;
+import static com.google.common.collect.Iterables.concat;
+
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
@@ -47,6 +49,7 @@
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.StoredEventHandler;
+import com.google.devtools.build.lib.packages.AspectClass;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.NativeAspectClass;
@@ -62,6 +65,7 @@
import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider;
import com.google.devtools.build.lib.skyframe.ActionLookupValue;
import com.google.devtools.build.lib.skyframe.AspectValue;
+import com.google.devtools.build.lib.skyframe.AspectValue.AspectKey;
import com.google.devtools.build.lib.skyframe.AspectValue.AspectValueKey;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetValue;
@@ -71,7 +75,6 @@
import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.util.OrderedSetMultimap;
-import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.util.Preconditions;
import com.google.devtools.build.lib.util.RegexFilter;
import com.google.devtools.build.lib.vfs.Path;
@@ -631,54 +634,13 @@
Collection<ConfiguredTarget> configuredTargets,
Collection<AspectValue> aspects,
Set<Artifact> artifactsToBuild) {
- addExtraActionsIfRequested(viewOptions, artifactsToBuild,
- Iterables.transform(configuredTargets,
- new Function<ConfiguredTarget, Pair<Label, ExtraActionArtifactsProvider>>() {
- @Nullable
- @Override
- public Pair<Label, ExtraActionArtifactsProvider> apply(
- ConfiguredTarget configuredTarget) {
- return Pair.of(
- configuredTarget.getLabel(),
- configuredTarget.getProvider(ExtraActionArtifactsProvider.class));
- }
- }));
- addExtraActionsIfRequested(viewOptions, artifactsToBuild,
- Iterables.transform(aspects,
- new Function<AspectValue, Pair<Label, ExtraActionArtifactsProvider>>() {
- @Nullable
- @Override
- public Pair<Label, ExtraActionArtifactsProvider> apply(
- AspectValue aspectValue) {
- return Pair.of(
- aspectValue.getLabel(),
- aspectValue
- .getConfiguredAspect()
- .getProvider(ExtraActionArtifactsProvider.class));
- }
- }
- ));
- }
-
- private void addExtraActionsIfRequested(BuildView.Options viewOptions,
- Set<Artifact> artifactsToBuild,
- Iterable<Pair<Label, ExtraActionArtifactsProvider>> providers) {
- NestedSetBuilder<ExtraArtifactSet> builder = NestedSetBuilder.stableOrder();
- for (Pair<Label, ExtraActionArtifactsProvider> labelAndProvider : providers) {
- ExtraActionArtifactsProvider provider = labelAndProvider.getSecond();
- if (provider != null) {
- if (viewOptions.extraActionTopLevelOnly) {
- builder.add(ExtraArtifactSet.of(
- labelAndProvider.getFirst(),
- provider.getExtraActionArtifacts()));
- } else {
- builder.addTransitive(provider.getTransitiveExtraActionArtifacts());
- }
- }
- }
+ Iterable<ExtraArtifactSet> xaSets =
+ concat(
+ addExtraActionsFromTargets(viewOptions, configuredTargets),
+ addExtraActionsFromAspects(viewOptions, aspects));
RegexFilter filter = viewOptions.extraActionFilter;
- for (ExtraArtifactSet set : builder.build()) {
+ for (ExtraArtifactSet set : xaSets) {
boolean filterMatches = filter == null || filter.isIncluded(set.getLabel().toString());
if (filterMatches) {
artifactsToBuild.addAll(set.getArtifacts());
@@ -686,6 +648,77 @@
}
}
+ private NestedSet<ExtraArtifactSet> addExtraActionsFromTargets(
+ BuildView.Options viewOptions, Collection<ConfiguredTarget> configuredTargets) {
+ NestedSetBuilder<ExtraArtifactSet> builder = NestedSetBuilder.stableOrder();
+ for (ConfiguredTarget target : configuredTargets) {
+ ExtraActionArtifactsProvider provider =
+ target.getProvider(ExtraActionArtifactsProvider.class);
+ if (provider != null) {
+ if (viewOptions.extraActionTopLevelOnly) {
+ // Collect all aspect-classes that topLevel might inject.
+ Set<AspectClass> aspectClasses = new HashSet<>();
+ for (Attribute attr : target.getTarget().getAssociatedRule().getAttributes()) {
+ aspectClasses.addAll(attr.getAspectClasses());
+ }
+
+ Iterable<Artifact> artifacts;
+ if (aspectClasses.isEmpty()) {
+ artifacts = provider.getExtraActionArtifacts();
+ } else {
+ ImmutableList.Builder<Artifact> artifactBuilder = ImmutableList.builder();
+ artifactBuilder.addAll(provider.getExtraActionArtifacts());
+ artifactBuilder.addAll(filterTransitiveExtraActions(provider, aspectClasses));
+ artifacts = artifactBuilder.build();
+ }
+ builder.add(ExtraArtifactSet.of(target.getLabel(), artifacts));
+ } else {
+ builder.addTransitive(provider.getTransitiveExtraActionArtifacts());
+ }
+ }
+ }
+ return builder.build();
+ }
+
+ /**
+ * Returns a list of actions from 'provider' that were registered by an aspect from
+ * 'aspectClasses'. All actions in 'provider' are considered - both direct and transitive.
+ */
+ private ImmutableList<Artifact> filterTransitiveExtraActions(
+ ExtraActionArtifactsProvider provider, Set<AspectClass> aspectClasses) {
+ ImmutableList.Builder<Artifact> artifacts = ImmutableList.builder();
+ // Add to 'artifacts' all extra-actions which were registered by aspects which 'topLevel'
+ // might have injected.
+ for (ExtraArtifactSet extraArtifactSet : provider.getTransitiveExtraActionArtifacts()) {
+ for (Artifact artifact : extraArtifactSet.getArtifacts()) {
+ ArtifactOwner owner = artifact.getArtifactOwner();
+ if (owner instanceof AspectKey) {
+ if (aspectClasses.contains(((AspectKey) owner).getAspectClass())) {
+ artifacts.add(artifact);
+ }
+ }
+ }
+ }
+ return artifacts.build();
+ }
+
+ private NestedSet<ExtraArtifactSet> addExtraActionsFromAspects(
+ BuildView.Options viewOptions, Collection<AspectValue> aspects) {
+ NestedSetBuilder<ExtraArtifactSet> builder = NestedSetBuilder.stableOrder();
+ for (AspectValue aspect : aspects) {
+ ExtraActionArtifactsProvider provider =
+ aspect.getConfiguredAspect().getProvider(ExtraActionArtifactsProvider.class);
+ if (provider != null) {
+ if (viewOptions.extraActionTopLevelOnly) {
+ builder.add(ExtraArtifactSet.of(aspect.getLabel(), provider.getExtraActionArtifacts()));
+ } else {
+ builder.addTransitive(provider.getTransitiveExtraActionArtifacts());
+ }
+ }
+ }
+ return builder.build();
+ }
+
private static void scheduleTestsIfRequested(Collection<ConfiguredTarget> targetsToTest,
Collection<ConfiguredTarget> targetsToTestExclusive, TopLevelArtifactContext topLevelOptions,
Collection<ConfiguredTarget> allTestTargets) {