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/test/java/com/google/devtools/build/lib/analysis/AspectTest.java b/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
index fe64dbd..7ecbba6 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/AspectTest.java
@@ -25,6 +25,7 @@
import com.google.common.collect.Iterables;
import com.google.common.eventbus.EventBus;
import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil.NullAction;
import com.google.devtools.build.lib.analysis.config.HostTransition;
import com.google.devtools.build.lib.analysis.util.AnalysisTestCase;
@@ -437,7 +438,7 @@
@Override
public ConfiguredAspect create(
ConfiguredTargetAndData ctadBase, RuleContext ruleContext, AspectParameters parameters)
- throws InterruptedException {
+ throws InterruptedException, ActionConflictException {
Object lateBoundPrereq = ruleContext.getPrerequisite(":late", TARGET);
return new ConfiguredAspect.Builder(this, parameters, ruleContext)
.addProvider(
@@ -507,7 +508,7 @@
@Override
public ConfiguredAspect create(
ConfiguredTargetAndData ctadBase, RuleContext ruleContext, AspectParameters parameters)
- throws InterruptedException {
+ throws InterruptedException, ActionConflictException {
ruleContext.registerAction(new NullAction(ruleContext.createOutputArtifact()));
return new ConfiguredAspect.Builder(this, parameters, ruleContext).build();
}
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java b/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java
index cebf5db..22220e5 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/util/TestAspects.java
@@ -228,7 +228,8 @@
implements ConfiguredAspectFactory {
@Override
public ConfiguredAspect create(
- ConfiguredTargetAndData ctadBase, RuleContext ruleContext, AspectParameters parameters) {
+ ConfiguredTargetAndData ctadBase, RuleContext ruleContext, AspectParameters parameters)
+ throws ActionConflictException {
String information = parameters.isEmpty()
? ""
: " data " + Iterables.getFirst(parameters.getAttribute("baz"), null);
@@ -274,7 +275,8 @@
@Override
public ConfiguredAspect create(
- ConfiguredTargetAndData ctadBase, RuleContext ruleContext, AspectParameters parameters) {
+ ConfiguredTargetAndData ctadBase, RuleContext ruleContext, AspectParameters parameters)
+ throws ActionConflictException {
return new ConfiguredAspect.Builder(this, parameters, ruleContext)
.addProvider(new FooProvider())
.build();
@@ -293,7 +295,8 @@
@Override
public ConfiguredAspect create(
- ConfiguredTargetAndData ctadBase, RuleContext ruleContext, AspectParameters parameters) {
+ ConfiguredTargetAndData ctadBase, RuleContext ruleContext, AspectParameters parameters)
+ throws ActionConflictException {
return new ConfiguredAspect.Builder(this, parameters, ruleContext)
.addProvider(new BarProvider())
.build();
@@ -428,7 +431,8 @@
@Override
public ConfiguredAspect create(
- ConfiguredTargetAndData ctadBase, RuleContext ruleContext, AspectParameters parameters) {
+ ConfiguredTargetAndData ctadBase, RuleContext ruleContext, AspectParameters parameters)
+ throws ActionConflictException {
StringBuilder information = new StringBuilder("aspect " + ruleContext.getLabel());
if (!parameters.isEmpty()) {
information.append(" data " + Iterables.getFirst(parameters.getAttribute("baz"), null));
@@ -475,7 +479,8 @@
@Override
public ConfiguredAspect create(
- ConfiguredTargetAndData ctadBase, RuleContext ruleContext, AspectParameters parameters) {
+ ConfiguredTargetAndData ctadBase, RuleContext ruleContext, AspectParameters parameters)
+ throws ActionConflictException {
ruleContext.ruleWarning("Aspect warning on " + ctadBase.getTarget().getLabel());
return new ConfiguredAspect.Builder(this, parameters, ruleContext).build();
}
@@ -531,7 +536,7 @@
@Override
public ConfiguredAspect create(
ConfiguredTargetAndData ctadBase, RuleContext context, AspectParameters parameters)
- throws InterruptedException {
+ throws InterruptedException, ActionConflictException {
return new ConfiguredAspect.Builder(this, parameters, context).build();
}
}
@@ -777,7 +782,7 @@
@Override
public ConfiguredAspect create(
ConfiguredTargetAndData ctadBase, RuleContext context, AspectParameters parameters)
- throws InterruptedException {
+ throws InterruptedException, ActionConflictException {
return ConfiguredAspect.builder(this, parameters, context)
.addProvider(Provider.class, new Provider(ctadBase.getConfiguredTarget().getLabel()))
.build();
diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkDefinedAspectsTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkDefinedAspectsTest.java
index 57170f8..b81b493 100644
--- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkDefinedAspectsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkDefinedAspectsTest.java
@@ -17,10 +17,12 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.devtools.build.lib.analysis.OutputGroupInfo.INTERNAL_SUFFIX;
+import static java.util.stream.Collectors.toList;
import static org.junit.Assert.fail;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.AnalysisResult;
import com.google.devtools.build.lib.analysis.ConfiguredAspect;
@@ -2589,6 +2591,58 @@
assertThat(objcProtoProvider).isNotNull();
}
+ @Test
+ public void testAspectActionProvider() throws Exception {
+ scratch.file(
+ "test/aspect.bzl",
+ "a1p = provider()",
+ "def _a1_impl(target,ctx):",
+ " ctx.actions.run_shell(",
+ " outputs = [ctx.actions.declare_file('a1')],",
+ " command = 'touch $@'",
+ " )",
+ " return struct(a1p=a1p())",
+ "a1 = aspect(_a1_impl, attr_aspects = ['dep'], provides = ['a1p'])",
+ "a2p = provider()",
+ "def _a2_impl(target, ctx):",
+ " value = []",
+ " if hasattr(ctx.rule.attr, 'dep') and hasattr(ctx.rule.attr.dep, 'a2p'):",
+ " value += ctx.rule.attr.dep.a2p.value",
+ " value += target.actions",
+ " return struct(a2p = a2p(value = value))",
+ "a2 = aspect(_a2_impl, attr_aspects = ['dep'], required_aspect_providers = ['a1p'])",
+ "def _r0_impl(ctx):",
+ " ctx.actions.run_shell(",
+ " outputs = [ctx.actions.declare_file('r0')],",
+ " command = 'touch $@'",
+ " )",
+ "def _r1_impl(ctx):",
+ " pass",
+ "def _r2_impl(ctx):",
+ " return struct(result = ctx.attr.dep.a2p.value)",
+ "r0 = rule(_r0_impl)",
+ "r1 = rule(_r1_impl, attrs = { 'dep' : attr.label(aspects = [a1])})",
+ "r2 = rule(_r2_impl, attrs = { 'dep' : attr.label(aspects = [a2])})");
+ scratch.file(
+ "test/BUILD",
+ "load(':aspect.bzl', 'r0', 'r1', 'r2')",
+ "r0(name = 'r0')",
+ "r1(name = 'r1', dep = ':r0')",
+ "r2(name = 'r2', dep = ':r1')");
+ AnalysisResult analysisResult = update("//test:r2");
+ ConfiguredTarget target = Iterables.getOnlyElement(analysisResult.getTargetsToBuild());
+ SkylarkList<?> result = (SkylarkList<?>) target.get("result");
+
+ // We should see both the action from the 'r0' rule, and the action from the 'a1' aspect
+ assertThat(result).hasSize(2);
+ assertThat(
+ result
+ .stream()
+ .map(a -> ((Action) a).getPrimaryOutput().getExecPath().getBaseName())
+ .collect(toList()))
+ .containsExactly("r0", "a1");
+ }
+
/** SkylarkAspectTest with "keep going" flag */
@RunWith(JUnit4.class)
public static final class WithKeepGoing extends SkylarkDefinedAspectsTest {