blob: dd8a0f76d40fccfff7346ef119ba206305f5f56c [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;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010021import com.google.common.collect.Multimap;
jhorvitz11dc1042021-08-13 07:30:19 -070022import com.google.devtools.build.lib.analysis.config.Fragment;
John Caterfb162702022-02-16 10:09:34 -080023import com.google.devtools.build.lib.analysis.config.ToolchainTypeRequirement;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000024import com.google.devtools.build.lib.cmdline.Label;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010025import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
ilistd7432e22020-06-04 13:51:45 -070026import com.google.devtools.build.lib.packages.Attribute.ComputedDefault;
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;
Googleraa55c4d2023-08-30 00:48:57 -070030import com.google.devtools.build.lib.starlarkbuildapi.StarlarkSubruleApi;
Kurt Alfred Kluever29e8e7d2022-07-04 06:50:48 -070031import com.google.errorprone.annotations.CanIgnoreReturnValue;
Michael Staibcd48cd52016-01-15 20:11:11 +000032import java.util.Collection;
John Cater6f2c3e22022-03-03 08:15:22 -080033import java.util.HashSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010034import java.util.LinkedHashMap;
Dmitry Lomov0d380642017-01-20 14:39:55 +000035import java.util.LinkedHashSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010036import java.util.Map;
John Cater6f2c3e22022-03-03 08:15:22 -080037import java.util.Set;
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 */
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;
John Caterfb162702022-02-16 10:09:34 -080066 private final ImmutableSet<ToolchainTypeRequirement> toolchainTypes;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010067
Dmitry Lomov0d380642017-01-20 14:39:55 +000068 /**
69 * Which attributes aspect should propagate along:
messa4fc24bc2021-05-20 01:42:18 -070070 *
Dmitry Lomov0d380642017-01-20 14:39:55 +000071 * <ul>
messa4fc24bc2021-05-20 01:42:18 -070072 * <li>A {@code null} value means propagate along all attributes
73 * <li>A (possibly empty) set means to propagate only along the attributes in a set
Dmitry Lomov0d380642017-01-20 14:39:55 +000074 * </ul>
75 */
76 @Nullable private final ImmutableSet<String> restrictToAttributes;
messa4fc24bc2021-05-20 01:42:18 -070077
Googlerb63ad3f2024-06-18 11:42:35 -070078 /** Toolchain types for which the aspect will propagate to matching resolved toolchains. */
79 private final ImmutableSet<Label> propagateToToolchainsTypes;
80
Dmitry Lomov0d380642017-01-20 14:39:55 +000081 @Nullable private final ConfigurationFragmentPolicy configurationFragmentPolicy;
dslomov99ea6b42017-04-25 17:46:17 +020082 private final boolean applyToFiles;
cparsons089148b2019-09-17 08:14:41 -070083 private final boolean applyToGeneratingRules;
Dmitry Lomovbb5901b2016-09-27 08:49:26 +000084
messaf8c34082021-06-04 02:51:04 -070085 private final ImmutableSet<AspectClass> requiredAspectClasses;
86
Googler7e3755d2022-06-01 12:46:09 -070087 private final ImmutableSet<Label> execCompatibleWith;
88 private final ImmutableMap<String, ExecGroup> execGroups;
Googleraa55c4d2023-08-30 00:48:57 -070089 private final ImmutableSet<? extends StarlarkSubruleApi> subrules;
Googler7e3755d2022-06-01 12:46:09 -070090
Dmitry Lomov65fde002017-02-07 17:24:04 +000091 public AdvertisedProviderSet getAdvertisedProviders() {
92 return advertisedProviders;
93 }
94
Googler7f748782021-11-22 17:20:58 -080095 private AspectDefinition(
Dmitry Lomovdce01702016-11-28 15:51:32 +000096 AspectClass aspectClass,
Dmitry Lomov65fde002017-02-07 17:24:04 +000097 AdvertisedProviderSet advertisedProviders,
Dmitry Lomovb5174c72017-01-10 10:57:17 +000098 RequiredProviders requiredProviders,
janakree5bf482018-03-26 10:55:59 -070099 RequiredProviders requiredProvidersForAspects,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100100 ImmutableMap<String, Attribute> attributes,
John Caterfb162702022-02-16 10:09:34 -0800101 ImmutableSet<ToolchainTypeRequirement> toolchainTypes,
Dmitry Lomov0d380642017-01-20 14:39:55 +0000102 @Nullable ImmutableSet<String> restrictToAttributes,
Googlerb63ad3f2024-06-18 11:42:35 -0700103 ImmutableSet<Label> propagateToToolchainsTypes,
dslomov99ea6b42017-04-25 17:46:17 +0200104 @Nullable ConfigurationFragmentPolicy configurationFragmentPolicy,
cparsons089148b2019-09-17 08:14:41 -0700105 boolean applyToFiles,
gregcedb271132021-04-05 15:50:50 -0700106 boolean applyToGeneratingRules,
Googler7e3755d2022-06-01 12:46:09 -0700107 ImmutableSet<AspectClass> requiredAspectClasses,
108 ImmutableSet<Label> execCompatibleWith,
Googleraa55c4d2023-08-30 00:48:57 -0700109 ImmutableMap<String, ExecGroup> execGroups,
110 ImmutableSet<? extends StarlarkSubruleApi> subrules) {
Dmitry Lomovdce01702016-11-28 15:51:32 +0000111 this.aspectClass = aspectClass;
Dmitry Lomov65fde002017-02-07 17:24:04 +0000112 this.advertisedProviders = advertisedProviders;
Dmitry Lomovb5174c72017-01-10 10:57:17 +0000113 this.requiredProviders = requiredProviders;
janakree5bf482018-03-26 10:55:59 -0700114 this.requiredProvidersForAspects = requiredProvidersForAspects;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100115 this.attributes = attributes;
John Caterfb162702022-02-16 10:09:34 -0800116 this.toolchainTypes = toolchainTypes;
Dmitry Lomov0d380642017-01-20 14:39:55 +0000117 this.restrictToAttributes = restrictToAttributes;
Googlerb63ad3f2024-06-18 11:42:35 -0700118 this.propagateToToolchainsTypes = propagateToToolchainsTypes;
Michael Staibcd48cd52016-01-15 20:11:11 +0000119 this.configurationFragmentPolicy = configurationFragmentPolicy;
dslomov99ea6b42017-04-25 17:46:17 +0200120 this.applyToFiles = applyToFiles;
cparsons089148b2019-09-17 08:14:41 -0700121 this.applyToGeneratingRules = applyToGeneratingRules;
messaf8c34082021-06-04 02:51:04 -0700122 this.requiredAspectClasses = requiredAspectClasses;
Googler7e3755d2022-06-01 12:46:09 -0700123 this.execCompatibleWith = execCompatibleWith;
124 this.execGroups = execGroups;
Googleraa55c4d2023-08-30 00:48:57 -0700125 this.subrules = subrules;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100126 }
127
128 public String getName() {
Dmitry Lomovdce01702016-11-28 15:51:32 +0000129 return aspectClass.getName();
130 }
131
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100132 /**
133 * Returns the attributes of the aspect in the form of a String -&gt; {@link Attribute} map.
134 *
135 * <p>All attributes are either implicit or late-bound.
136 */
137 public ImmutableMap<String, Attribute> getAttributes() {
138 return attributes;
139 }
140
John Cater13263f72017-05-24 19:06:47 +0200141 /** Returns the required toolchains declared by this aspect. */
John Caterfb162702022-02-16 10:09:34 -0800142 public ImmutableSet<ToolchainTypeRequirement> getToolchainTypes() {
143 return toolchainTypes;
John Cater13263f72017-05-24 19:06:47 +0200144 }
145
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100146 /**
Googler7e3755d2022-06-01 12:46:09 -0700147 * Returns the constraint values that must be present on an execution platform for this aspect.
148 */
149 public ImmutableSet<Label> execCompatibleWith() {
150 return execCompatibleWith;
151 }
152
153 /** Returns the execution groups that this aspect can use when creating actions. */
154 public ImmutableMap<String, ExecGroup> execGroups() {
155 return execGroups;
156 }
157
Googleraa55c4d2023-08-30 00:48:57 -0700158 /** Returns the subrules declared by this aspect. */
159 public ImmutableSet<? extends StarlarkSubruleApi> getSubrules() {
160 return subrules;
161 }
162
Googler7e3755d2022-06-01 12:46:09 -0700163 /**
messa4fc24bc2021-05-20 01:42:18 -0700164 * Returns {@link RequiredProviders} that a configured target must have so that this aspect can be
165 * applied to it.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100166 *
messa4fc24bc2021-05-20 01:42:18 -0700167 * <p>If a configured target does not satisfy required providers, the aspect is silently not
168 * created for it.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100169 */
Dmitry Lomovb5174c72017-01-10 10:57:17 +0000170 public RequiredProviders getRequiredProviders() {
171 return requiredProviders;
Eric Fellheimere27d0632015-09-25 21:35:26 +0000172 }
173
174 /**
messa4fc24bc2021-05-20 01:42:18 -0700175 * Aspects do not depend on other aspects applied to the same target <em>unless</em> the other
176 * aspect satisfies the {@link RequiredProviders} this method returns
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000177 */
178 public RequiredProviders getRequiredProvidersForAspects() {
179 return requiredProvidersForAspects;
180 }
181
messaf8c34082021-06-04 02:51:04 -0700182 /** Returns whether the aspect propagates along the give {@code attributeName} or not. */
lberki3bd28392019-02-05 01:01:02 -0800183 public boolean propagateAlong(String attributeName) {
Dmitry Lomov0d380642017-01-20 14:39:55 +0000184 if (restrictToAttributes != null) {
lberki3bd28392019-02-05 01:01:02 -0800185 return restrictToAttributes.contains(attributeName);
Dmitry Lomov0d380642017-01-20 14:39:55 +0000186 }
187 return true;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100188 }
189
Googlerb63ad3f2024-06-18 11:42:35 -0700190 /** Returns whether the aspect propagates to toolchains of the given {@code toolchainType}. */
191 public boolean canPropagateToToolchainType(Label toolchainType) {
192 return propagateToToolchainsTypes.contains(toolchainType);
193 }
194
Googler436a84f2024-07-11 14:57:39 -0700195 /** Returns whether the aspect propagates to toolchains. */
196 public boolean propagatesToToolchains() {
197 return !propagateToToolchainsTypes.isEmpty();
198 }
199
messa4fc24bc2021-05-20 01:42:18 -0700200 /** Returns the set of configuration fragments required by this Aspect. */
Michael Staibaf270462016-05-18 16:22:07 +0000201 public ConfigurationFragmentPolicy getConfigurationFragmentPolicy() {
Michael Staibcd48cd52016-01-15 20:11:11 +0000202 return configurationFragmentPolicy;
203 }
204
205 /**
dslomovce59d4d2017-08-04 17:32:47 +0200206 * Returns whether this aspect applies to (output) files.
dslomov99ea6b42017-04-25 17:46:17 +0200207 *
messa4fc24bc2021-05-20 01:42:18 -0700208 * <p>Currently only supported for top-level aspects and targets, and only for output files.
dslomov99ea6b42017-04-25 17:46:17 +0200209 */
210 public boolean applyToFiles() {
211 return applyToFiles;
212 }
213
cparsons089148b2019-09-17 08:14:41 -0700214 /**
215 * Returns whether this aspect should, when it would be applied to an output file, instead apply
216 * to the generating rule of that output file.
217 */
218 public boolean applyToGeneratingRules() {
219 return applyToGeneratingRules;
220 }
221
nharmataf2b26ad2019-03-06 09:37:00 -0800222 public static boolean satisfies(Aspect aspect, AdvertisedProviderSet advertisedProviderSet) {
jhorvitz9302ebd2021-06-28 11:09:06 -0700223 return aspect.getDefinition().requiredProviders.isSatisfiedBy(advertisedProviderSet);
Marian Loburfdd788e2015-03-25 09:36:28 +0000224 }
225
messaf8c34082021-06-04 02:51:04 -0700226 /** Checks if the given {@code maybeRequiredAspect} is required by this aspect definition */
227 public boolean requires(Aspect maybeRequiredAspect) {
228 return requiredAspectClasses.contains(maybeRequiredAspect.getAspectClass());
229 }
230
messa4fc24bc2021-05-20 01:42:18 -0700231 /** Collects all attribute labels from the specified aspectDefinition. */
Dmitry Lomov6073eb62016-01-21 21:26:32 +0000232 public static void addAllAttributesOfAspect(
Googlerb21cf252023-03-20 16:57:40 -0700233 Multimap<Attribute, Label> labelBuilder, Aspect aspect, DependencyFilter dependencyFilter) {
234 forEachLabelDepFromAllAttributesOfAspect(aspect, dependencyFilter, labelBuilder::put);
nharmataf2b26ad2019-03-06 09:37:00 -0800235 }
236
237 public static void forEachLabelDepFromAllAttributesOfAspect(
nharmataf2b26ad2019-03-06 09:37:00 -0800238 Aspect aspect,
239 DependencyFilter dependencyFilter,
240 BiConsumer<Attribute, Label> consumer) {
jhorvitz00d9ba02021-06-29 08:38:18 -0700241 LabelVisitor labelVisitor =
shreyax2bcbecf2018-09-26 12:27:32 -0700242 (label, aspectAttribute) -> {
wyv103ea9d2021-12-09 04:52:37 -0800243 if (label == null) {
shreyax2bcbecf2018-09-26 12:27:32 -0700244 return;
245 }
wyv103ea9d2021-12-09 04:52:37 -0800246 consumer.accept(aspectAttribute, label);
shreyax2bcbecf2018-09-26 12:27:32 -0700247 };
jhorvitz9302ebd2021-06-28 11:09:06 -0700248 for (Attribute aspectAttribute : aspect.getDefinition().attributes.values()) {
jhorvitz835f0a12021-07-02 06:14:33 -0700249 if (!dependencyFilter.test(aspect, aspectAttribute)) {
Marian Loburfdd788e2015-03-25 09:36:28 +0000250 continue;
251 }
nharmatad705c982017-04-04 19:09:15 +0000252 Type<?> type = aspectAttribute.getType();
Michael Staiba751f922017-02-14 15:50:04 +0000253 if (type.getLabelClass() != LabelClass.DEPENDENCY) {
254 continue;
255 }
Googlerb21cf252023-03-20 16:57:40 -0700256 visitSingleAttribute(aspectAttribute, aspectAttribute.getType(), labelVisitor);
Marian Loburfdd788e2015-03-25 09:36:28 +0000257 }
258 }
259
jhorvitz21e16592021-06-29 17:11:58 -0700260 private static <T> void visitSingleAttribute(
Googlerb21cf252023-03-20 16:57:40 -0700261 Attribute attribute, Type<T> type, LabelVisitor labelVisitor) {
Googler658b3a62023-08-11 10:42:53 -0700262 type.visitLabels(labelVisitor, type.cast(attribute.getDefaultValue(null)), attribute);
jhorvitz21e16592021-06-29 17:11:58 -0700263 }
264
Dmitry Lomov0c66dee2017-02-13 17:24:43 +0000265 public static Builder builder(AspectClass aspectClass) {
266 return new Builder(aspectClass);
267 }
268
messa4fc24bc2021-05-20 01:42:18 -0700269 /** Builder class for {@link AspectDefinition}. */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100270 public static final class Builder {
Dmitry Lomovdce01702016-11-28 15:51:32 +0000271 private final AspectClass aspectClass;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100272 private final Map<String, Attribute> attributes = new LinkedHashMap<>();
Dmitry Lomov65fde002017-02-07 17:24:04 +0000273 private final AdvertisedProviderSet.Builder advertisedProviders =
274 AdvertisedProviderSet.builder();
jhorvitz9302ebd2021-06-28 11:09:06 -0700275 private final RequiredProviders.Builder requiredProviders =
276 RequiredProviders.acceptAnyBuilder();
jhorvitz9302ebd2021-06-28 11:09:06 -0700277 private final RequiredProviders.Builder requiredAspectProviders =
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000278 RequiredProviders.acceptNoneBuilder();
messa4fc24bc2021-05-20 01:42:18 -0700279 @Nullable private LinkedHashSet<String> propagateAlongAttributes = new LinkedHashSet<>();
Googlerb63ad3f2024-06-18 11:42:35 -0700280 private ImmutableSet<Label> propagateToToolchainsTypes = ImmutableSet.of();
Michael Staibcd48cd52016-01-15 20:11:11 +0000281 private final ConfigurationFragmentPolicy.Builder configurationFragmentPolicy =
282 new ConfigurationFragmentPolicy.Builder();
dslomov99ea6b42017-04-25 17:46:17 +0200283 private boolean applyToFiles = false;
cparsons089148b2019-09-17 08:14:41 -0700284 private boolean applyToGeneratingRules = false;
John Cater6f2c3e22022-03-03 08:15:22 -0800285 private final Set<ToolchainTypeRequirement> toolchainTypes = new HashSet<>();
messaf8c34082021-06-04 02:51:04 -0700286 private ImmutableSet<AspectClass> requiredAspectClasses = ImmutableSet.of();
Googler7e3755d2022-06-01 12:46:09 -0700287 private ImmutableSet<Label> execCompatibleWith = ImmutableSet.of();
288 private ImmutableMap<String, ExecGroup> execGroups = ImmutableMap.of();
Googleraa55c4d2023-08-30 00:48:57 -0700289 private ImmutableSet<? extends StarlarkSubruleApi> subrules = ImmutableSet.of();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100290
Dmitry Lomovdce01702016-11-28 15:51:32 +0000291 public Builder(AspectClass aspectClass) {
292 this.aspectClass = aspectClass;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100293 }
294
Googler90bf7272022-12-21 14:24:13 -0800295 @CanIgnoreReturnValue
296 public Builder requireProviders(RequiredProviders requiredProviders) {
Googlerd32ea792024-01-19 13:54:03 -0800297 this.requireStarlarkProviderSets(requiredProviders.getStarlarkProviders());
Googler90bf7272022-12-21 14:24:13 -0800298 return this;
299 }
300
301 /**
messa1bca1bd2021-05-14 00:48:19 -0700302 * Asserts that this aspect can only be evaluated for rules that supply all of the providers
303 * from at least one set of required providers.
304 */
Kurt Alfred Kluever29e8e7d2022-07-04 06:50:48 -0700305 @CanIgnoreReturnValue
messa1bca1bd2021-05-14 00:48:19 -0700306 public Builder requireStarlarkProviderSets(
307 Iterable<ImmutableSet<StarlarkProviderIdentifier>> providerSets) {
308 for (ImmutableSet<StarlarkProviderIdentifier> providerSet : providerSets) {
309 if (!providerSet.isEmpty()) {
310 requiredProviders.addStarlarkSet(providerSet);
311 }
312 }
313 return this;
314 }
315
316 /**
elenairinaaeb21bc2017-09-27 12:13:52 -0400317 * Asserts that this aspect can only be evaluated for rules that supply all of the specified
gregce3377c112020-04-13 09:29:59 -0700318 * Starlark providers.
elenairinaaeb21bc2017-09-27 12:13:52 -0400319 */
Kurt Alfred Kluever29e8e7d2022-07-04 06:50:48 -0700320 @CanIgnoreReturnValue
gregce773b95f2020-05-19 09:51:09 -0700321 public Builder requireStarlarkProviders(StarlarkProviderIdentifier... starlarkProviders) {
322 requiredProviders.addStarlarkSet(ImmutableSet.copyOf(starlarkProviders));
elenairinaaeb21bc2017-09-27 12:13:52 -0400323 return this;
324 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100325
gregcedb271132021-04-05 15:50:50 -0700326 /**
messaf8c34082021-06-04 02:51:04 -0700327 * Asserts that this aspect requires a list of aspects to be applied before it on the configured
328 * target.
329 */
Kurt Alfred Kluever29e8e7d2022-07-04 06:50:48 -0700330 @CanIgnoreReturnValue
messaf8c34082021-06-04 02:51:04 -0700331 public Builder requiredAspectClasses(ImmutableSet<AspectClass> requiredAspectClasses) {
332 this.requiredAspectClasses = requiredAspectClasses;
333 return this;
334 }
335
Kurt Alfred Kluever29e8e7d2022-07-04 06:50:48 -0700336 @CanIgnoreReturnValue
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000337 public Builder requireAspectsWithProviders(
gregce74d84d42020-04-17 10:02:03 -0700338 Iterable<ImmutableSet<StarlarkProviderIdentifier>> providerSets) {
339 for (ImmutableSet<StarlarkProviderIdentifier> providerSet : providerSets) {
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000340 if (!providerSet.isEmpty()) {
gregce18694cd2020-05-12 15:40:05 -0700341 requiredAspectProviders.addStarlarkSet(providerSet);
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000342 }
343 }
344 return this;
345 }
346
gregce74d84d42020-04-17 10:02:03 -0700347 /** State that the aspect being built provides given providers. */
Kurt Alfred Kluever29e8e7d2022-07-04 06:50:48 -0700348 @CanIgnoreReturnValue
gregce74d84d42020-04-17 10:02:03 -0700349 public Builder advertiseProvider(ImmutableList<StarlarkProviderIdentifier> providers) {
350 for (StarlarkProviderIdentifier provider : providers) {
gregced7c1cef2020-05-12 07:51:48 -0700351 advertisedProviders.addStarlark(provider);
Dmitry Lomov65fde002017-02-07 17:24:04 +0000352 }
353 return this;
354 }
355
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100356 /**
messa4fc24bc2021-05-20 01:42:18 -0700357 * Declares that this aspect propagates along an {@code attribute} on the target associated with
358 * this aspect.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100359 *
jhorvitz9302ebd2021-06-28 11:09:06 -0700360 * <p>Specify multiple attributes by calling this method repeatedly.
Dmitry Lomov0d380642017-01-20 14:39:55 +0000361 *
messa4fc24bc2021-05-20 01:42:18 -0700362 * <p>Aspect can also declare to propagate along all attributes with {@link
363 * #propagateAlongAttributes}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100364 */
Kurt Alfred Kluever29e8e7d2022-07-04 06:50:48 -0700365 @CanIgnoreReturnValue
jhorvitz9302ebd2021-06-28 11:09:06 -0700366 public Builder propagateAlongAttribute(String attribute) {
Rumou Duan5b0b3102015-06-03 20:27:57 +0000367 Preconditions.checkNotNull(attribute);
messa4fc24bc2021-05-20 01:42:18 -0700368 Preconditions.checkState(
369 this.propagateAlongAttributes != null,
Dmitry Lomov0d380642017-01-20 14:39:55 +0000370 "Either propagate along all attributes, or along specific attributes, not both");
371
372 this.propagateAlongAttributes.add(attribute);
373
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100374 return this;
375 }
376
377 /**
messa4fc24bc2021-05-20 01:42:18 -0700378 * Declares that this aspect propagates along all attributes on the target associated with this
379 * aspect.
Dmitry Lomov0d380642017-01-20 14:39:55 +0000380 *
messa4fc24bc2021-05-20 01:42:18 -0700381 * <p>Specify either this or {@link #propagateAlongAttribute(String)}, not both.
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +0000382 */
Kurt Alfred Kluever29e8e7d2022-07-04 06:50:48 -0700383 @CanIgnoreReturnValue
jhorvitz9302ebd2021-06-28 11:09:06 -0700384 public Builder propagateAlongAllAttributes() {
messa4fc24bc2021-05-20 01:42:18 -0700385 Preconditions.checkState(
386 this.propagateAlongAttributes != null,
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000387 "Aspects for all attributes must only be specified once");
Dmitry Lomov0d380642017-01-20 14:39:55 +0000388
messa4fc24bc2021-05-20 01:42:18 -0700389 Preconditions.checkState(
390 this.propagateAlongAttributes.isEmpty(),
Dmitry Lomov0d380642017-01-20 14:39:55 +0000391 "Specify either aspects for all attributes, or for specific attributes, not both");
392 this.propagateAlongAttributes = null;
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000393 return this;
394 }
395
Googlerb63ad3f2024-06-18 11:42:35 -0700396 /** Declares that this aspect propagates to toolchains of the given types. */
397 @CanIgnoreReturnValue
398 public Builder propagateToToolchainsTypes(ImmutableSet<Label> toolchainsTypes) {
399 this.propagateToToolchainsTypes = toolchainsTypes;
400 return this;
401 }
402
Dmitry Lomovc15ba2e2015-10-30 15:50:01 +0000403 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100404 * Adds an attribute to the aspect.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100405 */
406 public <TYPE> Builder add(Attribute.Builder<TYPE> attr) {
407 Attribute attribute = attr.build();
Dmitry Lomovace678e2015-12-16 15:10:20 +0000408 return add(attribute);
409 }
410
411 /**
412 * Adds an attribute to the aspect.
413 *
Googler20e04822022-06-02 08:10:03 -0700414 * <p>Aspects attributes can be of any data type if they are not public, i.e. implicit (starting
415 * with '$') or late-bound (starting with ':'). While public attributes can only be of types
416 * string, integer or boolean.
ilistd7432e22020-06-04 13:51:45 -0700417 *
418 * <p>Aspect definition currently cannot handle {@link ComputedDefault} dependencies (type LABEL
419 * or LABEL_LIST), because all the dependencies are resolved from the aspect definition and the
420 * defining rule.
Dmitry Lomovace678e2015-12-16 15:10:20 +0000421 */
Kurt Alfred Kluever29e8e7d2022-07-04 06:50:48 -0700422 @CanIgnoreReturnValue
Dmitry Lomovace678e2015-12-16 15:10:20 +0000423 public Builder add(Attribute attribute) {
ilistd7432e22020-06-04 13:51:45 -0700424 Preconditions.checkArgument(
425 attribute.isImplicit()
426 || attribute.isLateBound()
messa14292d12021-12-20 07:46:23 -0800427 || (attribute.getType() == Type.STRING && attribute.checkAllowedValues())
messa30fd5082021-12-22 05:39:13 -0800428 || (attribute.getType() == Type.INTEGER && attribute.checkAllowedValues())
429 || attribute.getType() == Type.BOOLEAN,
ilistd7432e22020-06-04 13:51:45 -0700430 "%s: Invalid attribute '%s' (%s)",
431 aspectClass.getName(),
432 attribute.getName(),
433 attribute.getType());
434
435 // Attributes specifying dependencies using ComputedDefault value are currently not supported.
436 // The limitation is in place because:
437 // - blaze query requires that all possible values are knowable without BuildConguration
438 // - aspects can attach to any rule
439 // Current logic in #forEachLabelDepFromAllAttributesOfAspect is not enough,
440 // however {Conservative,Precise}AspectResolver can probably be improved to make that work.
441 Preconditions.checkArgument(
442 !(attribute.getType().getLabelClass() == LabelClass.DEPENDENCY
443 && (attribute.getDefaultValueUnchecked() instanceof ComputedDefault)),
444 "%s: Invalid attribute '%s' (%s) with computed default dependencies",
445 aspectClass.getName(),
446 attribute.getName(),
447 attribute.getType());
448 Preconditions.checkArgument(
449 !attributes.containsKey(attribute.getName()),
450 "%s: An attribute with the name '%s' already exists.",
451 aspectClass.getName(),
452 attribute.getName());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100453 attributes.put(attribute.getName(), attribute);
454 return this;
455 }
456
457 /**
Michael Staibcd48cd52016-01-15 20:11:11 +0000458 * Declares that the implementation of the associated aspect definition requires the given
Googler92f0d6a2023-01-06 09:45:16 -0800459 * fragments to be present in this rule's exec and target configurations.
Michael Staibcd48cd52016-01-15 20:11:11 +0000460 *
461 * <p>The value is inherited by subclasses.
462 */
Kurt Alfred Kluever29e8e7d2022-07-04 06:50:48 -0700463 @CanIgnoreReturnValue
jhorvitz11dc1042021-08-13 07:30:19 -0700464 public Builder requiresConfigurationFragments(
465 Class<? extends Fragment>... configurationFragments) {
messa4fc24bc2021-05-20 01:42:18 -0700466 configurationFragmentPolicy.requiresConfigurationFragments(
467 ImmutableSet.copyOf(configurationFragments));
Michael Staibcd48cd52016-01-15 20:11:11 +0000468 return this;
469 }
470
471 /**
Michael Staibcd48cd52016-01-15 20:11:11 +0000472 * Declares the configuration fragments that are required by this rule for the target
473 * configuration.
474 *
475 * <p>In contrast to {@link #requiresConfigurationFragments(Class...)}, this method takes the
gregce3377c112020-04-13 09:29:59 -0700476 * Starlark module names of fragments instead of their classes.
Michael Staibcd48cd52016-01-15 20:11:11 +0000477 */
Kurt Alfred Kluever29e8e7d2022-07-04 06:50:48 -0700478 @CanIgnoreReturnValue
gregce220a1c82020-05-01 10:19:52 -0700479 public Builder requiresConfigurationFragmentsByStarlarkBuiltinName(
Michael Staibcd48cd52016-01-15 20:11:11 +0000480 Collection<String> configurationFragmentNames) {
gregce220a1c82020-05-01 10:19:52 -0700481 configurationFragmentPolicy.requiresConfigurationFragmentsByStarlarkBuiltinName(
482 configurationFragmentNames);
Michael Staibcd48cd52016-01-15 20:11:11 +0000483 return this;
484 }
485
486 /**
twigg8e9f9e12020-09-17 09:07:58 -0700487 * Sets the policy for the case where the configuration is missing the required fragment class
488 * (see {@link #requiresConfigurationFragments}).
Michael Staibcd48cd52016-01-15 20:11:11 +0000489 */
Kurt Alfred Kluever29e8e7d2022-07-04 06:50:48 -0700490 @CanIgnoreReturnValue
twigg8e9f9e12020-09-17 09:07:58 -0700491 public Builder setMissingFragmentPolicy(
492 Class<?> fragmentClass, MissingFragmentPolicy missingFragmentPolicy) {
493 configurationFragmentPolicy.setMissingFragmentPolicy(fragmentClass, missingFragmentPolicy);
Michael Staibcd48cd52016-01-15 20:11:11 +0000494 return this;
495 }
496
dslomov99ea6b42017-04-25 17:46:17 +0200497 /**
498 * Sets whether this aspect should apply to files.
499 *
messa4fc24bc2021-05-20 01:42:18 -0700500 * <p>Default is <code>false</code>. Currently only supported for top-level aspects and targets,
501 * and only for output files.
dslomov99ea6b42017-04-25 17:46:17 +0200502 */
Kurt Alfred Kluever29e8e7d2022-07-04 06:50:48 -0700503 @CanIgnoreReturnValue
dslomov99ea6b42017-04-25 17:46:17 +0200504 public Builder applyToFiles(boolean propagateOverGeneratedFiles) {
505 this.applyToFiles = propagateOverGeneratedFiles;
506 return this;
507 }
508
cparsons089148b2019-09-17 08:14:41 -0700509 /**
510 * Sets whether this aspect should, when it would be applied to an output file, instead apply to
511 * the generating rule of that output file.
512 *
513 * <p>Default is <code>false</code>. Currently only supported for aspects which do not have a
514 * "required providers" list.
515 */
Kurt Alfred Kluever29e8e7d2022-07-04 06:50:48 -0700516 @CanIgnoreReturnValue
cparsons089148b2019-09-17 08:14:41 -0700517 public Builder applyToGeneratingRules(boolean applyToGeneratingRules) {
518 this.applyToGeneratingRules = applyToGeneratingRules;
519 return this;
520 }
521
John Cater13263f72017-05-24 19:06:47 +0200522 /** Adds the given toolchains as requirements for this aspect. */
John Cater6f2c3e22022-03-03 08:15:22 -0800523 public Builder addToolchainTypes(ToolchainTypeRequirement... toolchainTypes) {
524 return this.addToolchainTypes(ImmutableSet.copyOf(toolchainTypes));
John Caterfb162702022-02-16 10:09:34 -0800525 }
526
527 /** Adds the given toolchains as requirements for this aspect. */
Kurt Alfred Kluever29e8e7d2022-07-04 06:50:48 -0700528 @CanIgnoreReturnValue
John Cater6f2c3e22022-03-03 08:15:22 -0800529 public Builder addToolchainTypes(Collection<ToolchainTypeRequirement> toolchainTypes) {
John Caterfb162702022-02-16 10:09:34 -0800530 this.toolchainTypes.addAll(toolchainTypes);
jcater75828752018-04-27 12:53:19 -0700531 return this;
532 }
533
Michael Staibcd48cd52016-01-15 20:11:11 +0000534 /**
Googler7e3755d2022-06-01 12:46:09 -0700535 * Adds the given constraint values to the set required for execution platforms for this aspect.
536 */
Kurt Alfred Kluever29e8e7d2022-07-04 06:50:48 -0700537 @CanIgnoreReturnValue
Googler7e3755d2022-06-01 12:46:09 -0700538 public Builder execCompatibleWith(ImmutableSet<Label> execCompatibleWith) {
539 this.execCompatibleWith = execCompatibleWith;
540 return this;
541 }
542
543 /** Sets the execution groups that are available for actions created by this aspect. */
Kurt Alfred Kluever29e8e7d2022-07-04 06:50:48 -0700544 @CanIgnoreReturnValue
Googler7e3755d2022-06-01 12:46:09 -0700545 public Builder execGroups(ImmutableMap<String, ExecGroup> execGroups) {
546 // TODO(b/230337573): validate names
547 // TODO(b/230337573): handle copy_from_default
548 this.execGroups = execGroups;
549 return this;
550 }
551
Googleraa55c4d2023-08-30 00:48:57 -0700552 @CanIgnoreReturnValue
553 public Builder subrules(ImmutableSet<? extends StarlarkSubruleApi> subrules) {
554 this.subrules = subrules;
555 return this;
556 }
557
Googler7e3755d2022-06-01 12:46:09 -0700558 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100559 * Builds the aspect definition.
560 *
561 * <p>The builder object is reusable afterwards.
562 */
563 public AspectDefinition build() {
cparsons089148b2019-09-17 08:14:41 -0700564 RequiredProviders requiredProviders = this.requiredProviders.build();
565 if (applyToGeneratingRules && !requiredProviders.acceptsAny()) {
566 throw new IllegalStateException(
567 "An aspect cannot simultaneously have required providers "
568 + "and apply to generating rules.");
569 }
570
John Cater13263f72017-05-24 19:06:47 +0200571 return new AspectDefinition(
572 aspectClass,
Dmitry Lomov65fde002017-02-07 17:24:04 +0000573 advertisedProviders.build(),
cparsons089148b2019-09-17 08:14:41 -0700574 requiredProviders,
Dmitry Lomovf868b3e2017-01-17 10:25:28 +0000575 requiredAspectProviders.build(),
Dmitry Lomovbb5901b2016-09-27 08:49:26 +0000576 ImmutableMap.copyOf(attributes),
John Caterfb162702022-02-16 10:09:34 -0800577 ImmutableSet.copyOf(toolchainTypes),
John Cater13263f72017-05-24 19:06:47 +0200578 propagateAlongAttributes == null ? null : ImmutableSet.copyOf(propagateAlongAttributes),
Googlerb63ad3f2024-06-18 11:42:35 -0700579 propagateToToolchainsTypes,
dslomov99ea6b42017-04-25 17:46:17 +0200580 configurationFragmentPolicy.build(),
cparsons089148b2019-09-17 08:14:41 -0700581 applyToFiles,
gregcedb271132021-04-05 15:50:50 -0700582 applyToGeneratingRules,
Googler7e3755d2022-06-01 12:46:09 -0700583 requiredAspectClasses,
584 execCompatibleWith,
Googleraa55c4d2023-08-30 00:48:57 -0700585 execGroups,
586 subrules);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100587 }
588 }
589}