aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/AspectCompleteEvent.java78
-rw-r--r--src/main/java/com/google/devtools/build/lib/buildeventstream/BuildEventId.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto4
-rw-r--r--src/main/java/com/google/devtools/build/lib/buildtool/ExecutionProgressReceiver.java6
-rwxr-xr-xsrc/test/shell/integration/build_event_stream_test.sh24
5 files changed, 110 insertions, 12 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AspectCompleteEvent.java b/src/main/java/com/google/devtools/build/lib/analysis/AspectCompleteEvent.java
index 763a29454e..0bdbd9e71e 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/AspectCompleteEvent.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/AspectCompleteEvent.java
@@ -13,7 +13,18 @@
// limitations under the License.
package com.google.devtools.build.lib.analysis;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.TopLevelArtifactHelper.ArtifactsInOutputGroup;
+import com.google.devtools.build.lib.analysis.TopLevelArtifactHelper.ArtifactsToBuild;
+import com.google.devtools.build.lib.buildeventstream.BuildEventId;
+import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos;
+import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.File;
+import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.OutputGroup;
+import com.google.devtools.build.lib.buildeventstream.BuildEventWithOrderConstraint;
+import com.google.devtools.build.lib.buildeventstream.GenericBuildEvent;
+import com.google.devtools.build.lib.buildeventstream.PathConverter;
import com.google.devtools.build.lib.causes.Cause;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
@@ -21,25 +32,32 @@ import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.skyframe.AspectValue;
import com.google.devtools.build.lib.util.Preconditions;
import com.google.devtools.build.skyframe.SkyValue;
+import java.util.Collection;
-/**
- * This event is fired as soon as a top-level aspect is either built or fails.
- */
-public class AspectCompleteEvent implements SkyValue {
+/** This event is fired as soon as a top-level aspect is either built or fails. */
+public class AspectCompleteEvent implements SkyValue, BuildEventWithOrderConstraint {
private final AspectValue aspectValue;
private final NestedSet<Cause> rootCauses;
+ private final Collection<BuildEventId> postedAfter;
+ private final ArtifactsToBuild artifacts;
- private AspectCompleteEvent(AspectValue aspectValue, NestedSet<Cause> rootCauses) {
+ private AspectCompleteEvent(
+ AspectValue aspectValue, NestedSet<Cause> rootCauses, ArtifactsToBuild artifacts) {
this.aspectValue = aspectValue;
this.rootCauses =
(rootCauses == null) ? NestedSetBuilder.<Cause>emptySet(Order.STABLE_ORDER) : rootCauses;
+ ImmutableList.Builder postedAfterBuilder = ImmutableList.builder();
+ for (Cause cause : getRootCauses()) {
+ postedAfterBuilder.add(BuildEventId.fromCause(cause));
+ }
+ this.postedAfter = postedAfterBuilder.build();
+ this.artifacts = artifacts;
}
- /**
- * Construct a successful target completion event.
- */
- public static AspectCompleteEvent createSuccessful(AspectValue value) {
- return new AspectCompleteEvent(value, null);
+ /** Construct a successful target completion event. */
+ public static AspectCompleteEvent createSuccessful(
+ AspectValue value, ArtifactsToBuild artifacts) {
+ return new AspectCompleteEvent(value, null, artifacts);
}
/**
@@ -47,7 +65,7 @@ public class AspectCompleteEvent implements SkyValue {
*/
public static AspectCompleteEvent createFailed(AspectValue value, NestedSet<Cause> rootCauses) {
Preconditions.checkArgument(!Iterables.isEmpty(rootCauses));
- return new AspectCompleteEvent(value, rootCauses);
+ return new AspectCompleteEvent(value, rootCauses, null);
}
/**
@@ -68,4 +86,42 @@ public class AspectCompleteEvent implements SkyValue {
public Iterable<Cause> getRootCauses() {
return rootCauses;
}
+
+ @Override
+ public BuildEventId getEventId() {
+ return BuildEventId.aspectCompleted(
+ aspectValue.getLabel(), aspectValue.getAspect().getDescriptor().getDescription());
+ }
+
+ @Override
+ public Collection<BuildEventId> postedAfter() {
+ return postedAfter;
+ }
+
+ @Override
+ public Collection<BuildEventId> getChildrenEvents() {
+ return ImmutableList.of();
+ }
+
+ @Override
+ public BuildEventStreamProtos.BuildEvent asStreamProto(PathConverter pathConverter) {
+ BuildEventStreamProtos.TargetComplete.Builder builder =
+ BuildEventStreamProtos.TargetComplete.newBuilder();
+ builder.setSuccess(!failed());
+ if (artifacts != null) {
+ for (ArtifactsInOutputGroup artifactsInGroup : artifacts.getAllArtifactsByOutputGroup()) {
+ OutputGroup.Builder groupBuilder = OutputGroup.newBuilder();
+ groupBuilder.setName(artifactsInGroup.getOutputGroup());
+
+ File.Builder fileBuilder = File.newBuilder();
+ for (Artifact artifact : artifactsInGroup.getArtifacts()) {
+ String name = artifact.getFilename();
+ String uri = pathConverter.apply(artifact.getPath());
+ groupBuilder.addOutputFile(fileBuilder.setName(name).setUri(uri).build());
+ }
+ builder.addOutputGroup(groupBuilder.build());
+ }
+ }
+ return GenericBuildEvent.protoChaining(this).setCompleted(builder.build()).build();
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/buildeventstream/BuildEventId.java b/src/main/java/com/google/devtools/build/lib/buildeventstream/BuildEventId.java
index 3a89fa5aeb..81f9eac0aa 100644
--- a/src/main/java/com/google/devtools/build/lib/buildeventstream/BuildEventId.java
+++ b/src/main/java/com/google/devtools/build/lib/buildeventstream/BuildEventId.java
@@ -117,6 +117,16 @@ public final class BuildEventId implements Serializable {
BuildEventStreamProtos.BuildEventId.newBuilder().setTargetCompleted(targetId).build());
}
+ public static BuildEventId aspectCompleted(Label target, String aspect) {
+ BuildEventStreamProtos.BuildEventId.TargetCompletedId targetId =
+ BuildEventStreamProtos.BuildEventId.TargetCompletedId.newBuilder()
+ .setLabel(target.toString())
+ .setAspect(aspect)
+ .build();
+ return new BuildEventId(
+ BuildEventStreamProtos.BuildEventId.newBuilder().setTargetCompleted(targetId).build());
+ }
+
public static BuildEventId fromCause(Cause cause) {
return new BuildEventId(cause.getIdProto());
}
diff --git a/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto b/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto
index 072a7ef9ca..a4592faac1 100644
--- a/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto
+++ b/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto
@@ -63,6 +63,10 @@ message BuildEventId {
// does not include running the test if the target is a test target.
message TargetCompletedId {
string label = 1;
+
+ // If not empty, the id refers to the completion of the target for a given
+ // aspect.
+ string aspect = 2;
}
// Identifier of an event reporting that an action was completed (not all
diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionProgressReceiver.java b/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionProgressReceiver.java
index bb6fd0874f..bd8f8cb7a8 100644
--- a/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionProgressReceiver.java
+++ b/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionProgressReceiver.java
@@ -27,6 +27,7 @@ import com.google.devtools.build.lib.analysis.TopLevelArtifactHelper.ArtifactsTo
import com.google.devtools.build.lib.skyframe.ActionExecutionInactivityWatchdog;
import com.google.devtools.build.lib.skyframe.ActionExecutionValue;
import com.google.devtools.build.lib.skyframe.AspectCompletionValue;
+import com.google.devtools.build.lib.skyframe.AspectValue;
import com.google.devtools.build.lib.skyframe.SkyFunctions;
import com.google.devtools.build.lib.skyframe.SkyframeActionExecutor;
import com.google.devtools.build.lib.skyframe.TargetCompletionValue;
@@ -120,7 +121,10 @@ public final class ExecutionProgressReceiver
} else if (type.equals(SkyFunctions.ASPECT_COMPLETION)) {
AspectCompletionValue value = (AspectCompletionValue) skyValueSupplier.get();
if (value != null) {
- eventBus.post(AspectCompleteEvent.createSuccessful(value.getAspectValue()));
+ AspectValue aspectValue = value.getAspectValue();
+ ArtifactsToBuild artifacts =
+ TopLevelArtifactHelper.getAllArtifactsToBuild(aspectValue, topLevelArtifactContext);
+ eventBus.post(AspectCompleteEvent.createSuccessful(aspectValue, artifacts));
}
} else if (type.equals(SkyFunctions.ACTION_EXECUTION)) {
// Remember all completed actions, even those in error, regardless of having been cached or
diff --git a/src/test/shell/integration/build_event_stream_test.sh b/src/test/shell/integration/build_event_stream_test.sh
index e9700acad8..5a8a0fe880 100755
--- a/src/test/shell/integration/build_event_stream_test.sh
+++ b/src/test/shell/integration/build_event_stream_test.sh
@@ -73,6 +73,19 @@ genrule(
tags = ["tag1", "tag2"]
)
EOF
+cat > simpleaspect.bzl <<EOF
+def _simple_aspect_impl(target, ctx):
+ for orig_out in ctx.rule.attr.outs:
+ aspect_out = ctx.new_file(orig_out.name + ".aspect")
+ ctx.file_action(
+ output=aspect_out,
+ content = "Hello from aspect")
+ return struct(output_groups={
+ "aspect-out" : set([aspect_out]) })
+
+simple_aspect = aspect(implementation=_simple_aspect_impl)
+EOF
+touch BUILD
}
#### TESTS #############################################################
@@ -223,6 +236,17 @@ function test_target_complete() {
expect_log 'tag2'
}
+function test_aspect_artifacts() {
+ bazel build --experimental_build_event_text_file=$TEST_log \
+ --aspects=simpleaspect.bzl%simple_aspect \
+ --output_groups=aspect-out \
+ pkg:output_files_and_tags || fail "bazel build failed"
+ expect_log 'aspect.*simple_aspect'
+ expect_log 'name.*aspect-out'
+ expect_log 'name.*out1.txt.aspect'
+ expect_not_log 'aborted'
+}
+
function test_build_only() {
# When building but not testing a test, there won't be a test summary
# (as nothing was tested), so it should not be announced.