diff options
Diffstat (limited to 'src')
4 files changed, 122 insertions, 67 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/packages/AspectClass.java b/src/main/java/com/google/devtools/build/lib/packages/AspectClass.java index c0ea7cef8d..66d661aabf 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/AspectClass.java +++ b/src/main/java/com/google/devtools/build/lib/packages/AspectClass.java @@ -14,44 +14,45 @@ package com.google.devtools.build.lib.packages; +import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec; +import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; + /** - * A class of aspects. + * A class of aspects. * - * <p>An aspect allows a rule to create actions in its dependencies, without their knowledge. - * It can be viewed as the ability to attach shadow targets to transitive dependencies or a way - * to run visitations of certain parts of the transitive closure of a rule in such a way that can - * be cached (even partially) and reused between different configured targets requiring the same - * aspect. Some examples where aspects are useful: + * <p>An aspect allows a rule to create actions in its dependencies, without their knowledge. It can + * be viewed as the ability to attach shadow targets to transitive dependencies or a way to run + * visitations of certain parts of the transitive closure of a rule in such a way that can be cached + * (even partially) and reused between different configured targets requiring the same aspect. Some + * examples where aspects are useful: * - * <ul> - * <li>Converting the .jar files in the transitive closure of an Android binary to dexes</li> - * <li>Emitting Java sources for a <code>proto_library</code> and the messages it depends - * on</li> - * <li>Collecting all the dependencies of a rule to make sure that it does not contain a - * forbidden one</li> - * </ul> + * <ul> + * <li>Converting the .jar files in the transitive closure of an Android binary to dexes + * <li>Emitting Java sources for a <code>proto_library</code> and the messages it depends on + * <li>Collecting all the dependencies of a rule to make sure that it does not contain a forbidden + * one + * </ul> * - * <p>When a configured target requests that an aspect be attached to one of its dependencies, - * the {@link com.google.devtools.build.lib.analysis.TransitiveInfoProvider}s generated by that - * aspects are merged with those of the actual dependency, that is, - * {@link com.google.devtools.build.lib.analysis.RuleContext#getPrerequisite( - * String, RuleConfiguredTarget.Mode)} will - * contain the transitive info providers produced both by the dependency and the aspects that are - * attached to it. + * <p>When a configured target requests that an aspect be attached to one of its dependencies, the + * {@link com.google.devtools.build.lib.analysis.TransitiveInfoProvider}s generated by that aspects + * are merged with those of the actual dependency, that is, {@link + * com.google.devtools.build.lib.analysis.RuleContext#getPrerequisite( String, + * RuleConfiguredTarget.Mode)} will contain the transitive info providers produced both by the + * dependency and the aspects that are attached to it. * - * <p>Configured targets can specify which aspects should be attached to some of their dependencies - * by specifying this in their {@link com.google.devtools.build.lib.analysis.RuleDefinition}: each - * attribute can have a list of aspects to be applied to the rules in that attribute and each - * aspect can specify which {@link com.google.devtools.build.lib.analysis.TransitiveInfoProvider}s - * it needs on a rule so that it can do meaningful work (for example, dexing only makes sense for - * configured targets that produce Java code). + * <p>Configured targets can specify which aspects should be attached to some of their dependencies + * by specifying this in their {@link com.google.devtools.build.lib.analysis.RuleDefinition}: each + * attribute can have a list of aspects to be applied to the rules in that attribute and each aspect + * can specify which {@link com.google.devtools.build.lib.analysis.TransitiveInfoProvider}s it needs + * on a rule so that it can do meaningful work (for example, dexing only makes sense for configured + * targets that produce Java code). * - * <p>Aspects can be defined natively, in Java ({@link NativeAspectClass}) - * or in Skylark ({@link SkylarkAspectClass}). + * <p>Aspects can be defined natively, in Java ({@link NativeAspectClass}) or in Skylark ({@link + * SkylarkAspectClass}). * - * Bazel propagates aspects through a multistage process. The general pipeline is as follows: + * <p>Bazel propagates aspects through a multistage process. The general pipeline is as follows: * - * <pre> + * <pre> * {@link AspectClass} * | * V @@ -64,41 +65,36 @@ package com.google.devtools.build.lib.packages; * {@code ConfiguredAspect} <- {@code ConfiguredTarget} * </pre> * - * <ul> - * <li>{@link AspectClass} is a moniker for "user" definition of the aspect, be it - * a native aspect or a Skylark aspect. It contains either a reference to - * the native class implementing the aspect or the location of the Skylark definition - * of the aspect in the source tree, i.e. label of .bzl file + symbol name. - * </li> - * <li>{@link AspectParameters} is a (key,value) pair list that can be used to - * parameterize aspect classes</li> - * <li>{@link AspectDescriptor} is a pair - * of {@code AspectClass} and {@link AspectParameters}. It uniquely identifies - * the aspect and can be used in SkyKeys. - * </li> - * <li>{@link AspectDefinition} is a class encapsulating the aspect definition (what - * attributes aspoect has, and along which dependencies does it propagate. - * </li> - * <li>{@link Aspect} is a fully instantiated instance of an Aspect after it is loaded. - * Getting an {@code Aspect} from {@code AspectDescriptor} for Skylark aspects - * requires adding a Skyframe dependency. - * </li> - * <li>{@link com.google.devtools.build.lib.analysis.ConfiguredAspect} represents a result - * of application of an {@link Aspect} to a given - * {@link com.google.devtools.build.lib.analysis.ConfiguredTarget}. - * </li> - * </ul> + * <ul> + * <li>{@link AspectClass} is a moniker for "user" definition of the aspect, be it a native aspect + * or a Skylark aspect. It contains either a reference to the native class implementing the + * aspect or the location of the Skylark definition of the aspect in the source tree, i.e. + * label of .bzl file + symbol name. + * <li>{@link AspectParameters} is a (key,value) pair list that can be used to parameterize aspect + * classes + * <li>{@link AspectDescriptor} is a pair of {@code AspectClass} and {@link AspectParameters}. It + * uniquely identifies the aspect and can be used in SkyKeys. + * <li>{@link AspectDefinition} is a class encapsulating the aspect definition (what attributes + * aspoect has, and along which dependencies does it propagate. + * <li>{@link Aspect} is a fully instantiated instance of an Aspect after it is loaded. Getting an + * {@code Aspect} from {@code AspectDescriptor} for Skylark aspects requires adding a Skyframe + * dependency. + * <li>{@link com.google.devtools.build.lib.analysis.ConfiguredAspect} represents a result of + * application of an {@link Aspect} to a given {@link + * com.google.devtools.build.lib.analysis.ConfiguredTarget}. + * </ul> * - * {@link AspectDescriptor}, or in general, a tuple - * of ({@link AspectClass}, {@link AspectParameters}) is an identifier that should be - * used in SkyKeys or in other contexts that need equality for aspects. - * See also {@link com.google.devtools.build.lib.skyframe.AspectFunction} for details - * on Skyframe treatment of Aspects. + * {@link AspectDescriptor}, or in general, a tuple of ({@link AspectClass}, {@link + * AspectParameters}) is an identifier that should be used in SkyKeys or in other contexts that need + * equality for aspects. See also {@link com.google.devtools.build.lib.skyframe.AspectFunction} for + * details on Skyframe treatment of Aspects. * - * @see com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory - * @see com.google.devtools.build.lib.skyframe.AspectFunction + * @see com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory + * @see com.google.devtools.build.lib.skyframe.AspectFunction */ +@AutoCodec(strategy = AutoCodec.Strategy.POLYMORPHIC) public interface AspectClass { + ObjectCodec<AspectClass> CODEC = new AspectClass_AutoCodec(); /** * Returns an aspect name. diff --git a/src/main/java/com/google/devtools/build/lib/packages/AspectDescriptor.java b/src/main/java/com/google/devtools/build/lib/packages/AspectDescriptor.java index 0d6e7435bd..3d4058d248 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/AspectDescriptor.java +++ b/src/main/java/com/google/devtools/build/lib/packages/AspectDescriptor.java @@ -16,6 +16,8 @@ package com.google.devtools.build.lib.packages; import com.google.common.collect.ImmutableMultimap; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; +import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec; +import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; import com.google.protobuf.TextFormat; import java.util.Map.Entry; import java.util.Objects; @@ -23,15 +25,18 @@ import java.util.Objects; /** * A pair of {@link AspectClass} and {@link AspectParameters}. * - * Used for dependency resolution. + * <p>Used for dependency resolution. */ @Immutable +@AutoCodec public final class AspectDescriptor { + public static final ObjectCodec<AspectDescriptor> CODEC = new AspectDescriptor_AutoCodec(); + private final AspectClass aspectClass; private final AspectParameters aspectParameters; - public AspectDescriptor(AspectClass aspectClass, - AspectParameters aspectParameters) { + @AutoCodec.Instantiator + public AspectDescriptor(AspectClass aspectClass, AspectParameters aspectParameters) { this.aspectClass = aspectClass; this.aspectParameters = aspectParameters; } diff --git a/src/main/java/com/google/devtools/build/lib/packages/AspectParameters.java b/src/main/java/com/google/devtools/build/lib/packages/AspectParameters.java index 81d003300e..fe4dcd177e 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/AspectParameters.java +++ b/src/main/java/com/google/devtools/build/lib/packages/AspectParameters.java @@ -18,20 +18,34 @@ import static com.google.common.collect.Iterables.getOnlyElement; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Multimap; +import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec; +import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; import java.util.Objects; /** * Objects of this class contain values of some attributes of rules. Used for passing this * information to the aspects. */ +@AutoCodec public final class AspectParameters { + public static final ObjectCodec<AspectParameters> CODEC = new AspectParameters_AutoCodec(); + private final ImmutableMultimap<String, String> attributes; private AspectParameters(Multimap<String, String> attributes) { this.attributes = ImmutableMultimap.copyOf(attributes); } - public static final AspectParameters EMPTY = new AspectParameters.Builder().build(); + public static final AspectParameters EMPTY = new AspectParameters(ImmutableMultimap.of()); + + @AutoCodec.Instantiator + @AutoCodec.VisibleForSerialization + static AspectParameters create(ImmutableMultimap<String, String> attributes) { + if (attributes.isEmpty()) { + return EMPTY; + } + return new AspectParameters(attributes); + } /** * A builder for @{link {@link AspectParameters} class. @@ -52,7 +66,7 @@ public final class AspectParameters { * Creates a new instance of {@link AspectParameters} class. */ public AspectParameters build() { - return new AspectParameters(attributes.build()); + return create(attributes.build()); } } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectValue.java index e3b651f2af..0aca54b402 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectValue.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectValue.java @@ -35,8 +35,14 @@ import com.google.devtools.build.lib.packages.AspectParameters; import com.google.devtools.build.lib.packages.Package; import com.google.devtools.build.lib.skyframe.BuildConfigurationValue.Key; import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey.KeyAndHost; +import com.google.devtools.build.lib.skyframe.serialization.ImmutableListCodec; +import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec; +import com.google.devtools.build.lib.skyframe.serialization.SerializationException; import com.google.devtools.build.lib.syntax.SkylarkImport; import com.google.devtools.build.skyframe.SkyFunctionName; +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.CodedOutputStream; +import java.io.IOException; import java.util.List; import javax.annotation.Nullable; @@ -54,6 +60,7 @@ public final class AspectValue extends ActionLookupValue { /** A base class for a key representing an aspect applied to a particular target. */ public static class AspectKey extends AspectValueKey { + public static final ObjectCodec<AspectKey> CODEC = new AspectKeyCodec(); private final Label label; private final ImmutableList<AspectKey> baseKeys; private final BuildConfigurationValue.Key aspectConfigurationKey; @@ -243,7 +250,8 @@ public final class AspectValue extends ActionLookupValue { } /** An {@link AspectKey} for an aspect in the host configuration. */ - private static class HostAspectKey extends AspectKey { + static class HostAspectKey extends AspectKey { + static final ObjectCodec<AspectKey> CODEC = AspectKey.CODEC; private HostAspectKey( Label label, @@ -260,6 +268,38 @@ public final class AspectValue extends ActionLookupValue { } } + private static class AspectKeyCodec implements ObjectCodec<AspectKey> { + private final ImmutableListCodec<AspectKey> listCodec = new ImmutableListCodec<>(this); + + @Override + public Class<AspectKey> getEncodedClass() { + return AspectKey.class; + } + + @Override + public void serialize(AspectKey obj, CodedOutputStream codedOut) + throws SerializationException, IOException { + Label.CODEC.serialize(obj.label, codedOut); + ConfiguredTargetKey.CODEC.serialize(obj.baseConfiguredTargetKey, codedOut); + listCodec.serialize(obj.baseKeys, codedOut); + AspectDescriptor.CODEC.serialize(obj.aspectDescriptor, codedOut); + Key.CODEC.serialize(obj.aspectConfigurationKey, codedOut); + codedOut.writeBoolNoTag(obj.aspectConfigurationIsHost()); + } + + @Override + public AspectKey deserialize(CodedInputStream codedIn) + throws SerializationException, IOException { + return createAspectKey( + Label.CODEC.deserialize(codedIn), + ConfiguredTargetKey.CODEC.deserialize(codedIn), + listCodec.deserialize(codedIn), + AspectDescriptor.CODEC.deserialize(codedIn), + Key.CODEC.deserialize(codedIn), + codedIn.readBool()); + } + } + /** * The key for a skylark aspect. */ |