Expose aspect actions from Skylark.
Like with providers, consumers get a merged view of all actions from the merged configured target (all other aspects + the base target).
I had to rejig the aspect value / configured aspect to be symmetric with rule configured targets.
I do not expect significant memory bloat from this. All lists / maps already existed, only extra fields have been added.
RELNOTES: Expose aspect actions provider to Skylark.
PiperOrigin-RevId: 201697923
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspect.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspect.java
index a33e6fe..e99d134 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspect.java
@@ -18,10 +18,14 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
+import com.google.devtools.build.lib.actions.Actions;
+import com.google.devtools.build.lib.actions.Actions.GeneratingActions;
import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
@@ -57,12 +61,20 @@
@Immutable
@AutoCodec
public final class ConfiguredAspect {
- private final TransitiveInfoProviderMap providers;
private final AspectDescriptor descriptor;
+ private final ImmutableList<ActionAnalysisMetadata> actions;
+ private final ImmutableMap<Artifact, Integer> generatingActionIndex;
+ private final TransitiveInfoProviderMap providers;
@AutoCodec.VisibleForSerialization
- ConfiguredAspect(AspectDescriptor descriptor, TransitiveInfoProviderMap providers) {
+ ConfiguredAspect(
+ AspectDescriptor descriptor,
+ ImmutableList<ActionAnalysisMetadata> actions,
+ ImmutableMap<Artifact, Integer> generatingActionIndex,
+ TransitiveInfoProviderMap providers) {
this.descriptor = descriptor;
+ this.actions = actions;
+ this.generatingActionIndex = generatingActionIndex;
this.providers = providers;
}
@@ -80,6 +92,18 @@
return descriptor;
}
+ public ImmutableList<ActionAnalysisMetadata> getActions() {
+ return actions;
+ }
+
+ /**
+ * Returns a map where keys are artifacts that are action outputs of this rule, and values are the
+ * index of the action that generates that artifact.
+ */
+ public ImmutableMap<Artifact, Integer> getGeneratingActionIndex() {
+ return generatingActionIndex;
+ }
+
/** Returns the providers created by the aspect. */
public TransitiveInfoProviderMap getProviders() {
return providers;
@@ -112,11 +136,16 @@
}
public static ConfiguredAspect forAlias(ConfiguredAspect real) {
- return new ConfiguredAspect(real.descriptor, real.getProviders());
+ return new ConfiguredAspect(
+ real.descriptor, real.getActions(), real.getGeneratingActionIndex(), real.getProviders());
}
public static ConfiguredAspect forNonapplicableTarget(AspectDescriptor descriptor) {
- return new ConfiguredAspect(descriptor, new TransitiveInfoProviderMapBuilder().add().build());
+ return new ConfiguredAspect(
+ descriptor,
+ ImmutableList.of(),
+ ImmutableMap.of(),
+ new TransitiveInfoProviderMapBuilder().add().build());
}
public static Builder builder(
@@ -230,8 +259,7 @@
return this;
}
-
- public ConfiguredAspect build() {
+ public ConfiguredAspect build() throws ActionConflictException {
if (!outputGroupBuilders.isEmpty()) {
ImmutableMap.Builder<String, NestedSet<Artifact>> outputGroups = ImmutableMap.builder();
for (Map.Entry<String, NestedSetBuilder<Artifact>> entry : outputGroupBuilders.entrySet()) {
@@ -250,7 +278,17 @@
/* actionsWithoutExtraAction= */ ImmutableSet.<ActionAnalysisMetadata>of(),
ruleContext));
- return new ConfiguredAspect(descriptor, providers.build());
+ AnalysisEnvironment analysisEnvironment = ruleContext.getAnalysisEnvironment();
+ GeneratingActions generatingActions =
+ Actions.filterSharedActionsAndThrowActionConflict(
+ analysisEnvironment.getActionKeyContext(),
+ analysisEnvironment.getRegisteredActions());
+
+ return new ConfiguredAspect(
+ descriptor,
+ generatingActions.getActions(),
+ generatingActions.getGeneratingActionIndex(),
+ providers.build());
}
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspectFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspectFactory.java
index 18462fb..a613ec6 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspectFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspectFactory.java
@@ -13,6 +13,7 @@
// limitations under the License.
package com.google.devtools.build.lib.analysis;
+import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.packages.AspectParameters;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
@@ -30,5 +31,5 @@
*/
ConfiguredAspect create(
ConfiguredTargetAndData ctadBase, RuleContext context, AspectParameters parameters)
- throws InterruptedException;
+ throws ActionConflictException, InterruptedException;
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java
index 456c6a1..c04365a 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java
@@ -64,6 +64,7 @@
import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.profiler.memory.CurrentRuleTracker;
+import com.google.devtools.build.lib.skyframe.AspectFunction.AspectFunctionException;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
import com.google.devtools.build.lib.util.OrderedSetMultimap;
@@ -389,7 +390,7 @@
@Nullable ToolchainContext toolchainContext,
BuildConfiguration aspectConfiguration,
BuildConfiguration hostConfiguration)
- throws InterruptedException {
+ throws AspectFunctionException, InterruptedException {
// Load the requested toolchains into the ToolchainContext.
if (toolchainContext != null) {
@@ -424,8 +425,13 @@
return null;
}
- ConfiguredAspect configuredAspect =
- aspectFactory.create(associatedTarget, ruleContext, aspect.getParameters());
+ ConfiguredAspect configuredAspect;
+ try {
+ configuredAspect =
+ aspectFactory.create(associatedTarget, ruleContext, aspect.getParameters());
+ } catch (ActionConflictException e) {
+ throw new AspectFunctionException(e);
+ }
if (configuredAspect != null) {
validateAdvertisedProviders(
configuredAspect, aspect.getDefinition().getAdvertisedProviders(),
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/MergedConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/MergedConfiguredTarget.java
index bb1e908..1e60f64 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/MergedConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/MergedConfiguredTarget.java
@@ -15,6 +15,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
import com.google.devtools.build.lib.analysis.AnalysisUtils;
import com.google.devtools.build.lib.analysis.ConfiguredAspect;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
@@ -39,6 +40,7 @@
*/
public final class MergedConfiguredTarget extends AbstractConfiguredTarget {
private final ConfiguredTarget base;
+ private final ImmutableList<ConfiguredAspect> aspects;
private final TransitiveInfoProviderMap providers;
/**
@@ -52,9 +54,13 @@
}
}
- private MergedConfiguredTarget(ConfiguredTarget base, TransitiveInfoProviderMap providers) {
+ private MergedConfiguredTarget(
+ ConfiguredTarget base,
+ Iterable<ConfiguredAspect> aspects,
+ TransitiveInfoProviderMap providers) {
super(base.getLabel(), base.getConfigurationKey());
this.base = base;
+ this.aspects = ImmutableList.copyOf(aspects);
this.providers = providers;
}
@@ -81,6 +87,7 @@
result.accept((String) classAt);
}
}
+ result.accept(RuleConfiguredTarget.ACTIONS_FIELD_NAME);
}
@Override
@@ -94,6 +101,16 @@
@Override
protected Object rawGetSkylarkProvider(String providerKey) {
+ if (providerKey.equals(RuleConfiguredTarget.ACTIONS_FIELD_NAME)) {
+ ImmutableList.Builder<ActionAnalysisMetadata> actions = ImmutableList.builder();
+ for (ConfiguredAspect aspect : aspects) {
+ actions.addAll(aspect.getActions());
+ }
+ if (base instanceof RuleConfiguredTarget) {
+ actions.addAll(((RuleConfiguredTarget) base).getActions());
+ }
+ return actions.build();
+ }
Object provider = providers.getProvider(providerKey);
if (provider == null) {
provider = base.get(providerKey);
@@ -159,7 +176,7 @@
}
}
}
- return new MergedConfiguredTarget(base, aspectProviders.build());
+ return new MergedConfiguredTarget(base, aspects, aspectProviders.build());
}
private static ImmutableList<OutputGroupInfo> getAllOutputGroupProviders(
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/RuleConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/RuleConfiguredTarget.java
index bea36d8..2f668f6 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/RuleConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/RuleConfiguredTarget.java
@@ -60,7 +60,13 @@
*/
@AutoCodec(checkClassExplicitlyAllowed = true)
public final class RuleConfiguredTarget extends AbstractConfiguredTarget {
- private static final String ACTIONS_FIELD_NAME = "actions";
+ /**
+ * The name of the key for the 'actions' synthesized provider.
+ *
+ * <p>If you respond to this key you are expected to return a list of actions belonging to this
+ * configured target.
+ */
+ public static final String ACTIONS_FIELD_NAME = "actions";
/**
* The configuration transition for an attribute through which a prerequisite