blob: 217d67401d4ec7b78339b471c124f0ff72b5e2e5 [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2015 The Bazel Authors. All rights reserved.
Marian Lobur702cad72015-09-02 09:53:58 +00002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
Dmitry Lomov6231d082015-11-02 17:17:20 +000014package com.google.devtools.build.lib.packages;
Marian Lobur702cad72015-09-02 09:53:58 +000015
seancurran128123f2021-06-17 19:06:18 -070016import com.github.benmanes.caffeine.cache.Caffeine;
17import com.github.benmanes.caffeine.cache.LoadingCache;
tomlua155b532017-11-08 20:12:47 +010018import com.google.common.base.Preconditions;
messaf8c34082021-06-04 02:51:04 -070019import com.google.common.collect.ImmutableSet;
Dmitry Lomove8040172016-04-06 14:53:43 +000020import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
janakree5bf482018-03-26 10:55:59 -070021import com.google.devtools.build.lib.skyframe.serialization.DeserializationContext;
22import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec;
23import com.google.devtools.build.lib.skyframe.serialization.SerializationContext;
24import com.google.devtools.build.lib.skyframe.serialization.SerializationException;
25import com.google.protobuf.CodedInputStream;
26import com.google.protobuf.CodedOutputStream;
27import java.io.IOException;
Marian Lobur702cad72015-09-02 09:53:58 +000028
Marian Lobur702cad72015-09-02 09:53:58 +000029/**
Dmitry Lomove8040172016-04-06 14:53:43 +000030 * An instance of a given {@code AspectClass} with loaded definition and parameters.
31 *
32 * This is an aspect equivalent of {@link Rule} class for build rules.
33 *
34 * Note: this class does not have {@code equals()} and {@code hashCode()} redefined, so should
35 * not be used in SkyKeys.
Marian Lobur702cad72015-09-02 09:53:58 +000036 */
Dmitry Lomove8040172016-04-06 14:53:43 +000037@Immutable
Dmitry Lomov940ea072016-01-21 22:34:14 +000038public final class Aspect implements DependencyFilter.AttributeInfoProvider {
Carmi Grushko238bf4e2016-07-22 16:11:34 +000039
tomlu8306d432017-08-11 21:32:01 +020040 /**
41 * The aspect definition is a function of the aspect class + its parameters, so we can cache that.
42 *
43 * <p>The native aspects are loaded with blaze and are not stateful. Reference equality works fine
44 * in this case.
45 *
gregce3377c112020-04-13 09:29:59 -070046 * <p>Caching of Starlark aspects is not yet implemented.
tomlu8306d432017-08-11 21:32:01 +020047 */
nharmata4c8c1522019-02-25 14:25:44 -080048 private static final LoadingCache<
49 NativeAspectClass, LoadingCache<AspectParameters, AspectDefinition>>
50 definitionCache =
seancurran128123f2021-06-17 19:06:18 -070051 Caffeine.newBuilder()
nharmata4c8c1522019-02-25 14:25:44 -080052 .build(
seancurran128123f2021-06-17 19:06:18 -070053 nativeAspectClass ->
54 Caffeine.newBuilder().build(nativeAspectClass::getDefinition));
tomlu8306d432017-08-11 21:32:01 +020055
Dmitry Lomov15756522016-12-16 16:52:37 +000056 private final AspectDescriptor aspectDescriptor;
Dmitry Lomove8040172016-04-06 14:53:43 +000057 private final AspectDefinition aspectDefinition;
Marian Lobur702cad72015-09-02 09:53:58 +000058
Dmitry Lomove8040172016-04-06 14:53:43 +000059 private Aspect(
60 AspectClass aspectClass,
61 AspectDefinition aspectDefinition,
62 AspectParameters parameters) {
Dmitry Lomov15756522016-12-16 16:52:37 +000063 this.aspectDescriptor = new AspectDescriptor(
64 Preconditions.checkNotNull(aspectClass),
65 Preconditions.checkNotNull(parameters));
Dmitry Lomove8040172016-04-06 14:53:43 +000066 this.aspectDefinition = Preconditions.checkNotNull(aspectDefinition);
Marian Lobur702cad72015-09-02 09:53:58 +000067 }
68
messaf8c34082021-06-04 02:51:04 -070069 private Aspect(
70 AspectClass aspectClass,
71 AspectDefinition aspectDefinition,
72 AspectParameters parameters,
73 RequiredProviders inheritedRequiredProviders,
74 ImmutableSet<String> inheritedAttributeAspects) {
75 this.aspectDescriptor =
76 new AspectDescriptor(
77 Preconditions.checkNotNull(aspectClass),
78 Preconditions.checkNotNull(parameters),
messaed7ddfa2021-06-09 05:45:34 -070079 inheritedRequiredProviders,
messaf8c34082021-06-04 02:51:04 -070080 inheritedAttributeAspects);
81 this.aspectDefinition = Preconditions.checkNotNull(aspectDefinition);
82 }
83
84 public static Aspect forNative(
85 NativeAspectClass nativeAspectClass,
86 AspectParameters parameters,
87 RequiredProviders inheritedRequiredProviders,
88 ImmutableSet<String> inheritedAttributeAspects) {
seancurran128123f2021-06-17 19:06:18 -070089 AspectDefinition definition = definitionCache.get(nativeAspectClass).get(parameters);
messaf8c34082021-06-04 02:51:04 -070090 return new Aspect(
91 nativeAspectClass,
92 definition,
93 parameters,
94 inheritedRequiredProviders,
95 inheritedAttributeAspects);
96 }
97
Dmitry Lomove8040172016-04-06 14:53:43 +000098 public static Aspect forNative(
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +000099 NativeAspectClass nativeAspectClass, AspectParameters parameters) {
seancurran128123f2021-06-17 19:06:18 -0700100 AspectDefinition definition = definitionCache.get(nativeAspectClass).get(parameters);
tomlu8306d432017-08-11 21:32:01 +0200101 return new Aspect(nativeAspectClass, definition, parameters);
Dmitry Lomove8040172016-04-06 14:53:43 +0000102 }
103
Luis Fernando Pino Duquee82713d2016-04-26 16:22:38 +0000104 public static Aspect forNative(NativeAspectClass nativeAspectClass) {
Dmitry Lomove8040172016-04-06 14:53:43 +0000105 return forNative(nativeAspectClass, AspectParameters.EMPTY);
106 }
107
gregce18694cd2020-05-12 15:40:05 -0700108 public static Aspect forStarlark(
109 StarlarkAspectClass starlarkAspectClass,
tomlu8306d432017-08-11 21:32:01 +0200110 AspectDefinition aspectDefinition,
messaf8c34082021-06-04 02:51:04 -0700111 AspectParameters parameters,
112 RequiredProviders inheritedRequiredProviders,
113 ImmutableSet<String> inheritedAttributeAspects) {
114 return new Aspect(
115 starlarkAspectClass,
116 aspectDefinition,
117 parameters,
118 inheritedRequiredProviders,
119 inheritedAttributeAspects);
Marian Lobur702cad72015-09-02 09:53:58 +0000120 }
121
122 /**
Dmitry Lomov8ff06452015-10-21 19:16:30 +0000123 * Returns the aspectClass required for building the aspect.
Marian Lobur702cad72015-09-02 09:53:58 +0000124 */
Dmitry Lomov8ff06452015-10-21 19:16:30 +0000125 public AspectClass getAspectClass() {
Dmitry Lomov15756522016-12-16 16:52:37 +0000126 return aspectDescriptor.getAspectClass();
Marian Lobur702cad72015-09-02 09:53:58 +0000127 }
128
129 /**
130 * Returns parameters for evaluation of the aspect.
131 */
132 public AspectParameters getParameters() {
Dmitry Lomov15756522016-12-16 16:52:37 +0000133 return aspectDescriptor.getParameters();
134 }
135
136 public AspectDescriptor getDescriptor() {
137 return aspectDescriptor;
Marian Lobur702cad72015-09-02 09:53:58 +0000138 }
139
140 @Override
Marian Lobur702cad72015-09-02 09:53:58 +0000141 public String toString() {
Dmitry Lomov15756522016-12-16 16:52:37 +0000142 return String.format("Aspect %s", aspectDescriptor.toString());
Marian Lobur702cad72015-09-02 09:53:58 +0000143 }
Dmitry Lomov6231d082015-11-02 17:17:20 +0000144
145 public AspectDefinition getDefinition() {
Dmitry Lomove8040172016-04-06 14:53:43 +0000146 return aspectDefinition;
Dmitry Lomov6231d082015-11-02 17:17:20 +0000147 }
Dmitry Lomov940ea072016-01-21 22:34:14 +0000148
149 @Override
150 public boolean isAttributeValueExplicitlySpecified(Attribute attribute) {
151 // All aspect attributes are implicit.
152 return false;
153 }
janakree5bf482018-03-26 10:55:59 -0700154
155 /** {@link ObjectCodec} for {@link Aspect}. */
156 static class AspectCodec implements ObjectCodec<Aspect> {
157 @Override
158 public Class<Aspect> getEncodedClass() {
159 return Aspect.class;
160 }
161
162 @Override
163 public void serialize(SerializationContext context, Aspect obj, CodedOutputStream codedOut)
164 throws SerializationException, IOException {
165 context.serialize(obj.getDescriptor(), codedOut);
166 boolean nativeAspect = obj.getDescriptor().getAspectClass() instanceof NativeAspectClass;
167 codedOut.writeBoolNoTag(nativeAspect);
168 if (!nativeAspect) {
169 context.serialize(obj.getDefinition(), codedOut);
170 }
171 }
172
173 @Override
174 public Aspect deserialize(DeserializationContext context, CodedInputStream codedIn)
175 throws SerializationException, IOException {
176 AspectDescriptor aspectDescriptor = context.deserialize(codedIn);
177 if (codedIn.readBool()) {
178 return forNative(
179 (NativeAspectClass) aspectDescriptor.getAspectClass(),
180 aspectDescriptor.getParameters());
181 } else {
182 AspectDefinition aspectDefinition = context.deserialize(codedIn);
gregce18694cd2020-05-12 15:40:05 -0700183 return forStarlark(
184 (StarlarkAspectClass) aspectDescriptor.getAspectClass(),
janakree5bf482018-03-26 10:55:59 -0700185 aspectDefinition,
messaf8c34082021-06-04 02:51:04 -0700186 aspectDescriptor.getParameters(),
187 aspectDescriptor.getInheritedRequiredProviders(),
188 aspectDescriptor.getInheritedAttributeAspects());
janakree5bf482018-03-26 10:55:59 -0700189 }
190 }
191 }
Marian Lobur702cad72015-09-02 09:53:58 +0000192}