blob: bfbbecda206d6989934da74435559e348524822b [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
juliexxia44cd3a62018-12-19 11:57:16 -080017import static com.google.devtools.build.lib.packages.Attribute.ANY_RULE;
Florian Weikertea6c82d2016-09-05 12:15:31 +000018import static com.google.devtools.build.lib.packages.Attribute.attr;
Lukacs Berkiffa73ad2015-09-18 11:40:12 +000019import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
Googlerc5fcc862019-09-06 16:17:47 -070020import static com.google.devtools.build.lib.packages.Type.BOOLEAN;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010021
22import com.google.common.annotations.VisibleForTesting;
Lukacs Berki0e1a9942015-06-18 08:53:18 +000023import com.google.common.base.Function;
24import com.google.common.base.Functions;
tomlua155b532017-11-08 20:12:47 +010025import com.google.common.base.Preconditions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010026import com.google.common.base.Predicate;
27import com.google.common.base.Predicates;
28import com.google.common.collect.ImmutableList;
Lukacs Berki0e1a9942015-06-18 08:53:18 +000029import com.google.common.collect.ImmutableMap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010030import com.google.common.collect.ImmutableSet;
nharmataf3e99412019-01-28 10:06:29 -080031import com.google.common.collect.Interner;
John Cater9a8d16e2017-07-05 16:12:07 -040032import com.google.common.collect.Iterables;
cpeyserd852e482017-09-07 22:16:06 +020033import com.google.common.collect.Lists;
ulfjack5756b352020-01-23 04:53:22 -080034import com.google.common.collect.Maps;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010035import com.google.common.collect.Ordering;
gregcebe55e112018-01-30 11:04:53 -080036import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition;
mstaib860975a2018-04-26 15:00:52 -070037import com.google.devtools.build.lib.analysis.config.transitions.PatchTransition;
gregce74a895d2018-05-29 11:26:03 -070038import com.google.devtools.build.lib.analysis.config.transitions.SplitTransition;
John Caterb3b3e8b2019-04-03 09:18:42 -070039import com.google.devtools.build.lib.analysis.config.transitions.TransitionFactory;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000040import com.google.devtools.build.lib.cmdline.Label;
Lukacs Berkia6434362015-09-15 13:56:14 +000041import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
Brian Silvermand7d6d622016-03-17 09:53:39 +000042import com.google.devtools.build.lib.cmdline.PackageIdentifier;
dannarkf24479d2018-06-21 11:55:44 -070043import com.google.devtools.build.lib.cmdline.RepositoryName;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010044import com.google.devtools.build.lib.events.EventHandler;
Michajlo Matijkiw581f2c22016-07-25 20:12:16 +000045import com.google.devtools.build.lib.events.NullEventHandler;
schmitta4080da92019-05-20 13:12:46 -070046import com.google.devtools.build.lib.packages.Attribute.ComputedDefault;
Florian Weikertea6c82d2016-09-05 12:15:31 +000047import com.google.devtools.build.lib.packages.Attribute.SkylarkComputedDefaultTemplate;
48import com.google.devtools.build.lib.packages.Attribute.SkylarkComputedDefaultTemplate.CannotPrecomputeDefaultsException;
dannarkf24479d2018-06-21 11:55:44 -070049import com.google.devtools.build.lib.packages.BuildType.LabelConversionContext;
Lukacs Berkiffa73ad2015-09-18 11:40:12 +000050import com.google.devtools.build.lib.packages.BuildType.SelectorList;
Michael Staibb51251e2015-09-29 23:31:51 +000051import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy.MissingFragmentPolicy;
janakr6ff110e2018-03-21 21:44:27 -070052import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
gregce4aa059a2019-02-26 13:20:47 -080053import com.google.devtools.build.lib.packages.RuleClass.Builder.ThirdPartyLicenseExistencePolicy;
nharmata65a173a2017-08-07 16:11:04 +020054import com.google.devtools.build.lib.packages.RuleFactory.AttributeValues;
Googlerc5fcc862019-09-06 16:17:47 -070055import com.google.devtools.build.lib.packages.Type.ConversionException;
mjhalupka49581922018-02-28 11:04:31 -080056import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
57import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
Yue Gan36a26572016-05-25 11:48:10 +000058import com.google.devtools.build.lib.syntax.EvalException;
adonovanf5262c52020-04-02 09:25:14 -070059import com.google.devtools.build.lib.syntax.Location;
Googler4871cb02019-11-12 17:16:42 -080060import com.google.devtools.build.lib.syntax.Sequence;
Googler641bdf72019-11-12 10:32:26 -080061import com.google.devtools.build.lib.syntax.Starlark;
adonovanf3a344e82019-12-11 11:10:11 -080062import com.google.devtools.build.lib.syntax.StarlarkFunction;
adonovan40a737c2020-03-11 14:32:19 -070063import com.google.devtools.build.lib.syntax.StarlarkThread;
juliexxia1f332e02018-10-31 14:20:55 -070064import com.google.devtools.build.lib.util.FileTypeSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010065import com.google.devtools.build.lib.util.StringUtil;
66import com.google.devtools.build.lib.vfs.PathFragment;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010067import java.util.ArrayList;
Googler72f3a102017-12-01 16:28:28 -080068import java.util.Arrays;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010069import java.util.BitSet;
70import java.util.Collection;
gregceda4c9592017-07-27 22:09:34 +020071import java.util.Collections;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010072import java.util.HashMap;
cpeyserfb829992017-09-07 17:17:03 +020073import java.util.HashSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010074import java.util.LinkedHashMap;
gregceb46208d2019-03-11 13:21:34 -070075import java.util.LinkedHashSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010076import java.util.List;
77import java.util.Map;
mjhalupka49581922018-02-28 11:04:31 -080078import java.util.Objects;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010079import java.util.Set;
80import java.util.regex.Pattern;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010081import javax.annotation.Nullable;
82import javax.annotation.concurrent.Immutable;
83
84/**
85 * Instances of RuleClass encapsulate the set of attributes of a given "class" of rule, such as
86 * <code>cc_binary</code>.
87 *
janakrd3fe5e72018-03-30 12:49:12 -070088 * <p>This is an instance of the "meta-class" pattern for Rules: we achieve using <i>values</i> what
89 * subclasses achieve using <i>types</i>. (The "Design Patterns" book doesn't include this pattern,
90 * so think of it as something like a cross between a Flyweight and a State pattern. Like Flyweight,
91 * we avoid repeatedly storing data that belongs to many instances. Like State, we delegate from
92 * Rule to RuleClass for the specific behavior of that rule (though unlike state, a Rule object
93 * never changes its RuleClass). This avoids the need to declare one Java class per class of Rule,
94 * yet achieves the same behavior.)
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010095 *
96 * <p>The use of a metaclass also allows us to compute a mapping from Attributes to small integers
janakrd3fe5e72018-03-30 12:49:12 -070097 * and share this between all rules of the same metaclass. This means we can save the attribute
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010098 * dictionary for each rule instance using an array, which is much more compact than a hashtable.
99 *
100 * <p>Rule classes whose names start with "$" are considered "abstract"; since they are not valid
101 * identifiers, they cannot be named in the build language. However, they are useful for grouping
102 * related attributes which are inherited.
103 *
janakrd3fe5e72018-03-30 12:49:12 -0700104 * <p>The exact values in this class are important. In particular:
105 *
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100106 * <ul>
janakrd3fe5e72018-03-30 12:49:12 -0700107 * <li>Changing an attribute from MANDATORY to OPTIONAL creates the potential for null-pointer
108 * exceptions in code that expects a value.
109 * <li>Attributes whose names are preceded by a "$" or a ":" are "hidden", and cannot be redefined
110 * in a BUILD file. They are a useful way of adding a special dependency. By convention,
111 * attributes starting with "$" are implicit dependencies, and those starting with a ":" are
112 * late-bound implicit dependencies, i.e. dependencies that can only be resolved when the
113 * configuration is known.
114 * <li>Attributes should not be introduced into the hierarchy higher then necessary.
115 * <li>The 'deps' and 'data' attributes are treated specially by the code that builds the runfiles
116 * tree. All targets appearing in these attributes appears beneath the ".runfiles" tree; in
117 * addition, "deps" may have rule-specific semantics.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100118 * </ul>
juliexxia1f332e02018-10-31 14:20:55 -0700119 *
120 * TODO(bazel-team): Consider breaking up this class in more manageable subclasses.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100121 */
Janak Ramakrishnanc97ec7b2017-02-15 23:58:24 +0000122// Non-final only for mocking in tests. Do not subclass!
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100123@Immutable
janakrd3fe5e72018-03-30 12:49:12 -0700124@AutoCodec
Janak Ramakrishnanc97ec7b2017-02-15 23:58:24 +0000125public class RuleClass {
John Caterae6f7d52019-04-12 10:42:59 -0700126
michajlob839a512020-03-11 10:04:23 -0700127 /**
michajlo0a89cef2020-04-06 12:04:12 -0700128 * Maximum attributes per RuleClass. Current value was chosen to be high enough to be considered a
michajlob839a512020-03-11 10:04:23 -0700129 * non-breaking change for reasonable use. It was also chosen to be low enough to give significant
130 * headroom before hitting {@link AttributeContainer}'s limits.
131 */
michajlo7475b772020-03-12 15:10:11 -0700132 private static final int MAX_ATTRIBUTES = 200;
michajlob839a512020-03-11 10:04:23 -0700133
michajlo0a89cef2020-04-06 12:04:12 -0700134 /**
135 * Maximum attribute name length. Chosen to accommodate existing and prevent extreme outliers from
136 * forming - extreme values create bloat, both in memory usage and various outputs, including but
137 * not limited to, query output.
138 */
139 private static final int MAX_ATTRIBUTE_NAME_LENGTH = 128;
140
janakrd3fe5e72018-03-30 12:49:12 -0700141 @AutoCodec
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000142 static final Function<? super Rule, Map<String, Label>> NO_EXTERNAL_BINDINGS =
143 Functions.<Map<String, Label>>constant(ImmutableMap.<String, Label>of());
janakrd3fe5e72018-03-30 12:49:12 -0700144
145 @AutoCodec
mstaibe5538ad2017-04-04 18:32:23 +0000146 static final Function<? super Rule, Set<String>> NO_OPTION_REFERENCE =
147 Functions.<Set<String>>constant(ImmutableSet.<String>of());
Brian Silvermand7d6d622016-03-17 09:53:39 +0000148
nharmatab4060b62017-04-04 17:11:39 +0000149 public static final PathFragment THIRD_PARTY_PREFIX = PathFragment.create("third_party");
Googler9ad95082019-05-13 13:38:22 -0700150 public static final PathFragment EXPERIMENTAL_PREFIX = PathFragment.create("experimental");
John Caterae6f7d52019-04-12 10:42:59 -0700151 public static final String EXEC_COMPATIBLE_WITH_ATTR = "exec_compatible_with";
Googlerb5082462019-08-26 14:28:09 -0700152 public static final String EXEC_PROPERTIES = "exec_properties";
aiuto4d9bb522020-02-19 13:26:10 -0800153 /*
154 * The attribute that declares the set of license labels which apply to this target.
155 */
156 public static final String APPLICABLE_LICENSES_ATTR = "applicable_licenses";
Brian Silvermand7d6d622016-03-17 09:53:39 +0000157
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100158 /**
159 * A constraint for the package name of the Rule instances.
160 */
161 public static class PackageNameConstraint implements PredicateWithMessage<Rule> {
162
163 public static final int ANY_SEGMENT = 0;
164
165 private final int pathSegment;
166
167 private final Set<String> values;
168
169 /**
170 * The pathSegment-th segment of the package must be one of the specified values.
171 * The path segment indexing starts from 1.
172 */
173 public PackageNameConstraint(int pathSegment, String... values) {
174 this.values = ImmutableSet.copyOf(values);
175 this.pathSegment = pathSegment;
176 }
177
178 @Override
179 public boolean apply(Rule input) {
180 PathFragment path = input.getLabel().getPackageFragment();
181 if (pathSegment == ANY_SEGMENT) {
182 return path.getFirstSegment(values) != PathFragment.INVALID_SEGMENT;
183 } else {
184 return path.segmentCount() >= pathSegment
185 && values.contains(path.getSegment(pathSegment - 1));
186 }
187 }
188
189 @Override
190 public String getErrorReason(Rule param) {
191 if (pathSegment == ANY_SEGMENT) {
Francois-Rene Rideaucbebd632015-02-11 16:56:37 +0000192 return param.getRuleClass() + " rules have to be under a "
193 + StringUtil.joinEnglishList(values, "or", "'") + " directory";
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100194 } else if (pathSegment == 1) {
195 return param.getRuleClass() + " rules are only allowed in "
196 + StringUtil.joinEnglishList(StringUtil.append(values, "//", ""), "or");
197 } else {
Francois-Rene Rideaucbebd632015-02-11 16:56:37 +0000198 return param.getRuleClass() + " rules are only allowed in packages which "
199 + StringUtil.ordinal(pathSegment) + " is " + StringUtil.joinEnglishList(values, "or");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100200 }
201 }
202
203 @VisibleForTesting
204 public int getPathSegment() {
205 return pathSegment;
206 }
207
208 @VisibleForTesting
209 public Collection<String> getValues() {
210 return values;
211 }
212 }
213
cparsonse2d200f2018-03-06 16:15:11 -0800214 /** A factory or builder class for rule implementations. */
215 public interface ConfiguredTargetFactory<
216 TConfiguredTarget, TContext, TActionConflictException extends Throwable> {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100217 /**
218 * Returns a fully initialized configured target instance using the given context.
Chris Parsons4dfb22c2016-05-23 17:39:42 +0000219 *
220 * @throws RuleErrorException if configured target creation could not be completed due to rule
cparsonse2d200f2018-03-06 16:15:11 -0800221 * errors
222 * @throws TActionConflictException if there were conflicts during action registration
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100223 */
cparsonse2d200f2018-03-06 16:15:11 -0800224 TConfiguredTarget create(TContext ruleContext)
225 throws InterruptedException, RuleErrorException, TActionConflictException;
Chris Parsons4dfb22c2016-05-23 17:39:42 +0000226
227 /**
cparsonse2d200f2018-03-06 16:15:11 -0800228 * Exception indicating that configured target creation could not be completed. General error
229 * messaging should be done via {@link RuleErrorConsumer}; this exception only interrupts
230 * configured target creation in cases where it can no longer continue.
Chris Parsons4dfb22c2016-05-23 17:39:42 +0000231 */
janakr525ba252020-02-19 11:27:05 -0800232 final class RuleErrorException extends Exception {
233 RuleErrorException() {
Benjamin Petersonaf53a112019-06-05 10:47:11 -0700234 super();
235 }
236
janakr525ba252020-02-19 11:27:05 -0800237 RuleErrorException(String message) {
Benjamin Petersonaf53a112019-06-05 10:47:11 -0700238 super(message);
239 }
janakr525ba252020-02-19 11:27:05 -0800240
241 RuleErrorException(Throwable cause) {
242 super(cause);
243 }
244
245 RuleErrorException(String message, Throwable cause) {
246 super(message, cause);
247 }
Benjamin Petersonaf53a112019-06-05 10:47:11 -0700248 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100249 }
250
251 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100252 * For Bazel's constraint system: the attribute that declares the set of environments a rule
253 * supports, overriding the defaults for their respective groups.
254 */
255 public static final String RESTRICTED_ENVIRONMENT_ATTR = "restricted_to";
256
257 /**
258 * For Bazel's constraint system: the attribute that declares the set of environments a rule
259 * supports, appending them to the defaults for their respective groups.
260 */
261 public static final String COMPATIBLE_ENVIRONMENT_ATTR = "compatible_with";
262
263 /**
264 * For Bazel's constraint system: the implicit attribute used to store rule class restriction
265 * defaults as specified by {@link Builder#restrictedTo}.
266 */
267 public static final String DEFAULT_RESTRICTED_ENVIRONMENT_ATTR =
268 "$" + RESTRICTED_ENVIRONMENT_ATTR;
269
270 /**
271 * For Bazel's constraint system: the implicit attribute used to store rule class compatibility
272 * defaults as specified by {@link Builder#compatibleWith}.
273 */
274 public static final String DEFAULT_COMPATIBLE_ENVIRONMENT_ATTR =
275 "$" + COMPATIBLE_ENVIRONMENT_ATTR;
276
277 /**
gregce749962a2019-03-08 12:47:34 -0800278 * Name of the attribute that stores all {@link
279 * com.google.devtools.build.lib.rules.config.ConfigRuleClasses} labels this rule references (i.e.
280 * select() keys). This is specially populated in {@link #populateRuleAttributeValues}.
281 *
282 * <p>This isn't technically necessary for builds: select() keys are evaluated in {@link
283 * com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction#getConfigConditions} instead of
284 * normal dependency resolution because they're needed to determine other dependencies. So there's
285 * no intrinsic reason why we need an extra attribute to store them.
286 *
287 * <p>There are three reasons why we still create this attribute:
288 *
289 * <ol>
290 * <li>Collecting them once in {@link #populateRuleAttributeValues} instead of multiple times in
291 * ConfiguredTargetFunction saves extra looping over the rule's attributes.
292 * <li>Query's dependency resolution has no equivalent of {@link
293 * com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction#getConfigConditions} and
294 * we need to make sure its coverage remains complete.
295 * <li>Manual configuration trimming uses the normal dependency resolution process to work
296 * correctly and config_setting keys are subject to this trimming.
297 * </ol>
298 *
299 * <p>It should be possible to clean up these issues if we decide we don't want an artificial
300 * attribute dependency. But care has to be taken to do that safely.
301 */
302 public static final String CONFIG_SETTING_DEPS_ATTRIBUTE = "$config_dependencies";
303
304 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100305 * A support class to make it easier to create {@code RuleClass} instances.
306 * This class follows the 'fluent builder' pattern.
307 *
308 * <p>The {@link #addAttribute} method will throw an exception if an attribute
309 * of that name already exists. Use {@link #overrideAttribute} in that case.
310 */
311 public static final class Builder {
Laurent Le Brun6ce51e12015-07-07 11:54:41 +0000312 private static final Pattern RULE_NAME_PATTERN = Pattern.compile("[A-Za-z_][A-Za-z0-9_]*");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100313
314 /**
315 * The type of the rule class, which determines valid names and required
316 * attributes.
317 */
318 public enum RuleClassType {
319 /**
320 * Abstract rules are intended for rule classes that are just used to
321 * factor out common attributes, and for rule classes that are used only
322 * internally. These rules cannot be instantiated by a BUILD file.
323 *
324 * <p>The rule name must contain a '$' and {@link
325 * TargetUtils#isTestRuleName} must return false for the name.
326 */
327 ABSTRACT {
328 @Override
329 public void checkName(String name) {
330 Preconditions.checkArgument(
Ulf Adams07dba942015-03-05 14:47:37 +0000331 (name.contains("$") && !TargetUtils.isTestRuleName(name)) || name.isEmpty());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100332 }
333
334 @Override
335 public void checkAttributes(Map<String, Attribute> attributes) {
336 // No required attributes.
337 }
338 },
339
340 /**
341 * Invisible rule classes should contain a dollar sign so that they cannot be instantiated
342 * by the user. They are different from abstract rules in that they can be instantiated
343 * at will.
344 */
345 INVISIBLE {
346 @Override
347 public void checkName(String name) {
348 Preconditions.checkArgument(name.contains("$"));
349 }
350
351 @Override
352 public void checkAttributes(Map<String, Attribute> attributes) {
353 // No required attributes.
354 }
355 },
356
357 /**
358 * Normal rules are instantiable by BUILD files. Their names must therefore
359 * obey the rules for identifiers in the BUILD language. In addition,
360 * {@link TargetUtils#isTestRuleName} must return false for the name.
361 */
362 NORMAL {
363 @Override
364 public void checkName(String name) {
Ulf Adams07dba942015-03-05 14:47:37 +0000365 Preconditions.checkArgument(
366 !TargetUtils.isTestRuleName(name) && RULE_NAME_PATTERN.matcher(name).matches(),
367 "Invalid rule name: %s", name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100368 }
369
370 @Override
371 public void checkAttributes(Map<String, Attribute> attributes) {
372 for (Attribute attribute : REQUIRED_ATTRIBUTES_FOR_NORMAL_RULES) {
373 Attribute presentAttribute = attributes.get(attribute.getName());
374 Preconditions.checkState(presentAttribute != null,
375 "Missing mandatory '%s' attribute in normal rule class.", attribute.getName());
376 Preconditions.checkState(presentAttribute.getType().equals(attribute.getType()),
Francois-Rene Rideaucbebd632015-02-11 16:56:37 +0000377 "Mandatory attribute '%s' in normal rule class has incorrect type (expected"
378 + " %s).", attribute.getName(), attribute.getType());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100379 }
380 }
381 },
382
383 /**
384 * Workspace rules can only be instantiated from a WORKSPACE file. Their names obey the
385 * rule for identifiers.
386 */
387 WORKSPACE {
388 @Override
389 public void checkName(String name) {
390 Preconditions.checkArgument(RULE_NAME_PATTERN.matcher(name).matches());
391 }
392
393 @Override
394 public void checkAttributes(Map<String, Attribute> attributes) {
395 // No required attributes.
396 }
397 },
398
399 /**
400 * Test rules are instantiable by BUILD files and are handled specially
401 * when run with the 'test' command. Their names must obey the rules
402 * for identifiers in the BUILD language and {@link
403 * TargetUtils#isTestRuleName} must return true for the name.
404 *
405 * <p>In addition, test rules must contain certain attributes. See {@link
406 * Builder#REQUIRED_ATTRIBUTES_FOR_TESTS}.
407 */
408 TEST {
409 @Override
410 public void checkName(String name) {
411 Preconditions.checkArgument(TargetUtils.isTestRuleName(name)
412 && RULE_NAME_PATTERN.matcher(name).matches());
413 }
414
415 @Override
416 public void checkAttributes(Map<String, Attribute> attributes) {
417 for (Attribute attribute : REQUIRED_ATTRIBUTES_FOR_TESTS) {
418 Attribute presentAttribute = attributes.get(attribute.getName());
419 Preconditions.checkState(presentAttribute != null,
420 "Missing mandatory '%s' attribute in test rule class.", attribute.getName());
421 Preconditions.checkState(presentAttribute.getType().equals(attribute.getType()),
Googleraa437e02017-09-14 09:52:47 +0200422 "Mandatory attribute '%s' in test rule class has incorrect type (expected %s).",
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100423 attribute.getName(), attribute.getType());
424 }
425 }
Mark Schaller4fa83ac2015-07-10 16:59:37 +0000426 },
427
428 /**
429 * Placeholder rules are only instantiated when packages which refer to non-native rule
430 * classes are deserialized. At this time, non-native rule classes can't be serialized. To
431 * prevent crashes on deserialization, when a package containing a rule with a non-native rule
432 * class is deserialized, the rule is assigned a placeholder rule class. This is compatible
433 * with our limited set of package serialization use cases.
434 *
435 * Placeholder rule class names obey the rule for identifiers.
436 */
437 PLACEHOLDER {
438 @Override
439 public void checkName(String name) {
440 Preconditions.checkArgument(RULE_NAME_PATTERN.matcher(name).matches(), name);
441 }
442
443 @Override
444 public void checkAttributes(Map<String, Attribute> attributes) {
445 // No required attributes; this rule class cannot have the wrong set of attributes now
446 // because, if it did, the rule class would have failed to build before the package
447 // referring to it was serialized.
448 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100449 };
450
451 /**
452 * Checks whether the given name is valid for the current rule class type.
453 *
454 * @throws IllegalArgumentException if the name is not valid
455 */
456 public abstract void checkName(String name);
457
458 /**
459 * Checks whether the given set of attributes contains all the required
460 * attributes for the current rule class type.
461 *
462 * @throws IllegalArgumentException if a required attribute is missing
463 */
464 public abstract void checkAttributes(Map<String, Attribute> attributes);
465 }
466
Googler72f3a102017-12-01 16:28:28 -0800467 /** A predicate that filters rule classes based on their names. */
mjhalupka49581922018-02-28 11:04:31 -0800468 @AutoCodec
Googler72f3a102017-12-01 16:28:28 -0800469 public static class RuleClassNamePredicate {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100470
mjhalupka49581922018-02-28 11:04:31 -0800471 private static final RuleClassNamePredicate UNSPECIFIED_INSTANCE =
472 new RuleClassNamePredicate(ImmutableSet.of(), PredicateType.UNSPECIFIED, null);
473
474 private final ImmutableSet<String> ruleClassNames;
475
476 private final PredicateType predicateType;
477
Googler72f3a102017-12-01 16:28:28 -0800478 private final Predicate<String> ruleClassNamePredicate;
479 private final Predicate<RuleClass> ruleClassPredicate;
480 // if non-null, used ONLY for checking overlap
481 @Nullable private final Set<?> overlappable;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100482
mjhalupka49581922018-02-28 11:04:31 -0800483 @VisibleForSerialization
484 enum PredicateType {
485 ONLY,
486 All_EXCEPT,
487 UNSPECIFIED
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100488 }
489
mjhalupka49581922018-02-28 11:04:31 -0800490 @VisibleForSerialization
491 RuleClassNamePredicate(
492 ImmutableSet<String> ruleClassNames, PredicateType predicateType, Set<?> overlappable) {
493 this.ruleClassNames = ruleClassNames;
494 this.predicateType = predicateType;
Googler72f3a102017-12-01 16:28:28 -0800495 this.overlappable = overlappable;
mjhalupka49581922018-02-28 11:04:31 -0800496
497 switch (predicateType) {
498 case All_EXCEPT:
499 Predicate<String> containing = only(ruleClassNames).asPredicateOfRuleClassName();
500 ruleClassNamePredicate =
501 new DescribedPredicate<>(
502 Predicates.not(containing), "all but " + containing.toString());
503 ruleClassPredicate =
504 new DescribedPredicate<>(
505 Predicates.compose(ruleClassNamePredicate, RuleClass::getName),
506 ruleClassNamePredicate.toString());
507 break;
508 case ONLY:
509 ruleClassNamePredicate =
510 new DescribedPredicate<>(
511 Predicates.in(ruleClassNames), StringUtil.joinEnglishList(ruleClassNames));
512 ruleClassPredicate =
513 new DescribedPredicate<>(
514 Predicates.compose(ruleClassNamePredicate, RuleClass::getName),
515 ruleClassNamePredicate.toString());
516 break;
517 case UNSPECIFIED:
518 ruleClassNamePredicate = Predicates.alwaysTrue();
519 ruleClassPredicate = Predicates.alwaysTrue();
520 break;
521 default:
522 // This shouldn't happen normally since the constructor is private and within this file.
523 throw new IllegalArgumentException(
524 "Predicate type was not specified when constructing a RuleClassNamePredicate.");
525 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100526 }
527
Googler72f3a102017-12-01 16:28:28 -0800528 public static RuleClassNamePredicate only(Iterable<String> ruleClassNamesAsIterable) {
529 ImmutableSet<String> ruleClassNames = ImmutableSet.copyOf(ruleClassNamesAsIterable);
mjhalupka49581922018-02-28 11:04:31 -0800530 return new RuleClassNamePredicate(ruleClassNames, PredicateType.ONLY, ruleClassNames);
Googler72f3a102017-12-01 16:28:28 -0800531 }
532
533 public static RuleClassNamePredicate only(String... ruleClasses) {
534 return only(Arrays.asList(ruleClasses));
535 }
536
537 public static RuleClassNamePredicate allExcept(String... ruleClasses) {
538 ImmutableSet<String> ruleClassNames = ImmutableSet.copyOf(ruleClasses);
539 Preconditions.checkState(!ruleClassNames.isEmpty(), "Use unspecified() instead");
mjhalupka49581922018-02-28 11:04:31 -0800540 return new RuleClassNamePredicate(ruleClassNames, PredicateType.All_EXCEPT, null);
Googler72f3a102017-12-01 16:28:28 -0800541 }
542
543 /**
544 * This is a special sentinel value which represents a "default" {@link
545 * RuleClassNamePredicate} which is unspecified. Note that a call to its {@link
546 * RuleClassNamePredicate#asPredicateOfRuleClass} produces {@code
547 * Predicates.<RuleClass>alwaysTrue()}, which is a sentinel value for other parts of bazel.
548 */
549 public static RuleClassNamePredicate unspecified() {
mjhalupka49581922018-02-28 11:04:31 -0800550 return UNSPECIFIED_INSTANCE;
Googler72f3a102017-12-01 16:28:28 -0800551 }
552
553 public final Predicate<String> asPredicateOfRuleClassName() {
554 return ruleClassNamePredicate;
555 }
556
557 public final Predicate<RuleClass> asPredicateOfRuleClass() {
558 return ruleClassPredicate;
559 }
560
561 /**
562 * Determines whether two {@code RuleClassNamePredicate}s should be considered incompatible as
563 * rule class predicate and rule class warning predicate.
564 *
565 * <p>Specifically, if both list sets of explicit rule class names to permit, those two sets
566 * must be disjoint, so the restriction only applies when both predicates have been created by
567 * {@link #only}.
568 */
569 boolean consideredOverlapping(RuleClassNamePredicate that) {
570 return this.overlappable != null
571 && that.overlappable != null
572 && !Collections.disjoint(this.overlappable, that.overlappable);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100573 }
574
575 @Override
576 public int hashCode() {
mjhalupka49581922018-02-28 11:04:31 -0800577 return Objects.hash(ruleClassNames, predicateType);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100578 }
579
580 @Override
Googler72f3a102017-12-01 16:28:28 -0800581 public boolean equals(Object obj) {
582 // NOTE: Specifically not checking equality of ruleClassPredicate.
583 // By construction, if the name predicates are equals, the rule class predicates are, too.
584 return obj instanceof RuleClassNamePredicate
mjhalupka49581922018-02-28 11:04:31 -0800585 && ruleClassNames.equals(((RuleClassNamePredicate) obj).ruleClassNames)
586 && predicateType.equals(((RuleClassNamePredicate) obj).predicateType);
gregceda4c9592017-07-27 22:09:34 +0200587 }
588
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100589 @Override
590 public String toString() {
Googler72f3a102017-12-01 16:28:28 -0800591 return ruleClassNamePredicate.toString();
592 }
593
594 /** A pass-through predicate, except that an explicit {@link #toString()} is provided. */
595 private static class DescribedPredicate<T> implements Predicate<T> {
596 private final Predicate<T> delegate; // the actual predicate
597 private final String description;
598
599 private DescribedPredicate(Predicate<T> delegate, String description) {
600 this.delegate = delegate;
601 this.description = description;
602 }
603
604 @Override
605 public boolean apply(T input) {
606 return delegate.apply(input);
607 }
608
609 @Override
610 public int hashCode() {
611 return delegate.hashCode();
612 }
613
614 @Override
615 public boolean equals(Object obj) {
616 return obj instanceof DescribedPredicate
617 && delegate.equals(((DescribedPredicate<?>) obj).delegate);
618 }
619
620 @Override
621 public String toString() {
622 return description;
623 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100624 }
625 }
626
juliexxia1f332e02018-10-31 14:20:55 -0700627 /**
628 * Name of default attribute implicitly added to all Skylark RuleClasses that are {@code
629 * build_setting}s.
630 */
631 public static final String SKYLARK_BUILD_SETTING_DEFAULT_ATTR_NAME = "build_setting_default";
632
juliexxia44cd3a62018-12-19 11:57:16 -0800633 public static final String BUILD_SETTING_DEFAULT_NONCONFIGURABLE =
634 "Build setting defaults are referenced during analysis.";
635
Googler7807b6c2017-03-14 10:57:43 +0000636 /** List of required attributes for normal rules, name and type. */
637 public static final ImmutableList<Attribute> REQUIRED_ATTRIBUTES_FOR_NORMAL_RULES =
638 ImmutableList.of(attr("tags", Type.STRING_LIST).build());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100639
Googler7807b6c2017-03-14 10:57:43 +0000640 /** List of required attributes for test rules, name and type. */
641 public static final ImmutableList<Attribute> REQUIRED_ATTRIBUTES_FOR_TESTS =
642 ImmutableList.of(
643 attr("tags", Type.STRING_LIST).build(),
644 attr("size", Type.STRING).build(),
645 attr("timeout", Type.STRING).build(),
646 attr("flaky", Type.BOOLEAN).build(),
647 attr("shard_count", Type.INTEGER).build(),
648 attr("local", Type.BOOLEAN).build());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100649
650 private String name;
adonovanebb86fc2020-03-20 14:57:54 -0700651 private ImmutableList<StarlarkThread.CallStackEntry> callstack = ImmutableList.of();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100652 private final RuleClassType type;
653 private final boolean skylark;
Jon Brandveinead58ae2016-09-29 18:41:10 +0000654 private boolean skylarkTestable = false;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100655 private boolean documented;
656 private boolean publicByDefault = false;
657 private boolean binaryOutput = true;
658 private boolean workspaceOnly = false;
dslomov2ce98442017-10-23 19:14:02 +0200659 private boolean isExecutableSkylark = false;
cparsons55781c92018-10-17 12:03:08 -0700660 private boolean isAnalysisTest = false;
cparsons9d40c6b2019-02-25 12:24:40 -0800661 private boolean hasAnalysisTestTransition = false;
Googlerc2200fd2018-09-14 17:35:59 -0700662 private boolean hasFunctionTransitionWhitelist = false;
juliexxia30976d82019-03-12 10:59:26 -0700663 private boolean hasStarlarkRuleTransition = false;
gregce1d8d6dd2019-04-10 09:27:34 -0700664 private boolean ignoreLicenses = false;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100665 private ImplicitOutputsFunction implicitOutputsFunction = ImplicitOutputsFunction.NONE;
John Caterb3b3e8b2019-04-03 09:18:42 -0700666 private TransitionFactory<Rule> transitionFactory;
cparsonse2d200f2018-03-06 16:15:11 -0800667 private ConfiguredTargetFactory<?, ?, ?> configuredTargetFactory = null;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100668 private PredicateWithMessage<Rule> validityPredicate =
669 PredicatesWithMessage.<Rule>alwaysTrue();
670 private Predicate<String> preferredDependencyPredicate = Predicates.alwaysFalse();
Dmitry Lomovb91d3922017-01-09 20:12:57 +0000671 private AdvertisedProviderSet.Builder advertisedProviders = AdvertisedProviderSet.builder();
adonovanf3a344e82019-12-11 11:10:11 -0800672 private StarlarkFunction configuredTargetFunction = null;
juliexxia1f332e02018-10-31 14:20:55 -0700673 private BuildSetting buildSetting = null;
Lukacs Berki0e1a9942015-06-18 08:53:18 +0000674 private Function<? super Rule, Map<String, Label>> externalBindingsFunction =
675 NO_EXTERNAL_BINDINGS;
mstaibe5538ad2017-04-04 18:32:23 +0000676 private Function<? super Rule, ? extends Set<String>> optionReferenceFunction =
677 NO_OPTION_REFERENCE;
janakrd3fe5e72018-03-30 12:49:12 -0700678 /** This field and the next are null iff the rule is native. */
679 @Nullable private Label ruleDefinitionEnvironmentLabel;
680
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000681 @Nullable private String ruleDefinitionEnvironmentHashCode = null;
Michael Staibb51251e2015-09-29 23:31:51 +0000682 private ConfigurationFragmentPolicy.Builder configurationFragmentPolicy =
683 new ConfigurationFragmentPolicy.Builder();
Florian Weikert3f53fbb2015-08-07 22:25:50 +0000684
Greg Estrenc04c88f2015-03-06 19:45:50 +0000685 private boolean supportsConstraintChecking = true;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100686
gregce4aa059a2019-02-26 13:20:47 -0800687 /**
688 * The policy on whether Bazel should enforce that third_party rules declare <code>licenses().
689 * </code>. This is only intended for the migration of <a
690 * href="https://github.com/bazelbuild/bazel/issues/7444">GitHub #7444</a>. Our final end state
691 * is to have no license-related logic whatsoever. But that's going to take some time.
692 */
693 public enum ThirdPartyLicenseExistencePolicy {
694 /**
695 * Always do this check, overriding whatever {@link
gregce3f6da0a2019-04-04 09:40:07 -0700696 * StarlarkSemanticsOptions#incompatibleDisableThirdPartyLicenseChecking} says.
gregce4aa059a2019-02-26 13:20:47 -0800697 */
698 ALWAYS_CHECK,
699
700 /**
701 * Never do this check, overriding whatever {@link
gregce3f6da0a2019-04-04 09:40:07 -0700702 * StarlarkSemanticsOptions#incompatibleDisableThirdPartyLicenseChecking} says.
gregce4aa059a2019-02-26 13:20:47 -0800703 */
704 NEVER_CHECK,
705
gregce3f6da0a2019-04-04 09:40:07 -0700706 /**
707 * Do whatever {@link StarlarkSemanticsOptions#incompatibleDisableThirdPartyLicenseChecking}
708 * says.
709 */
gregce4aa059a2019-02-26 13:20:47 -0800710 USER_CONTROLLABLE
711 }
712
713 private ThirdPartyLicenseExistencePolicy thirdPartyLicenseExistencePolicy;
714
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100715 private final Map<String, Attribute> attributes = new LinkedHashMap<>();
cpeyserfb829992017-09-07 17:17:03 +0200716 private final Set<Label> requiredToolchains = new HashSet<>();
jcater01bb1f92019-06-17 12:09:11 -0700717 private boolean useToolchainResolution = true;
John Cateree45c662018-06-05 11:09:01 -0700718 private Set<Label> executionPlatformConstraints = new HashSet<>();
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -0700719 private OutputFile.Kind outputFileKind = OutputFile.Kind.FILE;
juliexxia693048d2020-04-01 06:41:42 -0700720 private final Map<String, ExecGroup> execGroups = new HashMap<>();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100721
722 /**
723 * Constructs a new {@code RuleClassBuilder} using all attributes from all
724 * parent rule classes. An attribute cannot exist in more than one parent.
725 *
gregce64c36e12017-07-26 23:48:56 +0200726 * <p>The rule type affects the allowed names and the required
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100727 * attributes (see {@link RuleClassType}).
728 *
729 * @throws IllegalArgumentException if an attribute with the same name exists
730 * in more than one parent
731 */
732 public Builder(String name, RuleClassType type, boolean skylark, RuleClass... parents) {
733 this.name = name;
734 this.skylark = skylark;
735 this.type = type;
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000736 Preconditions.checkState(skylark || type != RuleClassType.PLACEHOLDER, name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100737 this.documented = type != RuleClassType.ABSTRACT;
738 for (RuleClass parent : parents) {
739 if (parent.getValidityPredicate() != PredicatesWithMessage.<Rule>alwaysTrue()) {
740 setValidityPredicate(parent.getValidityPredicate());
741 }
742 if (parent.preferredDependencyPredicate != Predicates.<String>alwaysFalse()) {
743 setPreferredDependencyPredicate(parent.preferredDependencyPredicate);
744 }
Michael Staibff66c192016-01-14 22:40:37 +0000745 configurationFragmentPolicy
746 .includeConfigurationFragmentsFrom(parent.getConfigurationFragmentPolicy());
Michael Staibb51251e2015-09-29 23:31:51 +0000747 configurationFragmentPolicy.setMissingFragmentPolicy(
748 parent.getConfigurationFragmentPolicy().getMissingFragmentPolicy());
Greg Estrenc04c88f2015-03-06 19:45:50 +0000749 supportsConstraintChecking = parent.supportsConstraintChecking;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100750
cpeyserd78b3742017-08-04 19:48:53 +0200751 addRequiredToolchains(parent.getRequiredToolchains());
jcater01bb1f92019-06-17 12:09:11 -0700752 useToolchainResolution = parent.useToolchainResolution;
John Cateree45c662018-06-05 11:09:01 -0700753 addExecutionPlatformConstraints(parent.getExecutionPlatformConstraints());
juliexxia693048d2020-04-01 06:41:42 -0700754 try {
755 addExecGroups(parent.getExecGroups());
756 } catch (DuplicateExecGroupError e) {
757 throw new IllegalArgumentException(
758 String.format(
759 "An execution group named '%s' is inherited multiple times in %s ruleclass",
760 e.getDuplicateGroup(), name));
761 }
cpeyserd78b3742017-08-04 19:48:53 +0200762
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100763 for (Attribute attribute : parent.getAttributes()) {
764 String attrName = attribute.getName();
765 Preconditions.checkArgument(
dannarke64a8162018-06-13 13:48:20 -0700766 !attributes.containsKey(attrName) || attributes.get(attrName).equals(attribute),
Googler2935d672015-03-12 01:25:11 +0000767 "Attribute %s is inherited multiple times in %s ruleclass",
768 attrName,
769 name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100770 attributes.put(attrName, attribute);
771 }
Lukacs Berkiac4f9422015-05-29 10:06:30 +0000772
Dmitry Lomovb91d3922017-01-09 20:12:57 +0000773 advertisedProviders.addParent(parent.getAdvertisedProviders());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100774 }
775 // TODO(bazel-team): move this testonly attribute setting to somewhere else
776 // preferably to some base RuleClass implementation.
777 if (this.type.equals(RuleClassType.TEST)) {
778 Attribute.Builder<Boolean> testOnlyAttr = attr("testonly", BOOLEAN).value(true)
779 .nonconfigurable("policy decision: this shouldn't depend on the configuration");
780 if (attributes.containsKey("testonly")) {
781 override(testOnlyAttr);
782 } else {
783 add(testOnlyAttr);
784 }
785 }
786 }
787
788 /**
789 * Checks that required attributes for test rules are present, creates the
790 * {@link RuleClass} object and returns it.
791 *
792 * @throws IllegalStateException if any of the required attributes is missing
793 */
794 public RuleClass build() {
tomlu72642a22017-10-18 06:23:14 +0200795 // For built-ins, name == key
796 return build(name, name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100797 }
798
tomlu72642a22017-10-18 06:23:14 +0200799 /** Same as {@link #build} except with setting the name and key parameters. */
800 public RuleClass build(String name, String key) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100801 Preconditions.checkArgument(this.name.isEmpty() || this.name.equals(name));
802 type.checkName(name);
michajlob839a512020-03-11 10:04:23 -0700803
michajlo0a89cef2020-04-06 12:04:12 -0700804 checkAttributes(name, type, attributes);
michajlob839a512020-03-11 10:04:23 -0700805
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100806 Preconditions.checkState(
807 (type == RuleClassType.ABSTRACT)
janakr6ff110e2018-03-21 21:44:27 -0700808 == (configuredTargetFactory == null && configuredTargetFunction == null),
809 "Bad combo for %s: %s %s %s",
810 name,
811 type,
812 configuredTargetFactory,
813 configuredTargetFunction);
Damien Martin-Guillerez653df882016-02-17 21:46:22 +0000814 if (!workspaceOnly) {
janakrd3fe5e72018-03-30 12:49:12 -0700815 if (skylark) {
816 assertSkylarkRuleClassHasImplementationFunction();
817 assertSkylarkRuleClassHasEnvironmentLabel();
818 }
Damien Martin-Guillerez653df882016-02-17 21:46:22 +0000819 Preconditions.checkState(externalBindingsFunction == NO_EXTERNAL_BINDINGS);
820 }
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000821 if (type == RuleClassType.PLACEHOLDER) {
822 Preconditions.checkNotNull(ruleDefinitionEnvironmentHashCode, this.name);
823 }
John Cater04be3f82019-11-07 12:20:25 -0800824
juliexxia1f332e02018-10-31 14:20:55 -0700825 if (buildSetting != null) {
826 Type<?> type = buildSetting.getType();
827 Attribute.Builder<?> attrBuilder =
828 attr(SKYLARK_BUILD_SETTING_DEFAULT_ATTR_NAME, type)
juliexxia44cd3a62018-12-19 11:57:16 -0800829 .nonconfigurable(BUILD_SETTING_DEFAULT_NONCONFIGURABLE)
juliexxia1f332e02018-10-31 14:20:55 -0700830 .mandatory();
831 if (BuildType.isLabelType(type)) {
832 attrBuilder.allowedFileTypes(FileTypeSet.ANY_FILE);
juliexxia44cd3a62018-12-19 11:57:16 -0800833 attrBuilder.allowedRuleClasses(ANY_RULE);
juliexxia1f332e02018-10-31 14:20:55 -0700834 }
835 this.add(attrBuilder);
John Catera6e3e872019-08-07 13:24:34 -0700836
837 // Build setting rules should opt out of toolchain resolution, since they form part of the
838 // configuration.
839 this.useToolchainResolution(false);
juliexxia1f332e02018-10-31 14:20:55 -0700840 }
John Cateree45c662018-06-05 11:09:01 -0700841
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000842 return new RuleClass(
843 name,
adonovanebb86fc2020-03-20 14:57:54 -0700844 callstack,
tomlu72642a22017-10-18 06:23:14 +0200845 key,
janakr6ff110e2018-03-21 21:44:27 -0700846 type,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000847 skylark,
Jon Brandveinead58ae2016-09-29 18:41:10 +0000848 skylarkTestable,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000849 documented,
850 publicByDefault,
851 binaryOutput,
852 workspaceOnly,
dslomov2ce98442017-10-23 19:14:02 +0200853 isExecutableSkylark,
cparsons55781c92018-10-17 12:03:08 -0700854 isAnalysisTest,
cparsons9d40c6b2019-02-25 12:24:40 -0800855 hasAnalysisTestTransition,
Googlerc2200fd2018-09-14 17:35:59 -0700856 hasFunctionTransitionWhitelist,
gregce1d8d6dd2019-04-10 09:27:34 -0700857 ignoreLicenses,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000858 implicitOutputsFunction,
Michael Staib2a675202017-03-20 18:06:48 +0000859 transitionFactory,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000860 configuredTargetFactory,
861 validityPredicate,
862 preferredDependencyPredicate,
Dmitry Lomovb91d3922017-01-09 20:12:57 +0000863 advertisedProviders.build(),
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000864 configuredTargetFunction,
865 externalBindingsFunction,
mstaibe5538ad2017-04-04 18:32:23 +0000866 optionReferenceFunction,
janakrd3fe5e72018-03-30 12:49:12 -0700867 ruleDefinitionEnvironmentLabel,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000868 ruleDefinitionEnvironmentHashCode,
869 configurationFragmentPolicy.build(),
870 supportsConstraintChecking,
gregce4aa059a2019-02-26 13:20:47 -0800871 thirdPartyLicenseExistencePolicy,
John Catereca28402017-05-17 21:44:12 +0200872 requiredToolchains,
jcater01bb1f92019-06-17 12:09:11 -0700873 useToolchainResolution,
John Cateree45c662018-06-05 11:09:01 -0700874 executionPlatformConstraints,
juliexxia693048d2020-04-01 06:41:42 -0700875 execGroups,
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -0700876 outputFileKind,
juliexxia1f332e02018-10-31 14:20:55 -0700877 attributes.values(),
878 buildSetting);
janakrd3fe5e72018-03-30 12:49:12 -0700879 }
880
michajlo0a89cef2020-04-06 12:04:12 -0700881 private static void checkAttributes(
882 String ruleClassName, RuleClassType ruleClassType, Map<String, Attribute> attributes) {
883 Preconditions.checkArgument(
884 attributes.size() <= MAX_ATTRIBUTES,
885 "Rule class %s declared too many attributes (%s > %s)",
886 ruleClassName,
887 attributes.size(),
888 MAX_ATTRIBUTES);
889
890 for (String attributeName : attributes.keySet()) {
891 // TODO(b/151171037): This check would make more sense at Attribute creation time, but the
892 // use of unchecked exceptions in these APIs makes it brittle.
893 Preconditions.checkArgument(
894 attributeName.length() <= MAX_ATTRIBUTE_NAME_LENGTH,
895 "Attribute %s.%s's name is too long (%s > %s)",
896 ruleClassName,
897 attributeName,
898 attributeName.length(),
899 MAX_ATTRIBUTE_NAME_LENGTH);
900 }
901
902 ruleClassType.checkAttributes(attributes);
903 }
904
janakrd3fe5e72018-03-30 12:49:12 -0700905 private void assertSkylarkRuleClassHasImplementationFunction() {
906 Preconditions.checkState(
907 (type == RuleClassType.NORMAL || type == RuleClassType.TEST)
908 == (configuredTargetFunction != null),
909 "%s %s",
910 type,
911 configuredTargetFunction);
912 }
913
914 private void assertSkylarkRuleClassHasEnvironmentLabel() {
915 Preconditions.checkState(
916 (type == RuleClassType.NORMAL
917 || type == RuleClassType.TEST
918 || type == RuleClassType.PLACEHOLDER)
919 == (ruleDefinitionEnvironmentLabel != null),
laurentlb7dcad732018-10-25 05:17:20 -0700920 "Concrete Starlark rule classes can't have null labels: %s %s",
janakrd3fe5e72018-03-30 12:49:12 -0700921 ruleDefinitionEnvironmentLabel,
922 type);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100923 }
924
jcater6e132862019-07-16 08:50:04 -0700925 /**
926 * Declares that the implementation of the associated rule class requires the given fragments to
927 * be present in this rule's host and target configurations.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100928 *
Greg Estren693f17f2015-11-06 16:45:45 +0000929 * <p>The value is inherited by subclasses.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100930 */
Michael Staibb51251e2015-09-29 23:31:51 +0000931 public Builder requiresConfigurationFragments(Class<?>... configurationFragments) {
Michael Staibff66c192016-01-14 22:40:37 +0000932 configurationFragmentPolicy.requiresConfigurationFragments(
933 ImmutableSet.<Class<?>>copyOf(configurationFragments));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100934 return this;
935 }
936
Ulf Adams71423eb2015-08-06 11:51:17 +0000937 /**
Greg Estren693f17f2015-11-06 16:45:45 +0000938 * Declares that the implementation of the associated rule class requires the given
gregce614dc502017-12-20 17:24:46 -0800939 * fragments to be present in the given configuration that isn't the rule's configuration but
940 * is also readable by the rule.
941 *
942 * <p>You probably don't want to use this, because rules generally shouldn't read configurations
943 * other than their own. If you want to declare host config fragments, see
944 * {@link com.google.devtools.build.lib.analysis.config.ConfigAwareRuleClassBuilder}.
Greg Estren693f17f2015-11-06 16:45:45 +0000945 *
946 * <p>The value is inherited by subclasses.
947 */
gregcebe55e112018-01-30 11:04:53 -0800948 public Builder requiresConfigurationFragments(ConfigurationTransition transition,
gregce614dc502017-12-20 17:24:46 -0800949 Class<?>... configurationFragments) {
950 configurationFragmentPolicy.requiresConfigurationFragments(
951 transition,
Michael Staibff66c192016-01-14 22:40:37 +0000952 ImmutableSet.<Class<?>>copyOf(configurationFragments));
Greg Estren693f17f2015-11-06 16:45:45 +0000953 return this;
954 }
955
956 /**
Michael Staibff66c192016-01-14 22:40:37 +0000957 * Declares the configuration fragments that are required by this rule for the target
958 * configuration.
Greg Estren693f17f2015-11-06 16:45:45 +0000959 *
960 * <p>In contrast to {@link #requiresConfigurationFragments(Class...)}, this method takes the
Michael Staibff66c192016-01-14 22:40:37 +0000961 * Skylark module names of fragments instead of their classes.
Greg Estren693f17f2015-11-06 16:45:45 +0000962 */
Michael Staibff66c192016-01-14 22:40:37 +0000963 public Builder requiresConfigurationFragmentsBySkylarkModuleName(
964 Collection<String> configurationFragmentNames) {
965 configurationFragmentPolicy
966 .requiresConfigurationFragmentsBySkylarkModuleName(configurationFragmentNames);
967 return this;
968 }
969
970 /**
971 * Declares the configuration fragments that are required by this rule for the host
972 * configuration.
973 *
Michael Staibff66c192016-01-14 22:40:37 +0000974 */
gregce614dc502017-12-20 17:24:46 -0800975 /**
976 * Declares that the implementation of the associated rule class requires the given
977 * fragments to be present in the given configuration that isn't the rule's configuration but
978 * is also readable by the rule.
979 *
gregcebe55e112018-01-30 11:04:53 -0800980 * <p>In contrast to {@link #requiresConfigurationFragments(ConfigurationTransition, Class...)},
981 * this method takes Skylark module names of fragments instead of their classes.
gregce614dc502017-12-20 17:24:46 -0800982 * *
983 * <p>You probably don't want to use this, because rules generally shouldn't read configurations
984 * other than their own. If you want to declare host config fragments, see
985 * {@link com.google.devtools.build.lib.analysis.config.ConfigAwareRuleClassBuilder}.
986 *
987 * <p>The value is inherited by subclasses.
988 */
gregcebe55e112018-01-30 11:04:53 -0800989 public Builder requiresConfigurationFragmentsBySkylarkModuleName(
990 ConfigurationTransition transition, Collection<String> configurationFragmentNames) {
gregce614dc502017-12-20 17:24:46 -0800991 configurationFragmentPolicy.requiresConfigurationFragmentsBySkylarkModuleName(transition,
992 configurationFragmentNames);
Greg Estren693f17f2015-11-06 16:45:45 +0000993 return this;
994 }
995
adonovanebb86fc2020-03-20 14:57:54 -0700996 /** Sets the Starlark call stack associated with this rule class's creation. */
997 public Builder setCallStack(ImmutableList<StarlarkThread.CallStackEntry> callstack) {
998 this.callstack = callstack;
999 return this;
1000 }
1001
Jon Brandveinead58ae2016-09-29 18:41:10 +00001002 public Builder setSkylarkTestable() {
laurentlb7dcad732018-10-25 05:17:20 -07001003 Preconditions.checkState(skylark, "Cannot set skylarkTestable on a non-Starlark rule");
Jon Brandveinead58ae2016-09-29 18:41:10 +00001004 skylarkTestable = true;
1005 return this;
1006 }
1007
Greg Estren693f17f2015-11-06 16:45:45 +00001008 /**
Ulf Adams71423eb2015-08-06 11:51:17 +00001009 * Sets the policy for the case where the configuration is missing required fragments (see
1010 * {@link #requiresConfigurationFragments}).
1011 */
1012 public Builder setMissingFragmentPolicy(MissingFragmentPolicy missingFragmentPolicy) {
Michael Staibb51251e2015-09-29 23:31:51 +00001013 configurationFragmentPolicy.setMissingFragmentPolicy(missingFragmentPolicy);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001014 return this;
1015 }
Florian Weikert3f8aac92015-09-07 12:06:02 +00001016
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001017 public Builder setUndocumented() {
1018 documented = false;
1019 return this;
1020 }
1021
1022 public Builder publicByDefault() {
1023 publicByDefault = true;
1024 return this;
1025 }
1026
1027 public Builder setWorkspaceOnly() {
1028 workspaceOnly = true;
1029 return this;
1030 }
1031
1032 /**
1033 * Determines the outputs of this rule to be created beneath the {@code
1034 * genfiles} directory. By default, files are created beneath the {@code bin}
1035 * directory.
1036 *
1037 * <p>This property is not inherited and this method should not be called by
1038 * builder of {@link RuleClassType#ABSTRACT} rule class.
1039 *
1040 * @throws IllegalStateException if called for abstract rule class builder
1041 */
1042 public Builder setOutputToGenfiles() {
1043 Preconditions.checkState(type != RuleClassType.ABSTRACT,
1044 "Setting not inherited property (output to genrules) of abstract rule class '%s'", name);
1045 this.binaryOutput = false;
1046 return this;
1047 }
1048
1049 /**
1050 * Sets the implicit outputs function of the rule class. The default implicit
1051 * outputs function is {@link ImplicitOutputsFunction#NONE}.
1052 *
1053 * <p>This property is not inherited and this method should not be called by
1054 * builder of {@link RuleClassType#ABSTRACT} rule class.
1055 *
1056 * @throws IllegalStateException if called for abstract rule class builder
1057 */
1058 public Builder setImplicitOutputsFunction(
1059 ImplicitOutputsFunction implicitOutputsFunction) {
1060 Preconditions.checkState(type != RuleClassType.ABSTRACT,
1061 "Setting not inherited property (implicit output function) of abstract rule class '%s'",
1062 name);
1063 this.implicitOutputsFunction = implicitOutputsFunction;
1064 return this;
1065 }
1066
Cal Peyser19dda252017-01-11 23:37:05 +00001067 /**
gregce64c36e12017-07-26 23:48:56 +02001068 * Applies the given transition to all incoming edges for this rule class.
Cal Peyser19dda252017-01-11 23:37:05 +00001069 *
gregce74a895d2018-05-29 11:26:03 -07001070 * <p>This cannot be a {@link SplitTransition} because that requires coordination with the
John Caterb3b3e8b2019-04-03 09:18:42 -07001071 * rule's parent: use {@link Attribute.Builder#cfg(TransitionFactory)} on the parent to declare
1072 * splits.
gregce74a895d2018-05-29 11:26:03 -07001073 *
jcater98a09b62019-04-02 13:06:19 -07001074 * <p>If you need the transition to depend on the rule it's being applied to, use {@link
John Caterb3b3e8b2019-04-03 09:18:42 -07001075 * #cfg(TransitionFactory)}.
Cal Peyser19dda252017-01-11 23:37:05 +00001076 */
mstaib860975a2018-04-26 15:00:52 -07001077 public Builder cfg(PatchTransition transition) {
John Caterb3b3e8b2019-04-03 09:18:42 -07001078 return cfg((TransitionFactory<Rule>) (unused) -> (transition));
Michael Staib2a675202017-03-20 18:06:48 +00001079 }
1080
gregce64c36e12017-07-26 23:48:56 +02001081 /**
1082 * Applies the given transition factory to all incoming edges for this rule class.
1083 *
John Cateree45c662018-06-05 11:09:01 -07001084 * <p>Unlike {@link #cfg(PatchTransition)}, the factory can examine the rule when deciding what
1085 * transition to use.
gregce64c36e12017-07-26 23:48:56 +02001086 */
John Caterb3b3e8b2019-04-03 09:18:42 -07001087 public Builder cfg(TransitionFactory<Rule> transitionFactory) {
Michael Staib2a675202017-03-20 18:06:48 +00001088 Preconditions.checkState(type != RuleClassType.ABSTRACT,
1089 "Setting not inherited property (cfg) of abstract rule class '%s'", name);
gregcef19fcfe2017-06-02 16:04:07 -04001090 Preconditions.checkState(this.transitionFactory == null,
Michael Staib2a675202017-03-20 18:06:48 +00001091 "Property cfg has already been set");
1092 Preconditions.checkNotNull(transitionFactory);
John Caterb3b3e8b2019-04-03 09:18:42 -07001093 Preconditions.checkArgument(!transitionFactory.isSplit());
Michael Staib2a675202017-03-20 18:06:48 +00001094 this.transitionFactory = transitionFactory;
Cal Peyser19dda252017-01-11 23:37:05 +00001095 return this;
1096 }
1097
juliexxia30976d82019-03-12 10:59:26 -07001098 public void setHasStarlarkRuleTransition() {
1099 hasStarlarkRuleTransition = true;
1100 }
1101
1102 public boolean hasStarlarkRuleTransition() {
1103 return hasStarlarkRuleTransition;
1104 }
1105
cparsonse2d200f2018-03-06 16:15:11 -08001106 public Builder factory(ConfiguredTargetFactory<?, ?, ?> factory) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001107 this.configuredTargetFactory = factory;
1108 return this;
1109 }
1110
gregce4aa059a2019-02-26 13:20:47 -08001111 public Builder setThirdPartyLicenseExistencePolicy(ThirdPartyLicenseExistencePolicy policy) {
1112 this.thirdPartyLicenseExistencePolicy = policy;
1113 return this;
1114 }
1115
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001116 public Builder setValidityPredicate(PredicateWithMessage<Rule> predicate) {
1117 this.validityPredicate = predicate;
1118 return this;
1119 }
1120
1121 public Builder setPreferredDependencyPredicate(Predicate<String> predicate) {
1122 this.preferredDependencyPredicate = predicate;
1123 return this;
1124 }
1125
1126 /**
1127 * State that the rule class being built possibly supplies the specified provider to its direct
1128 * dependencies.
1129 *
1130 * <p>When computing the set of aspects required for a rule, only the providers listed here are
1131 * considered. The presence of a provider here does not mean that the rule <b>must</b> implement
1132 * said provider, merely that it <b>can</b>. After the configured target is constructed from
1133 * this rule, aspects will be filtered according to the set of actual providers.
1134 *
1135 * <p>This is here so that we can do the loading phase overestimation required for
1136 * "blaze query", which does not have the configured targets available.
1137 *
1138 * <p>It's okay for the rule class eventually not to supply it (possibly based on analysis phase
1139 * logic), but if a provider is not advertised but is supplied, aspects that require the it will
1140 * not be evaluated for the rule.
1141 */
1142 public Builder advertiseProvider(Class<?>... providers) {
Dmitry Lomovb91d3922017-01-09 20:12:57 +00001143 for (Class<?> provider : providers) {
1144 advertisedProviders.addNative(provider);
1145 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001146 return this;
1147 }
1148
elenairinaaeb21bc2017-09-27 12:13:52 -04001149 public Builder advertiseSkylarkProvider(SkylarkProviderIdentifier... skylarkProviders) {
1150 for (SkylarkProviderIdentifier skylarkProviderIdentifier : skylarkProviders) {
1151 advertisedProviders.addSkylark(skylarkProviderIdentifier);
1152 }
1153 return this;
1154 }
1155
Lukacs Berki549bfce2016-04-22 15:29:12 +00001156 /**
1157 * Set if the rule can have any provider. This is true for "alias" rules like
1158 * <code>bind</code> .
1159 */
1160 public Builder canHaveAnyProvider() {
Dmitry Lomovb91d3922017-01-09 20:12:57 +00001161 advertisedProviders.canHaveAnyProvider();
Lukacs Berki549bfce2016-04-22 15:29:12 +00001162 return this;
1163 }
1164
dbabkina2823422018-05-02 02:42:53 -07001165 public Builder addAttribute(Attribute attribute) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001166 Preconditions.checkState(!attributes.containsKey(attribute.getName()),
1167 "An attribute with the name '%s' already exists.", attribute.getName());
1168 attributes.put(attribute.getName(), attribute);
dbabkina2823422018-05-02 02:42:53 -07001169 return this;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001170 }
1171
1172 private void overrideAttribute(Attribute attribute) {
1173 String attrName = attribute.getName();
1174 Preconditions.checkState(attributes.containsKey(attrName),
1175 "No such attribute '%s' to override in ruleclass '%s'.", attrName, name);
1176 Type<?> origType = attributes.get(attrName).getType();
1177 Type<?> newType = attribute.getType();
1178 Preconditions.checkState(origType.equals(newType),
1179 "The type of the new attribute '%s' is different from the original one '%s'.",
1180 newType, origType);
1181 attributes.put(attrName, attribute);
1182 }
1183
1184 /**
michajlob839a512020-03-11 10:04:23 -07001185 * Builds provided attribute and attaches it to this rule class.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001186 *
michajlob839a512020-03-11 10:04:23 -07001187 * <p>Typically rule classes should only declare a handful of attributes - this expectation is
1188 * enforced when the instance is built.
michajlo0a89cef2020-04-06 12:04:12 -07001189 *
1190 * <p>Attribute names should be meaningful but short; overly long names are rejected at
1191 * instantiation.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001192 */
1193 public <TYPE> Builder add(Attribute.Builder<TYPE> attr) {
1194 addAttribute(attr.build());
1195 return this;
1196 }
1197
1198 /**
1199 * Builds attribute from the attribute builder and overrides the attribute
1200 * with the same name.
1201 *
1202 * @throws IllegalArgumentException if the attribute does not override one of the same name
1203 */
1204 public <TYPE> Builder override(Attribute.Builder<TYPE> attr) {
1205 overrideAttribute(attr.build());
1206 return this;
1207 }
1208
1209 /**
1210 * Adds or overrides the attribute in the rule class. Meant for Skylark usage.
Florian Weikerte96b0b82015-09-25 11:35:11 +00001211 *
1212 * @throws IllegalArgumentException if the attribute overrides an existing attribute (will be
1213 * legal in the future).
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001214 */
1215 public void addOrOverrideAttribute(Attribute attribute) {
Florian Weikerte96b0b82015-09-25 11:35:11 +00001216 String name = attribute.getName();
1217 // Attributes may be overridden in the future.
1218 Preconditions.checkArgument(!attributes.containsKey(name),
1219 "There is already a built-in attribute '%s' which cannot be overridden", name);
1220 addAttribute(attribute);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001221 }
1222
Mark Schaller4fa83ac2015-07-10 16:59:37 +00001223 /** True if the rule class contains an attribute named {@code name}. */
1224 public boolean contains(String name) {
1225 return attributes.containsKey(name);
1226 }
1227
adonovanf3a344e82019-12-11 11:10:11 -08001228 /** Sets the rule implementation function. Meant for Skylark usage. */
1229 public Builder setConfiguredTargetFunction(StarlarkFunction func) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001230 this.configuredTargetFunction = func;
1231 return this;
1232 }
1233
juliexxia1f332e02018-10-31 14:20:55 -07001234 public Builder setBuildSetting(BuildSetting buildSetting) {
1235 this.buildSetting = buildSetting;
1236 return this;
1237 }
1238
Lukacs Berki0e1a9942015-06-18 08:53:18 +00001239 public Builder setExternalBindingsFunction(Function<? super Rule, Map<String, Label>> func) {
1240 this.externalBindingsFunction = func;
1241 return this;
1242 }
1243
janakrd3fe5e72018-03-30 12:49:12 -07001244 /** Sets the rule definition environment label and hash code. Meant for Skylark usage. */
1245 public Builder setRuleDefinitionEnvironmentLabelAndHashCode(Label label, String hashCode) {
1246 this.ruleDefinitionEnvironmentLabel = Preconditions.checkNotNull(label, this.name);
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001247 this.ruleDefinitionEnvironmentHashCode = Preconditions.checkNotNull(hashCode, this.name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001248 return this;
1249 }
1250
juliexxia84d1a662018-12-26 14:07:04 -08001251 public Label getRuleDefinitionEnvironmentLabel() {
1252 return this.ruleDefinitionEnvironmentLabel;
1253 }
1254
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001255 /**
1256 * Removes an attribute with the same name from this rule class.
1257 *
1258 * @throws IllegalArgumentException if the attribute with this name does
1259 * not exist
1260 */
1261 public <TYPE> Builder removeAttribute(String name) {
1262 Preconditions.checkState(attributes.containsKey(name), "No such attribute '%s' to remove.",
1263 name);
1264 attributes.remove(name);
1265 return this;
1266 }
1267
1268 /**
1269 * This rule class outputs a default executable for every rule with the same name as
1270 * the rules's. Only works for Skylark.
1271 */
dslomov2ce98442017-10-23 19:14:02 +02001272 public <TYPE> Builder setExecutableSkylark() {
1273 this.isExecutableSkylark = true;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001274 return this;
1275 }
1276
cparsons55781c92018-10-17 12:03:08 -07001277 /** This rule class is marked as an analysis test. */
1278 public Builder setIsAnalysisTest() {
1279 this.isAnalysisTest = true;
1280 return this;
1281 }
1282
juliexxia84d1a662018-12-26 14:07:04 -08001283 public boolean isAnalysisTest() {
1284 return this.isAnalysisTest;
1285 }
1286
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001287 /**
cparsons9d40c6b2019-02-25 12:24:40 -08001288 * This rule class has at least one attribute with an analysis test transition. (A
1289 * starlark-defined transition using analysis_test_transition()).
1290 */
1291 public Builder setHasAnalysisTestTransition() {
1292 this.hasAnalysisTestTransition = true;
1293 return this;
1294 }
1295
cparsons9d40c6b2019-02-25 12:24:40 -08001296 /**
Googlerc2200fd2018-09-14 17:35:59 -07001297 * This rule class has the _whitelist_function_transition attribute. Intended only for Skylark
1298 * rules.
1299 */
1300 public <TYPE> Builder setHasFunctionTransitionWhitelist() {
1301 this.hasFunctionTransitionWhitelist = true;
1302 return this;
1303 }
1304
gregce1d8d6dd2019-04-10 09:27:34 -07001305 /**
1306 * This rule class never declares a license regardless of what the rule's or package's <code>
1307 * licenses</code> attribute says.
1308 */
1309 // TODO(b/130286108): remove the licenses attribute completely from such rules.
1310 public Builder setIgnoreLicenses() {
1311 this.ignoreLicenses = true;
Googlerfdb17eb2019-01-28 15:14:32 -08001312 return this;
1313 }
1314
juliexxia84d1a662018-12-26 14:07:04 -08001315 public RuleClassType getType() {
1316 return this.type;
1317 }
1318
Googlerc2200fd2018-09-14 17:35:59 -07001319 /**
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -07001320 * Sets the kind of output files this rule creates.
1321 * DO NOT USE! This only exists to support the non-open-sourced {@code fileset} rule.
1322 * {@see OutputFile.Kind}.
1323 */
1324 public Builder setOutputFileKind(OutputFile.Kind outputFileKind) {
nharmata0d493ba2019-01-07 11:06:44 -08001325 this.outputFileKind = Preconditions.checkNotNull(outputFileKind);
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -07001326 return this;
1327 }
1328
1329
1330
1331 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001332 * Declares that instances of this rule are compatible with the specified environments,
1333 * in addition to the defaults declared by their environment groups. This can be overridden
1334 * by rule-specific declarations. See
1335 * {@link com.google.devtools.build.lib.analysis.constraints.ConstraintSemantics} for details.
1336 */
1337 public <TYPE> Builder compatibleWith(Label... environments) {
gregce614dc502017-12-20 17:24:46 -08001338 add(
1339 attr(DEFAULT_COMPATIBLE_ENVIRONMENT_ATTR, LABEL_LIST)
1340 .value(ImmutableList.copyOf(environments)));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001341 return this;
1342 }
1343
1344 /**
1345 * Declares that instances of this rule are restricted to the specified environments, i.e.
1346 * these override the defaults declared by their environment groups. This can be overridden
1347 * by rule-specific declarations. See
1348 * {@link com.google.devtools.build.lib.analysis.constraints.ConstraintSemantics} for details.
1349 *
1350 * <p>The input list cannot be empty.
1351 */
1352 public <TYPE> Builder restrictedTo(Label firstEnvironment, Label... otherEnvironments) {
1353 ImmutableList<Label> environments = ImmutableList.<Label>builder().add(firstEnvironment)
1354 .add(otherEnvironments).build();
gregce614dc502017-12-20 17:24:46 -08001355 add(
1356 attr(DEFAULT_RESTRICTED_ENVIRONMENT_ATTR, LABEL_LIST)
1357 .value(environments));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001358 return this;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001359 }
1360
1361 /**
Greg Estrenc04c88f2015-03-06 19:45:50 +00001362 * Exempts rules of this type from the constraint enforcement system. This should only be
1363 * applied to rules that are intrinsically incompatible with constraint checking (any
1364 * application of this method weakens the reach and strength of the system).
1365 *
1366 * @param reason user-informative message explaining the reason for exemption (not used)
1367 */
1368 public <TYPE> Builder exemptFromConstraintChecking(String reason) {
1369 Preconditions.checkState(this.supportsConstraintChecking);
1370 this.supportsConstraintChecking = false;
Greg Estren2ffc4fe2015-06-02 19:40:41 +00001371 attributes.remove(RuleClass.COMPATIBLE_ENVIRONMENT_ATTR);
1372 attributes.remove(RuleClass.RESTRICTED_ENVIRONMENT_ATTR);
Greg Estrenc04c88f2015-03-06 19:45:50 +00001373 return this;
1374 }
1375
1376 /**
mstaibe5538ad2017-04-04 18:32:23 +00001377 * Causes rules of this type to implicitly reference the configuration fragments associated with
1378 * the options its attributes reference.
1379 *
1380 * <p>This is only intended for use by {@code config_setting} - other rules should not use this!
1381 */
1382 public Builder setOptionReferenceFunctionForConfigSettingOnly(
1383 Function<? super Rule, ? extends Set<String>> optionReferenceFunction) {
1384 this.optionReferenceFunction = Preconditions.checkNotNull(optionReferenceFunction);
1385 return this;
1386 }
1387
John Cateree45c662018-06-05 11:09:01 -07001388 /**
1389 * Causes rules of this type to require the specified toolchains be available via toolchain
1390 * resolution when a target is configured.
1391 */
John Cater9a8d16e2017-07-05 16:12:07 -04001392 public Builder addRequiredToolchains(Iterable<Label> toolchainLabels) {
1393 Iterables.addAll(this.requiredToolchains, toolchainLabels);
John Catereca28402017-05-17 21:44:12 +02001394 return this;
1395 }
1396
John Cateree45c662018-06-05 11:09:01 -07001397 /**
1398 * Causes rules of this type to require the specified toolchains be available via toolchain
1399 * resolution when a target is configured.
1400 */
cpeyserd852e482017-09-07 22:16:06 +02001401 public Builder addRequiredToolchains(Label... toolchainLabels) {
John Cateree45c662018-06-05 11:09:01 -07001402 return this.addRequiredToolchains(Lists.newArrayList(toolchainLabels));
1403 }
1404
1405 /**
juliexxia693048d2020-04-01 06:41:42 -07001406 * Adds execution groups to this rule class. Errors out if multiple groups with the same name
1407 * are added.
1408 */
1409 public Builder addExecGroups(Map<String, ExecGroup> execGroups) throws DuplicateExecGroupError {
1410 for (Map.Entry<String, ExecGroup> group : execGroups.entrySet()) {
1411 String name = group.getKey();
1412 if (this.execGroups.put(name, group.getValue()) != null) {
1413 throw new DuplicateExecGroupError(name);
1414 }
1415 }
1416 return this;
1417 }
1418
1419 /** An error to help report {@link ExecGroup}s with the same name */
1420 static class DuplicateExecGroupError extends EvalException {
1421 private final String duplicateGroup;
1422
1423 DuplicateExecGroupError(String duplicateGroup) {
1424 super(
1425 null,
1426 String.format("Multiple execution groups with the same name: '%s'.", duplicateGroup));
1427 this.duplicateGroup = duplicateGroup;
1428 }
1429
1430 String getDuplicateGroup() {
1431 return duplicateGroup;
1432 }
1433 }
1434
1435 /**
jcater01bb1f92019-06-17 12:09:11 -07001436 * Causes rules to use toolchain resolution to determine the execution platform and toolchains.
1437 * Rules that are part of configuring toolchains and platforms should set this to {@code false}.
John Cateree45c662018-06-05 11:09:01 -07001438 */
jcater01bb1f92019-06-17 12:09:11 -07001439 public Builder useToolchainResolution(boolean flag) {
1440 this.useToolchainResolution = flag;
cpeyserd852e482017-09-07 22:16:06 +02001441 return this;
1442 }
1443
John Cateree45c662018-06-05 11:09:01 -07001444 /**
John Cateree45c662018-06-05 11:09:01 -07001445 * Adds additional execution platform constraints that apply for all targets from this rule.
1446 *
1447 * <p>Please note that this value is inherited by child rules.
1448 */
1449 public Builder addExecutionPlatformConstraints(Label... constraints) {
1450 return this.addExecutionPlatformConstraints(Lists.newArrayList(constraints));
1451 }
1452
1453 /**
1454 * Adds additional execution platform constraints that apply for all targets from this rule.
1455 *
1456 * <p>Please note that this value is inherited by child rules.
1457 */
1458 public Builder addExecutionPlatformConstraints(Iterable<Label> constraints) {
1459 Iterables.addAll(this.executionPlatformConstraints, constraints);
John Cater856b4dd2017-11-21 08:06:16 -08001460 return this;
1461 }
1462
mstaibe5538ad2017-04-04 18:32:23 +00001463 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001464 * Returns an Attribute.Builder object which contains a replica of the
1465 * same attribute in the parent rule if exists.
1466 *
1467 * @param name the name of the attribute
1468 */
1469 public Attribute.Builder<?> copy(String name) {
1470 Preconditions.checkArgument(attributes.containsKey(name),
1471 "Attribute %s does not exist in parent rule class.", name);
1472 return attributes.get(name).cloneBuilder();
1473 }
1474 }
1475
1476 private final String name; // e.g. "cc_library"
adonovanebb86fc2020-03-20 14:57:54 -07001477 private final ImmutableList<StarlarkThread.CallStackEntry> callstack; // of call to 'rule'
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001478
tomlu72642a22017-10-18 06:23:14 +02001479 private final String key; // Just the name for native, label + name for skylark
1480
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001481 /**
1482 * The kind of target represented by this RuleClass (e.g. "cc_library rule").
1483 * Note: Even though there is partial duplication with the {@link RuleClass#name} field,
1484 * we want to store this as a separate field instead of generating it on demand in order to
1485 * avoid string duplication.
1486 */
1487 private final String targetKind;
1488
janakr6ff110e2018-03-21 21:44:27 -07001489 private final RuleClassType type;
Michajlo Matijkiwbc042c62015-10-29 13:22:52 +00001490 private final boolean isSkylark;
Jon Brandveinead58ae2016-09-29 18:41:10 +00001491 private final boolean skylarkTestable;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001492 private final boolean documented;
1493 private final boolean publicByDefault;
1494 private final boolean binaryOutput;
1495 private final boolean workspaceOnly;
dslomov2ce98442017-10-23 19:14:02 +02001496 private final boolean isExecutableSkylark;
cparsons55781c92018-10-17 12:03:08 -07001497 private final boolean isAnalysisTest;
cparsons9d40c6b2019-02-25 12:24:40 -08001498 private final boolean hasAnalysisTestTransition;
Googlerc2200fd2018-09-14 17:35:59 -07001499 private final boolean hasFunctionTransitionWhitelist;
gregce1d8d6dd2019-04-10 09:27:34 -07001500 private final boolean ignoreLicenses;
ulfjack5756b352020-01-23 04:53:22 -08001501 private final boolean hasAspects;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001502
1503 /**
1504 * A (unordered) mapping from attribute names to small integers indexing into
1505 * the {@code attributes} array.
1506 */
Miguel Alcon Pintod7795f42015-10-23 21:55:52 +00001507 private final Map<String, Integer> attributeIndex;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001508
1509 /**
1510 * All attributes of this rule class (including inherited ones) ordered by
1511 * attributeIndex value.
1512 */
Eric Fellheimera954fae2015-08-27 19:37:52 +00001513 private final ImmutableList<Attribute> attributes;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001514
Michajlo Matijkiwcdd5b0e2015-12-09 18:17:44 +00001515 /** Names of the non-configurable attributes of this rule class. */
1516 private final ImmutableList<String> nonConfigurableAttributes;
1517
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001518 /**
1519 * The set of implicit outputs generated by a rule, expressed as a function
1520 * of that rule.
1521 */
1522 private final ImplicitOutputsFunction implicitOutputsFunction;
1523
1524 /**
Michael Staib2a675202017-03-20 18:06:48 +00001525 * A factory which will produce a configuration transition that should be applied on any edge of
1526 * the configured target graph that leads into a target of this rule class.
Cal Peyser19dda252017-01-11 23:37:05 +00001527 */
John Caterb3b3e8b2019-04-03 09:18:42 -07001528 private final TransitionFactory<Rule> transitionFactory;
Cal Peyser19dda252017-01-11 23:37:05 +00001529
cparsonse2d200f2018-03-06 16:15:11 -08001530 /** The factory that creates configured targets from this rule. */
1531 private final ConfiguredTargetFactory<?, ?, ?> configuredTargetFactory;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001532
1533 /**
1534 * The constraint the package name of the rule instance must fulfill
1535 */
1536 private final PredicateWithMessage<Rule> validityPredicate;
1537
1538 /**
1539 * See {@link #isPreferredDependency}.
1540 */
1541 private final Predicate<String> preferredDependencyPredicate;
1542
1543 /**
1544 * The list of transitive info providers this class advertises to aspects.
1545 */
Dmitry Lomovb91d3922017-01-09 20:12:57 +00001546 private final AdvertisedProviderSet advertisedProviders;
Lukacs Berki549bfce2016-04-22 15:29:12 +00001547
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001548 /**
1549 * The Skylark rule implementation of this RuleClass. Null for non Skylark executable RuleClasses.
1550 */
adonovanf3a344e82019-12-11 11:10:11 -08001551 @Nullable private final StarlarkFunction configuredTargetFunction;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001552
1553 /**
juliexxia1f332e02018-10-31 14:20:55 -07001554 * The BuildSetting associated with this rule. Null for all RuleClasses except Skylark-defined
1555 * rules that pass {@code build_setting} to their {@code rule()} declaration.
1556 */
1557 @Nullable private final BuildSetting buildSetting;
1558
1559 /**
Lukacs Berki0e1a9942015-06-18 08:53:18 +00001560 * Returns the extra bindings a workspace function adds to the WORKSPACE file.
1561 */
1562 private final Function<? super Rule, Map<String, Label>> externalBindingsFunction;
1563
1564 /**
mstaibe5538ad2017-04-04 18:32:23 +00001565 * Returns the options referenced by this rule's attributes.
1566 */
1567 private final Function<? super Rule, ? extends Set<String>> optionReferenceFunction;
1568
1569 /**
janakrd3fe5e72018-03-30 12:49:12 -07001570 * The Skylark rule definition environment's label and hash code of this RuleClass. Null for non
1571 * Skylark executable RuleClasses.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001572 */
janakrd3fe5e72018-03-30 12:49:12 -07001573 @Nullable private final Label ruleDefinitionEnvironmentLabel;
1574
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001575 @Nullable private final String ruleDefinitionEnvironmentHashCode;
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -07001576 private final OutputFile.Kind outputFileKind;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001577
1578 /**
Michael Staibb51251e2015-09-29 23:31:51 +00001579 * The set of configuration fragments which are legal for this rule's implementation to access.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001580 */
Michael Staibb51251e2015-09-29 23:31:51 +00001581 private final ConfigurationFragmentPolicy configurationFragmentPolicy;
Greg Estrenc04c88f2015-03-06 19:45:50 +00001582
1583 /**
1584 * Determines whether instances of this rule should be checked for constraint compatibility
1585 * with their dependencies and the rules that depend on them. This should be true for
1586 * everything except for rules that are intrinsically incompatible with the constraint system.
1587 */
1588 private final boolean supportsConstraintChecking;
1589
gregce4aa059a2019-02-26 13:20:47 -08001590 private final ThirdPartyLicenseExistencePolicy thirdPartyLicenseExistencePolicy;
1591
cpeyserfb829992017-09-07 17:17:03 +02001592 private final ImmutableSet<Label> requiredToolchains;
jcater01bb1f92019-06-17 12:09:11 -07001593 private final boolean useToolchainResolution;
John Cateree45c662018-06-05 11:09:01 -07001594 private final ImmutableSet<Label> executionPlatformConstraints;
juliexxia693048d2020-04-01 06:41:42 -07001595 private final ImmutableMap<String, ExecGroup> execGroups;
John Catereca28402017-05-17 21:44:12 +02001596
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001597 /**
John Catereca28402017-05-17 21:44:12 +02001598 * Constructs an instance of RuleClass whose name is 'name', attributes are 'attributes'. The
1599 * {@code srcsAllowedFiles} determines which types of files are allowed as parameters to the
1600 * "srcs" attribute; rules are always allowed. For the "deps" attribute, there are four cases:
1601 *
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001602 * <ul>
John Catereca28402017-05-17 21:44:12 +02001603 * <li>if the parameter is a file, it is allowed if its file type is given in {@code
1604 * depsAllowedFiles},
1605 * <li>if the parameter is a rule and the rule class is accepted by {@code depsAllowedRules},
1606 * then it is allowed,
1607 * <li>if the parameter is a rule and the rule class is not accepted by {@code
1608 * depsAllowedRules}, but accepted by {@code depsAllowedRulesWithWarning}, then it is
1609 * allowed, but triggers a warning;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001610 * <li>all other parameters trigger an error.
1611 * </ul>
1612 *
John Catereca28402017-05-17 21:44:12 +02001613 * <p>The {@code depsAllowedRules} predicate should have a {@code toString} method which returns a
1614 * plain English enumeration of the allowed rule class names, if it does not allow all rule
1615 * classes.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001616 */
1617 @VisibleForTesting
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001618 RuleClass(
1619 String name,
adonovanebb86fc2020-03-20 14:57:54 -07001620 ImmutableList<StarlarkThread.CallStackEntry> callstack,
tomlu72642a22017-10-18 06:23:14 +02001621 String key,
janakr6ff110e2018-03-21 21:44:27 -07001622 RuleClassType type,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001623 boolean isSkylark,
Jon Brandveinead58ae2016-09-29 18:41:10 +00001624 boolean skylarkTestable,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001625 boolean documented,
1626 boolean publicByDefault,
1627 boolean binaryOutput,
1628 boolean workspaceOnly,
dslomov2ce98442017-10-23 19:14:02 +02001629 boolean isExecutableSkylark,
cparsons55781c92018-10-17 12:03:08 -07001630 boolean isAnalysisTest,
cparsons9d40c6b2019-02-25 12:24:40 -08001631 boolean hasAnalysisTestTransition,
Googlerc2200fd2018-09-14 17:35:59 -07001632 boolean hasFunctionTransitionWhitelist,
gregce1d8d6dd2019-04-10 09:27:34 -07001633 boolean ignoreLicenses,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001634 ImplicitOutputsFunction implicitOutputsFunction,
John Caterb3b3e8b2019-04-03 09:18:42 -07001635 TransitionFactory<Rule> transitionFactory,
cparsonse2d200f2018-03-06 16:15:11 -08001636 ConfiguredTargetFactory<?, ?, ?> configuredTargetFactory,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001637 PredicateWithMessage<Rule> validityPredicate,
1638 Predicate<String> preferredDependencyPredicate,
Dmitry Lomovb91d3922017-01-09 20:12:57 +00001639 AdvertisedProviderSet advertisedProviders,
adonovanf3a344e82019-12-11 11:10:11 -08001640 @Nullable StarlarkFunction configuredTargetFunction,
Lukacs Berki0e1a9942015-06-18 08:53:18 +00001641 Function<? super Rule, Map<String, Label>> externalBindingsFunction,
mstaibe5538ad2017-04-04 18:32:23 +00001642 Function<? super Rule, ? extends Set<String>> optionReferenceFunction,
janakrd3fe5e72018-03-30 12:49:12 -07001643 @Nullable Label ruleDefinitionEnvironmentLabel,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001644 String ruleDefinitionEnvironmentHashCode,
Michael Staibb51251e2015-09-29 23:31:51 +00001645 ConfigurationFragmentPolicy configurationFragmentPolicy,
Greg Estrenc04c88f2015-03-06 19:45:50 +00001646 boolean supportsConstraintChecking,
gregce4aa059a2019-02-26 13:20:47 -08001647 ThirdPartyLicenseExistencePolicy thirdPartyLicenseExistencePolicy,
cpeyserfb829992017-09-07 17:17:03 +02001648 Set<Label> requiredToolchains,
jcater01bb1f92019-06-17 12:09:11 -07001649 boolean useToolchainResolution,
John Cateree45c662018-06-05 11:09:01 -07001650 Set<Label> executionPlatformConstraints,
juliexxia693048d2020-04-01 06:41:42 -07001651 Map<String, ExecGroup> execGroups,
cparsons55781c92018-10-17 12:03:08 -07001652 OutputFile.Kind outputFileKind,
juliexxia1f332e02018-10-31 14:20:55 -07001653 Collection<Attribute> attributes,
1654 @Nullable BuildSetting buildSetting) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001655 this.name = name;
adonovanebb86fc2020-03-20 14:57:54 -07001656 this.callstack = callstack;
tomlu72642a22017-10-18 06:23:14 +02001657 this.key = key;
janakr6ff110e2018-03-21 21:44:27 -07001658 this.type = type;
Michajlo Matijkiwbc042c62015-10-29 13:22:52 +00001659 this.isSkylark = isSkylark;
Googlerb448eef2017-05-02 21:50:24 +02001660 this.targetKind = name + Rule.targetKindSuffix();
Jon Brandveinead58ae2016-09-29 18:41:10 +00001661 this.skylarkTestable = skylarkTestable;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001662 this.documented = documented;
1663 this.publicByDefault = publicByDefault;
1664 this.binaryOutput = binaryOutput;
1665 this.implicitOutputsFunction = implicitOutputsFunction;
Michael Staib2a675202017-03-20 18:06:48 +00001666 this.transitionFactory = transitionFactory;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001667 this.configuredTargetFactory = configuredTargetFactory;
1668 this.validityPredicate = validityPredicate;
1669 this.preferredDependencyPredicate = preferredDependencyPredicate;
1670 this.advertisedProviders = advertisedProviders;
1671 this.configuredTargetFunction = configuredTargetFunction;
Lukacs Berki0e1a9942015-06-18 08:53:18 +00001672 this.externalBindingsFunction = externalBindingsFunction;
mstaibe5538ad2017-04-04 18:32:23 +00001673 this.optionReferenceFunction = optionReferenceFunction;
janakrd3fe5e72018-03-30 12:49:12 -07001674 this.ruleDefinitionEnvironmentLabel = ruleDefinitionEnvironmentLabel;
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001675 this.ruleDefinitionEnvironmentHashCode = ruleDefinitionEnvironmentHashCode;
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -07001676 this.outputFileKind = outputFileKind;
Dmitry Lomov94387c22015-12-08 16:30:06 +00001677 validateNoClashInPublicNames(attributes);
Eric Fellheimera954fae2015-08-27 19:37:52 +00001678 this.attributes = ImmutableList.copyOf(attributes);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001679 this.workspaceOnly = workspaceOnly;
dslomov2ce98442017-10-23 19:14:02 +02001680 this.isExecutableSkylark = isExecutableSkylark;
cparsons55781c92018-10-17 12:03:08 -07001681 this.isAnalysisTest = isAnalysisTest;
cparsons9d40c6b2019-02-25 12:24:40 -08001682 this.hasAnalysisTestTransition = hasAnalysisTestTransition;
Googlerc2200fd2018-09-14 17:35:59 -07001683 this.hasFunctionTransitionWhitelist = hasFunctionTransitionWhitelist;
gregce1d8d6dd2019-04-10 09:27:34 -07001684 this.ignoreLicenses = ignoreLicenses;
Michael Staibb51251e2015-09-29 23:31:51 +00001685 this.configurationFragmentPolicy = configurationFragmentPolicy;
Greg Estrenc04c88f2015-03-06 19:45:50 +00001686 this.supportsConstraintChecking = supportsConstraintChecking;
gregce4aa059a2019-02-26 13:20:47 -08001687 this.thirdPartyLicenseExistencePolicy = thirdPartyLicenseExistencePolicy;
cpeyserfb829992017-09-07 17:17:03 +02001688 this.requiredToolchains = ImmutableSet.copyOf(requiredToolchains);
jcater01bb1f92019-06-17 12:09:11 -07001689 this.useToolchainResolution = useToolchainResolution;
John Cateree45c662018-06-05 11:09:01 -07001690 this.executionPlatformConstraints = ImmutableSet.copyOf(executionPlatformConstraints);
juliexxia693048d2020-04-01 06:41:42 -07001691 this.execGroups = ImmutableMap.copyOf(execGroups);
juliexxia1f332e02018-10-31 14:20:55 -07001692 this.buildSetting = buildSetting;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001693
Michajlo Matijkiwcdd5b0e2015-12-09 18:17:44 +00001694 // Create the index and collect non-configurable attributes.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001695 int index = 0;
ulfjack5756b352020-01-23 04:53:22 -08001696 attributeIndex = Maps.newHashMapWithExpectedSize(attributes.size());
1697 boolean computedHasAspects = false;
Michajlo Matijkiwcdd5b0e2015-12-09 18:17:44 +00001698 ImmutableList.Builder<String> nonConfigurableAttributesBuilder = ImmutableList.builder();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001699 for (Attribute attribute : attributes) {
ulfjack5756b352020-01-23 04:53:22 -08001700 computedHasAspects |= attribute.hasAspects();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001701 attributeIndex.put(attribute.getName(), index++);
Michajlo Matijkiwcdd5b0e2015-12-09 18:17:44 +00001702 if (!attribute.isConfigurable()) {
1703 nonConfigurableAttributesBuilder.add(attribute.getName());
1704 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001705 }
ulfjack5756b352020-01-23 04:53:22 -08001706 this.hasAspects = computedHasAspects;
Michajlo Matijkiwcdd5b0e2015-12-09 18:17:44 +00001707 this.nonConfigurableAttributes = nonConfigurableAttributesBuilder.build();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001708 }
1709
janakrd3fe5e72018-03-30 12:49:12 -07001710 private void validateNoClashInPublicNames(Iterable<Attribute> attributes) {
Dmitry Lomov94387c22015-12-08 16:30:06 +00001711 Map<String, Attribute> publicToPrivateNames = new HashMap<>();
1712 for (Attribute attribute : attributes) {
1713 String publicName = attribute.getPublicName();
1714 if (publicToPrivateNames.containsKey(publicName)) {
1715 throw new IllegalStateException(
1716 String.format(
1717 "Rule %s: Attributes %s and %s have an identical public name: %s",
1718 name,
1719 attribute.getName(),
1720 publicToPrivateNames.get(publicName).getName(),
1721 publicName));
1722 }
1723 publicToPrivateNames.put(publicName, attribute);
1724 }
1725 }
1726
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001727 /**
Michajlo Matijkiw6d471412016-08-09 20:35:45 +00001728 * Returns the default function for determining the set of implicit outputs generated by a given
1729 * rule. If not otherwise specified, this will be the implementation used by {@link Rule}s
1730 * created with this {@link RuleClass}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001731 *
Michajlo Matijkiw6d471412016-08-09 20:35:45 +00001732 * <p>Do not use this value to calculate implicit outputs for a rule, instead use
1733 * {@link Rule#getImplicitOutputsFunction()}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001734 *
Michajlo Matijkiw6d471412016-08-09 20:35:45 +00001735 * <p>An implicit output is an OutputFile that automatically comes into existence when a rule of
1736 * this class is declared, and whose name is derived from the name of the rule.
1737 *
1738 * <p>Implicit outputs are a widely-relied upon. All ".so", and "_deploy.jar" targets referenced
1739 * in BUILD files are examples.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001740 */
1741 @VisibleForTesting
Michajlo Matijkiw6d471412016-08-09 20:35:45 +00001742 public ImplicitOutputsFunction getDefaultImplicitOutputsFunction() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001743 return implicitOutputsFunction;
1744 }
1745
John Caterb3b3e8b2019-04-03 09:18:42 -07001746 public TransitionFactory<Rule> getTransitionFactory() {
Michael Staib2a675202017-03-20 18:06:48 +00001747 return transitionFactory;
Cal Peyser19dda252017-01-11 23:37:05 +00001748 }
1749
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001750 @SuppressWarnings("unchecked")
cparsonse2d200f2018-03-06 16:15:11 -08001751 public <CT, RC, ACE extends Throwable>
1752 ConfiguredTargetFactory<CT, RC, ACE> getConfiguredTargetFactory() {
1753 return (ConfiguredTargetFactory<CT, RC, ACE>) configuredTargetFactory;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001754 }
1755
1756 /**
1757 * Returns the class of rule that this RuleClass represents (e.g. "cc_library").
1758 */
1759 public String getName() {
1760 return name;
1761 }
1762
adonovanebb86fc2020-03-20 14:57:54 -07001763 /**
1764 * Returns the stack of Starlark active function calls at the moment this rule class was created.
1765 * Entries appear outermost first, and exclude the built-in itself ('rule' or 'repository_rule').
1766 * Empty for non-Starlark rules.
1767 */
1768 public ImmutableList<StarlarkThread.CallStackEntry> getCallStack() {
1769 return callstack;
1770 }
1771
janakr6ff110e2018-03-21 21:44:27 -07001772 /** Returns the type of rule that this RuleClass represents. Only for use during serialization. */
1773 public RuleClassType getRuleClassType() {
1774 return type;
1775 }
1776
tomlu72642a22017-10-18 06:23:14 +02001777 /** Returns a unique key. Used for profiling purposes. */
1778 public String getKey() {
1779 return key;
1780 }
1781
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001782 /**
1783 * Returns the target kind of this class of rule (e.g. "cc_library rule").
1784 */
1785 String getTargetKind() {
1786 return targetKind;
1787 }
1788
1789 public boolean getWorkspaceOnly() {
1790 return workspaceOnly;
1791 }
1792
1793 /**
1794 * Returns true iff the attribute 'attrName' is defined for this rule class,
1795 * and has type 'type'.
1796 */
1797 public boolean hasAttr(String attrName, Type<?> type) {
1798 Integer index = getAttributeIndex(attrName);
1799 return index != null && getAttribute(index).getType() == type;
1800 }
1801
1802 /**
1803 * Returns the index of the specified attribute name. Use of indices allows
1804 * space-efficient storage of attribute values in rules, since hashtables are
1805 * not required. (The index mapping is specific to each RuleClass and an
1806 * attribute may have a different index in the parent RuleClass.)
1807 *
1808 * <p>Returns null if the named attribute is not defined for this class of Rule.
1809 */
1810 Integer getAttributeIndex(String attrName) {
1811 return attributeIndex.get(attrName);
1812 }
1813
1814 /**
1815 * Returns the attribute whose index is 'attrIndex'. Fails if attrIndex is
1816 * not in range.
1817 */
1818 Attribute getAttribute(int attrIndex) {
Eric Fellheimera954fae2015-08-27 19:37:52 +00001819 return attributes.get(attrIndex);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001820 }
1821
1822 /**
Michajlo Matijkiw0446c952015-10-28 19:59:00 +00001823 * Returns the attribute whose name is 'attrName'; fails with NullPointerException if not found.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001824 */
1825 public Attribute getAttributeByName(String attrName) {
Michajlo Matijkiw0446c952015-10-28 19:59:00 +00001826 Integer attrIndex = Preconditions.checkNotNull(getAttributeIndex(attrName),
1827 "Attribute %s does not exist", attrName);
1828 return attributes.get(attrIndex);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001829 }
1830
1831 /**
1832 * Returns the attribute whose name is {@code attrName}, or null if not
1833 * found.
1834 */
1835 Attribute getAttributeByNameMaybe(String attrName) {
1836 Integer i = getAttributeIndex(attrName);
Eric Fellheimera954fae2015-08-27 19:37:52 +00001837 return i == null ? null : attributes.get(i);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001838 }
1839
1840 /**
1841 * Returns the number of attributes defined for this rule class.
1842 */
1843 public int getAttributeCount() {
1844 return attributeIndex.size();
1845 }
1846
1847 /**
1848 * Returns an (immutable) list of all Attributes defined for this class of
1849 * rule, ordered by increasing index.
1850 */
1851 public List<Attribute> getAttributes() {
Eric Fellheimera954fae2015-08-27 19:37:52 +00001852 return attributes;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001853 }
1854
Michajlo Matijkiwcdd5b0e2015-12-09 18:17:44 +00001855 /** Returns set of non-configurable attribute names defined for this class of rule. */
1856 public List<String> getNonConfigurableAttributes() {
1857 return nonConfigurableAttributes;
1858 }
1859
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001860 public PredicateWithMessage<Rule> getValidityPredicate() {
1861 return validityPredicate;
1862 }
1863
1864 /**
1865 * Returns the set of advertised transitive info providers.
1866 *
1867 * <p>When computing the set of aspects required for a rule, only the providers listed here are
1868 * considered. The presence of a provider here does not mean that the rule <b>must</b> implement
1869 * said provider, merely that it <b>can</b>. After the configured target is constructed from this
1870 * rule, aspects will be filtered according to the set of actual providers.
1871 *
1872 * <p>This is here so that we can do the loading phase overestimation required for "blaze query",
1873 * which does not have the configured targets available.
Dmitry Lomovb91d3922017-01-09 20:12:57 +00001874 **/
1875 public AdvertisedProviderSet getAdvertisedProviders() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001876 return advertisedProviders;
1877 }
Lukacs Berki549bfce2016-04-22 15:29:12 +00001878 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001879 * For --compile_one_dependency: if multiple rules consume the specified target,
1880 * should we choose this one over the "unpreferred" options?
1881 */
1882 public boolean isPreferredDependency(String filename) {
1883 return preferredDependencyPredicate.apply(filename);
1884 }
1885
1886 /**
Michael Staibb51251e2015-09-29 23:31:51 +00001887 * Returns this rule's policy for configuration fragment access.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001888 */
Michael Staibb51251e2015-09-29 23:31:51 +00001889 public ConfigurationFragmentPolicy getConfigurationFragmentPolicy() {
1890 return configurationFragmentPolicy;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001891 }
1892
1893 /**
Greg Estrenc04c88f2015-03-06 19:45:50 +00001894 * Returns true if rules of this type can be used with the constraint enforcement system.
1895 */
1896 public boolean supportsConstraintChecking() {
1897 return supportsConstraintChecking;
1898 }
1899
ulfjack5756b352020-01-23 04:53:22 -08001900 public boolean hasAspects() {
1901 return hasAspects;
1902 }
1903
Greg Estrenc04c88f2015-03-06 19:45:50 +00001904 /**
Mark Schalleree624452016-01-13 18:41:24 +00001905 * Creates a new {@link Rule} {@code r} where {@code r.getPackage()} is the {@link Package}
1906 * associated with {@code pkgBuilder}.
1907 *
1908 * <p>The created {@link Rule} will be populated with attribute values from {@code
1909 * attributeValues} or the default attribute values associated with this {@link RuleClass} and
1910 * {@code pkgBuilder}.
1911 *
Florian Weikertea6c82d2016-09-05 12:15:31 +00001912 * <p>The created {@link Rule} will also be populated with output files. These output files will
1913 * have been collected from the explicitly provided values of type {@link BuildType#OUTPUT} and
1914 * {@link BuildType#OUTPUT_LIST} as well as from the implicit outputs determined by this {@link
1915 * RuleClass} and the values in {@code attributeValues}.
Mark Schalleree624452016-01-13 18:41:24 +00001916 *
1917 * <p>This performs several validity checks. Invalid output file labels result in a thrown {@link
Florian Weikertea6c82d2016-09-05 12:15:31 +00001918 * LabelSyntaxException}. Computed default attributes that fail during precomputation result in a
1919 * {@link CannotPrecomputeDefaultsException}. All other errors are reported on {@code
1920 * eventHandler}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001921 */
nharmata65a173a2017-08-07 16:11:04 +02001922 <T> Rule createRule(
Mark Schalleree624452016-01-13 18:41:24 +00001923 Package.Builder pkgBuilder,
1924 Label ruleLabel,
nharmata65a173a2017-08-07 16:11:04 +02001925 AttributeValues<T> attributeValues,
Mark Schalleree624452016-01-13 18:41:24 +00001926 EventHandler eventHandler,
Mark Schalleree624452016-01-13 18:41:24 +00001927 Location location,
adonovan40a737c2020-03-11 14:32:19 -07001928 List<StarlarkThread.CallStackEntry> callstack,
Greg Estren37cd5c42019-01-30 12:25:50 -08001929 AttributeContainer attributeContainer,
1930 boolean checkThirdPartyRulesHaveLicenses)
Florian Weikertea6c82d2016-09-05 12:15:31 +00001931 throws LabelSyntaxException, InterruptedException, CannotPrecomputeDefaultsException {
adonovan40a737c2020-03-11 14:32:19 -07001932 Rule rule = pkgBuilder.createRule(ruleLabel, this, location, callstack, attributeContainer);
Michajlo Matijkiw581f2c22016-07-25 20:12:16 +00001933 populateRuleAttributeValues(rule, pkgBuilder, attributeValues, eventHandler);
1934 checkAspectAllowedValues(rule, eventHandler);
1935 rule.populateOutputFiles(eventHandler, pkgBuilder);
Michajlo Matijkiw581f2c22016-07-25 20:12:16 +00001936 checkForDuplicateLabels(rule, eventHandler);
gregce4aa059a2019-02-26 13:20:47 -08001937
1938 boolean actuallyCheckLicense;
1939 if (thirdPartyLicenseExistencePolicy == ThirdPartyLicenseExistencePolicy.ALWAYS_CHECK) {
1940 actuallyCheckLicense = true;
1941 } else if (thirdPartyLicenseExistencePolicy == ThirdPartyLicenseExistencePolicy.NEVER_CHECK) {
1942 actuallyCheckLicense = false;
1943 } else {
1944 actuallyCheckLicense = checkThirdPartyRulesHaveLicenses;
1945 }
1946
1947 if (actuallyCheckLicense) {
Greg Estren37cd5c42019-01-30 12:25:50 -08001948 checkThirdPartyRuleHasLicense(rule, pkgBuilder, eventHandler);
1949 }
Michajlo Matijkiw581f2c22016-07-25 20:12:16 +00001950 checkForValidSizeAndTimeoutValues(rule, eventHandler);
1951 rule.checkValidityPredicate(eventHandler);
Nathan Harmatacf738442016-06-28 14:52:21 +00001952 rule.checkForNullLabels();
1953 return rule;
1954 }
1955
1956 /**
1957 * Same as {@link #createRule}, except without some internal sanity checks.
1958 *
1959 * <p>Don't call this function unless you know what you're doing.
1960 */
nharmata65a173a2017-08-07 16:11:04 +02001961 <T> Rule createRuleUnchecked(
Nathan Harmatacf738442016-06-28 14:52:21 +00001962 Package.Builder pkgBuilder,
1963 Label ruleLabel,
nharmata65a173a2017-08-07 16:11:04 +02001964 AttributeValues<T> attributeValues,
Nathan Harmatacf738442016-06-28 14:52:21 +00001965 Location location,
adonovan40a737c2020-03-11 14:32:19 -07001966 List<StarlarkThread.CallStackEntry> callstack,
Michajlo Matijkiw6d471412016-08-09 20:35:45 +00001967 AttributeContainer attributeContainer,
1968 ImplicitOutputsFunction implicitOutputsFunction)
nharmata59c16f62017-08-07 19:49:09 +02001969 throws InterruptedException, CannotPrecomputeDefaultsException {
adonovan40a737c2020-03-11 14:32:19 -07001970 Rule rule =
1971 pkgBuilder.createRule(
1972 ruleLabel, this, location, callstack, attributeContainer, implicitOutputsFunction);
Michajlo Matijkiw581f2c22016-07-25 20:12:16 +00001973 populateRuleAttributeValues(rule, pkgBuilder, attributeValues, NullEventHandler.INSTANCE);
nharmata59c16f62017-08-07 19:49:09 +02001974 rule.populateOutputFilesUnchecked(NullEventHandler.INSTANCE, pkgBuilder);
Mark Schalleree624452016-01-13 18:41:24 +00001975 return rule;
1976 }
1977
1978 /**
1979 * Populates the attributes table of the new {@link Rule} with the values in the {@code
1980 * attributeValues} map and with default values provided by this {@link RuleClass} and the {@code
1981 * pkgBuilder}.
1982 *
1983 * <p>Errors are reported on {@code eventHandler}.
1984 */
nharmata65a173a2017-08-07 16:11:04 +02001985 private <T> void populateRuleAttributeValues(
Mark Schalleree624452016-01-13 18:41:24 +00001986 Rule rule,
1987 Package.Builder pkgBuilder,
nharmata65a173a2017-08-07 16:11:04 +02001988 AttributeValues<T> attributeValues,
Florian Weikertea6c82d2016-09-05 12:15:31 +00001989 EventHandler eventHandler)
1990 throws InterruptedException, CannotPrecomputeDefaultsException {
Mark Schalleree624452016-01-13 18:41:24 +00001991 BitSet definedAttrIndices =
dannarkf24479d2018-06-21 11:55:44 -07001992 populateDefinedRuleAttributeValues(
nharmataf3e99412019-01-28 10:06:29 -08001993 rule,
1994 pkgBuilder.getRepositoryMapping(),
1995 attributeValues,
1996 pkgBuilder.getListInterner(),
1997 eventHandler);
Mark Schalleree624452016-01-13 18:41:24 +00001998 populateDefaultRuleAttributeValues(rule, pkgBuilder, definedAttrIndices, eventHandler);
1999 // Now that all attributes are bound to values, collect and store configurable attribute keys.
2000 populateConfigDependenciesAttribute(rule);
2001 }
2002
2003 /**
2004 * Populates the attributes table of the new {@link Rule} with the values in the {@code
2005 * attributeValues} map.
2006 *
2007 * <p>Handles the special cases of the attribute named {@code "name"} and attributes with value
Googler641bdf72019-11-12 10:32:26 -08002008 * {@link Starlark#NONE}.
Mark Schalleree624452016-01-13 18:41:24 +00002009 *
dannarkf24479d2018-06-21 11:55:44 -07002010 * <p>Returns a bitset {@code b} where {@code b.get(i)} is {@code true} if this method set a value
2011 * for the attribute with index {@code i} in this {@link RuleClass}. Errors are reported on {@code
2012 * eventHandler}.
Mark Schalleree624452016-01-13 18:41:24 +00002013 */
nharmata65a173a2017-08-07 16:11:04 +02002014 private <T> BitSet populateDefinedRuleAttributeValues(
dannarkf24479d2018-06-21 11:55:44 -07002015 Rule rule,
2016 ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
2017 AttributeValues<T> attributeValues,
nharmataf3e99412019-01-28 10:06:29 -08002018 Interner<ImmutableList<?>> listInterner,
dannarkf24479d2018-06-21 11:55:44 -07002019 EventHandler eventHandler) {
Mark Schalleree624452016-01-13 18:41:24 +00002020 BitSet definedAttrIndices = new BitSet();
nharmata65a173a2017-08-07 16:11:04 +02002021 for (T attributeAccessor : attributeValues.getAttributeAccessors()) {
2022 String attributeName = attributeValues.getName(attributeAccessor);
2023 Object attributeValue = attributeValues.getValue(attributeAccessor);
Mark Schalleree624452016-01-13 18:41:24 +00002024 // Ignore all None values.
Googler641bdf72019-11-12 10:32:26 -08002025 if (attributeValue == Starlark.NONE) {
Mark Schalleree624452016-01-13 18:41:24 +00002026 continue;
2027 }
2028
2029 // Check that the attribute's name belongs to a valid attribute for this rule class.
2030 Integer attrIndex = getAttributeIndex(attributeName);
2031 if (attrIndex == null) {
2032 rule.reportError(
2033 String.format(
2034 "%s: no such attribute '%s' in '%s' rule", rule.getLabel(), attributeName, name),
2035 eventHandler);
2036 continue;
2037 }
2038 Attribute attr = getAttribute(attrIndex);
2039
gregce1d8d6dd2019-04-10 09:27:34 -07002040 if (attributeName.equals("licenses") && ignoreLicenses) {
2041 setRuleAttributeValue(rule, eventHandler, attr, License.NO_LICENSE, /*explicit=*/ false);
2042 definedAttrIndices.set(attrIndex);
2043 continue;
2044 }
2045
Mark Schalleree624452016-01-13 18:41:24 +00002046 // Convert the build-lang value to a native value, if necessary.
2047 Object nativeAttributeValue;
2048 if (attributeValues.valuesAreBuildLanguageTyped()) {
2049 try {
dannarkf24479d2018-06-21 11:55:44 -07002050 nativeAttributeValue =
nharmataf3e99412019-01-28 10:06:29 -08002051 convertFromBuildLangType(rule, attr, attributeValue, repositoryMapping, listInterner);
Mark Schalleree624452016-01-13 18:41:24 +00002052 } catch (ConversionException e) {
2053 rule.reportError(String.format("%s: %s", rule.getLabel(), e.getMessage()), eventHandler);
2054 continue;
2055 }
2056 } else {
2057 nativeAttributeValue = attributeValue;
2058 }
2059
nharmata65a173a2017-08-07 16:11:04 +02002060 boolean explicit = attributeValues.isExplicitlySpecified(attributeAccessor);
Mark Schalleree624452016-01-13 18:41:24 +00002061 setRuleAttributeValue(rule, eventHandler, attr, nativeAttributeValue, explicit);
2062 definedAttrIndices.set(attrIndex);
Mark Schalleree624452016-01-13 18:41:24 +00002063 }
2064 return definedAttrIndices;
2065 }
2066
Mark Schalleree624452016-01-13 18:41:24 +00002067 /**
2068 * Populates the attributes table of the new {@link Rule} with default values provided by this
Florian Weikertea6c82d2016-09-05 12:15:31 +00002069 * {@link RuleClass} and the {@code pkgBuilder}. This will only provide values for attributes that
2070 * haven't already been populated, using {@code definedAttrIndices} to determine whether an
Mark Schalleree624452016-01-13 18:41:24 +00002071 * attribute was populated.
2072 *
2073 * <p>Errors are reported on {@code eventHandler}.
2074 */
2075 private void populateDefaultRuleAttributeValues(
Florian Weikertea6c82d2016-09-05 12:15:31 +00002076 Rule rule, Package.Builder pkgBuilder, BitSet definedAttrIndices, EventHandler eventHandler)
2077 throws InterruptedException, CannotPrecomputeDefaultsException {
Mark Schalleree624452016-01-13 18:41:24 +00002078 // Set defaults; ensure that every mandatory attribute has a value. Use the default if none
2079 // is specified.
2080 List<Attribute> attrsWithComputedDefaults = new ArrayList<>();
2081 int numAttributes = getAttributeCount();
2082 for (int attrIndex = 0; attrIndex < numAttributes; ++attrIndex) {
2083 if (definedAttrIndices.get(attrIndex)) {
2084 continue;
2085 }
2086 Attribute attr = getAttribute(attrIndex);
2087 if (attr.isMandatory()) {
2088 rule.reportError(
2089 String.format(
2090 "%s: missing value for mandatory attribute '%s' in '%s' rule",
2091 rule.getLabel(),
2092 attr.getName(),
2093 name),
2094 eventHandler);
2095 }
2096
gregce1d8d6dd2019-04-10 09:27:34 -07002097 if (attr.getName().equals("licenses") && ignoreLicenses) {
2098 rule.setAttributeValue(attr, License.NO_LICENSE, /*explicit=*/ false);
2099 } else if (attr.hasComputedDefault()) {
Mark Schalleree624452016-01-13 18:41:24 +00002100 // Note that it is necessary to set all non-computed default values before calling
2101 // Attribute#getDefaultValue for computed default attributes. Computed default attributes
2102 // may have a condition predicate (i.e. the predicate returned by Attribute#getCondition)
2103 // that depends on non-computed default attribute values, and that condition predicate is
2104 // evaluated by the call to Attribute#getDefaultValue.
2105 attrsWithComputedDefaults.add(attr);
cparsonscaceacd2017-11-04 01:00:59 +01002106 } else if (attr.isLateBound()) {
2107 rule.setAttributeValue(attr, attr.getLateBoundDefault(), /*explicit=*/ false);
Mark Schalleree624452016-01-13 18:41:24 +00002108 } else {
2109 Object defaultValue = getAttributeNoncomputedDefaultValue(attr, pkgBuilder);
Mark Schalleree624452016-01-13 18:41:24 +00002110 rule.setAttributeValue(attr, defaultValue, /*explicit=*/ false);
2111 checkAllowedValues(rule, attr, eventHandler);
2112 }
2113 }
2114
2115 // Set computed default attribute values now that all other (i.e. non-computed) default values
2116 // have been set.
2117 for (Attribute attr : attrsWithComputedDefaults) {
Florian Weikertea6c82d2016-09-05 12:15:31 +00002118 // If Attribute#hasComputedDefault was true above, Attribute#getDefaultValue returns the
2119 // computed default function object or a Skylark computed default template. Note that we
2120 // cannot determine the exact value of the computed default function here because it may
2121 // depend on other attribute values that are configurable (i.e. they came from select({..})
2122 // expressions in the build language, and they require configuration data from the analysis
2123 // phase to be resolved). Instead, we're setting the attribute value to a reference to the
2124 // computed default function, or if #getDefaultValue is a Skylark computed default
2125 // template, setting the attribute value to a reference to the SkylarkComputedDefault
2126 // returned from SkylarkComputedDefaultTemplate#computePossibleValues.
2127 //
2128 // SkylarkComputedDefaultTemplate#computePossibleValues pre-computes all possible values the
2129 // function may evaluate to, and records them in a lookup table. By calling it here, with an
2130 // EventHandler, any errors that might occur during the function's evaluation can
2131 // be discovered and propagated here.
2132 Object valueToSet;
2133 Object defaultValue = attr.getDefaultValue(rule);
2134 if (defaultValue instanceof SkylarkComputedDefaultTemplate) {
2135 SkylarkComputedDefaultTemplate template = (SkylarkComputedDefaultTemplate) defaultValue;
2136 valueToSet = template.computePossibleValues(attr, rule, eventHandler);
schmitta4080da92019-05-20 13:12:46 -07002137 } else if (defaultValue instanceof ComputedDefault) {
2138 // Compute all possible values to verify that the ComputedDefault is well-defined. This was
2139 // previously done implicitly as part of visiting all labels to check for null-ness in
2140 // Rule.checkForNullLabels, but that was changed to skip non-label attributes to improve
2141 // performance.
2142 ((ComputedDefault) defaultValue).getPossibleValues(attr.getType(), rule);
2143 valueToSet = defaultValue;
Florian Weikertea6c82d2016-09-05 12:15:31 +00002144 } else {
2145 valueToSet = defaultValue;
2146 }
2147 rule.setAttributeValue(attr, valueToSet, /*explicit=*/ false);
Mark Schalleree624452016-01-13 18:41:24 +00002148 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002149 }
2150
2151 /**
2152 * Collects all labels used as keys for configurable attributes and places them into
2153 * the special implicit attribute that tracks them.
2154 */
2155 private static void populateConfigDependenciesAttribute(Rule rule) {
2156 RawAttributeMapper attributes = RawAttributeMapper.of(rule);
gregce749962a2019-03-08 12:47:34 -08002157 Attribute configDepsAttribute =
2158 attributes.getAttributeDefinition(CONFIG_SETTING_DEPS_ATTRIBUTE);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002159 if (configDepsAttribute == null) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002160 return;
2161 }
2162
felly7615e1a2019-05-16 03:45:26 -07002163 LinkedHashSet<Label> configLabels = new LinkedHashSet<>();
2164 for (Attribute attr : rule.getAttributes()) {
2165 SelectorList<?> selectorList = attributes.getSelectorList(attr.getName(), attr.getType());
2166 if (selectorList != null) {
2167 configLabels.addAll(selectorList.getKeyLabels());
2168 }
2169 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002170
2171 rule.setAttributeValue(configDepsAttribute, ImmutableList.copyOf(configLabels),
2172 /*explicit=*/false);
2173 }
2174
Nathan Harmatafcb17112016-04-13 16:56:58 +00002175 public void checkAttributesNonEmpty(
michajloc1062a42018-09-26 14:53:38 -07002176 RuleErrorConsumer ruleErrorConsumer, AttributeMap attributes) {
Nathan Harmatafcb17112016-04-13 16:56:58 +00002177 for (String attributeName : attributes.getAttributeNames()) {
2178 Attribute attr = attributes.getAttributeDefinition(attributeName);
2179 if (!attr.isNonEmpty()) {
2180 continue;
2181 }
2182 Object attributeValue = attributes.get(attributeName, attr.getType());
Francois-Rene Rideau93ed7f12015-10-20 15:39:33 +00002183
Nathan Harmatafcb17112016-04-13 16:56:58 +00002184 boolean isEmpty = false;
Googler4871cb02019-11-12 17:16:42 -08002185 if (attributeValue instanceof Sequence) {
2186 isEmpty = ((Sequence<?>) attributeValue).isEmpty();
Nathan Harmatafcb17112016-04-13 16:56:58 +00002187 } else if (attributeValue instanceof List<?>) {
2188 isEmpty = ((List<?>) attributeValue).isEmpty();
2189 } else if (attributeValue instanceof Map<?, ?>) {
2190 isEmpty = ((Map<?, ?>) attributeValue).isEmpty();
2191 }
Francois-Rene Rideau5e00ec62015-10-20 17:02:19 +00002192
Nathan Harmatafcb17112016-04-13 16:56:58 +00002193 if (isEmpty) {
2194 ruleErrorConsumer.attributeError(attr.getName(), "attribute must be non empty");
2195 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002196 }
2197 }
2198
2199 /**
2200 * Report an error for each label that appears more than once in a LABEL_LIST attribute
2201 * of the given rule.
2202 *
2203 * @param rule The rule.
2204 * @param eventHandler The eventHandler to use to report the duplicated deps.
2205 */
2206 private static void checkForDuplicateLabels(Rule rule, EventHandler eventHandler) {
2207 for (Attribute attribute : rule.getAttributes()) {
Lukacs Berkiffa73ad2015-09-18 11:40:12 +00002208 if (attribute.getType() == BuildType.LABEL_LIST) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002209 checkForDuplicateLabels(rule, attribute, eventHandler);
2210 }
2211 }
2212 }
2213
2214 /**
2215 * Reports an error against the specified rule if it's beneath third_party
2216 * but does not have a declared license.
2217 */
2218 private static void checkThirdPartyRuleHasLicense(Rule rule,
Han-Wen Nienhuys086e5f22015-04-21 11:39:59 +00002219 Package.Builder pkgBuilder, EventHandler eventHandler) {
gregce1d8d6dd2019-04-10 09:27:34 -07002220 if (rule.getRuleClassObject().ignoreLicenses()) {
Googlerfdb17eb2019-01-28 15:14:32 -08002221 // A package license is sufficient; ignore rules that don't include it.
2222 return;
2223 }
Brian Silvermand7d6d622016-03-17 09:53:39 +00002224 if (isThirdPartyPackage(rule.getLabel().getPackageIdentifier())) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002225 License license = rule.getLicense();
2226 if (license == null) {
2227 license = pkgBuilder.getDefaultLicense();
2228 }
lberki0d8d4cf2017-09-05 16:01:44 +02002229 if (!license.isSpecified()) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002230 rule.reportError("third-party rule '" + rule.getLabel() + "' lacks a license declaration "
2231 + "with one of the following types: notice, reciprocal, permissive, "
2232 + "restricted, unencumbered, by_exception_only",
2233 eventHandler);
2234 }
2235 }
2236 }
2237
2238 /**
2239 * Report an error for each label that appears more than once in the given attribute
2240 * of the given rule.
2241 *
2242 * @param rule The rule.
2243 * @param attribute The attribute to check. Must exist in rule and be of type LABEL_LIST.
2244 * @param eventHandler The eventHandler to use to report the duplicated deps.
2245 */
2246 private static void checkForDuplicateLabels(Rule rule, Attribute attribute,
2247 EventHandler eventHandler) {
Greg Estren14348c02015-04-16 16:26:19 +00002248 Set<Label> duplicates = AggregatingAttributeMapper.of(rule).checkForDuplicateLabels(attribute);
2249 for (Label label : duplicates) {
2250 rule.reportError(
2251 String.format("Label '%s' is duplicated in the '%s' attribute of rule '%s'",
2252 label, attribute.getName(), rule.getName()), eventHandler);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002253 }
2254 }
2255
2256 /**
2257 * Report an error if the rule has a timeout or size attribute that is not a
2258 * legal value. These attributes appear on all tests.
2259 *
2260 * @param rule the rule to check
2261 * @param eventHandler the eventHandler to use to report the duplicated deps
2262 */
2263 private static void checkForValidSizeAndTimeoutValues(Rule rule, EventHandler eventHandler) {
2264 if (rule.getRuleClassObject().hasAttr("size", Type.STRING)) {
2265 String size = NonconfigurableAttributeMapper.of(rule).get("size", Type.STRING);
2266 if (TestSize.getTestSize(size) == null) {
2267 rule.reportError(
2268 String.format("In rule '%s', size '%s' is not a valid size.", rule.getName(), size),
2269 eventHandler);
2270 }
2271 }
2272 if (rule.getRuleClassObject().hasAttr("timeout", Type.STRING)) {
2273 String timeout = NonconfigurableAttributeMapper.of(rule).get("timeout", Type.STRING);
2274 if (TestTimeout.getTestTimeout(timeout) == null) {
2275 rule.reportError(
2276 String.format(
2277 "In rule '%s', timeout '%s' is not a valid timeout.", rule.getName(), timeout),
2278 eventHandler);
2279 }
2280 }
2281 }
2282
2283 /**
2284 * Returns the default value for the specified rule attribute.
2285 *
Francois-Rene Rideau5dcdbf92015-02-19 18:36:17 +00002286 * <p>For most rule attributes, the default value is either explicitly specified
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002287 * in the attribute, or implicitly based on the type of the attribute, except
2288 * for some special cases (e.g. "licenses", "distribs") where it comes from
2289 * some other source, such as state in the package.
2290 *
Francois-Rene Rideau5dcdbf92015-02-19 18:36:17 +00002291 * <p>Precondition: {@code !attr.hasComputedDefault()}. (Computed defaults are
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002292 * evaluated in second pass.)
2293 */
2294 private static Object getAttributeNoncomputedDefaultValue(Attribute attr,
Han-Wen Nienhuys086e5f22015-04-21 11:39:59 +00002295 Package.Builder pkgBuilder) {
aiuto4d9bb522020-02-19 13:26:10 -08002296 // TODO(b/149505729): Determine the right semantics for someone trying to define their own
2297 // attribute named applicable_licenses.
2298 if (attr.getName().equals("applicable_licenses")) {
2299 return pkgBuilder.getDefaultApplicableLicenses();
2300 }
gregce82281ad2019-02-27 08:01:07 -08002301 // Starlark rules may define their own "licenses" attributes with different types -
2302 // we shouldn't trigger the special "licenses" on those cases.
2303 if (attr.getName().equals("licenses") && attr.getType() == BuildType.LICENSE) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002304 return pkgBuilder.getDefaultLicense();
2305 }
2306 if (attr.getName().equals("distribs")) {
2307 return pkgBuilder.getDefaultDistribs();
2308 }
2309 return attr.getDefaultValue(null);
2310 }
2311
2312 /**
Mark Schalleree624452016-01-13 18:41:24 +00002313 * Sets the value of attribute {@code attr} in {@code rule} to the native value {@code
2314 * nativeAttrVal}, and sets the value's explicitness to {@code explicit}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002315 *
Mark Schalleree624452016-01-13 18:41:24 +00002316 * <p>Handles the special case of the "visibility" attribute by also setting the rule's
2317 * visibility with {@link Rule#setVisibility}.
2318 *
2319 * <p>Checks that {@code nativeAttrVal} is an allowed value via {@link #checkAllowedValues}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002320 */
Mark Schalleree624452016-01-13 18:41:24 +00002321 private static void setRuleAttributeValue(
2322 Rule rule,
2323 EventHandler eventHandler,
2324 Attribute attr,
2325 Object nativeAttrVal,
2326 boolean explicit) {
2327 if (attr.getName().equals("visibility")) {
2328 @SuppressWarnings("unchecked")
2329 List<Label> attrList = (List<Label>) nativeAttrVal;
Francois-Rene Rideaucbebd632015-02-11 16:56:37 +00002330 if (!attrList.isEmpty()
2331 && ConstantRuleVisibility.LEGACY_PUBLIC_LABEL.equals(attrList.get(0))) {
Mark Schalleree624452016-01-13 18:41:24 +00002332 rule.reportError(
2333 rule.getLabel() + ": //visibility:legacy_public only allowed in package declaration",
2334 eventHandler);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002335 }
Yue Gan36a26572016-05-25 11:48:10 +00002336 try {
michajlocab889d2020-02-20 17:48:36 -08002337 rule.setVisibility(PackageUtils.getVisibility(rule.getLabel(), attrList));
Yue Gan36a26572016-05-25 11:48:10 +00002338 } catch (EvalException e) {
2339 rule.reportError(rule.getLabel() + " " + e.getMessage(), eventHandler);
2340 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002341 }
Mark Schalleree624452016-01-13 18:41:24 +00002342 rule.setAttributeValue(attr, nativeAttrVal, explicit);
Michael Staibff938b32015-08-27 19:22:59 +00002343 checkAllowedValues(rule, attr, eventHandler);
Mark Schalleree624452016-01-13 18:41:24 +00002344 }
2345
2346 /**
2347 * Converts the build-language-typed {@code buildLangValue} to a native value via {@link
laurentlb1d273cd2018-05-16 12:12:26 -07002348 * BuildType#selectableConvert}. Canonicalizes the value's order if it is a {@link List} type and
2349 * {@code attr.isOrderIndependent()} returns {@code true}.
Mark Schalleree624452016-01-13 18:41:24 +00002350 *
laurentlb1d273cd2018-05-16 12:12:26 -07002351 * <p>Throws {@link ConversionException} if the conversion fails, or if {@code buildLangValue} is
2352 * a selector expression but {@code attr.isConfigurable()} is {@code false}.
Mark Schalleree624452016-01-13 18:41:24 +00002353 */
dannarkf24479d2018-06-21 11:55:44 -07002354 private static Object convertFromBuildLangType(
2355 Rule rule,
2356 Attribute attr,
2357 Object buildLangValue,
nharmataf3e99412019-01-28 10:06:29 -08002358 ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
2359 Interner<ImmutableList<?>> listInterner)
Mark Schalleree624452016-01-13 18:41:24 +00002360 throws ConversionException {
dannarkf24479d2018-06-21 11:55:44 -07002361 LabelConversionContext context = new LabelConversionContext(rule.getLabel(), repositoryMapping);
2362 Object converted =
2363 BuildType.selectableConvert(
2364 attr.getType(),
2365 buildLangValue,
2366 new AttributeConversionContext(attr.getName(), rule.getRuleClass()),
2367 context);
Mark Schalleree624452016-01-13 18:41:24 +00002368
2369 if ((converted instanceof SelectorList<?>) && !attr.isConfigurable()) {
2370 throw new ConversionException(
2371 String.format("attribute \"%s\" is not configurable", attr.getName()));
2372 }
2373
laurentlb1d273cd2018-05-16 12:12:26 -07002374 if (converted instanceof List<?>) {
Mark Schalleree624452016-01-13 18:41:24 +00002375 if (attr.isOrderIndependent()) {
2376 @SuppressWarnings("unchecked")
2377 List<? extends Comparable<?>> list = (List<? extends Comparable<?>>) converted;
2378 converted = Ordering.natural().sortedCopy(list);
2379 }
nharmataf3e99412019-01-28 10:06:29 -08002380 // It's common for multiple rule instances in the same package to have the same value for some
2381 // attributes. As a concrete example, consider a package having several 'java_test' instances,
2382 // each with the same exact 'tags' attribute value.
2383 converted = listInterner.intern(ImmutableList.copyOf((List<?>) converted));
Mark Schalleree624452016-01-13 18:41:24 +00002384 }
2385
2386 return converted;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002387 }
2388
Michael Staibff938b32015-08-27 19:22:59 +00002389 /**
Michajlo Matijkiw7b7fce12016-09-20 19:52:07 +00002390 * Provides a {@link #toString()} description of the attribute being converted for
2391 * {@link BuildType#selectableConvert}. This is preferred over a raw string to avoid uselessly
2392 * constructing strings which are never used. A separate class instead of inline to avoid
2393 * accidental memory leaks.
2394 */
2395 private static class AttributeConversionContext {
2396 private final String attrName;
2397 private final String ruleClass;
2398
2399 AttributeConversionContext(String attrName, String ruleClass) {
2400 this.attrName = attrName;
2401 this.ruleClass = ruleClass;
2402 }
2403
2404 @Override
2405 public String toString() {
2406 return "attribute '" + attrName + "' in '" + ruleClass + "' rule";
2407 }
2408 }
2409
2410
2411 /**
Michael Staibff938b32015-08-27 19:22:59 +00002412 * Verifies that the rule has a valid value for the attribute according to its allowed values.
2413 *
2414 * <p>If the value for the given attribute on the given rule is invalid, an error will be recorded
2415 * in the given EventHandler.
2416 *
2417 * <p>If the rule is configurable, all of its potential values are evaluated, and errors for each
2418 * of the invalid values are reported.
2419 */
Mark Schalleree624452016-01-13 18:41:24 +00002420 private static void checkAllowedValues(
2421 Rule rule, Attribute attribute, EventHandler eventHandler) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002422 if (attribute.checkAllowedValues()) {
2423 PredicateWithMessage<Object> allowedValues = attribute.getAllowedValues();
Michael Staibff938b32015-08-27 19:22:59 +00002424 Iterable<?> values =
2425 AggregatingAttributeMapper.of(rule).visitAttribute(
2426 attribute.getName(), attribute.getType());
2427 for (Object value : values) {
2428 if (!allowedValues.apply(value)) {
Mark Schalleree624452016-01-13 18:41:24 +00002429 rule.reportError(
2430 String.format(
2431 "%s: invalid value in '%s' attribute: %s",
2432 rule.getLabel(),
2433 attribute.getName(),
2434 allowedValues.getErrorReason(value)),
2435 eventHandler);
Michael Staibff938b32015-08-27 19:22:59 +00002436 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002437 }
2438 }
2439 }
2440
Googler74558fc2016-05-06 21:47:42 +00002441 private static void checkAspectAllowedValues(
2442 Rule rule, EventHandler eventHandler) {
ulfjack5756b352020-01-23 04:53:22 -08002443 if (rule.hasAspects()) {
2444 for (Attribute attrOfRule : rule.getAttributes()) {
2445 for (Aspect aspect : attrOfRule.getAspects(rule)) {
2446 for (Attribute attrOfAspect : aspect.getDefinition().getAttributes().values()) {
2447 // By this point the AspectDefinition has been created and values assigned.
2448 if (attrOfAspect.checkAllowedValues()) {
2449 PredicateWithMessage<Object> allowedValues = attrOfAspect.getAllowedValues();
2450 Object value = attrOfAspect.getDefaultValue(rule);
2451 if (!allowedValues.apply(value)) {
2452 if (RawAttributeMapper.of(rule).isConfigurable(attrOfAspect.getName())) {
2453 rule.reportError(
2454 String.format(
2455 "%s: attribute '%s' has a select() and aspect %s also declares "
2456 + "'%s'. Aspect attributes don't currently support select().",
2457 rule.getLabel(),
2458 attrOfAspect.getName(),
2459 aspect.getDefinition().getName(),
2460 rule.getLabel()),
2461 eventHandler);
2462 } else {
2463 rule.reportError(
2464 String.format(
2465 "%s: invalid value in '%s' attribute: %s",
2466 rule.getLabel(),
2467 attrOfAspect.getName(),
2468 allowedValues.getErrorReason(value)),
2469 eventHandler);
2470 }
gregce7deab0a2019-03-11 12:20:05 -07002471 }
Googler74558fc2016-05-06 21:47:42 +00002472 }
2473 }
2474 }
2475 }
2476 }
2477 }
2478
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002479 @Override
2480 public String toString() {
2481 return name;
2482 }
2483
2484 public boolean isDocumented() {
2485 return documented;
2486 }
2487
2488 public boolean isPublicByDefault() {
2489 return publicByDefault;
2490 }
2491
2492 /**
2493 * Returns true iff the outputs of this rule should be created beneath the
2494 * <i>bin</i> directory, false if beneath <i>genfiles</i>. For most rule
2495 * classes, this is a constant, but for genrule, it is a property of the
2496 * individual rule instance, derived from the 'output_to_bindir' attribute;
2497 * see Rule.hasBinaryOutput().
2498 */
Laurent Le Brunc2efe452015-04-08 16:27:21 +00002499 @VisibleForTesting
2500 public boolean hasBinaryOutput() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002501 return binaryOutput;
2502 }
2503
adonovanf3a344e82019-12-11 11:10:11 -08002504 /** Returns this RuleClass's custom Skylark rule implementation. */
2505 @Nullable
2506 public StarlarkFunction getConfiguredTargetFunction() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002507 return configuredTargetFunction;
2508 }
2509
juliexxia1f332e02018-10-31 14:20:55 -07002510 @Nullable
2511 public BuildSetting getBuildSetting() {
2512 return buildSetting;
2513 }
2514
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002515 /**
Lukacs Berki0e1a9942015-06-18 08:53:18 +00002516 * Returns a function that computes the external bindings a repository function contributes to
2517 * the WORKSPACE file.
2518 */
2519 public Function<? super Rule, Map<String, Label>> getExternalBindingsFunction() {
2520 return externalBindingsFunction;
2521 }
2522
2523 /**
mstaibe5538ad2017-04-04 18:32:23 +00002524 * Returns a function that computes the options referenced by a rule.
2525 */
2526 public Function<? super Rule, ? extends Set<String>> getOptionReferenceFunction() {
2527 return optionReferenceFunction;
2528 }
2529
2530 /**
janakrd3fe5e72018-03-30 12:49:12 -07002531 * For Skylark rule classes, returns this RuleClass's rule definition environment's label, which
2532 * is never null. Is null for native rules' RuleClass objects.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002533 */
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00002534 @Nullable
janakrd3fe5e72018-03-30 12:49:12 -07002535 public Label getRuleDefinitionEnvironmentLabel() {
2536 return ruleDefinitionEnvironmentLabel;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002537 }
2538
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00002539 /**
janakrd3fe5e72018-03-30 12:49:12 -07002540 * Returns the hash code for the RuleClass's rule definition environment. Will be null for native
2541 * rules' RuleClass objects.
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00002542 */
2543 @Nullable
2544 public String getRuleDefinitionEnvironmentHashCode() {
2545 return ruleDefinitionEnvironmentHashCode;
2546 }
2547
Jon Brandveinead58ae2016-09-29 18:41:10 +00002548 /** Returns true if this RuleClass is a Skylark-defined RuleClass. */
Michajlo Matijkiwbc042c62015-10-29 13:22:52 +00002549 public boolean isSkylark() {
2550 return isSkylark;
2551 }
2552
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002553 /**
Jon Brandveinead58ae2016-09-29 18:41:10 +00002554 * Returns true if this RuleClass is Skylark-defined and is subject to analysis-time
2555 * tests.
2556 */
2557 public boolean isSkylarkTestable() {
2558 return skylarkTestable;
2559 }
2560
2561 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002562 * Returns true if this rule class outputs a default executable for every rule.
2563 */
dslomov2ce98442017-10-23 19:14:02 +02002564 public boolean isExecutableSkylark() {
2565 return isExecutableSkylark;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002566 }
Brian Silvermand7d6d622016-03-17 09:53:39 +00002567
cparsons55781c92018-10-17 12:03:08 -07002568 /** Returns true if this rule class is an analysis test (set by analysis_test = true). */
2569 public boolean isAnalysisTest() {
2570 return isAnalysisTest;
2571 }
2572
Googlerc2200fd2018-09-14 17:35:59 -07002573 /**
cparsons9d40c6b2019-02-25 12:24:40 -08002574 * Returns true if this rule class has at least one attribute with an analysis test transition. (A
2575 * starlark-defined transition using analysis_test_transition()).
2576 */
2577 public boolean hasAnalysisTestTransition() {
2578 return hasAnalysisTestTransition;
2579 }
2580
2581 /**
Googlerc2200fd2018-09-14 17:35:59 -07002582 * Returns true if this rule class has the _whitelist_function_transition attribute.
2583 */
2584 public boolean hasFunctionTransitionWhitelist() {
2585 return hasFunctionTransitionWhitelist;
2586 }
2587
gregce1d8d6dd2019-04-10 09:27:34 -07002588 /**
2589 * If true, no rule of this class ever declares a license regardless of what the rule's or
2590 * package's <code>licenses</code> attribute says.
2591 *
2592 * <p>This is useful for rule types that don't make sense for license checking.
2593 */
2594 public boolean ignoreLicenses() {
2595 return ignoreLicenses;
Googlerfdb17eb2019-01-28 15:14:32 -08002596 }
2597
cpeyserfb829992017-09-07 17:17:03 +02002598 public ImmutableSet<Label> getRequiredToolchains() {
John Catereca28402017-05-17 21:44:12 +02002599 return requiredToolchains;
2600 }
2601
jcater01bb1f92019-06-17 12:09:11 -07002602 public boolean useToolchainResolution() {
2603 return useToolchainResolution;
John Cater856b4dd2017-11-21 08:06:16 -08002604 }
2605
John Cateree45c662018-06-05 11:09:01 -07002606 public ImmutableSet<Label> getExecutionPlatformConstraints() {
2607 return executionPlatformConstraints;
2608 }
2609
juliexxia693048d2020-04-01 06:41:42 -07002610 public ImmutableMap<String, ExecGroup> getExecGroups() {
2611 return execGroups;
2612 }
2613
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -07002614 public OutputFile.Kind getOutputFileKind() {
2615 return outputFileKind;
2616 }
2617
Brian Silvermand7d6d622016-03-17 09:53:39 +00002618 public static boolean isThirdPartyPackage(PackageIdentifier packageIdentifier) {
2619 if (!packageIdentifier.getRepository().isMain()) {
2620 return false;
2621 }
2622
2623 if (!packageIdentifier.getPackageFragment().startsWith(THIRD_PARTY_PREFIX)) {
2624 return false;
2625 }
2626
2627 if (packageIdentifier.getPackageFragment().segmentCount() <= 1) {
2628 return false;
2629 }
2630
2631 return true;
2632 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002633}