blob: abf181e1c83f7e86a06d3e7c94f0638ca5a6c9d3 [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;
ilist85e89a62020-04-24 08:52:25 -070024import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
gregcebe55e112018-01-30 11:04:53 -080025import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000026import com.google.devtools.build.lib.cmdline.Label;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010027import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
Michael Staibcd48cd52016-01-15 20:11:11 +000028import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy.MissingFragmentPolicy;
Googlerc5fcc862019-09-06 16:17:47 -070029import com.google.devtools.build.lib.packages.Type.LabelClass;
30import com.google.devtools.build.lib.packages.Type.LabelVisitor;
janakree5bf482018-03-26 10:55:59 -070031import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
John Cater13263f72017-05-24 19:06:47 +020032import java.util.ArrayList;
Michael Staibcd48cd52016-01-15 20:11:11 +000033import java.util.Collection;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010034import java.util.LinkedHashMap;
Dmitry Lomov0d380642017-01-20 14:39:55 +000035import java.util.LinkedHashSet;
John Cater13263f72017-05-24 19:06:47 +020036import java.util.List;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010037import java.util.Map;
nharmataf2b26ad2019-03-06 09:37:00 -080038import java.util.function.BiConsumer;
Michael Staibcd48cd52016-01-15 20:11:11 +000039import javax.annotation.Nullable;
40
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010041/**
janakree5bf482018-03-26 10:55:59 -070042 * The definition of an aspect (see {@link Aspect} for more information).
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010043 *
44 * <p>Contains enough information to build up the configured target graph except for the actual way
janakree5bf482018-03-26 10:55:59 -070045 * to build the Skyframe node (that is the territory of {@link com.google.devtools.build.lib.view
46 * AspectFactory}). In particular:
47 *
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010048 * <ul>
49 * <li>The condition that must be fulfilled for an aspect to be able to operate on a configured
50 * target
51 * <li>The (implicit or late-bound) attributes of the aspect that denote dependencies the aspect
52 * itself needs (e.g. runtime libraries for a new language for protocol buffers)
53 * <li>The aspects this aspect requires from its direct dependencies
54 * </ul>
55 *
56 * <p>The way to build the Skyframe node is not here because this data needs to be accessible from
57 * the {@code .packages} package and that one requires references to the {@code .view} package.
58 */
janakree5bf482018-03-26 10:55:59 -070059@AutoCodec
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010060@Immutable
61public final class AspectDefinition {
Dmitry Lomovdce01702016-11-28 15:51:32 +000062 private final AspectClass aspectClass;
Dmitry Lomov65fde002017-02-07 17:24:04 +000063 private final AdvertisedProviderSet advertisedProviders;
Dmitry Lomovb5174c72017-01-10 10:57:17 +000064 private final RequiredProviders requiredProviders;
Dmitry Lomovf868b3e2017-01-17 10:25:28 +000065 private final RequiredProviders requiredProvidersForAspects;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010066 private final ImmutableMap<String, Attribute> attributes;
cpeyserfb829992017-09-07 17:17:03 +020067 private final ImmutableSet<Label> requiredToolchains;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010068
Dmitry Lomov0d380642017-01-20 14:39:55 +000069 /**
70 * Which attributes aspect should propagate along:
71 * <ul>
72 * <li>A {@code null} value means propagate along all attributes</li>
73 * <li>A (possibly empty) set means to propagate only along the attributes in a set</li>
74 * </ul>
75 */
76 @Nullable private final ImmutableSet<String> restrictToAttributes;
77 @Nullable private final ConfigurationFragmentPolicy configurationFragmentPolicy;
dslomov99ea6b42017-04-25 17:46:17 +020078 private final boolean applyToFiles;
cparsons089148b2019-09-17 08:14:41 -070079 private final boolean applyToGeneratingRules;
Dmitry Lomovbb5901b2016-09-27 08:49:26 +000080
Dmitry Lomov65fde002017-02-07 17:24:04 +000081 public AdvertisedProviderSet getAdvertisedProviders() {
82 return advertisedProviders;
83 }
84
janakree5bf482018-03-26 10:55:59 -070085 @AutoCodec.VisibleForSerialization
86 AspectDefinition(
Dmitry Lomovdce01702016-11-28 15:51:32 +000087 AspectClass aspectClass,
Dmitry Lomov65fde002017-02-07 17:24:04 +000088 AdvertisedProviderSet advertisedProviders,
Dmitry Lomovb5174c72017-01-10 10:57:17 +000089 RequiredProviders requiredProviders,
janakree5bf482018-03-26 10:55:59 -070090 RequiredProviders requiredProvidersForAspects,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010091 ImmutableMap<String, Attribute> attributes,
cpeyserfb829992017-09-07 17:17:03 +020092 ImmutableSet<Label> requiredToolchains,
Dmitry Lomov0d380642017-01-20 14:39:55 +000093 @Nullable ImmutableSet<String> restrictToAttributes,
dslomov99ea6b42017-04-25 17:46:17 +020094 @Nullable ConfigurationFragmentPolicy configurationFragmentPolicy,
cparsons089148b2019-09-17 08:14:41 -070095 boolean applyToFiles,
96 boolean applyToGeneratingRules) {
Dmitry Lomovdce01702016-11-28 15:51:32 +000097 this.aspectClass = aspectClass;
Dmitry Lomov65fde002017-02-07 17:24:04 +000098 this.advertisedProviders = advertisedProviders;
Dmitry Lomovb5174c72017-01-10 10:57:17 +000099 this.requiredProviders = requiredProviders;
janakree5bf482018-03-26 10:55:59 -0700100 this.requiredProvidersForAspects = requiredProvidersForAspects;
Dmitry Lomova7019882016-12-05 16:57:02 +0000101
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100102 this.attributes = attributes;
John Cater13263f72017-05-24 19:06:47 +0200103 this.requiredToolchains = requiredToolchains;
Dmitry Lomov0d380642017-01-20 14:39:55 +0000104 this.restrictToAttributes = restrictToAttributes;
Michael Staibcd48cd52016-01-15 20:11:11 +0000105 this.configurationFragmentPolicy = configurationFragmentPolicy;
dslomov99ea6b42017-04-25 17:46:17 +0200106 this.applyToFiles = applyToFiles;
cparsons089148b2019-09-17 08:14:41 -0700107 this.applyToGeneratingRules = applyToGeneratingRules;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100108 }
109
110 public String getName() {
Dmitry Lomovdce01702016-11-28 15:51:32 +0000111 return aspectClass.getName();
112 }
113
114 public AspectClass getAspectClass() {
115 return aspectClass;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100116 }
117
118 /**
119 * Returns the attributes of the aspect in the form of a String -&gt; {@link Attribute} map.
120 *
121 * <p>All attributes are either implicit or late-bound.
122 */
123 public ImmutableMap<String, Attribute> getAttributes() {
124 return attributes;
125 }
126
John Cater13263f72017-05-24 19:06:47 +0200127 /** Returns the required toolchains declared by this aspect. */
cpeyserfb829992017-09-07 17:17:03 +0200128 public ImmutableSet<Label> getRequiredToolchains() {
John Cater13263f72017-05-24 19:06:47 +0200129 return requiredToolchains;
130 }
131
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100132 /**
Dmitry Lomovb5174c72017-01-10 10:57:17 +0000133 * Returns {@link RequiredProviders} that a configured target must have so that
134 * this aspect can be applied to it.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100135 *
Dmitry Lomovb5174c72017-01-10 10:57:17 +0000136 * <p>If a configured target does not satisfy required providers, the aspect is
137 * silently not created for it.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100138 */
Dmitry Lomovb5174c72017-01-10 10:57:17 +0000139 public RequiredProviders getRequiredProviders() {
140 return requiredProviders;
Eric Fellheimere27d0632015-09-25 21:35:26 +0000141 }
142
143 /**
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000144 * Aspects do not depend on other aspects applied to the same target <em>unless</em>
145 * the other aspect satisfies the {@link RequiredProviders} this method returns
146 */
147 public RequiredProviders getRequiredProvidersForAspects() {
148 return requiredProvidersForAspects;
149 }
150
lberki3bd28392019-02-05 01:01:02 -0800151 /** Returns the set of required aspects for a given attribute. */
152 public boolean propagateAlong(String attributeName) {
Dmitry Lomov0d380642017-01-20 14:39:55 +0000153 if (restrictToAttributes != null) {
lberki3bd28392019-02-05 01:01:02 -0800154 return restrictToAttributes.contains(attributeName);
Dmitry Lomov0d380642017-01-20 14:39:55 +0000155 }
156 return true;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100157 }
158
159 /**
Michael Staibaf270462016-05-18 16:22:07 +0000160 * Returns the set of configuration fragments required by this Aspect.
Michael Staibcd48cd52016-01-15 20:11:11 +0000161 */
Michael Staibaf270462016-05-18 16:22:07 +0000162 public ConfigurationFragmentPolicy getConfigurationFragmentPolicy() {
Michael Staibcd48cd52016-01-15 20:11:11 +0000163 return configurationFragmentPolicy;
164 }
165
166 /**
dslomovce59d4d2017-08-04 17:32:47 +0200167 * Returns whether this aspect applies to (output) files.
dslomov99ea6b42017-04-25 17:46:17 +0200168 *
dslomovce59d4d2017-08-04 17:32:47 +0200169 * Currently only supported for top-level aspects and targets, and
170 * only for output files.
dslomov99ea6b42017-04-25 17:46:17 +0200171 */
172 public boolean applyToFiles() {
173 return applyToFiles;
174 }
175
cparsons089148b2019-09-17 08:14:41 -0700176 /**
177 * Returns whether this aspect should, when it would be applied to an output file, instead apply
178 * to the generating rule of that output file.
179 */
180 public boolean applyToGeneratingRules() {
181 return applyToGeneratingRules;
182 }
183
nharmataf2b26ad2019-03-06 09:37:00 -0800184 public static boolean satisfies(Aspect aspect, AdvertisedProviderSet advertisedProviderSet) {
185 return aspect.getDefinition().getRequiredProviders().isSatisfiedBy(advertisedProviderSet);
Marian Loburfdd788e2015-03-25 09:36:28 +0000186 }
187
Nathan Harmata19f22382016-06-15 19:06:56 +0000188 @Nullable
189 private static Label maybeGetRepositoryRelativeLabel(Rule from, @Nullable Label label) {
190 return label == null ? null : from.getLabel().resolveRepositoryRelative(label);
191 }
192
Marian Loburfdd788e2015-03-25 09:36:28 +0000193 /**
194 * Collects all attribute labels from the specified aspectDefinition.
195 */
Dmitry Lomov6073eb62016-01-21 21:26:32 +0000196 public static void addAllAttributesOfAspect(
Michael Staiba751f922017-02-14 15:50:04 +0000197 final Rule from,
198 final Multimap<Attribute, Label> labelBuilder,
Dmitry Lomov940ea072016-01-21 22:34:14 +0000199 Aspect aspect,
200 DependencyFilter dependencyFilter) {
nharmataf2b26ad2019-03-06 09:37:00 -0800201 forEachLabelDepFromAllAttributesOfAspect(from, aspect, dependencyFilter, labelBuilder::put);
202 }
203
204 public static void forEachLabelDepFromAllAttributesOfAspect(
205 Rule from,
206 Aspect aspect,
207 DependencyFilter dependencyFilter,
208 BiConsumer<Attribute, Label> consumer) {
shreyax2bcbecf2018-09-26 12:27:32 -0700209 LabelVisitor<Attribute> labelVisitor =
210 (label, aspectAttribute) -> {
nharmataf2b26ad2019-03-06 09:37:00 -0800211 Label repositoryRelativeLabel = maybeGetRepositoryRelativeLabel(from, label);
212 if (repositoryRelativeLabel == null) {
shreyax2bcbecf2018-09-26 12:27:32 -0700213 return;
214 }
nharmataf2b26ad2019-03-06 09:37:00 -0800215 consumer.accept(aspectAttribute, repositoryRelativeLabel);
shreyax2bcbecf2018-09-26 12:27:32 -0700216 };
nharmataf2b26ad2019-03-06 09:37:00 -0800217 for (Attribute aspectAttribute : aspect.getDefinition().getAttributes().values()) {
Dmitry Lomov940ea072016-01-21 22:34:14 +0000218 if (!dependencyFilter.apply(aspect, aspectAttribute)) {
Marian Loburfdd788e2015-03-25 09:36:28 +0000219 continue;
220 }
nharmatad705c982017-04-04 19:09:15 +0000221 Type<?> type = aspectAttribute.getType();
Michael Staiba751f922017-02-14 15:50:04 +0000222 if (type.getLabelClass() != LabelClass.DEPENDENCY) {
223 continue;
224 }
shreyax2bcbecf2018-09-26 12:27:32 -0700225 type.visitLabels(labelVisitor, aspectAttribute.getDefaultValue(from), aspectAttribute);
Marian Loburfdd788e2015-03-25 09:36:28 +0000226 }
227 }
228
Dmitry Lomov0c66dee2017-02-13 17:24:43 +0000229 public static Builder builder(AspectClass aspectClass) {
230 return new Builder(aspectClass);
231 }
232
Marian Loburfdd788e2015-03-25 09:36:28 +0000233 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100234 * Builder class for {@link AspectDefinition}.
235 */
236 public static final class Builder {
Dmitry Lomovdce01702016-11-28 15:51:32 +0000237 private final AspectClass aspectClass;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100238 private final Map<String, Attribute> attributes = new LinkedHashMap<>();
Dmitry Lomov65fde002017-02-07 17:24:04 +0000239 private final AdvertisedProviderSet.Builder advertisedProviders =
240 AdvertisedProviderSet.builder();
Dmitry Lomovb5174c72017-01-10 10:57:17 +0000241 private RequiredProviders.Builder requiredProviders = RequiredProviders.acceptAnyBuilder();
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000242 private RequiredProviders.Builder requiredAspectProviders =
243 RequiredProviders.acceptNoneBuilder();
Dmitry Lomov0d380642017-01-20 14:39:55 +0000244 @Nullable
245 private LinkedHashSet<String> propagateAlongAttributes = new LinkedHashSet<>();
Michael Staibcd48cd52016-01-15 20:11:11 +0000246 private final ConfigurationFragmentPolicy.Builder configurationFragmentPolicy =
247 new ConfigurationFragmentPolicy.Builder();
dslomov99ea6b42017-04-25 17:46:17 +0200248 private boolean applyToFiles = false;
cparsons089148b2019-09-17 08:14:41 -0700249 private boolean applyToGeneratingRules = false;
John Cater9a8d16e2017-07-05 16:12:07 -0400250 private final List<Label> requiredToolchains = new ArrayList<>();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100251
Dmitry Lomovdce01702016-11-28 15:51:32 +0000252 public Builder(AspectClass aspectClass) {
253 this.aspectClass = aspectClass;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100254 }
255
256 /**
Rumou Duan6f8393f2016-11-30 16:03:10 +0000257 * Asserts that this aspect can only be evaluated for rules that supply all of the providers
258 * from at least one set of required providers.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100259 */
ilist85e89a62020-04-24 08:52:25 -0700260 public Builder requireProviderSets(
261 Iterable<ImmutableSet<Class<? extends TransitiveInfoProvider>>> providerSets) {
262 for (ImmutableSet<Class<? extends TransitiveInfoProvider>> providerSet : providerSets) {
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000263 requiredProviders.addNativeSet(providerSet);
Rumou Duan6f8393f2016-11-30 16:03:10 +0000264 }
Rumou Duan6f8393f2016-11-30 16:03:10 +0000265 return this;
266 }
267
268 /**
269 * Asserts that this aspect can only be evaluated for rules that supply all of the specified
270 * providers.
271 */
ilist85e89a62020-04-24 08:52:25 -0700272 public Builder requireProviders(Class<? extends TransitiveInfoProvider>... providers) {
Dmitry Lomovb5174c72017-01-10 10:57:17 +0000273 requiredProviders.addNativeSet(ImmutableSet.copyOf(providers));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100274 return this;
275 }
cparsons089148b2019-09-17 08:14:41 -0700276
elenairinaaeb21bc2017-09-27 12:13:52 -0400277 /**
278 * Asserts that this aspect can only be evaluated for rules that supply all of the specified
gregce3377c112020-04-13 09:29:59 -0700279 * Starlark providers.
elenairinaaeb21bc2017-09-27 12:13:52 -0400280 */
gregce773b95f2020-05-19 09:51:09 -0700281 public Builder requireStarlarkProviders(StarlarkProviderIdentifier... starlarkProviders) {
282 requiredProviders.addStarlarkSet(ImmutableSet.copyOf(starlarkProviders));
elenairinaaeb21bc2017-09-27 12:13:52 -0400283 return this;
284 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100285
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000286 public Builder requireAspectsWithProviders(
gregce74d84d42020-04-17 10:02:03 -0700287 Iterable<ImmutableSet<StarlarkProviderIdentifier>> providerSets) {
288 for (ImmutableSet<StarlarkProviderIdentifier> providerSet : providerSets) {
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000289 if (!providerSet.isEmpty()) {
gregce18694cd2020-05-12 15:40:05 -0700290 requiredAspectProviders.addStarlarkSet(providerSet);
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000291 }
292 }
293 return this;
294 }
295
296 public Builder requireAspectsWithNativeProviders(
ilist85e89a62020-04-24 08:52:25 -0700297 Class<? extends TransitiveInfoProvider>... providers) {
Dmitry Lomove851fe22017-02-14 23:11:23 +0000298 requiredAspectProviders.addNativeSet(ImmutableSet.copyOf(providers));
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000299 return this;
300 }
301
Dmitry Lomov65fde002017-02-07 17:24:04 +0000302 /**
303 * State that the aspect being built provides given providers.
304 */
305 public Builder advertiseProvider(Class<?>... providers) {
306 for (Class<?> provider : providers) {
307 advertisedProviders.addNative(provider);
308 }
309 return this;
310 }
311
gregce74d84d42020-04-17 10:02:03 -0700312 /** State that the aspect being built provides given providers. */
313 public Builder advertiseProvider(ImmutableList<StarlarkProviderIdentifier> providers) {
314 for (StarlarkProviderIdentifier provider : providers) {
gregced7c1cef2020-05-12 07:51:48 -0700315 advertisedProviders.addStarlark(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
gregce3377c112020-04-13 09:29:59 -0700422 * Starlark module names of fragments instead of their classes.
Michael Staibcd48cd52016-01-15 20:11:11 +0000423 */
gregce220a1c82020-05-01 10:19:52 -0700424 public Builder requiresConfigurationFragmentsByStarlarkBuiltinName(
Michael Staibcd48cd52016-01-15 20:11:11 +0000425 Collection<String> configurationFragmentNames) {
gregce220a1c82020-05-01 10:19:52 -0700426 configurationFragmentPolicy.requiresConfigurationFragmentsByStarlarkBuiltinName(
427 configurationFragmentNames);
Michael Staibcd48cd52016-01-15 20:11:11 +0000428 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...)},
gregce3377c112020-04-13 09:29:59 -0700437 * this method takes the Starlark 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
gregce3377c112020-04-13 09:29:59 -0700440 * configurations other than their own. If you want to declare host config fragments, see {@link
441 * com.google.devtools.build.lib.analysis.config.ConfigAwareAspectBuilder}.
Michael Staibcd48cd52016-01-15 20:11:11 +0000442 */
gregce220a1c82020-05-01 10:19:52 -0700443 public Builder requiresConfigurationFragmentsByStarlarkBuiltinName(
gregcebe55e112018-01-30 11:04:53 -0800444 ConfigurationTransition transition, Collection<String> configurationFragmentNames) {
gregce220a1c82020-05-01 10:19:52 -0700445 configurationFragmentPolicy.requiresConfigurationFragmentsByStarlarkBuiltinName(
446 transition, 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}