blob: 35e02b2f9c9b1cac58cbcab3391b1a10a17a1f52 [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002//
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.
14
15package com.google.devtools.build.lib.packages;
16
tomlua155b532017-11-08 20:12:47 +010017import com.google.common.base.Preconditions;
Dmitry Lomov65fde002017-02-07 17:24:04 +000018import com.google.common.collect.ImmutableList;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010019import com.google.common.collect.ImmutableMap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010020import com.google.common.collect.ImmutableSet;
jcater75828752018-04-27 12:53:19 -070021import com.google.common.collect.Iterables;
jcater75828752018-04-27 12:53:19 -070022import com.google.common.collect.Lists;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010023import com.google.common.collect.Multimap;
gregcebe55e112018-01-30 11:04:53 -080024import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000025import com.google.devtools.build.lib.cmdline.Label;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010026import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
Michael Staibcd48cd52016-01-15 20:11:11 +000027import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy.MissingFragmentPolicy;
Googlerc5fcc862019-09-06 16:17:47 -070028import com.google.devtools.build.lib.packages.Type.LabelClass;
29import com.google.devtools.build.lib.packages.Type.LabelVisitor;
janakree5bf482018-03-26 10:55:59 -070030import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
John Cater13263f72017-05-24 19:06:47 +020031import java.util.ArrayList;
Michael Staibcd48cd52016-01-15 20:11:11 +000032import java.util.Collection;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010033import java.util.LinkedHashMap;
Dmitry Lomov0d380642017-01-20 14:39:55 +000034import java.util.LinkedHashSet;
John Cater13263f72017-05-24 19:06:47 +020035import java.util.List;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010036import java.util.Map;
nharmataf2b26ad2019-03-06 09:37:00 -080037import java.util.function.BiConsumer;
Michael Staibcd48cd52016-01-15 20:11:11 +000038import javax.annotation.Nullable;
39
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010040/**
janakree5bf482018-03-26 10:55:59 -070041 * The definition of an aspect (see {@link Aspect} for more information).
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010042 *
43 * <p>Contains enough information to build up the configured target graph except for the actual way
janakree5bf482018-03-26 10:55:59 -070044 * to build the Skyframe node (that is the territory of {@link com.google.devtools.build.lib.view
45 * AspectFactory}). In particular:
46 *
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010047 * <ul>
48 * <li>The condition that must be fulfilled for an aspect to be able to operate on a configured
49 * target
50 * <li>The (implicit or late-bound) attributes of the aspect that denote dependencies the aspect
51 * itself needs (e.g. runtime libraries for a new language for protocol buffers)
52 * <li>The aspects this aspect requires from its direct dependencies
53 * </ul>
54 *
55 * <p>The way to build the Skyframe node is not here because this data needs to be accessible from
56 * the {@code .packages} package and that one requires references to the {@code .view} package.
57 */
janakree5bf482018-03-26 10:55:59 -070058@AutoCodec
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010059@Immutable
60public final class AspectDefinition {
Dmitry Lomovdce01702016-11-28 15:51:32 +000061 private final AspectClass aspectClass;
Dmitry Lomov65fde002017-02-07 17:24:04 +000062 private final AdvertisedProviderSet advertisedProviders;
Dmitry Lomovb5174c72017-01-10 10:57:17 +000063 private final RequiredProviders requiredProviders;
Dmitry Lomovf868b3e2017-01-17 10:25:28 +000064 private final RequiredProviders requiredProvidersForAspects;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010065 private final ImmutableMap<String, Attribute> attributes;
cpeyserfb829992017-09-07 17:17:03 +020066 private final ImmutableSet<Label> requiredToolchains;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010067
Dmitry Lomov0d380642017-01-20 14:39:55 +000068 /**
69 * Which attributes aspect should propagate along:
70 * <ul>
71 * <li>A {@code null} value means propagate along all attributes</li>
72 * <li>A (possibly empty) set means to propagate only along the attributes in a set</li>
73 * </ul>
74 */
75 @Nullable private final ImmutableSet<String> restrictToAttributes;
76 @Nullable private final ConfigurationFragmentPolicy configurationFragmentPolicy;
dslomov99ea6b42017-04-25 17:46:17 +020077 private final boolean applyToFiles;
cparsons089148b2019-09-17 08:14:41 -070078 private final boolean applyToGeneratingRules;
Dmitry Lomovbb5901b2016-09-27 08:49:26 +000079
Dmitry Lomov65fde002017-02-07 17:24:04 +000080 public AdvertisedProviderSet getAdvertisedProviders() {
81 return advertisedProviders;
82 }
83
janakree5bf482018-03-26 10:55:59 -070084 @AutoCodec.VisibleForSerialization
85 AspectDefinition(
Dmitry Lomovdce01702016-11-28 15:51:32 +000086 AspectClass aspectClass,
Dmitry Lomov65fde002017-02-07 17:24:04 +000087 AdvertisedProviderSet advertisedProviders,
Dmitry Lomovb5174c72017-01-10 10:57:17 +000088 RequiredProviders requiredProviders,
janakree5bf482018-03-26 10:55:59 -070089 RequiredProviders requiredProvidersForAspects,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010090 ImmutableMap<String, Attribute> attributes,
cpeyserfb829992017-09-07 17:17:03 +020091 ImmutableSet<Label> requiredToolchains,
Dmitry Lomov0d380642017-01-20 14:39:55 +000092 @Nullable ImmutableSet<String> restrictToAttributes,
dslomov99ea6b42017-04-25 17:46:17 +020093 @Nullable ConfigurationFragmentPolicy configurationFragmentPolicy,
cparsons089148b2019-09-17 08:14:41 -070094 boolean applyToFiles,
95 boolean applyToGeneratingRules) {
Dmitry Lomovdce01702016-11-28 15:51:32 +000096 this.aspectClass = aspectClass;
Dmitry Lomov65fde002017-02-07 17:24:04 +000097 this.advertisedProviders = advertisedProviders;
Dmitry Lomovb5174c72017-01-10 10:57:17 +000098 this.requiredProviders = requiredProviders;
janakree5bf482018-03-26 10:55:59 -070099 this.requiredProvidersForAspects = requiredProvidersForAspects;
Dmitry Lomova7019882016-12-05 16:57:02 +0000100
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100101 this.attributes = attributes;
John Cater13263f72017-05-24 19:06:47 +0200102 this.requiredToolchains = requiredToolchains;
Dmitry Lomov0d380642017-01-20 14:39:55 +0000103 this.restrictToAttributes = restrictToAttributes;
Michael Staibcd48cd52016-01-15 20:11:11 +0000104 this.configurationFragmentPolicy = configurationFragmentPolicy;
dslomov99ea6b42017-04-25 17:46:17 +0200105 this.applyToFiles = applyToFiles;
cparsons089148b2019-09-17 08:14:41 -0700106 this.applyToGeneratingRules = applyToGeneratingRules;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100107 }
108
109 public String getName() {
Dmitry Lomovdce01702016-11-28 15:51:32 +0000110 return aspectClass.getName();
111 }
112
113 public AspectClass getAspectClass() {
114 return aspectClass;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100115 }
116
117 /**
118 * Returns the attributes of the aspect in the form of a String -&gt; {@link Attribute} map.
119 *
120 * <p>All attributes are either implicit or late-bound.
121 */
122 public ImmutableMap<String, Attribute> getAttributes() {
123 return attributes;
124 }
125
John Cater13263f72017-05-24 19:06:47 +0200126 /** Returns the required toolchains declared by this aspect. */
cpeyserfb829992017-09-07 17:17:03 +0200127 public ImmutableSet<Label> getRequiredToolchains() {
John Cater13263f72017-05-24 19:06:47 +0200128 return requiredToolchains;
129 }
130
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100131 /**
Dmitry Lomovb5174c72017-01-10 10:57:17 +0000132 * Returns {@link RequiredProviders} that a configured target must have so that
133 * this aspect can be applied to it.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100134 *
Dmitry Lomovb5174c72017-01-10 10:57:17 +0000135 * <p>If a configured target does not satisfy required providers, the aspect is
136 * silently not created for it.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100137 */
Dmitry Lomovb5174c72017-01-10 10:57:17 +0000138 public RequiredProviders getRequiredProviders() {
139 return requiredProviders;
Eric Fellheimere27d0632015-09-25 21:35:26 +0000140 }
141
142 /**
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000143 * Aspects do not depend on other aspects applied to the same target <em>unless</em>
144 * the other aspect satisfies the {@link RequiredProviders} this method returns
145 */
146 public RequiredProviders getRequiredProvidersForAspects() {
147 return requiredProvidersForAspects;
148 }
149
lberki3bd28392019-02-05 01:01:02 -0800150 /** Returns the set of required aspects for a given attribute. */
151 public boolean propagateAlong(String attributeName) {
Dmitry Lomov0d380642017-01-20 14:39:55 +0000152 if (restrictToAttributes != null) {
lberki3bd28392019-02-05 01:01:02 -0800153 return restrictToAttributes.contains(attributeName);
Dmitry Lomov0d380642017-01-20 14:39:55 +0000154 }
155 return true;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100156 }
157
158 /**
Michael Staibaf270462016-05-18 16:22:07 +0000159 * Returns the set of configuration fragments required by this Aspect.
Michael Staibcd48cd52016-01-15 20:11:11 +0000160 */
Michael Staibaf270462016-05-18 16:22:07 +0000161 public ConfigurationFragmentPolicy getConfigurationFragmentPolicy() {
Michael Staibcd48cd52016-01-15 20:11:11 +0000162 return configurationFragmentPolicy;
163 }
164
165 /**
dslomovce59d4d2017-08-04 17:32:47 +0200166 * Returns whether this aspect applies to (output) files.
dslomov99ea6b42017-04-25 17:46:17 +0200167 *
dslomovce59d4d2017-08-04 17:32:47 +0200168 * Currently only supported for top-level aspects and targets, and
169 * only for output files.
dslomov99ea6b42017-04-25 17:46:17 +0200170 */
171 public boolean applyToFiles() {
172 return applyToFiles;
173 }
174
cparsons089148b2019-09-17 08:14:41 -0700175 /**
176 * Returns whether this aspect should, when it would be applied to an output file, instead apply
177 * to the generating rule of that output file.
178 */
179 public boolean applyToGeneratingRules() {
180 return applyToGeneratingRules;
181 }
182
nharmataf2b26ad2019-03-06 09:37:00 -0800183 public static boolean satisfies(Aspect aspect, AdvertisedProviderSet advertisedProviderSet) {
184 return aspect.getDefinition().getRequiredProviders().isSatisfiedBy(advertisedProviderSet);
Marian Loburfdd788e2015-03-25 09:36:28 +0000185 }
186
Nathan Harmata19f22382016-06-15 19:06:56 +0000187 @Nullable
188 private static Label maybeGetRepositoryRelativeLabel(Rule from, @Nullable Label label) {
189 return label == null ? null : from.getLabel().resolveRepositoryRelative(label);
190 }
191
Marian Loburfdd788e2015-03-25 09:36:28 +0000192 /**
193 * Collects all attribute labels from the specified aspectDefinition.
194 */
Dmitry Lomov6073eb62016-01-21 21:26:32 +0000195 public static void addAllAttributesOfAspect(
Michael Staiba751f922017-02-14 15:50:04 +0000196 final Rule from,
197 final Multimap<Attribute, Label> labelBuilder,
Dmitry Lomov940ea072016-01-21 22:34:14 +0000198 Aspect aspect,
199 DependencyFilter dependencyFilter) {
nharmataf2b26ad2019-03-06 09:37:00 -0800200 forEachLabelDepFromAllAttributesOfAspect(from, aspect, dependencyFilter, labelBuilder::put);
201 }
202
203 public static void forEachLabelDepFromAllAttributesOfAspect(
204 Rule from,
205 Aspect aspect,
206 DependencyFilter dependencyFilter,
207 BiConsumer<Attribute, Label> consumer) {
shreyax2bcbecf2018-09-26 12:27:32 -0700208 LabelVisitor<Attribute> labelVisitor =
209 (label, aspectAttribute) -> {
nharmataf2b26ad2019-03-06 09:37:00 -0800210 Label repositoryRelativeLabel = maybeGetRepositoryRelativeLabel(from, label);
211 if (repositoryRelativeLabel == null) {
shreyax2bcbecf2018-09-26 12:27:32 -0700212 return;
213 }
nharmataf2b26ad2019-03-06 09:37:00 -0800214 consumer.accept(aspectAttribute, repositoryRelativeLabel);
shreyax2bcbecf2018-09-26 12:27:32 -0700215 };
nharmataf2b26ad2019-03-06 09:37:00 -0800216 for (Attribute aspectAttribute : aspect.getDefinition().getAttributes().values()) {
Dmitry Lomov940ea072016-01-21 22:34:14 +0000217 if (!dependencyFilter.apply(aspect, aspectAttribute)) {
Marian Loburfdd788e2015-03-25 09:36:28 +0000218 continue;
219 }
nharmatad705c982017-04-04 19:09:15 +0000220 Type<?> type = aspectAttribute.getType();
Michael Staiba751f922017-02-14 15:50:04 +0000221 if (type.getLabelClass() != LabelClass.DEPENDENCY) {
222 continue;
223 }
shreyax2bcbecf2018-09-26 12:27:32 -0700224 type.visitLabels(labelVisitor, aspectAttribute.getDefaultValue(from), aspectAttribute);
Marian Loburfdd788e2015-03-25 09:36:28 +0000225 }
226 }
227
Dmitry Lomov0c66dee2017-02-13 17:24:43 +0000228 public static Builder builder(AspectClass aspectClass) {
229 return new Builder(aspectClass);
230 }
231
Marian Loburfdd788e2015-03-25 09:36:28 +0000232 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100233 * Builder class for {@link AspectDefinition}.
234 */
235 public static final class Builder {
Dmitry Lomovdce01702016-11-28 15:51:32 +0000236 private final AspectClass aspectClass;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100237 private final Map<String, Attribute> attributes = new LinkedHashMap<>();
Dmitry Lomov65fde002017-02-07 17:24:04 +0000238 private final AdvertisedProviderSet.Builder advertisedProviders =
239 AdvertisedProviderSet.builder();
Dmitry Lomovb5174c72017-01-10 10:57:17 +0000240 private RequiredProviders.Builder requiredProviders = RequiredProviders.acceptAnyBuilder();
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000241 private RequiredProviders.Builder requiredAspectProviders =
242 RequiredProviders.acceptNoneBuilder();
Dmitry Lomov0d380642017-01-20 14:39:55 +0000243 @Nullable
244 private LinkedHashSet<String> propagateAlongAttributes = new LinkedHashSet<>();
Michael Staibcd48cd52016-01-15 20:11:11 +0000245 private final ConfigurationFragmentPolicy.Builder configurationFragmentPolicy =
246 new ConfigurationFragmentPolicy.Builder();
dslomov99ea6b42017-04-25 17:46:17 +0200247 private boolean applyToFiles = false;
cparsons089148b2019-09-17 08:14:41 -0700248 private boolean applyToGeneratingRules = false;
John Cater9a8d16e2017-07-05 16:12:07 -0400249 private final List<Label> requiredToolchains = new ArrayList<>();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100250
Dmitry Lomovdce01702016-11-28 15:51:32 +0000251 public Builder(AspectClass aspectClass) {
252 this.aspectClass = aspectClass;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100253 }
254
255 /**
Rumou Duan6f8393f2016-11-30 16:03:10 +0000256 * Asserts that this aspect can only be evaluated for rules that supply all of the providers
257 * from at least one set of required providers.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100258 */
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000259 public Builder requireProviderSets(Iterable<ImmutableSet<Class<?>>> providerSets) {
260 for (ImmutableSet<Class<?>> providerSet : providerSets) {
261 requiredProviders.addNativeSet(providerSet);
Rumou Duan6f8393f2016-11-30 16:03:10 +0000262 }
Rumou Duan6f8393f2016-11-30 16:03:10 +0000263 return this;
264 }
265
266 /**
267 * Asserts that this aspect can only be evaluated for rules that supply all of the specified
268 * providers.
269 */
Dmitry Lomovb5174c72017-01-10 10:57:17 +0000270 public Builder requireProviders(Class<?>... providers) {
271 requiredProviders.addNativeSet(ImmutableSet.copyOf(providers));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100272 return this;
273 }
cparsons089148b2019-09-17 08:14:41 -0700274
elenairinaaeb21bc2017-09-27 12:13:52 -0400275 /**
276 * Asserts that this aspect can only be evaluated for rules that supply all of the specified
277 * Skylark providers.
278 */
279 public Builder requireSkylarkProviders(SkylarkProviderIdentifier... skylarkProviders) {
280 requiredProviders.addSkylarkSet(ImmutableSet.copyOf(skylarkProviders));
281 return this;
282 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100283
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000284 public Builder requireAspectsWithProviders(
285 Iterable<ImmutableSet<SkylarkProviderIdentifier>> providerSets) {
286 for (ImmutableSet<SkylarkProviderIdentifier> providerSet : providerSets) {
287 if (!providerSet.isEmpty()) {
288 requiredAspectProviders.addSkylarkSet(providerSet);
289 }
290 }
291 return this;
292 }
293
294 public Builder requireAspectsWithNativeProviders(
Dmitry Lomove851fe22017-02-14 23:11:23 +0000295 Class<?>... providers) {
296 requiredAspectProviders.addNativeSet(ImmutableSet.copyOf(providers));
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000297 return this;
298 }
299
Dmitry Lomov65fde002017-02-07 17:24:04 +0000300 /**
301 * State that the aspect being built provides given providers.
302 */
303 public Builder advertiseProvider(Class<?>... providers) {
304 for (Class<?> provider : providers) {
305 advertisedProviders.addNative(provider);
306 }
307 return this;
308 }
309
310 /**
311 * State that the aspect being built provides given providers.
312 */
313 public Builder advertiseProvider(ImmutableList<SkylarkProviderIdentifier> providers) {
314 for (SkylarkProviderIdentifier provider : providers) {
Dmitry Lomov8ff5a872017-03-04 00:58:14 +0000315 advertisedProviders.addSkylark(provider);
Dmitry Lomov65fde002017-02-07 17:24:04 +0000316 }
317 return this;
318 }
319
320
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000321
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100322 /**
Dmitry Lomov0d380642017-01-20 14:39:55 +0000323 * Declares that this aspect propagates along an {@code attribute} on the target
324 * associated with this aspect.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100325 *
Dmitry Lomov0d380642017-01-20 14:39:55 +0000326 * Specify multiple attributes by calling {@link #propagateAlongAttribute(String)}
327 * repeatedly.
328 *
329 * Aspect can also declare to propagate along all attributes with
330 * {@link #propagateAlongAttributes}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100331 */
Dmitry Lomov0d380642017-01-20 14:39:55 +0000332 public final Builder propagateAlongAttribute(String attribute) {
Rumou Duan5b0b3102015-06-03 20:27:57 +0000333 Preconditions.checkNotNull(attribute);
Dmitry Lomov0d380642017-01-20 14:39:55 +0000334 Preconditions.checkState(this.propagateAlongAttributes != null,
335 "Either propagate along all attributes, or along specific attributes, not both");
336
337 this.propagateAlongAttributes.add(attribute);
338
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100339 return this;
340 }
341
342 /**
Dmitry Lomov0d380642017-01-20 14:39:55 +0000343 * Declares that this aspect propagates along all attributes on the target
344 * associated with this aspect.
345 *
346 * Specify either this or {@link #propagateAlongAttribute(String)}, not both.
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +0000347 */
Dmitry Lomov0d380642017-01-20 14:39:55 +0000348 public final Builder propagateAlongAllAttributes() {
349 Preconditions.checkState(this.propagateAlongAttributes != null,
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000350 "Aspects for all attributes must only be specified once");
Dmitry Lomov0d380642017-01-20 14:39:55 +0000351
352 Preconditions.checkState(this.propagateAlongAttributes.isEmpty(),
353 "Specify either aspects for all attributes, or for specific attributes, not both");
354 this.propagateAlongAttributes = null;
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000355 return this;
356 }
357
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +0000358 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100359 * Adds an attribute to the aspect.
360 *
361 * <p>Since aspects do not appear in BUILD files, the attribute must be either implicit
362 * (not available in the BUILD file, starting with '$') or late-bound (determined after the
363 * configuration is available, starting with ':')
364 */
365 public <TYPE> Builder add(Attribute.Builder<TYPE> attr) {
366 Attribute attribute = attr.build();
Dmitry Lomovace678e2015-12-16 15:10:20 +0000367 return add(attribute);
368 }
369
370 /**
371 * Adds an attribute to the aspect.
372 *
373 * <p>Since aspects do not appear in BUILD files, the attribute must be either implicit
374 * (not available in the BUILD file, starting with '$') or late-bound (determined after the
375 * configuration is available, starting with ':')
376 */
377 public Builder add(Attribute attribute) {
Googler74558fc2016-05-06 21:47:42 +0000378 Preconditions.checkArgument(attribute.isImplicit() || attribute.isLateBound()
379 || (attribute.getType() == Type.STRING && attribute.checkAllowedValues()),
380 "Invalid attribute '%s' (%s)", attribute.getName(), attribute.getType());
Michael Staibcd48cd52016-01-15 20:11:11 +0000381 Preconditions.checkArgument(!attributes.containsKey(attribute.getName()),
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100382 "An attribute with the name '%s' already exists.", attribute.getName());
383 attributes.put(attribute.getName(), attribute);
384 return this;
385 }
386
387 /**
Michael Staibcd48cd52016-01-15 20:11:11 +0000388 * Declares that the implementation of the associated aspect definition requires the given
389 * fragments to be present in this rule's host and target configurations.
390 *
391 * <p>The value is inherited by subclasses.
392 */
393 public Builder requiresConfigurationFragments(Class<?>... configurationFragments) {
Michael Staibcd48cd52016-01-15 20:11:11 +0000394 configurationFragmentPolicy
395 .requiresConfigurationFragments(ImmutableSet.copyOf(configurationFragments));
396 return this;
397 }
398
399 /**
400 * Declares that the implementation of the associated aspect definition requires the given
gregce614dc502017-12-20 17:24:46 -0800401 * fragments to be present in the given configuration that isn't the aspect's configuration but
402 * is also readable by the aspect.
403 *
404 * <p>You probably don't want to use this, because aspects generally shouldn't read
405 * configurations other than their own. If you want to declare host config fragments, see
406 * {@link com.google.devtools.build.lib.analysis.config.ConfigAwareAspectBuilder}.
Michael Staibcd48cd52016-01-15 20:11:11 +0000407 *
408 * <p>The value is inherited by subclasses.
409 */
gregcebe55e112018-01-30 11:04:53 -0800410 public Builder requiresConfigurationFragments(ConfigurationTransition transition,
gregce614dc502017-12-20 17:24:46 -0800411 Class<?>... configurationFragments) {
412 configurationFragmentPolicy.requiresConfigurationFragments(transition,
413 ImmutableSet.copyOf(configurationFragments));
Michael Staibcd48cd52016-01-15 20:11:11 +0000414 return this;
415 }
416
417 /**
418 * Declares the configuration fragments that are required by this rule for the target
419 * configuration.
420 *
421 * <p>In contrast to {@link #requiresConfigurationFragments(Class...)}, this method takes the
422 * Skylark module names of fragments instead of their classes.
423 */
424 public Builder requiresConfigurationFragmentsBySkylarkModuleName(
425 Collection<String> configurationFragmentNames) {
Michael Staibcd48cd52016-01-15 20:11:11 +0000426 configurationFragmentPolicy
427 .requiresConfigurationFragmentsBySkylarkModuleName(configurationFragmentNames);
428 return this;
429 }
430
431 /**
gregce614dc502017-12-20 17:24:46 -0800432 * Declares that the implementation of the associated aspect definition requires the given
433 * fragments to be present in the given configuration that isn't the aspect's configuration but
434 * is also readable by the aspect.
Michael Staibcd48cd52016-01-15 20:11:11 +0000435 *
gregcebe55e112018-01-30 11:04:53 -0800436 * <p>In contrast to {@link #requiresConfigurationFragments(ConfigurationTransition, Class...)},
437 * this method takes the Skylark module names of fragments instead of their classes.
gregce614dc502017-12-20 17:24:46 -0800438 *
439 * <p>You probably don't want to use this, because aspects generally shouldn't read
440 * configurations other than their own. If you want to declare host config fragments, see
441 * {@link com.google.devtools.build.lib.analysis.config.ConfigAwareAspectBuilder}.
Michael Staibcd48cd52016-01-15 20:11:11 +0000442 */
gregcebe55e112018-01-30 11:04:53 -0800443 public Builder requiresConfigurationFragmentsBySkylarkModuleName(
444 ConfigurationTransition transition, Collection<String> configurationFragmentNames) {
gregce614dc502017-12-20 17:24:46 -0800445 configurationFragmentPolicy.requiresConfigurationFragmentsBySkylarkModuleName(transition,
446 configurationFragmentNames);
Michael Staibcd48cd52016-01-15 20:11:11 +0000447 return this;
448 }
449
450 /**
451 * Sets the policy for the case where the configuration is missing required fragments (see
452 * {@link #requiresConfigurationFragments}).
453 */
454 public Builder setMissingFragmentPolicy(MissingFragmentPolicy missingFragmentPolicy) {
Michael Staibcd48cd52016-01-15 20:11:11 +0000455 configurationFragmentPolicy.setMissingFragmentPolicy(missingFragmentPolicy);
456 return this;
457 }
458
dslomov99ea6b42017-04-25 17:46:17 +0200459 /**
460 * Sets whether this aspect should apply to files.
461 *
462 * Default is <code>false</code>.
dslomovce59d4d2017-08-04 17:32:47 +0200463 * Currently only supported for top-level aspects and targets, and only for
464 * output files.
dslomov99ea6b42017-04-25 17:46:17 +0200465 */
466 public Builder applyToFiles(boolean propagateOverGeneratedFiles) {
467 this.applyToFiles = propagateOverGeneratedFiles;
468 return this;
469 }
470
cparsons089148b2019-09-17 08:14:41 -0700471 /**
472 * Sets whether this aspect should, when it would be applied to an output file, instead apply to
473 * the generating rule of that output file.
474 *
475 * <p>Default is <code>false</code>. Currently only supported for aspects which do not have a
476 * "required providers" list.
477 */
478 public Builder applyToGeneratingRules(boolean applyToGeneratingRules) {
479 this.applyToGeneratingRules = applyToGeneratingRules;
480 return this;
481 }
482
John Cater13263f72017-05-24 19:06:47 +0200483 /** Adds the given toolchains as requirements for this aspect. */
jcater75828752018-04-27 12:53:19 -0700484 public Builder addRequiredToolchains(Label... toolchainLabels) {
485 Iterables.addAll(this.requiredToolchains, Lists.newArrayList(toolchainLabels));
486 return this;
487 }
488
489 /** Adds the given toolchains as requirements for this aspect. */
John Cater9a8d16e2017-07-05 16:12:07 -0400490 public Builder addRequiredToolchains(List<Label> requiredToolchains) {
John Cater13263f72017-05-24 19:06:47 +0200491 this.requiredToolchains.addAll(requiredToolchains);
492 return this;
493 }
Michael Staibcd48cd52016-01-15 20:11:11 +0000494 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100495 * Builds the aspect definition.
496 *
497 * <p>The builder object is reusable afterwards.
498 */
499 public AspectDefinition build() {
cparsons089148b2019-09-17 08:14:41 -0700500 RequiredProviders requiredProviders = this.requiredProviders.build();
501 if (applyToGeneratingRules && !requiredProviders.acceptsAny()) {
502 throw new IllegalStateException(
503 "An aspect cannot simultaneously have required providers "
504 + "and apply to generating rules.");
505 }
506
John Cater13263f72017-05-24 19:06:47 +0200507 return new AspectDefinition(
508 aspectClass,
Dmitry Lomov65fde002017-02-07 17:24:04 +0000509 advertisedProviders.build(),
cparsons089148b2019-09-17 08:14:41 -0700510 requiredProviders,
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000511 requiredAspectProviders.build(),
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000512 ImmutableMap.copyOf(attributes),
cpeyserfb829992017-09-07 17:17:03 +0200513 ImmutableSet.copyOf(requiredToolchains),
John Cater13263f72017-05-24 19:06:47 +0200514 propagateAlongAttributes == null ? null : ImmutableSet.copyOf(propagateAlongAttributes),
dslomov99ea6b42017-04-25 17:46:17 +0200515 configurationFragmentPolicy.build(),
cparsons089148b2019-09-17 08:14:41 -0700516 applyToFiles,
517 applyToGeneratingRules);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100518 }
519 }
520}