blob: 8ca63fc6f73018121ce1581661f27a2d8b72a42f [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;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010034import com.google.common.collect.Ordering;
gregcebe55e112018-01-30 11:04:53 -080035import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition;
mstaib860975a2018-04-26 15:00:52 -070036import com.google.devtools.build.lib.analysis.config.transitions.PatchTransition;
gregce74a895d2018-05-29 11:26:03 -070037import com.google.devtools.build.lib.analysis.config.transitions.SplitTransition;
John Caterb3b3e8b2019-04-03 09:18:42 -070038import com.google.devtools.build.lib.analysis.config.transitions.TransitionFactory;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000039import com.google.devtools.build.lib.cmdline.Label;
Lukacs Berkia6434362015-09-15 13:56:14 +000040import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
Brian Silvermand7d6d622016-03-17 09:53:39 +000041import com.google.devtools.build.lib.cmdline.PackageIdentifier;
dannarkf24479d2018-06-21 11:55:44 -070042import com.google.devtools.build.lib.cmdline.RepositoryName;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010043import com.google.devtools.build.lib.events.EventHandler;
44import com.google.devtools.build.lib.events.Location;
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;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010058import com.google.devtools.build.lib.syntax.Argument;
Francois-Rene Rideau95b0d0c2015-04-22 16:52:13 +000059import com.google.devtools.build.lib.syntax.BaseFunction;
Yue Gan36a26572016-05-25 11:48:10 +000060import com.google.devtools.build.lib.syntax.EvalException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010061import com.google.devtools.build.lib.syntax.FuncallExpression;
Francois-Rene Rideau0f7ba342015-08-31 16:16:21 +000062import com.google.devtools.build.lib.syntax.Runtime;
Francois-Rene Rideau93ed7f12015-10-20 15:39:33 +000063import com.google.devtools.build.lib.syntax.SkylarkList;
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
janakrd3fe5e72018-03-30 12:49:12 -0700127 @AutoCodec
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000128 static final Function<? super Rule, Map<String, Label>> NO_EXTERNAL_BINDINGS =
129 Functions.<Map<String, Label>>constant(ImmutableMap.<String, Label>of());
janakrd3fe5e72018-03-30 12:49:12 -0700130
131 @AutoCodec
mstaibe5538ad2017-04-04 18:32:23 +0000132 static final Function<? super Rule, Set<String>> NO_OPTION_REFERENCE =
133 Functions.<Set<String>>constant(ImmutableSet.<String>of());
Brian Silvermand7d6d622016-03-17 09:53:39 +0000134
nharmatab4060b62017-04-04 17:11:39 +0000135 public static final PathFragment THIRD_PARTY_PREFIX = PathFragment.create("third_party");
Googler9ad95082019-05-13 13:38:22 -0700136 public static final PathFragment EXPERIMENTAL_PREFIX = PathFragment.create("experimental");
John Caterae6f7d52019-04-12 10:42:59 -0700137 public static final String EXEC_COMPATIBLE_WITH_ATTR = "exec_compatible_with";
Googlerb5082462019-08-26 14:28:09 -0700138 public static final String EXEC_PROPERTIES = "exec_properties";
Brian Silvermand7d6d622016-03-17 09:53:39 +0000139
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100140 /**
141 * A constraint for the package name of the Rule instances.
142 */
143 public static class PackageNameConstraint implements PredicateWithMessage<Rule> {
144
145 public static final int ANY_SEGMENT = 0;
146
147 private final int pathSegment;
148
149 private final Set<String> values;
150
151 /**
152 * The pathSegment-th segment of the package must be one of the specified values.
153 * The path segment indexing starts from 1.
154 */
155 public PackageNameConstraint(int pathSegment, String... values) {
156 this.values = ImmutableSet.copyOf(values);
157 this.pathSegment = pathSegment;
158 }
159
160 @Override
161 public boolean apply(Rule input) {
162 PathFragment path = input.getLabel().getPackageFragment();
163 if (pathSegment == ANY_SEGMENT) {
164 return path.getFirstSegment(values) != PathFragment.INVALID_SEGMENT;
165 } else {
166 return path.segmentCount() >= pathSegment
167 && values.contains(path.getSegment(pathSegment - 1));
168 }
169 }
170
171 @Override
172 public String getErrorReason(Rule param) {
173 if (pathSegment == ANY_SEGMENT) {
Francois-Rene Rideaucbebd632015-02-11 16:56:37 +0000174 return param.getRuleClass() + " rules have to be under a "
175 + StringUtil.joinEnglishList(values, "or", "'") + " directory";
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100176 } else if (pathSegment == 1) {
177 return param.getRuleClass() + " rules are only allowed in "
178 + StringUtil.joinEnglishList(StringUtil.append(values, "//", ""), "or");
179 } else {
Francois-Rene Rideaucbebd632015-02-11 16:56:37 +0000180 return param.getRuleClass() + " rules are only allowed in packages which "
181 + StringUtil.ordinal(pathSegment) + " is " + StringUtil.joinEnglishList(values, "or");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100182 }
183 }
184
185 @VisibleForTesting
186 public int getPathSegment() {
187 return pathSegment;
188 }
189
190 @VisibleForTesting
191 public Collection<String> getValues() {
192 return values;
193 }
194 }
195
cparsonse2d200f2018-03-06 16:15:11 -0800196 /** A factory or builder class for rule implementations. */
197 public interface ConfiguredTargetFactory<
198 TConfiguredTarget, TContext, TActionConflictException extends Throwable> {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100199 /**
200 * Returns a fully initialized configured target instance using the given context.
Chris Parsons4dfb22c2016-05-23 17:39:42 +0000201 *
202 * @throws RuleErrorException if configured target creation could not be completed due to rule
cparsonse2d200f2018-03-06 16:15:11 -0800203 * errors
204 * @throws TActionConflictException if there were conflicts during action registration
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100205 */
cparsonse2d200f2018-03-06 16:15:11 -0800206 TConfiguredTarget create(TContext ruleContext)
207 throws InterruptedException, RuleErrorException, TActionConflictException;
Chris Parsons4dfb22c2016-05-23 17:39:42 +0000208
209 /**
cparsonse2d200f2018-03-06 16:15:11 -0800210 * Exception indicating that configured target creation could not be completed. General error
211 * messaging should be done via {@link RuleErrorConsumer}; this exception only interrupts
212 * configured target creation in cases where it can no longer continue.
Chris Parsons4dfb22c2016-05-23 17:39:42 +0000213 */
Benjamin Petersonaf53a112019-06-05 10:47:11 -0700214 public static final class RuleErrorException extends Exception {
215 public RuleErrorException() {
216 super();
217 }
218
219 public RuleErrorException(String message) {
220 super(message);
221 }
222 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100223 }
224
225 /**
John Cateree45c662018-06-05 11:09:01 -0700226 * Describes in which way a rule implementation allows additional execution platform constraints.
227 */
228 public enum ExecutionPlatformConstraintsAllowed {
229 /**
230 * Allows additional execution platform constraints to be added in the rule definition, which
231 * apply to all targets of that rule.
232 */
jcater01cc4792018-06-12 11:19:00 -0700233 PER_RULE(1),
John Cateree45c662018-06-05 11:09:01 -0700234 /**
235 * Users are allowed to specify additional execution platform constraints for each target, using
236 * the 'exec_compatible_with' attribute. This also allows setting constraints in the rule
237 * definition, like PER_RULE.
238 */
jcater01cc4792018-06-12 11:19:00 -0700239 PER_TARGET(2);
240
241 private final int priority;
242
243 ExecutionPlatformConstraintsAllowed(int priority) {
244 this.priority = priority;
245 }
246
247 public int priority() {
248 return priority;
249 }
250
251 public static ExecutionPlatformConstraintsAllowed highestPriority(
252 ExecutionPlatformConstraintsAllowed first, ExecutionPlatformConstraintsAllowed... rest) {
253 ExecutionPlatformConstraintsAllowed result = first;
254 for (ExecutionPlatformConstraintsAllowed value : rest) {
255 if (result == null || result.priority() < value.priority()) {
256 result = value;
257 }
258 }
259 return result;
260 }
John Cateree45c662018-06-05 11:09:01 -0700261 }
262
263 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100264 * For Bazel's constraint system: the attribute that declares the set of environments a rule
265 * supports, overriding the defaults for their respective groups.
266 */
267 public static final String RESTRICTED_ENVIRONMENT_ATTR = "restricted_to";
268
269 /**
270 * For Bazel's constraint system: the attribute that declares the set of environments a rule
271 * supports, appending them to the defaults for their respective groups.
272 */
273 public static final String COMPATIBLE_ENVIRONMENT_ATTR = "compatible_with";
274
275 /**
276 * For Bazel's constraint system: the implicit attribute used to store rule class restriction
277 * defaults as specified by {@link Builder#restrictedTo}.
278 */
279 public static final String DEFAULT_RESTRICTED_ENVIRONMENT_ATTR =
280 "$" + RESTRICTED_ENVIRONMENT_ATTR;
281
282 /**
283 * For Bazel's constraint system: the implicit attribute used to store rule class compatibility
284 * defaults as specified by {@link Builder#compatibleWith}.
285 */
286 public static final String DEFAULT_COMPATIBLE_ENVIRONMENT_ATTR =
287 "$" + COMPATIBLE_ENVIRONMENT_ATTR;
288
289 /**
gregce749962a2019-03-08 12:47:34 -0800290 * Name of the attribute that stores all {@link
291 * com.google.devtools.build.lib.rules.config.ConfigRuleClasses} labels this rule references (i.e.
292 * select() keys). This is specially populated in {@link #populateRuleAttributeValues}.
293 *
294 * <p>This isn't technically necessary for builds: select() keys are evaluated in {@link
295 * com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction#getConfigConditions} instead of
296 * normal dependency resolution because they're needed to determine other dependencies. So there's
297 * no intrinsic reason why we need an extra attribute to store them.
298 *
299 * <p>There are three reasons why we still create this attribute:
300 *
301 * <ol>
302 * <li>Collecting them once in {@link #populateRuleAttributeValues} instead of multiple times in
303 * ConfiguredTargetFunction saves extra looping over the rule's attributes.
304 * <li>Query's dependency resolution has no equivalent of {@link
305 * com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction#getConfigConditions} and
306 * we need to make sure its coverage remains complete.
307 * <li>Manual configuration trimming uses the normal dependency resolution process to work
308 * correctly and config_setting keys are subject to this trimming.
309 * </ol>
310 *
311 * <p>It should be possible to clean up these issues if we decide we don't want an artificial
312 * attribute dependency. But care has to be taken to do that safely.
313 */
314 public static final String CONFIG_SETTING_DEPS_ATTRIBUTE = "$config_dependencies";
315
316 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100317 * A support class to make it easier to create {@code RuleClass} instances.
318 * This class follows the 'fluent builder' pattern.
319 *
320 * <p>The {@link #addAttribute} method will throw an exception if an attribute
321 * of that name already exists. Use {@link #overrideAttribute} in that case.
322 */
323 public static final class Builder {
Laurent Le Brun6ce51e12015-07-07 11:54:41 +0000324 private static final Pattern RULE_NAME_PATTERN = Pattern.compile("[A-Za-z_][A-Za-z0-9_]*");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100325
326 /**
327 * The type of the rule class, which determines valid names and required
328 * attributes.
329 */
330 public enum RuleClassType {
331 /**
332 * Abstract rules are intended for rule classes that are just used to
333 * factor out common attributes, and for rule classes that are used only
334 * internally. These rules cannot be instantiated by a BUILD file.
335 *
336 * <p>The rule name must contain a '$' and {@link
337 * TargetUtils#isTestRuleName} must return false for the name.
338 */
339 ABSTRACT {
340 @Override
341 public void checkName(String name) {
342 Preconditions.checkArgument(
Ulf Adams07dba942015-03-05 14:47:37 +0000343 (name.contains("$") && !TargetUtils.isTestRuleName(name)) || name.isEmpty());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100344 }
345
346 @Override
347 public void checkAttributes(Map<String, Attribute> attributes) {
348 // No required attributes.
349 }
350 },
351
352 /**
353 * Invisible rule classes should contain a dollar sign so that they cannot be instantiated
354 * by the user. They are different from abstract rules in that they can be instantiated
355 * at will.
356 */
357 INVISIBLE {
358 @Override
359 public void checkName(String name) {
360 Preconditions.checkArgument(name.contains("$"));
361 }
362
363 @Override
364 public void checkAttributes(Map<String, Attribute> attributes) {
365 // No required attributes.
366 }
367 },
368
369 /**
370 * Normal rules are instantiable by BUILD files. Their names must therefore
371 * obey the rules for identifiers in the BUILD language. In addition,
372 * {@link TargetUtils#isTestRuleName} must return false for the name.
373 */
374 NORMAL {
375 @Override
376 public void checkName(String name) {
Ulf Adams07dba942015-03-05 14:47:37 +0000377 Preconditions.checkArgument(
378 !TargetUtils.isTestRuleName(name) && RULE_NAME_PATTERN.matcher(name).matches(),
379 "Invalid rule name: %s", name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100380 }
381
382 @Override
383 public void checkAttributes(Map<String, Attribute> attributes) {
384 for (Attribute attribute : REQUIRED_ATTRIBUTES_FOR_NORMAL_RULES) {
385 Attribute presentAttribute = attributes.get(attribute.getName());
386 Preconditions.checkState(presentAttribute != null,
387 "Missing mandatory '%s' attribute in normal rule class.", attribute.getName());
388 Preconditions.checkState(presentAttribute.getType().equals(attribute.getType()),
Francois-Rene Rideaucbebd632015-02-11 16:56:37 +0000389 "Mandatory attribute '%s' in normal rule class has incorrect type (expected"
390 + " %s).", attribute.getName(), attribute.getType());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100391 }
392 }
393 },
394
395 /**
396 * Workspace rules can only be instantiated from a WORKSPACE file. Their names obey the
397 * rule for identifiers.
398 */
399 WORKSPACE {
400 @Override
401 public void checkName(String name) {
402 Preconditions.checkArgument(RULE_NAME_PATTERN.matcher(name).matches());
403 }
404
405 @Override
406 public void checkAttributes(Map<String, Attribute> attributes) {
407 // No required attributes.
408 }
409 },
410
411 /**
412 * Test rules are instantiable by BUILD files and are handled specially
413 * when run with the 'test' command. Their names must obey the rules
414 * for identifiers in the BUILD language and {@link
415 * TargetUtils#isTestRuleName} must return true for the name.
416 *
417 * <p>In addition, test rules must contain certain attributes. See {@link
418 * Builder#REQUIRED_ATTRIBUTES_FOR_TESTS}.
419 */
420 TEST {
421 @Override
422 public void checkName(String name) {
423 Preconditions.checkArgument(TargetUtils.isTestRuleName(name)
424 && RULE_NAME_PATTERN.matcher(name).matches());
425 }
426
427 @Override
428 public void checkAttributes(Map<String, Attribute> attributes) {
429 for (Attribute attribute : REQUIRED_ATTRIBUTES_FOR_TESTS) {
430 Attribute presentAttribute = attributes.get(attribute.getName());
431 Preconditions.checkState(presentAttribute != null,
432 "Missing mandatory '%s' attribute in test rule class.", attribute.getName());
433 Preconditions.checkState(presentAttribute.getType().equals(attribute.getType()),
Googleraa437e02017-09-14 09:52:47 +0200434 "Mandatory attribute '%s' in test rule class has incorrect type (expected %s).",
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100435 attribute.getName(), attribute.getType());
436 }
437 }
Mark Schaller4fa83ac2015-07-10 16:59:37 +0000438 },
439
440 /**
441 * Placeholder rules are only instantiated when packages which refer to non-native rule
442 * classes are deserialized. At this time, non-native rule classes can't be serialized. To
443 * prevent crashes on deserialization, when a package containing a rule with a non-native rule
444 * class is deserialized, the rule is assigned a placeholder rule class. This is compatible
445 * with our limited set of package serialization use cases.
446 *
447 * Placeholder rule class names obey the rule for identifiers.
448 */
449 PLACEHOLDER {
450 @Override
451 public void checkName(String name) {
452 Preconditions.checkArgument(RULE_NAME_PATTERN.matcher(name).matches(), name);
453 }
454
455 @Override
456 public void checkAttributes(Map<String, Attribute> attributes) {
457 // No required attributes; this rule class cannot have the wrong set of attributes now
458 // because, if it did, the rule class would have failed to build before the package
459 // referring to it was serialized.
460 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100461 };
462
463 /**
464 * Checks whether the given name is valid for the current rule class type.
465 *
466 * @throws IllegalArgumentException if the name is not valid
467 */
468 public abstract void checkName(String name);
469
470 /**
471 * Checks whether the given set of attributes contains all the required
472 * attributes for the current rule class type.
473 *
474 * @throws IllegalArgumentException if a required attribute is missing
475 */
476 public abstract void checkAttributes(Map<String, Attribute> attributes);
477 }
478
Googler72f3a102017-12-01 16:28:28 -0800479 /** A predicate that filters rule classes based on their names. */
mjhalupka49581922018-02-28 11:04:31 -0800480 @AutoCodec
Googler72f3a102017-12-01 16:28:28 -0800481 public static class RuleClassNamePredicate {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100482
mjhalupka49581922018-02-28 11:04:31 -0800483 private static final RuleClassNamePredicate UNSPECIFIED_INSTANCE =
484 new RuleClassNamePredicate(ImmutableSet.of(), PredicateType.UNSPECIFIED, null);
485
486 private final ImmutableSet<String> ruleClassNames;
487
488 private final PredicateType predicateType;
489
Googler72f3a102017-12-01 16:28:28 -0800490 private final Predicate<String> ruleClassNamePredicate;
491 private final Predicate<RuleClass> ruleClassPredicate;
492 // if non-null, used ONLY for checking overlap
493 @Nullable private final Set<?> overlappable;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100494
mjhalupka49581922018-02-28 11:04:31 -0800495 @VisibleForSerialization
496 enum PredicateType {
497 ONLY,
498 All_EXCEPT,
499 UNSPECIFIED
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100500 }
501
mjhalupka49581922018-02-28 11:04:31 -0800502 @VisibleForSerialization
503 RuleClassNamePredicate(
504 ImmutableSet<String> ruleClassNames, PredicateType predicateType, Set<?> overlappable) {
505 this.ruleClassNames = ruleClassNames;
506 this.predicateType = predicateType;
Googler72f3a102017-12-01 16:28:28 -0800507 this.overlappable = overlappable;
mjhalupka49581922018-02-28 11:04:31 -0800508
509 switch (predicateType) {
510 case All_EXCEPT:
511 Predicate<String> containing = only(ruleClassNames).asPredicateOfRuleClassName();
512 ruleClassNamePredicate =
513 new DescribedPredicate<>(
514 Predicates.not(containing), "all but " + containing.toString());
515 ruleClassPredicate =
516 new DescribedPredicate<>(
517 Predicates.compose(ruleClassNamePredicate, RuleClass::getName),
518 ruleClassNamePredicate.toString());
519 break;
520 case ONLY:
521 ruleClassNamePredicate =
522 new DescribedPredicate<>(
523 Predicates.in(ruleClassNames), StringUtil.joinEnglishList(ruleClassNames));
524 ruleClassPredicate =
525 new DescribedPredicate<>(
526 Predicates.compose(ruleClassNamePredicate, RuleClass::getName),
527 ruleClassNamePredicate.toString());
528 break;
529 case UNSPECIFIED:
530 ruleClassNamePredicate = Predicates.alwaysTrue();
531 ruleClassPredicate = Predicates.alwaysTrue();
532 break;
533 default:
534 // This shouldn't happen normally since the constructor is private and within this file.
535 throw new IllegalArgumentException(
536 "Predicate type was not specified when constructing a RuleClassNamePredicate.");
537 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100538 }
539
Googler72f3a102017-12-01 16:28:28 -0800540 public static RuleClassNamePredicate only(Iterable<String> ruleClassNamesAsIterable) {
541 ImmutableSet<String> ruleClassNames = ImmutableSet.copyOf(ruleClassNamesAsIterable);
mjhalupka49581922018-02-28 11:04:31 -0800542 return new RuleClassNamePredicate(ruleClassNames, PredicateType.ONLY, ruleClassNames);
Googler72f3a102017-12-01 16:28:28 -0800543 }
544
545 public static RuleClassNamePredicate only(String... ruleClasses) {
546 return only(Arrays.asList(ruleClasses));
547 }
548
549 public static RuleClassNamePredicate allExcept(String... ruleClasses) {
550 ImmutableSet<String> ruleClassNames = ImmutableSet.copyOf(ruleClasses);
551 Preconditions.checkState(!ruleClassNames.isEmpty(), "Use unspecified() instead");
mjhalupka49581922018-02-28 11:04:31 -0800552 return new RuleClassNamePredicate(ruleClassNames, PredicateType.All_EXCEPT, null);
Googler72f3a102017-12-01 16:28:28 -0800553 }
554
555 /**
556 * This is a special sentinel value which represents a "default" {@link
557 * RuleClassNamePredicate} which is unspecified. Note that a call to its {@link
558 * RuleClassNamePredicate#asPredicateOfRuleClass} produces {@code
559 * Predicates.<RuleClass>alwaysTrue()}, which is a sentinel value for other parts of bazel.
560 */
561 public static RuleClassNamePredicate unspecified() {
mjhalupka49581922018-02-28 11:04:31 -0800562 return UNSPECIFIED_INSTANCE;
Googler72f3a102017-12-01 16:28:28 -0800563 }
564
565 public final Predicate<String> asPredicateOfRuleClassName() {
566 return ruleClassNamePredicate;
567 }
568
569 public final Predicate<RuleClass> asPredicateOfRuleClass() {
570 return ruleClassPredicate;
571 }
572
573 /**
574 * Determines whether two {@code RuleClassNamePredicate}s should be considered incompatible as
575 * rule class predicate and rule class warning predicate.
576 *
577 * <p>Specifically, if both list sets of explicit rule class names to permit, those two sets
578 * must be disjoint, so the restriction only applies when both predicates have been created by
579 * {@link #only}.
580 */
581 boolean consideredOverlapping(RuleClassNamePredicate that) {
582 return this.overlappable != null
583 && that.overlappable != null
584 && !Collections.disjoint(this.overlappable, that.overlappable);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100585 }
586
587 @Override
588 public int hashCode() {
mjhalupka49581922018-02-28 11:04:31 -0800589 return Objects.hash(ruleClassNames, predicateType);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100590 }
591
592 @Override
Googler72f3a102017-12-01 16:28:28 -0800593 public boolean equals(Object obj) {
594 // NOTE: Specifically not checking equality of ruleClassPredicate.
595 // By construction, if the name predicates are equals, the rule class predicates are, too.
596 return obj instanceof RuleClassNamePredicate
mjhalupka49581922018-02-28 11:04:31 -0800597 && ruleClassNames.equals(((RuleClassNamePredicate) obj).ruleClassNames)
598 && predicateType.equals(((RuleClassNamePredicate) obj).predicateType);
gregceda4c9592017-07-27 22:09:34 +0200599 }
600
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100601 @Override
602 public String toString() {
Googler72f3a102017-12-01 16:28:28 -0800603 return ruleClassNamePredicate.toString();
604 }
605
606 /** A pass-through predicate, except that an explicit {@link #toString()} is provided. */
607 private static class DescribedPredicate<T> implements Predicate<T> {
608 private final Predicate<T> delegate; // the actual predicate
609 private final String description;
610
611 private DescribedPredicate(Predicate<T> delegate, String description) {
612 this.delegate = delegate;
613 this.description = description;
614 }
615
616 @Override
617 public boolean apply(T input) {
618 return delegate.apply(input);
619 }
620
621 @Override
622 public int hashCode() {
623 return delegate.hashCode();
624 }
625
626 @Override
627 public boolean equals(Object obj) {
628 return obj instanceof DescribedPredicate
629 && delegate.equals(((DescribedPredicate<?>) obj).delegate);
630 }
631
632 @Override
633 public String toString() {
634 return description;
635 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100636 }
637 }
638
juliexxia1f332e02018-10-31 14:20:55 -0700639 /**
640 * Name of default attribute implicitly added to all Skylark RuleClasses that are {@code
641 * build_setting}s.
642 */
643 public static final String SKYLARK_BUILD_SETTING_DEFAULT_ATTR_NAME = "build_setting_default";
644
juliexxia44cd3a62018-12-19 11:57:16 -0800645 public static final String BUILD_SETTING_DEFAULT_NONCONFIGURABLE =
646 "Build setting defaults are referenced during analysis.";
647
Googler7807b6c2017-03-14 10:57:43 +0000648 /** List of required attributes for normal rules, name and type. */
649 public static final ImmutableList<Attribute> REQUIRED_ATTRIBUTES_FOR_NORMAL_RULES =
650 ImmutableList.of(attr("tags", Type.STRING_LIST).build());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100651
Googler7807b6c2017-03-14 10:57:43 +0000652 /** List of required attributes for test rules, name and type. */
653 public static final ImmutableList<Attribute> REQUIRED_ATTRIBUTES_FOR_TESTS =
654 ImmutableList.of(
655 attr("tags", Type.STRING_LIST).build(),
656 attr("size", Type.STRING).build(),
657 attr("timeout", Type.STRING).build(),
658 attr("flaky", Type.BOOLEAN).build(),
659 attr("shard_count", Type.INTEGER).build(),
660 attr("local", Type.BOOLEAN).build());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100661
662 private String name;
663 private final RuleClassType type;
664 private final boolean skylark;
Jon Brandveinead58ae2016-09-29 18:41:10 +0000665 private boolean skylarkTestable = false;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100666 private boolean documented;
667 private boolean publicByDefault = false;
668 private boolean binaryOutput = true;
669 private boolean workspaceOnly = false;
dslomov2ce98442017-10-23 19:14:02 +0200670 private boolean isExecutableSkylark = false;
cparsons55781c92018-10-17 12:03:08 -0700671 private boolean isAnalysisTest = false;
cparsons9d40c6b2019-02-25 12:24:40 -0800672 private boolean hasAnalysisTestTransition = false;
Googlerc2200fd2018-09-14 17:35:59 -0700673 private boolean hasFunctionTransitionWhitelist = false;
juliexxia30976d82019-03-12 10:59:26 -0700674 private boolean hasStarlarkRuleTransition = false;
gregce1d8d6dd2019-04-10 09:27:34 -0700675 private boolean ignoreLicenses = false;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100676 private ImplicitOutputsFunction implicitOutputsFunction = ImplicitOutputsFunction.NONE;
John Caterb3b3e8b2019-04-03 09:18:42 -0700677 private TransitionFactory<Rule> transitionFactory;
cparsonse2d200f2018-03-06 16:15:11 -0800678 private ConfiguredTargetFactory<?, ?, ?> configuredTargetFactory = null;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100679 private PredicateWithMessage<Rule> validityPredicate =
680 PredicatesWithMessage.<Rule>alwaysTrue();
681 private Predicate<String> preferredDependencyPredicate = Predicates.alwaysFalse();
Dmitry Lomovb91d3922017-01-09 20:12:57 +0000682 private AdvertisedProviderSet.Builder advertisedProviders = AdvertisedProviderSet.builder();
Francois-Rene Rideau95b0d0c2015-04-22 16:52:13 +0000683 private BaseFunction configuredTargetFunction = null;
juliexxia1f332e02018-10-31 14:20:55 -0700684 private BuildSetting buildSetting = null;
Lukacs Berki0e1a9942015-06-18 08:53:18 +0000685 private Function<? super Rule, Map<String, Label>> externalBindingsFunction =
686 NO_EXTERNAL_BINDINGS;
mstaibe5538ad2017-04-04 18:32:23 +0000687 private Function<? super Rule, ? extends Set<String>> optionReferenceFunction =
688 NO_OPTION_REFERENCE;
janakrd3fe5e72018-03-30 12:49:12 -0700689 /** This field and the next are null iff the rule is native. */
690 @Nullable private Label ruleDefinitionEnvironmentLabel;
691
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000692 @Nullable private String ruleDefinitionEnvironmentHashCode = null;
Michael Staibb51251e2015-09-29 23:31:51 +0000693 private ConfigurationFragmentPolicy.Builder configurationFragmentPolicy =
694 new ConfigurationFragmentPolicy.Builder();
Florian Weikert3f53fbb2015-08-07 22:25:50 +0000695
Greg Estrenc04c88f2015-03-06 19:45:50 +0000696 private boolean supportsConstraintChecking = true;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100697
gregce4aa059a2019-02-26 13:20:47 -0800698 /**
699 * The policy on whether Bazel should enforce that third_party rules declare <code>licenses().
700 * </code>. This is only intended for the migration of <a
701 * href="https://github.com/bazelbuild/bazel/issues/7444">GitHub #7444</a>. Our final end state
702 * is to have no license-related logic whatsoever. But that's going to take some time.
703 */
704 public enum ThirdPartyLicenseExistencePolicy {
705 /**
706 * Always do this check, overriding whatever {@link
gregce3f6da0a2019-04-04 09:40:07 -0700707 * StarlarkSemanticsOptions#incompatibleDisableThirdPartyLicenseChecking} says.
gregce4aa059a2019-02-26 13:20:47 -0800708 */
709 ALWAYS_CHECK,
710
711 /**
712 * Never do this check, overriding whatever {@link
gregce3f6da0a2019-04-04 09:40:07 -0700713 * StarlarkSemanticsOptions#incompatibleDisableThirdPartyLicenseChecking} says.
gregce4aa059a2019-02-26 13:20:47 -0800714 */
715 NEVER_CHECK,
716
gregce3f6da0a2019-04-04 09:40:07 -0700717 /**
718 * Do whatever {@link StarlarkSemanticsOptions#incompatibleDisableThirdPartyLicenseChecking}
719 * says.
720 */
gregce4aa059a2019-02-26 13:20:47 -0800721 USER_CONTROLLABLE
722 }
723
724 private ThirdPartyLicenseExistencePolicy thirdPartyLicenseExistencePolicy;
725
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100726 private final Map<String, Attribute> attributes = new LinkedHashMap<>();
cpeyserfb829992017-09-07 17:17:03 +0200727 private final Set<Label> requiredToolchains = new HashSet<>();
jcater01bb1f92019-06-17 12:09:11 -0700728 private boolean useToolchainResolution = true;
John Cateree45c662018-06-05 11:09:01 -0700729 private ExecutionPlatformConstraintsAllowed executionPlatformConstraintsAllowed =
730 ExecutionPlatformConstraintsAllowed.PER_RULE;
731 private Set<Label> executionPlatformConstraints = new HashSet<>();
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -0700732 private OutputFile.Kind outputFileKind = OutputFile.Kind.FILE;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100733
734 /**
735 * Constructs a new {@code RuleClassBuilder} using all attributes from all
736 * parent rule classes. An attribute cannot exist in more than one parent.
737 *
gregce64c36e12017-07-26 23:48:56 +0200738 * <p>The rule type affects the allowed names and the required
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100739 * attributes (see {@link RuleClassType}).
740 *
741 * @throws IllegalArgumentException if an attribute with the same name exists
742 * in more than one parent
743 */
744 public Builder(String name, RuleClassType type, boolean skylark, RuleClass... parents) {
745 this.name = name;
746 this.skylark = skylark;
747 this.type = type;
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000748 Preconditions.checkState(skylark || type != RuleClassType.PLACEHOLDER, name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100749 this.documented = type != RuleClassType.ABSTRACT;
750 for (RuleClass parent : parents) {
751 if (parent.getValidityPredicate() != PredicatesWithMessage.<Rule>alwaysTrue()) {
752 setValidityPredicate(parent.getValidityPredicate());
753 }
754 if (parent.preferredDependencyPredicate != Predicates.<String>alwaysFalse()) {
755 setPreferredDependencyPredicate(parent.preferredDependencyPredicate);
756 }
Michael Staibff66c192016-01-14 22:40:37 +0000757 configurationFragmentPolicy
758 .includeConfigurationFragmentsFrom(parent.getConfigurationFragmentPolicy());
Michael Staibb51251e2015-09-29 23:31:51 +0000759 configurationFragmentPolicy.setMissingFragmentPolicy(
760 parent.getConfigurationFragmentPolicy().getMissingFragmentPolicy());
Greg Estrenc04c88f2015-03-06 19:45:50 +0000761 supportsConstraintChecking = parent.supportsConstraintChecking;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100762
cpeyserd78b3742017-08-04 19:48:53 +0200763 addRequiredToolchains(parent.getRequiredToolchains());
jcater01bb1f92019-06-17 12:09:11 -0700764 useToolchainResolution = parent.useToolchainResolution;
jcater01cc4792018-06-12 11:19:00 -0700765
766 // Make sure we use the highest priority value from all parents.
767 executionPlatformConstraintsAllowed(
768 ExecutionPlatformConstraintsAllowed.highestPriority(
769 executionPlatformConstraintsAllowed, parent.executionPlatformConstraintsAllowed()));
John Cateree45c662018-06-05 11:09:01 -0700770 addExecutionPlatformConstraints(parent.getExecutionPlatformConstraints());
cpeyserd78b3742017-08-04 19:48:53 +0200771
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100772 for (Attribute attribute : parent.getAttributes()) {
773 String attrName = attribute.getName();
John Catera0f88c02019-04-25 07:02:00 -0700774 // TODO(https://github.com/bazelbuild/bazel/issues/8134): Define the attribute on a
775 // standard base class and remove this check entirely.
776 if (attrName.equals(RuleClass.EXEC_COMPATIBLE_WITH_ATTR)) {
777 // Don't inherit: this will be re-created
778 continue;
779 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100780 Preconditions.checkArgument(
dannarke64a8162018-06-13 13:48:20 -0700781 !attributes.containsKey(attrName) || attributes.get(attrName).equals(attribute),
Googler2935d672015-03-12 01:25:11 +0000782 "Attribute %s is inherited multiple times in %s ruleclass",
783 attrName,
784 name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100785 attributes.put(attrName, attribute);
786 }
Lukacs Berkiac4f9422015-05-29 10:06:30 +0000787
Dmitry Lomovb91d3922017-01-09 20:12:57 +0000788 advertisedProviders.addParent(parent.getAdvertisedProviders());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100789 }
790 // TODO(bazel-team): move this testonly attribute setting to somewhere else
791 // preferably to some base RuleClass implementation.
792 if (this.type.equals(RuleClassType.TEST)) {
793 Attribute.Builder<Boolean> testOnlyAttr = attr("testonly", BOOLEAN).value(true)
794 .nonconfigurable("policy decision: this shouldn't depend on the configuration");
795 if (attributes.containsKey("testonly")) {
796 override(testOnlyAttr);
797 } else {
798 add(testOnlyAttr);
799 }
800 }
801 }
802
803 /**
804 * Checks that required attributes for test rules are present, creates the
805 * {@link RuleClass} object and returns it.
806 *
807 * @throws IllegalStateException if any of the required attributes is missing
808 */
809 public RuleClass build() {
tomlu72642a22017-10-18 06:23:14 +0200810 // For built-ins, name == key
811 return build(name, name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100812 }
813
tomlu72642a22017-10-18 06:23:14 +0200814 /** Same as {@link #build} except with setting the name and key parameters. */
815 public RuleClass build(String name, String key) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100816 Preconditions.checkArgument(this.name.isEmpty() || this.name.equals(name));
817 type.checkName(name);
818 type.checkAttributes(attributes);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100819 Preconditions.checkState(
820 (type == RuleClassType.ABSTRACT)
janakr6ff110e2018-03-21 21:44:27 -0700821 == (configuredTargetFactory == null && configuredTargetFunction == null),
822 "Bad combo for %s: %s %s %s",
823 name,
824 type,
825 configuredTargetFactory,
826 configuredTargetFunction);
Damien Martin-Guillerez653df882016-02-17 21:46:22 +0000827 if (!workspaceOnly) {
janakrd3fe5e72018-03-30 12:49:12 -0700828 if (skylark) {
829 assertSkylarkRuleClassHasImplementationFunction();
830 assertSkylarkRuleClassHasEnvironmentLabel();
831 }
Damien Martin-Guillerez653df882016-02-17 21:46:22 +0000832 Preconditions.checkState(externalBindingsFunction == NO_EXTERNAL_BINDINGS);
833 }
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000834 if (type == RuleClassType.PLACEHOLDER) {
835 Preconditions.checkNotNull(ruleDefinitionEnvironmentHashCode, this.name);
836 }
jcater5f292bb2018-06-19 14:14:34 -0700837 if (executionPlatformConstraintsAllowed == ExecutionPlatformConstraintsAllowed.PER_TARGET
John Caterae6f7d52019-04-12 10:42:59 -0700838 && !this.contains(EXEC_COMPATIBLE_WITH_ATTR)) {
John Cateree45c662018-06-05 11:09:01 -0700839 this.add(
John Caterae6f7d52019-04-12 10:42:59 -0700840 attr(EXEC_COMPATIBLE_WITH_ATTR, BuildType.LABEL_LIST)
John Cateree45c662018-06-05 11:09:01 -0700841 .allowedFileTypes()
842 .nonconfigurable("Used in toolchain resolution")
843 .value(ImmutableList.of()));
844 }
juliexxia1f332e02018-10-31 14:20:55 -0700845 if (buildSetting != null) {
846 Type<?> type = buildSetting.getType();
847 Attribute.Builder<?> attrBuilder =
848 attr(SKYLARK_BUILD_SETTING_DEFAULT_ATTR_NAME, type)
juliexxia44cd3a62018-12-19 11:57:16 -0800849 .nonconfigurable(BUILD_SETTING_DEFAULT_NONCONFIGURABLE)
juliexxia1f332e02018-10-31 14:20:55 -0700850 .mandatory();
851 if (BuildType.isLabelType(type)) {
852 attrBuilder.allowedFileTypes(FileTypeSet.ANY_FILE);
juliexxia44cd3a62018-12-19 11:57:16 -0800853 attrBuilder.allowedRuleClasses(ANY_RULE);
juliexxia1f332e02018-10-31 14:20:55 -0700854 }
855 this.add(attrBuilder);
John Catera6e3e872019-08-07 13:24:34 -0700856
857 // Build setting rules should opt out of toolchain resolution, since they form part of the
858 // configuration.
859 this.useToolchainResolution(false);
juliexxia1f332e02018-10-31 14:20:55 -0700860 }
John Cateree45c662018-06-05 11:09:01 -0700861
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000862 return new RuleClass(
863 name,
tomlu72642a22017-10-18 06:23:14 +0200864 key,
janakr6ff110e2018-03-21 21:44:27 -0700865 type,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000866 skylark,
Jon Brandveinead58ae2016-09-29 18:41:10 +0000867 skylarkTestable,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000868 documented,
869 publicByDefault,
870 binaryOutput,
871 workspaceOnly,
dslomov2ce98442017-10-23 19:14:02 +0200872 isExecutableSkylark,
cparsons55781c92018-10-17 12:03:08 -0700873 isAnalysisTest,
cparsons9d40c6b2019-02-25 12:24:40 -0800874 hasAnalysisTestTransition,
Googlerc2200fd2018-09-14 17:35:59 -0700875 hasFunctionTransitionWhitelist,
gregce1d8d6dd2019-04-10 09:27:34 -0700876 ignoreLicenses,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000877 implicitOutputsFunction,
Michael Staib2a675202017-03-20 18:06:48 +0000878 transitionFactory,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000879 configuredTargetFactory,
880 validityPredicate,
881 preferredDependencyPredicate,
Dmitry Lomovb91d3922017-01-09 20:12:57 +0000882 advertisedProviders.build(),
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000883 configuredTargetFunction,
884 externalBindingsFunction,
mstaibe5538ad2017-04-04 18:32:23 +0000885 optionReferenceFunction,
janakrd3fe5e72018-03-30 12:49:12 -0700886 ruleDefinitionEnvironmentLabel,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000887 ruleDefinitionEnvironmentHashCode,
888 configurationFragmentPolicy.build(),
889 supportsConstraintChecking,
gregce4aa059a2019-02-26 13:20:47 -0800890 thirdPartyLicenseExistencePolicy,
John Catereca28402017-05-17 21:44:12 +0200891 requiredToolchains,
jcater01bb1f92019-06-17 12:09:11 -0700892 useToolchainResolution,
John Cateree45c662018-06-05 11:09:01 -0700893 executionPlatformConstraintsAllowed,
894 executionPlatformConstraints,
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -0700895 outputFileKind,
juliexxia1f332e02018-10-31 14:20:55 -0700896 attributes.values(),
897 buildSetting);
janakrd3fe5e72018-03-30 12:49:12 -0700898 }
899
900 private void assertSkylarkRuleClassHasImplementationFunction() {
901 Preconditions.checkState(
902 (type == RuleClassType.NORMAL || type == RuleClassType.TEST)
903 == (configuredTargetFunction != null),
904 "%s %s",
905 type,
906 configuredTargetFunction);
907 }
908
909 private void assertSkylarkRuleClassHasEnvironmentLabel() {
910 Preconditions.checkState(
911 (type == RuleClassType.NORMAL
912 || type == RuleClassType.TEST
913 || type == RuleClassType.PLACEHOLDER)
914 == (ruleDefinitionEnvironmentLabel != null),
laurentlb7dcad732018-10-25 05:17:20 -0700915 "Concrete Starlark rule classes can't have null labels: %s %s",
janakrd3fe5e72018-03-30 12:49:12 -0700916 ruleDefinitionEnvironmentLabel,
917 type);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100918 }
919
jcater6e132862019-07-16 08:50:04 -0700920 /**
921 * Declares that the implementation of the associated rule class requires the given fragments to
922 * be present in this rule's host and target configurations.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100923 *
Greg Estren693f17f2015-11-06 16:45:45 +0000924 * <p>The value is inherited by subclasses.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100925 */
Michael Staibb51251e2015-09-29 23:31:51 +0000926 public Builder requiresConfigurationFragments(Class<?>... configurationFragments) {
Michael Staibff66c192016-01-14 22:40:37 +0000927 configurationFragmentPolicy.requiresConfigurationFragments(
928 ImmutableSet.<Class<?>>copyOf(configurationFragments));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100929 return this;
930 }
931
Ulf Adams71423eb2015-08-06 11:51:17 +0000932 /**
Greg Estren693f17f2015-11-06 16:45:45 +0000933 * Declares that the implementation of the associated rule class requires the given
gregce614dc502017-12-20 17:24:46 -0800934 * fragments to be present in the given configuration that isn't the rule's configuration but
935 * is also readable by the rule.
936 *
937 * <p>You probably don't want to use this, because rules generally shouldn't read configurations
938 * other than their own. If you want to declare host config fragments, see
939 * {@link com.google.devtools.build.lib.analysis.config.ConfigAwareRuleClassBuilder}.
Greg Estren693f17f2015-11-06 16:45:45 +0000940 *
941 * <p>The value is inherited by subclasses.
942 */
gregcebe55e112018-01-30 11:04:53 -0800943 public Builder requiresConfigurationFragments(ConfigurationTransition transition,
gregce614dc502017-12-20 17:24:46 -0800944 Class<?>... configurationFragments) {
945 configurationFragmentPolicy.requiresConfigurationFragments(
946 transition,
Michael Staibff66c192016-01-14 22:40:37 +0000947 ImmutableSet.<Class<?>>copyOf(configurationFragments));
Greg Estren693f17f2015-11-06 16:45:45 +0000948 return this;
949 }
950
951 /**
Michael Staibff66c192016-01-14 22:40:37 +0000952 * Declares the configuration fragments that are required by this rule for the target
953 * configuration.
Greg Estren693f17f2015-11-06 16:45:45 +0000954 *
955 * <p>In contrast to {@link #requiresConfigurationFragments(Class...)}, this method takes the
Michael Staibff66c192016-01-14 22:40:37 +0000956 * Skylark module names of fragments instead of their classes.
Greg Estren693f17f2015-11-06 16:45:45 +0000957 */
Michael Staibff66c192016-01-14 22:40:37 +0000958 public Builder requiresConfigurationFragmentsBySkylarkModuleName(
959 Collection<String> configurationFragmentNames) {
960 configurationFragmentPolicy
961 .requiresConfigurationFragmentsBySkylarkModuleName(configurationFragmentNames);
962 return this;
963 }
964
965 /**
966 * Declares the configuration fragments that are required by this rule for the host
967 * configuration.
968 *
Michael Staibff66c192016-01-14 22:40:37 +0000969 */
gregce614dc502017-12-20 17:24:46 -0800970 /**
971 * Declares that the implementation of the associated rule class requires the given
972 * fragments to be present in the given configuration that isn't the rule's configuration but
973 * is also readable by the rule.
974 *
gregcebe55e112018-01-30 11:04:53 -0800975 * <p>In contrast to {@link #requiresConfigurationFragments(ConfigurationTransition, Class...)},
976 * this method takes Skylark module names of fragments instead of their classes.
gregce614dc502017-12-20 17:24:46 -0800977 * *
978 * <p>You probably don't want to use this, because rules generally shouldn't read configurations
979 * other than their own. If you want to declare host config fragments, see
980 * {@link com.google.devtools.build.lib.analysis.config.ConfigAwareRuleClassBuilder}.
981 *
982 * <p>The value is inherited by subclasses.
983 */
gregcebe55e112018-01-30 11:04:53 -0800984 public Builder requiresConfigurationFragmentsBySkylarkModuleName(
985 ConfigurationTransition transition, Collection<String> configurationFragmentNames) {
gregce614dc502017-12-20 17:24:46 -0800986 configurationFragmentPolicy.requiresConfigurationFragmentsBySkylarkModuleName(transition,
987 configurationFragmentNames);
Greg Estren693f17f2015-11-06 16:45:45 +0000988 return this;
989 }
990
Jon Brandveinead58ae2016-09-29 18:41:10 +0000991 public Builder setSkylarkTestable() {
laurentlb7dcad732018-10-25 05:17:20 -0700992 Preconditions.checkState(skylark, "Cannot set skylarkTestable on a non-Starlark rule");
Jon Brandveinead58ae2016-09-29 18:41:10 +0000993 skylarkTestable = true;
994 return this;
995 }
996
Greg Estren693f17f2015-11-06 16:45:45 +0000997 /**
Ulf Adams71423eb2015-08-06 11:51:17 +0000998 * Sets the policy for the case where the configuration is missing required fragments (see
999 * {@link #requiresConfigurationFragments}).
1000 */
1001 public Builder setMissingFragmentPolicy(MissingFragmentPolicy missingFragmentPolicy) {
Michael Staibb51251e2015-09-29 23:31:51 +00001002 configurationFragmentPolicy.setMissingFragmentPolicy(missingFragmentPolicy);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001003 return this;
1004 }
Florian Weikert3f8aac92015-09-07 12:06:02 +00001005
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001006 public Builder setUndocumented() {
1007 documented = false;
1008 return this;
1009 }
1010
1011 public Builder publicByDefault() {
1012 publicByDefault = true;
1013 return this;
1014 }
1015
1016 public Builder setWorkspaceOnly() {
1017 workspaceOnly = true;
1018 return this;
1019 }
1020
1021 /**
1022 * Determines the outputs of this rule to be created beneath the {@code
1023 * genfiles} directory. By default, files are created beneath the {@code bin}
1024 * directory.
1025 *
1026 * <p>This property is not inherited and this method should not be called by
1027 * builder of {@link RuleClassType#ABSTRACT} rule class.
1028 *
1029 * @throws IllegalStateException if called for abstract rule class builder
1030 */
1031 public Builder setOutputToGenfiles() {
1032 Preconditions.checkState(type != RuleClassType.ABSTRACT,
1033 "Setting not inherited property (output to genrules) of abstract rule class '%s'", name);
1034 this.binaryOutput = false;
1035 return this;
1036 }
1037
1038 /**
1039 * Sets the implicit outputs function of the rule class. The default implicit
1040 * outputs function is {@link ImplicitOutputsFunction#NONE}.
1041 *
1042 * <p>This property is not inherited and this method should not be called by
1043 * builder of {@link RuleClassType#ABSTRACT} rule class.
1044 *
1045 * @throws IllegalStateException if called for abstract rule class builder
1046 */
1047 public Builder setImplicitOutputsFunction(
1048 ImplicitOutputsFunction implicitOutputsFunction) {
1049 Preconditions.checkState(type != RuleClassType.ABSTRACT,
1050 "Setting not inherited property (implicit output function) of abstract rule class '%s'",
1051 name);
1052 this.implicitOutputsFunction = implicitOutputsFunction;
1053 return this;
1054 }
1055
Cal Peyser19dda252017-01-11 23:37:05 +00001056 /**
gregce64c36e12017-07-26 23:48:56 +02001057 * Applies the given transition to all incoming edges for this rule class.
Cal Peyser19dda252017-01-11 23:37:05 +00001058 *
gregce74a895d2018-05-29 11:26:03 -07001059 * <p>This cannot be a {@link SplitTransition} because that requires coordination with the
John Caterb3b3e8b2019-04-03 09:18:42 -07001060 * rule's parent: use {@link Attribute.Builder#cfg(TransitionFactory)} on the parent to declare
1061 * splits.
gregce74a895d2018-05-29 11:26:03 -07001062 *
jcater98a09b62019-04-02 13:06:19 -07001063 * <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 -07001064 * #cfg(TransitionFactory)}.
Cal Peyser19dda252017-01-11 23:37:05 +00001065 */
mstaib860975a2018-04-26 15:00:52 -07001066 public Builder cfg(PatchTransition transition) {
John Caterb3b3e8b2019-04-03 09:18:42 -07001067 return cfg((TransitionFactory<Rule>) (unused) -> (transition));
Michael Staib2a675202017-03-20 18:06:48 +00001068 }
1069
gregce64c36e12017-07-26 23:48:56 +02001070 /**
1071 * Applies the given transition factory to all incoming edges for this rule class.
1072 *
John Cateree45c662018-06-05 11:09:01 -07001073 * <p>Unlike {@link #cfg(PatchTransition)}, the factory can examine the rule when deciding what
1074 * transition to use.
gregce64c36e12017-07-26 23:48:56 +02001075 */
John Caterb3b3e8b2019-04-03 09:18:42 -07001076 public Builder cfg(TransitionFactory<Rule> transitionFactory) {
Michael Staib2a675202017-03-20 18:06:48 +00001077 Preconditions.checkState(type != RuleClassType.ABSTRACT,
1078 "Setting not inherited property (cfg) of abstract rule class '%s'", name);
gregcef19fcfe2017-06-02 16:04:07 -04001079 Preconditions.checkState(this.transitionFactory == null,
Michael Staib2a675202017-03-20 18:06:48 +00001080 "Property cfg has already been set");
1081 Preconditions.checkNotNull(transitionFactory);
John Caterb3b3e8b2019-04-03 09:18:42 -07001082 Preconditions.checkArgument(!transitionFactory.isSplit());
Michael Staib2a675202017-03-20 18:06:48 +00001083 this.transitionFactory = transitionFactory;
Cal Peyser19dda252017-01-11 23:37:05 +00001084 return this;
1085 }
1086
juliexxia30976d82019-03-12 10:59:26 -07001087 public void setHasStarlarkRuleTransition() {
1088 hasStarlarkRuleTransition = true;
1089 }
1090
1091 public boolean hasStarlarkRuleTransition() {
1092 return hasStarlarkRuleTransition;
1093 }
1094
cparsonse2d200f2018-03-06 16:15:11 -08001095 public Builder factory(ConfiguredTargetFactory<?, ?, ?> factory) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001096 this.configuredTargetFactory = factory;
1097 return this;
1098 }
1099
gregce4aa059a2019-02-26 13:20:47 -08001100 public Builder setThirdPartyLicenseExistencePolicy(ThirdPartyLicenseExistencePolicy policy) {
1101 this.thirdPartyLicenseExistencePolicy = policy;
1102 return this;
1103 }
1104
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001105 public Builder setValidityPredicate(PredicateWithMessage<Rule> predicate) {
1106 this.validityPredicate = predicate;
1107 return this;
1108 }
1109
1110 public Builder setPreferredDependencyPredicate(Predicate<String> predicate) {
1111 this.preferredDependencyPredicate = predicate;
1112 return this;
1113 }
1114
1115 /**
1116 * State that the rule class being built possibly supplies the specified provider to its direct
1117 * dependencies.
1118 *
1119 * <p>When computing the set of aspects required for a rule, only the providers listed here are
1120 * considered. The presence of a provider here does not mean that the rule <b>must</b> implement
1121 * said provider, merely that it <b>can</b>. After the configured target is constructed from
1122 * this rule, aspects will be filtered according to the set of actual providers.
1123 *
1124 * <p>This is here so that we can do the loading phase overestimation required for
1125 * "blaze query", which does not have the configured targets available.
1126 *
1127 * <p>It's okay for the rule class eventually not to supply it (possibly based on analysis phase
1128 * logic), but if a provider is not advertised but is supplied, aspects that require the it will
1129 * not be evaluated for the rule.
1130 */
1131 public Builder advertiseProvider(Class<?>... providers) {
Dmitry Lomovb91d3922017-01-09 20:12:57 +00001132 for (Class<?> provider : providers) {
1133 advertisedProviders.addNative(provider);
1134 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001135 return this;
1136 }
1137
elenairinaaeb21bc2017-09-27 12:13:52 -04001138 public Builder advertiseSkylarkProvider(SkylarkProviderIdentifier... skylarkProviders) {
1139 for (SkylarkProviderIdentifier skylarkProviderIdentifier : skylarkProviders) {
1140 advertisedProviders.addSkylark(skylarkProviderIdentifier);
1141 }
1142 return this;
1143 }
1144
Lukacs Berki549bfce2016-04-22 15:29:12 +00001145 /**
1146 * Set if the rule can have any provider. This is true for "alias" rules like
1147 * <code>bind</code> .
1148 */
1149 public Builder canHaveAnyProvider() {
Dmitry Lomovb91d3922017-01-09 20:12:57 +00001150 advertisedProviders.canHaveAnyProvider();
Lukacs Berki549bfce2016-04-22 15:29:12 +00001151 return this;
1152 }
1153
dbabkina2823422018-05-02 02:42:53 -07001154 public Builder addAttribute(Attribute attribute) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001155 Preconditions.checkState(!attributes.containsKey(attribute.getName()),
1156 "An attribute with the name '%s' already exists.", attribute.getName());
1157 attributes.put(attribute.getName(), attribute);
dbabkina2823422018-05-02 02:42:53 -07001158 return this;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001159 }
1160
1161 private void overrideAttribute(Attribute attribute) {
1162 String attrName = attribute.getName();
1163 Preconditions.checkState(attributes.containsKey(attrName),
1164 "No such attribute '%s' to override in ruleclass '%s'.", attrName, name);
1165 Type<?> origType = attributes.get(attrName).getType();
1166 Type<?> newType = attribute.getType();
1167 Preconditions.checkState(origType.equals(newType),
1168 "The type of the new attribute '%s' is different from the original one '%s'.",
1169 newType, origType);
1170 attributes.put(attrName, attribute);
1171 }
1172
1173 /**
1174 * Builds attribute from the attribute builder and adds it to this rule
1175 * class.
1176 *
1177 * @param attr attribute builder
1178 */
1179 public <TYPE> Builder add(Attribute.Builder<TYPE> attr) {
1180 addAttribute(attr.build());
1181 return this;
1182 }
1183
1184 /**
1185 * Builds attribute from the attribute builder and overrides the attribute
1186 * with the same name.
1187 *
1188 * @throws IllegalArgumentException if the attribute does not override one of the same name
1189 */
1190 public <TYPE> Builder override(Attribute.Builder<TYPE> attr) {
1191 overrideAttribute(attr.build());
1192 return this;
1193 }
1194
1195 /**
1196 * Adds or overrides the attribute in the rule class. Meant for Skylark usage.
Florian Weikerte96b0b82015-09-25 11:35:11 +00001197 *
1198 * @throws IllegalArgumentException if the attribute overrides an existing attribute (will be
1199 * legal in the future).
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001200 */
1201 public void addOrOverrideAttribute(Attribute attribute) {
Florian Weikerte96b0b82015-09-25 11:35:11 +00001202 String name = attribute.getName();
1203 // Attributes may be overridden in the future.
1204 Preconditions.checkArgument(!attributes.containsKey(name),
1205 "There is already a built-in attribute '%s' which cannot be overridden", name);
1206 addAttribute(attribute);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001207 }
1208
Mark Schaller4fa83ac2015-07-10 16:59:37 +00001209 /** True if the rule class contains an attribute named {@code name}. */
1210 public boolean contains(String name) {
1211 return attributes.containsKey(name);
1212 }
1213
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001214 /**
1215 * Sets the rule implementation function. Meant for Skylark usage.
1216 */
Francois-Rene Rideau95b0d0c2015-04-22 16:52:13 +00001217 public Builder setConfiguredTargetFunction(BaseFunction func) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001218 this.configuredTargetFunction = func;
1219 return this;
1220 }
1221
juliexxia1f332e02018-10-31 14:20:55 -07001222 public Builder setBuildSetting(BuildSetting buildSetting) {
1223 this.buildSetting = buildSetting;
1224 return this;
1225 }
1226
Lukacs Berki0e1a9942015-06-18 08:53:18 +00001227 public Builder setExternalBindingsFunction(Function<? super Rule, Map<String, Label>> func) {
1228 this.externalBindingsFunction = func;
1229 return this;
1230 }
1231
janakrd3fe5e72018-03-30 12:49:12 -07001232 /** Sets the rule definition environment label and hash code. Meant for Skylark usage. */
1233 public Builder setRuleDefinitionEnvironmentLabelAndHashCode(Label label, String hashCode) {
1234 this.ruleDefinitionEnvironmentLabel = Preconditions.checkNotNull(label, this.name);
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001235 this.ruleDefinitionEnvironmentHashCode = Preconditions.checkNotNull(hashCode, this.name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001236 return this;
1237 }
1238
juliexxia84d1a662018-12-26 14:07:04 -08001239 public Label getRuleDefinitionEnvironmentLabel() {
1240 return this.ruleDefinitionEnvironmentLabel;
1241 }
1242
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001243 /**
1244 * Removes an attribute with the same name from this rule class.
1245 *
1246 * @throws IllegalArgumentException if the attribute with this name does
1247 * not exist
1248 */
1249 public <TYPE> Builder removeAttribute(String name) {
1250 Preconditions.checkState(attributes.containsKey(name), "No such attribute '%s' to remove.",
1251 name);
1252 attributes.remove(name);
1253 return this;
1254 }
1255
1256 /**
1257 * This rule class outputs a default executable for every rule with the same name as
1258 * the rules's. Only works for Skylark.
1259 */
dslomov2ce98442017-10-23 19:14:02 +02001260 public <TYPE> Builder setExecutableSkylark() {
1261 this.isExecutableSkylark = true;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001262 return this;
1263 }
1264
cparsons55781c92018-10-17 12:03:08 -07001265 /** This rule class is marked as an analysis test. */
1266 public Builder setIsAnalysisTest() {
1267 this.isAnalysisTest = true;
1268 return this;
1269 }
1270
juliexxia84d1a662018-12-26 14:07:04 -08001271 public boolean isAnalysisTest() {
1272 return this.isAnalysisTest;
1273 }
1274
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001275 /**
cparsons9d40c6b2019-02-25 12:24:40 -08001276 * This rule class has at least one attribute with an analysis test transition. (A
1277 * starlark-defined transition using analysis_test_transition()).
1278 */
1279 public Builder setHasAnalysisTestTransition() {
1280 this.hasAnalysisTestTransition = true;
1281 return this;
1282 }
1283
cparsons9d40c6b2019-02-25 12:24:40 -08001284 /**
Googlerc2200fd2018-09-14 17:35:59 -07001285 * This rule class has the _whitelist_function_transition attribute. Intended only for Skylark
1286 * rules.
1287 */
1288 public <TYPE> Builder setHasFunctionTransitionWhitelist() {
1289 this.hasFunctionTransitionWhitelist = true;
1290 return this;
1291 }
1292
gregce1d8d6dd2019-04-10 09:27:34 -07001293 /**
1294 * This rule class never declares a license regardless of what the rule's or package's <code>
1295 * licenses</code> attribute says.
1296 */
1297 // TODO(b/130286108): remove the licenses attribute completely from such rules.
1298 public Builder setIgnoreLicenses() {
1299 this.ignoreLicenses = true;
Googlerfdb17eb2019-01-28 15:14:32 -08001300 return this;
1301 }
1302
juliexxia84d1a662018-12-26 14:07:04 -08001303 public RuleClassType getType() {
1304 return this.type;
1305 }
1306
Googlerc2200fd2018-09-14 17:35:59 -07001307 /**
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -07001308 * Sets the kind of output files this rule creates.
1309 * DO NOT USE! This only exists to support the non-open-sourced {@code fileset} rule.
1310 * {@see OutputFile.Kind}.
1311 */
1312 public Builder setOutputFileKind(OutputFile.Kind outputFileKind) {
nharmata0d493ba2019-01-07 11:06:44 -08001313 this.outputFileKind = Preconditions.checkNotNull(outputFileKind);
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -07001314 return this;
1315 }
1316
1317
1318
1319 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001320 * Declares that instances of this rule are compatible with the specified environments,
1321 * in addition to the defaults declared by their environment groups. This can be overridden
1322 * by rule-specific declarations. See
1323 * {@link com.google.devtools.build.lib.analysis.constraints.ConstraintSemantics} for details.
1324 */
1325 public <TYPE> Builder compatibleWith(Label... environments) {
gregce614dc502017-12-20 17:24:46 -08001326 add(
1327 attr(DEFAULT_COMPATIBLE_ENVIRONMENT_ATTR, LABEL_LIST)
1328 .value(ImmutableList.copyOf(environments)));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001329 return this;
1330 }
1331
1332 /**
1333 * Declares that instances of this rule are restricted to the specified environments, i.e.
1334 * these override the defaults declared by their environment groups. This can be overridden
1335 * by rule-specific declarations. See
1336 * {@link com.google.devtools.build.lib.analysis.constraints.ConstraintSemantics} for details.
1337 *
1338 * <p>The input list cannot be empty.
1339 */
1340 public <TYPE> Builder restrictedTo(Label firstEnvironment, Label... otherEnvironments) {
1341 ImmutableList<Label> environments = ImmutableList.<Label>builder().add(firstEnvironment)
1342 .add(otherEnvironments).build();
gregce614dc502017-12-20 17:24:46 -08001343 add(
1344 attr(DEFAULT_RESTRICTED_ENVIRONMENT_ATTR, LABEL_LIST)
1345 .value(environments));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001346 return this;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001347 }
1348
1349 /**
Greg Estrenc04c88f2015-03-06 19:45:50 +00001350 * Exempts rules of this type from the constraint enforcement system. This should only be
1351 * applied to rules that are intrinsically incompatible with constraint checking (any
1352 * application of this method weakens the reach and strength of the system).
1353 *
1354 * @param reason user-informative message explaining the reason for exemption (not used)
1355 */
1356 public <TYPE> Builder exemptFromConstraintChecking(String reason) {
1357 Preconditions.checkState(this.supportsConstraintChecking);
1358 this.supportsConstraintChecking = false;
Greg Estren2ffc4fe2015-06-02 19:40:41 +00001359 attributes.remove(RuleClass.COMPATIBLE_ENVIRONMENT_ATTR);
1360 attributes.remove(RuleClass.RESTRICTED_ENVIRONMENT_ATTR);
Greg Estrenc04c88f2015-03-06 19:45:50 +00001361 return this;
1362 }
1363
1364 /**
mstaibe5538ad2017-04-04 18:32:23 +00001365 * Causes rules of this type to implicitly reference the configuration fragments associated with
1366 * the options its attributes reference.
1367 *
1368 * <p>This is only intended for use by {@code config_setting} - other rules should not use this!
1369 */
1370 public Builder setOptionReferenceFunctionForConfigSettingOnly(
1371 Function<? super Rule, ? extends Set<String>> optionReferenceFunction) {
1372 this.optionReferenceFunction = Preconditions.checkNotNull(optionReferenceFunction);
1373 return this;
1374 }
1375
John Cateree45c662018-06-05 11:09:01 -07001376 /**
1377 * Causes rules of this type to require the specified toolchains be available via toolchain
1378 * resolution when a target is configured.
1379 */
John Cater9a8d16e2017-07-05 16:12:07 -04001380 public Builder addRequiredToolchains(Iterable<Label> toolchainLabels) {
1381 Iterables.addAll(this.requiredToolchains, toolchainLabels);
John Catereca28402017-05-17 21:44:12 +02001382 return this;
1383 }
1384
John Cateree45c662018-06-05 11:09:01 -07001385 /**
1386 * Causes rules of this type to require the specified toolchains be available via toolchain
1387 * resolution when a target is configured.
1388 */
cpeyserd852e482017-09-07 22:16:06 +02001389 public Builder addRequiredToolchains(Label... toolchainLabels) {
John Cateree45c662018-06-05 11:09:01 -07001390 return this.addRequiredToolchains(Lists.newArrayList(toolchainLabels));
1391 }
1392
1393 /**
jcater01bb1f92019-06-17 12:09:11 -07001394 * Causes rules to use toolchain resolution to determine the execution platform and toolchains.
1395 * Rules that are part of configuring toolchains and platforms should set this to {@code false}.
John Cateree45c662018-06-05 11:09:01 -07001396 */
jcater01bb1f92019-06-17 12:09:11 -07001397 public Builder useToolchainResolution(boolean flag) {
1398 this.useToolchainResolution = flag;
cpeyserd852e482017-09-07 22:16:06 +02001399 return this;
1400 }
1401
John Cateree45c662018-06-05 11:09:01 -07001402 /**
1403 * Specifies whether targets of this rule can add additional constraints on the execution
1404 * platform selected. If this is {@link ExecutionPlatformConstraintsAllowed#PER_TARGET}, there
1405 * will be an attribute named {@code exec_compatible_with} that can be used to add these
1406 * constraints.
1407 *
1408 * <p>Please note that this value is not inherited by child rules, and must be re-set on them if
1409 * the same behavior is required.
1410 */
1411 public Builder executionPlatformConstraintsAllowed(ExecutionPlatformConstraintsAllowed value) {
1412 this.executionPlatformConstraintsAllowed = value;
1413 return this;
1414 }
1415
1416 /**
1417 * Adds additional execution platform constraints that apply for all targets from this rule.
1418 *
1419 * <p>Please note that this value is inherited by child rules.
1420 */
1421 public Builder addExecutionPlatformConstraints(Label... constraints) {
1422 return this.addExecutionPlatformConstraints(Lists.newArrayList(constraints));
1423 }
1424
1425 /**
1426 * Adds additional execution platform constraints that apply for all targets from this rule.
1427 *
1428 * <p>Please note that this value is inherited by child rules.
1429 */
1430 public Builder addExecutionPlatformConstraints(Iterable<Label> constraints) {
1431 Iterables.addAll(this.executionPlatformConstraints, constraints);
John Cater856b4dd2017-11-21 08:06:16 -08001432 return this;
1433 }
1434
mstaibe5538ad2017-04-04 18:32:23 +00001435 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001436 * Returns an Attribute.Builder object which contains a replica of the
1437 * same attribute in the parent rule if exists.
1438 *
1439 * @param name the name of the attribute
1440 */
1441 public Attribute.Builder<?> copy(String name) {
1442 Preconditions.checkArgument(attributes.containsKey(name),
1443 "Attribute %s does not exist in parent rule class.", name);
1444 return attributes.get(name).cloneBuilder();
1445 }
1446 }
1447
1448 private final String name; // e.g. "cc_library"
1449
tomlu72642a22017-10-18 06:23:14 +02001450 private final String key; // Just the name for native, label + name for skylark
1451
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001452 /**
1453 * The kind of target represented by this RuleClass (e.g. "cc_library rule").
1454 * Note: Even though there is partial duplication with the {@link RuleClass#name} field,
1455 * we want to store this as a separate field instead of generating it on demand in order to
1456 * avoid string duplication.
1457 */
1458 private final String targetKind;
1459
janakr6ff110e2018-03-21 21:44:27 -07001460 private final RuleClassType type;
Michajlo Matijkiwbc042c62015-10-29 13:22:52 +00001461 private final boolean isSkylark;
Jon Brandveinead58ae2016-09-29 18:41:10 +00001462 private final boolean skylarkTestable;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001463 private final boolean documented;
1464 private final boolean publicByDefault;
1465 private final boolean binaryOutput;
1466 private final boolean workspaceOnly;
dslomov2ce98442017-10-23 19:14:02 +02001467 private final boolean isExecutableSkylark;
cparsons55781c92018-10-17 12:03:08 -07001468 private final boolean isAnalysisTest;
cparsons9d40c6b2019-02-25 12:24:40 -08001469 private final boolean hasAnalysisTestTransition;
Googlerc2200fd2018-09-14 17:35:59 -07001470 private final boolean hasFunctionTransitionWhitelist;
gregce1d8d6dd2019-04-10 09:27:34 -07001471 private final boolean ignoreLicenses;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001472
1473 /**
1474 * A (unordered) mapping from attribute names to small integers indexing into
1475 * the {@code attributes} array.
1476 */
Miguel Alcon Pintod7795f42015-10-23 21:55:52 +00001477 private final Map<String, Integer> attributeIndex;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001478
1479 /**
1480 * All attributes of this rule class (including inherited ones) ordered by
1481 * attributeIndex value.
1482 */
Eric Fellheimera954fae2015-08-27 19:37:52 +00001483 private final ImmutableList<Attribute> attributes;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001484
Michajlo Matijkiwcdd5b0e2015-12-09 18:17:44 +00001485 /** Names of the non-configurable attributes of this rule class. */
1486 private final ImmutableList<String> nonConfigurableAttributes;
1487
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001488 /**
1489 * The set of implicit outputs generated by a rule, expressed as a function
1490 * of that rule.
1491 */
1492 private final ImplicitOutputsFunction implicitOutputsFunction;
1493
1494 /**
Michael Staib2a675202017-03-20 18:06:48 +00001495 * A factory which will produce a configuration transition that should be applied on any edge of
1496 * the configured target graph that leads into a target of this rule class.
Cal Peyser19dda252017-01-11 23:37:05 +00001497 */
John Caterb3b3e8b2019-04-03 09:18:42 -07001498 private final TransitionFactory<Rule> transitionFactory;
Cal Peyser19dda252017-01-11 23:37:05 +00001499
cparsonse2d200f2018-03-06 16:15:11 -08001500 /** The factory that creates configured targets from this rule. */
1501 private final ConfiguredTargetFactory<?, ?, ?> configuredTargetFactory;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001502
1503 /**
1504 * The constraint the package name of the rule instance must fulfill
1505 */
1506 private final PredicateWithMessage<Rule> validityPredicate;
1507
1508 /**
1509 * See {@link #isPreferredDependency}.
1510 */
1511 private final Predicate<String> preferredDependencyPredicate;
1512
1513 /**
1514 * The list of transitive info providers this class advertises to aspects.
1515 */
Dmitry Lomovb91d3922017-01-09 20:12:57 +00001516 private final AdvertisedProviderSet advertisedProviders;
Lukacs Berki549bfce2016-04-22 15:29:12 +00001517
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001518 /**
1519 * The Skylark rule implementation of this RuleClass. Null for non Skylark executable RuleClasses.
1520 */
Francois-Rene Rideau95b0d0c2015-04-22 16:52:13 +00001521 @Nullable private final BaseFunction configuredTargetFunction;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001522
1523 /**
juliexxia1f332e02018-10-31 14:20:55 -07001524 * The BuildSetting associated with this rule. Null for all RuleClasses except Skylark-defined
1525 * rules that pass {@code build_setting} to their {@code rule()} declaration.
1526 */
1527 @Nullable private final BuildSetting buildSetting;
1528
1529 /**
Lukacs Berki0e1a9942015-06-18 08:53:18 +00001530 * Returns the extra bindings a workspace function adds to the WORKSPACE file.
1531 */
1532 private final Function<? super Rule, Map<String, Label>> externalBindingsFunction;
1533
1534 /**
mstaibe5538ad2017-04-04 18:32:23 +00001535 * Returns the options referenced by this rule's attributes.
1536 */
1537 private final Function<? super Rule, ? extends Set<String>> optionReferenceFunction;
1538
1539 /**
janakrd3fe5e72018-03-30 12:49:12 -07001540 * The Skylark rule definition environment's label and hash code of this RuleClass. Null for non
1541 * Skylark executable RuleClasses.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001542 */
janakrd3fe5e72018-03-30 12:49:12 -07001543 @Nullable private final Label ruleDefinitionEnvironmentLabel;
1544
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001545 @Nullable private final String ruleDefinitionEnvironmentHashCode;
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -07001546 private final OutputFile.Kind outputFileKind;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001547
1548 /**
Michael Staibb51251e2015-09-29 23:31:51 +00001549 * The set of configuration fragments which are legal for this rule's implementation to access.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001550 */
Michael Staibb51251e2015-09-29 23:31:51 +00001551 private final ConfigurationFragmentPolicy configurationFragmentPolicy;
Greg Estrenc04c88f2015-03-06 19:45:50 +00001552
1553 /**
1554 * Determines whether instances of this rule should be checked for constraint compatibility
1555 * with their dependencies and the rules that depend on them. This should be true for
1556 * everything except for rules that are intrinsically incompatible with the constraint system.
1557 */
1558 private final boolean supportsConstraintChecking;
1559
gregce4aa059a2019-02-26 13:20:47 -08001560 private final ThirdPartyLicenseExistencePolicy thirdPartyLicenseExistencePolicy;
1561
cpeyserfb829992017-09-07 17:17:03 +02001562 private final ImmutableSet<Label> requiredToolchains;
jcater01bb1f92019-06-17 12:09:11 -07001563 private final boolean useToolchainResolution;
John Cateree45c662018-06-05 11:09:01 -07001564 private final ExecutionPlatformConstraintsAllowed executionPlatformConstraintsAllowed;
1565 private final ImmutableSet<Label> executionPlatformConstraints;
John Catereca28402017-05-17 21:44:12 +02001566
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001567 /**
John Catereca28402017-05-17 21:44:12 +02001568 * Constructs an instance of RuleClass whose name is 'name', attributes are 'attributes'. The
1569 * {@code srcsAllowedFiles} determines which types of files are allowed as parameters to the
1570 * "srcs" attribute; rules are always allowed. For the "deps" attribute, there are four cases:
1571 *
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001572 * <ul>
John Catereca28402017-05-17 21:44:12 +02001573 * <li>if the parameter is a file, it is allowed if its file type is given in {@code
1574 * depsAllowedFiles},
1575 * <li>if the parameter is a rule and the rule class is accepted by {@code depsAllowedRules},
1576 * then it is allowed,
1577 * <li>if the parameter is a rule and the rule class is not accepted by {@code
1578 * depsAllowedRules}, but accepted by {@code depsAllowedRulesWithWarning}, then it is
1579 * allowed, but triggers a warning;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001580 * <li>all other parameters trigger an error.
1581 * </ul>
1582 *
John Catereca28402017-05-17 21:44:12 +02001583 * <p>The {@code depsAllowedRules} predicate should have a {@code toString} method which returns a
1584 * plain English enumeration of the allowed rule class names, if it does not allow all rule
1585 * classes.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001586 */
1587 @VisibleForTesting
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001588 RuleClass(
1589 String name,
tomlu72642a22017-10-18 06:23:14 +02001590 String key,
janakr6ff110e2018-03-21 21:44:27 -07001591 RuleClassType type,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001592 boolean isSkylark,
Jon Brandveinead58ae2016-09-29 18:41:10 +00001593 boolean skylarkTestable,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001594 boolean documented,
1595 boolean publicByDefault,
1596 boolean binaryOutput,
1597 boolean workspaceOnly,
dslomov2ce98442017-10-23 19:14:02 +02001598 boolean isExecutableSkylark,
cparsons55781c92018-10-17 12:03:08 -07001599 boolean isAnalysisTest,
cparsons9d40c6b2019-02-25 12:24:40 -08001600 boolean hasAnalysisTestTransition,
Googlerc2200fd2018-09-14 17:35:59 -07001601 boolean hasFunctionTransitionWhitelist,
gregce1d8d6dd2019-04-10 09:27:34 -07001602 boolean ignoreLicenses,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001603 ImplicitOutputsFunction implicitOutputsFunction,
John Caterb3b3e8b2019-04-03 09:18:42 -07001604 TransitionFactory<Rule> transitionFactory,
cparsonse2d200f2018-03-06 16:15:11 -08001605 ConfiguredTargetFactory<?, ?, ?> configuredTargetFactory,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001606 PredicateWithMessage<Rule> validityPredicate,
1607 Predicate<String> preferredDependencyPredicate,
Dmitry Lomovb91d3922017-01-09 20:12:57 +00001608 AdvertisedProviderSet advertisedProviders,
Francois-Rene Rideau95b0d0c2015-04-22 16:52:13 +00001609 @Nullable BaseFunction configuredTargetFunction,
Lukacs Berki0e1a9942015-06-18 08:53:18 +00001610 Function<? super Rule, Map<String, Label>> externalBindingsFunction,
mstaibe5538ad2017-04-04 18:32:23 +00001611 Function<? super Rule, ? extends Set<String>> optionReferenceFunction,
janakrd3fe5e72018-03-30 12:49:12 -07001612 @Nullable Label ruleDefinitionEnvironmentLabel,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001613 String ruleDefinitionEnvironmentHashCode,
Michael Staibb51251e2015-09-29 23:31:51 +00001614 ConfigurationFragmentPolicy configurationFragmentPolicy,
Greg Estrenc04c88f2015-03-06 19:45:50 +00001615 boolean supportsConstraintChecking,
gregce4aa059a2019-02-26 13:20:47 -08001616 ThirdPartyLicenseExistencePolicy thirdPartyLicenseExistencePolicy,
cpeyserfb829992017-09-07 17:17:03 +02001617 Set<Label> requiredToolchains,
jcater01bb1f92019-06-17 12:09:11 -07001618 boolean useToolchainResolution,
John Cateree45c662018-06-05 11:09:01 -07001619 ExecutionPlatformConstraintsAllowed executionPlatformConstraintsAllowed,
1620 Set<Label> executionPlatformConstraints,
cparsons55781c92018-10-17 12:03:08 -07001621 OutputFile.Kind outputFileKind,
juliexxia1f332e02018-10-31 14:20:55 -07001622 Collection<Attribute> attributes,
1623 @Nullable BuildSetting buildSetting) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001624 this.name = name;
tomlu72642a22017-10-18 06:23:14 +02001625 this.key = key;
janakr6ff110e2018-03-21 21:44:27 -07001626 this.type = type;
Michajlo Matijkiwbc042c62015-10-29 13:22:52 +00001627 this.isSkylark = isSkylark;
Googlerb448eef2017-05-02 21:50:24 +02001628 this.targetKind = name + Rule.targetKindSuffix();
Jon Brandveinead58ae2016-09-29 18:41:10 +00001629 this.skylarkTestable = skylarkTestable;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001630 this.documented = documented;
1631 this.publicByDefault = publicByDefault;
1632 this.binaryOutput = binaryOutput;
1633 this.implicitOutputsFunction = implicitOutputsFunction;
Michael Staib2a675202017-03-20 18:06:48 +00001634 this.transitionFactory = transitionFactory;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001635 this.configuredTargetFactory = configuredTargetFactory;
1636 this.validityPredicate = validityPredicate;
1637 this.preferredDependencyPredicate = preferredDependencyPredicate;
1638 this.advertisedProviders = advertisedProviders;
1639 this.configuredTargetFunction = configuredTargetFunction;
Lukacs Berki0e1a9942015-06-18 08:53:18 +00001640 this.externalBindingsFunction = externalBindingsFunction;
mstaibe5538ad2017-04-04 18:32:23 +00001641 this.optionReferenceFunction = optionReferenceFunction;
janakrd3fe5e72018-03-30 12:49:12 -07001642 this.ruleDefinitionEnvironmentLabel = ruleDefinitionEnvironmentLabel;
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001643 this.ruleDefinitionEnvironmentHashCode = ruleDefinitionEnvironmentHashCode;
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -07001644 this.outputFileKind = outputFileKind;
Dmitry Lomov94387c22015-12-08 16:30:06 +00001645 validateNoClashInPublicNames(attributes);
Eric Fellheimera954fae2015-08-27 19:37:52 +00001646 this.attributes = ImmutableList.copyOf(attributes);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001647 this.workspaceOnly = workspaceOnly;
dslomov2ce98442017-10-23 19:14:02 +02001648 this.isExecutableSkylark = isExecutableSkylark;
cparsons55781c92018-10-17 12:03:08 -07001649 this.isAnalysisTest = isAnalysisTest;
cparsons9d40c6b2019-02-25 12:24:40 -08001650 this.hasAnalysisTestTransition = hasAnalysisTestTransition;
Googlerc2200fd2018-09-14 17:35:59 -07001651 this.hasFunctionTransitionWhitelist = hasFunctionTransitionWhitelist;
gregce1d8d6dd2019-04-10 09:27:34 -07001652 this.ignoreLicenses = ignoreLicenses;
Michael Staibb51251e2015-09-29 23:31:51 +00001653 this.configurationFragmentPolicy = configurationFragmentPolicy;
Greg Estrenc04c88f2015-03-06 19:45:50 +00001654 this.supportsConstraintChecking = supportsConstraintChecking;
gregce4aa059a2019-02-26 13:20:47 -08001655 this.thirdPartyLicenseExistencePolicy = thirdPartyLicenseExistencePolicy;
cpeyserfb829992017-09-07 17:17:03 +02001656 this.requiredToolchains = ImmutableSet.copyOf(requiredToolchains);
jcater01bb1f92019-06-17 12:09:11 -07001657 this.useToolchainResolution = useToolchainResolution;
John Cateree45c662018-06-05 11:09:01 -07001658 this.executionPlatformConstraintsAllowed = executionPlatformConstraintsAllowed;
1659 this.executionPlatformConstraints = ImmutableSet.copyOf(executionPlatformConstraints);
juliexxia1f332e02018-10-31 14:20:55 -07001660 this.buildSetting = buildSetting;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001661
Michajlo Matijkiwcdd5b0e2015-12-09 18:17:44 +00001662 // Create the index and collect non-configurable attributes.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001663 int index = 0;
janakrd3fe5e72018-03-30 12:49:12 -07001664 attributeIndex = new HashMap<>(attributes.size());
Michajlo Matijkiwcdd5b0e2015-12-09 18:17:44 +00001665 ImmutableList.Builder<String> nonConfigurableAttributesBuilder = ImmutableList.builder();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001666 for (Attribute attribute : attributes) {
1667 attributeIndex.put(attribute.getName(), index++);
Michajlo Matijkiwcdd5b0e2015-12-09 18:17:44 +00001668 if (!attribute.isConfigurable()) {
1669 nonConfigurableAttributesBuilder.add(attribute.getName());
1670 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001671 }
Michajlo Matijkiwcdd5b0e2015-12-09 18:17:44 +00001672 this.nonConfigurableAttributes = nonConfigurableAttributesBuilder.build();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001673 }
1674
janakrd3fe5e72018-03-30 12:49:12 -07001675 private void validateNoClashInPublicNames(Iterable<Attribute> attributes) {
Dmitry Lomov94387c22015-12-08 16:30:06 +00001676 Map<String, Attribute> publicToPrivateNames = new HashMap<>();
1677 for (Attribute attribute : attributes) {
1678 String publicName = attribute.getPublicName();
1679 if (publicToPrivateNames.containsKey(publicName)) {
1680 throw new IllegalStateException(
1681 String.format(
1682 "Rule %s: Attributes %s and %s have an identical public name: %s",
1683 name,
1684 attribute.getName(),
1685 publicToPrivateNames.get(publicName).getName(),
1686 publicName));
1687 }
1688 publicToPrivateNames.put(publicName, attribute);
1689 }
1690 }
1691
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001692 /**
Michajlo Matijkiw6d471412016-08-09 20:35:45 +00001693 * Returns the default function for determining the set of implicit outputs generated by a given
1694 * rule. If not otherwise specified, this will be the implementation used by {@link Rule}s
1695 * created with this {@link RuleClass}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001696 *
Michajlo Matijkiw6d471412016-08-09 20:35:45 +00001697 * <p>Do not use this value to calculate implicit outputs for a rule, instead use
1698 * {@link Rule#getImplicitOutputsFunction()}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001699 *
Michajlo Matijkiw6d471412016-08-09 20:35:45 +00001700 * <p>An implicit output is an OutputFile that automatically comes into existence when a rule of
1701 * this class is declared, and whose name is derived from the name of the rule.
1702 *
1703 * <p>Implicit outputs are a widely-relied upon. All ".so", and "_deploy.jar" targets referenced
1704 * in BUILD files are examples.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001705 */
1706 @VisibleForTesting
Michajlo Matijkiw6d471412016-08-09 20:35:45 +00001707 public ImplicitOutputsFunction getDefaultImplicitOutputsFunction() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001708 return implicitOutputsFunction;
1709 }
1710
John Caterb3b3e8b2019-04-03 09:18:42 -07001711 public TransitionFactory<Rule> getTransitionFactory() {
Michael Staib2a675202017-03-20 18:06:48 +00001712 return transitionFactory;
Cal Peyser19dda252017-01-11 23:37:05 +00001713 }
1714
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001715 @SuppressWarnings("unchecked")
cparsonse2d200f2018-03-06 16:15:11 -08001716 public <CT, RC, ACE extends Throwable>
1717 ConfiguredTargetFactory<CT, RC, ACE> getConfiguredTargetFactory() {
1718 return (ConfiguredTargetFactory<CT, RC, ACE>) configuredTargetFactory;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001719 }
1720
1721 /**
1722 * Returns the class of rule that this RuleClass represents (e.g. "cc_library").
1723 */
1724 public String getName() {
1725 return name;
1726 }
1727
janakr6ff110e2018-03-21 21:44:27 -07001728 /** Returns the type of rule that this RuleClass represents. Only for use during serialization. */
1729 public RuleClassType getRuleClassType() {
1730 return type;
1731 }
1732
tomlu72642a22017-10-18 06:23:14 +02001733 /** Returns a unique key. Used for profiling purposes. */
1734 public String getKey() {
1735 return key;
1736 }
1737
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001738 /**
1739 * Returns the target kind of this class of rule (e.g. "cc_library rule").
1740 */
1741 String getTargetKind() {
1742 return targetKind;
1743 }
1744
1745 public boolean getWorkspaceOnly() {
1746 return workspaceOnly;
1747 }
1748
1749 /**
1750 * Returns true iff the attribute 'attrName' is defined for this rule class,
1751 * and has type 'type'.
1752 */
1753 public boolean hasAttr(String attrName, Type<?> type) {
1754 Integer index = getAttributeIndex(attrName);
1755 return index != null && getAttribute(index).getType() == type;
1756 }
1757
1758 /**
1759 * Returns the index of the specified attribute name. Use of indices allows
1760 * space-efficient storage of attribute values in rules, since hashtables are
1761 * not required. (The index mapping is specific to each RuleClass and an
1762 * attribute may have a different index in the parent RuleClass.)
1763 *
1764 * <p>Returns null if the named attribute is not defined for this class of Rule.
1765 */
1766 Integer getAttributeIndex(String attrName) {
1767 return attributeIndex.get(attrName);
1768 }
1769
1770 /**
1771 * Returns the attribute whose index is 'attrIndex'. Fails if attrIndex is
1772 * not in range.
1773 */
1774 Attribute getAttribute(int attrIndex) {
Eric Fellheimera954fae2015-08-27 19:37:52 +00001775 return attributes.get(attrIndex);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001776 }
1777
1778 /**
Michajlo Matijkiw0446c952015-10-28 19:59:00 +00001779 * Returns the attribute whose name is 'attrName'; fails with NullPointerException if not found.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001780 */
1781 public Attribute getAttributeByName(String attrName) {
Michajlo Matijkiw0446c952015-10-28 19:59:00 +00001782 Integer attrIndex = Preconditions.checkNotNull(getAttributeIndex(attrName),
1783 "Attribute %s does not exist", attrName);
1784 return attributes.get(attrIndex);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001785 }
1786
1787 /**
1788 * Returns the attribute whose name is {@code attrName}, or null if not
1789 * found.
1790 */
1791 Attribute getAttributeByNameMaybe(String attrName) {
1792 Integer i = getAttributeIndex(attrName);
Eric Fellheimera954fae2015-08-27 19:37:52 +00001793 return i == null ? null : attributes.get(i);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001794 }
1795
1796 /**
1797 * Returns the number of attributes defined for this rule class.
1798 */
1799 public int getAttributeCount() {
1800 return attributeIndex.size();
1801 }
1802
1803 /**
1804 * Returns an (immutable) list of all Attributes defined for this class of
1805 * rule, ordered by increasing index.
1806 */
1807 public List<Attribute> getAttributes() {
Eric Fellheimera954fae2015-08-27 19:37:52 +00001808 return attributes;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001809 }
1810
Michajlo Matijkiwcdd5b0e2015-12-09 18:17:44 +00001811 /** Returns set of non-configurable attribute names defined for this class of rule. */
1812 public List<String> getNonConfigurableAttributes() {
1813 return nonConfigurableAttributes;
1814 }
1815
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001816 public PredicateWithMessage<Rule> getValidityPredicate() {
1817 return validityPredicate;
1818 }
1819
1820 /**
1821 * Returns the set of advertised transitive info providers.
1822 *
1823 * <p>When computing the set of aspects required for a rule, only the providers listed here are
1824 * considered. The presence of a provider here does not mean that the rule <b>must</b> implement
1825 * said provider, merely that it <b>can</b>. After the configured target is constructed from this
1826 * rule, aspects will be filtered according to the set of actual providers.
1827 *
1828 * <p>This is here so that we can do the loading phase overestimation required for "blaze query",
1829 * which does not have the configured targets available.
Dmitry Lomovb91d3922017-01-09 20:12:57 +00001830 **/
1831 public AdvertisedProviderSet getAdvertisedProviders() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001832 return advertisedProviders;
1833 }
Lukacs Berki549bfce2016-04-22 15:29:12 +00001834 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001835 * For --compile_one_dependency: if multiple rules consume the specified target,
1836 * should we choose this one over the "unpreferred" options?
1837 */
1838 public boolean isPreferredDependency(String filename) {
1839 return preferredDependencyPredicate.apply(filename);
1840 }
1841
1842 /**
Michael Staibb51251e2015-09-29 23:31:51 +00001843 * Returns this rule's policy for configuration fragment access.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001844 */
Michael Staibb51251e2015-09-29 23:31:51 +00001845 public ConfigurationFragmentPolicy getConfigurationFragmentPolicy() {
1846 return configurationFragmentPolicy;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001847 }
1848
1849 /**
Greg Estrenc04c88f2015-03-06 19:45:50 +00001850 * Returns true if rules of this type can be used with the constraint enforcement system.
1851 */
1852 public boolean supportsConstraintChecking() {
1853 return supportsConstraintChecking;
1854 }
1855
1856 /**
Mark Schalleree624452016-01-13 18:41:24 +00001857 * Creates a new {@link Rule} {@code r} where {@code r.getPackage()} is the {@link Package}
1858 * associated with {@code pkgBuilder}.
1859 *
1860 * <p>The created {@link Rule} will be populated with attribute values from {@code
1861 * attributeValues} or the default attribute values associated with this {@link RuleClass} and
1862 * {@code pkgBuilder}.
1863 *
Florian Weikertea6c82d2016-09-05 12:15:31 +00001864 * <p>The created {@link Rule} will also be populated with output files. These output files will
1865 * have been collected from the explicitly provided values of type {@link BuildType#OUTPUT} and
1866 * {@link BuildType#OUTPUT_LIST} as well as from the implicit outputs determined by this {@link
1867 * RuleClass} and the values in {@code attributeValues}.
Mark Schalleree624452016-01-13 18:41:24 +00001868 *
1869 * <p>This performs several validity checks. Invalid output file labels result in a thrown {@link
Florian Weikertea6c82d2016-09-05 12:15:31 +00001870 * LabelSyntaxException}. Computed default attributes that fail during precomputation result in a
1871 * {@link CannotPrecomputeDefaultsException}. All other errors are reported on {@code
1872 * eventHandler}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001873 */
nharmata65a173a2017-08-07 16:11:04 +02001874 <T> Rule createRule(
Mark Schalleree624452016-01-13 18:41:24 +00001875 Package.Builder pkgBuilder,
1876 Label ruleLabel,
nharmata65a173a2017-08-07 16:11:04 +02001877 AttributeValues<T> attributeValues,
Mark Schalleree624452016-01-13 18:41:24 +00001878 EventHandler eventHandler,
1879 @Nullable FuncallExpression ast,
1880 Location location,
Greg Estren37cd5c42019-01-30 12:25:50 -08001881 AttributeContainer attributeContainer,
1882 boolean checkThirdPartyRulesHaveLicenses)
Florian Weikertea6c82d2016-09-05 12:15:31 +00001883 throws LabelSyntaxException, InterruptedException, CannotPrecomputeDefaultsException {
Michajlo Matijkiw581f2c22016-07-25 20:12:16 +00001884 Rule rule = pkgBuilder.createRule(ruleLabel, this, location, attributeContainer);
1885 populateRuleAttributeValues(rule, pkgBuilder, attributeValues, eventHandler);
1886 checkAspectAllowedValues(rule, eventHandler);
1887 rule.populateOutputFiles(eventHandler, pkgBuilder);
1888 if (ast != null) {
1889 populateAttributeLocations(rule, ast);
1890 }
1891 checkForDuplicateLabels(rule, eventHandler);
gregce4aa059a2019-02-26 13:20:47 -08001892
1893 boolean actuallyCheckLicense;
1894 if (thirdPartyLicenseExistencePolicy == ThirdPartyLicenseExistencePolicy.ALWAYS_CHECK) {
1895 actuallyCheckLicense = true;
1896 } else if (thirdPartyLicenseExistencePolicy == ThirdPartyLicenseExistencePolicy.NEVER_CHECK) {
1897 actuallyCheckLicense = false;
1898 } else {
1899 actuallyCheckLicense = checkThirdPartyRulesHaveLicenses;
1900 }
1901
1902 if (actuallyCheckLicense) {
Greg Estren37cd5c42019-01-30 12:25:50 -08001903 checkThirdPartyRuleHasLicense(rule, pkgBuilder, eventHandler);
1904 }
Michajlo Matijkiw581f2c22016-07-25 20:12:16 +00001905 checkForValidSizeAndTimeoutValues(rule, eventHandler);
1906 rule.checkValidityPredicate(eventHandler);
Nathan Harmatacf738442016-06-28 14:52:21 +00001907 rule.checkForNullLabels();
1908 return rule;
1909 }
1910
1911 /**
1912 * Same as {@link #createRule}, except without some internal sanity checks.
1913 *
1914 * <p>Don't call this function unless you know what you're doing.
1915 */
nharmata65a173a2017-08-07 16:11:04 +02001916 <T> Rule createRuleUnchecked(
Nathan Harmatacf738442016-06-28 14:52:21 +00001917 Package.Builder pkgBuilder,
1918 Label ruleLabel,
nharmata65a173a2017-08-07 16:11:04 +02001919 AttributeValues<T> attributeValues,
Nathan Harmatacf738442016-06-28 14:52:21 +00001920 Location location,
Michajlo Matijkiw6d471412016-08-09 20:35:45 +00001921 AttributeContainer attributeContainer,
1922 ImplicitOutputsFunction implicitOutputsFunction)
nharmata59c16f62017-08-07 19:49:09 +02001923 throws InterruptedException, CannotPrecomputeDefaultsException {
Michajlo Matijkiw6d471412016-08-09 20:35:45 +00001924 Rule rule = pkgBuilder.createRule(
1925 ruleLabel,
1926 this,
1927 location,
1928 attributeContainer,
1929 implicitOutputsFunction);
Michajlo Matijkiw581f2c22016-07-25 20:12:16 +00001930 populateRuleAttributeValues(rule, pkgBuilder, attributeValues, NullEventHandler.INSTANCE);
nharmata59c16f62017-08-07 19:49:09 +02001931 rule.populateOutputFilesUnchecked(NullEventHandler.INSTANCE, pkgBuilder);
Mark Schalleree624452016-01-13 18:41:24 +00001932 return rule;
1933 }
1934
1935 /**
1936 * Populates the attributes table of the new {@link Rule} with the values in the {@code
1937 * attributeValues} map and with default values provided by this {@link RuleClass} and the {@code
1938 * pkgBuilder}.
1939 *
1940 * <p>Errors are reported on {@code eventHandler}.
1941 */
nharmata65a173a2017-08-07 16:11:04 +02001942 private <T> void populateRuleAttributeValues(
Mark Schalleree624452016-01-13 18:41:24 +00001943 Rule rule,
1944 Package.Builder pkgBuilder,
nharmata65a173a2017-08-07 16:11:04 +02001945 AttributeValues<T> attributeValues,
Florian Weikertea6c82d2016-09-05 12:15:31 +00001946 EventHandler eventHandler)
1947 throws InterruptedException, CannotPrecomputeDefaultsException {
Mark Schalleree624452016-01-13 18:41:24 +00001948 BitSet definedAttrIndices =
dannarkf24479d2018-06-21 11:55:44 -07001949 populateDefinedRuleAttributeValues(
nharmataf3e99412019-01-28 10:06:29 -08001950 rule,
1951 pkgBuilder.getRepositoryMapping(),
1952 attributeValues,
1953 pkgBuilder.getListInterner(),
1954 eventHandler);
Mark Schalleree624452016-01-13 18:41:24 +00001955 populateDefaultRuleAttributeValues(rule, pkgBuilder, definedAttrIndices, eventHandler);
1956 // Now that all attributes are bound to values, collect and store configurable attribute keys.
1957 populateConfigDependenciesAttribute(rule);
1958 }
1959
1960 /**
1961 * Populates the attributes table of the new {@link Rule} with the values in the {@code
1962 * attributeValues} map.
1963 *
1964 * <p>Handles the special cases of the attribute named {@code "name"} and attributes with value
1965 * {@link Runtime#NONE}.
1966 *
dannarkf24479d2018-06-21 11:55:44 -07001967 * <p>Returns a bitset {@code b} where {@code b.get(i)} is {@code true} if this method set a value
1968 * for the attribute with index {@code i} in this {@link RuleClass}. Errors are reported on {@code
1969 * eventHandler}.
Mark Schalleree624452016-01-13 18:41:24 +00001970 */
nharmata65a173a2017-08-07 16:11:04 +02001971 private <T> BitSet populateDefinedRuleAttributeValues(
dannarkf24479d2018-06-21 11:55:44 -07001972 Rule rule,
1973 ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
1974 AttributeValues<T> attributeValues,
nharmataf3e99412019-01-28 10:06:29 -08001975 Interner<ImmutableList<?>> listInterner,
dannarkf24479d2018-06-21 11:55:44 -07001976 EventHandler eventHandler) {
Mark Schalleree624452016-01-13 18:41:24 +00001977 BitSet definedAttrIndices = new BitSet();
nharmata65a173a2017-08-07 16:11:04 +02001978 for (T attributeAccessor : attributeValues.getAttributeAccessors()) {
1979 String attributeName = attributeValues.getName(attributeAccessor);
1980 Object attributeValue = attributeValues.getValue(attributeAccessor);
Mark Schalleree624452016-01-13 18:41:24 +00001981 // Ignore all None values.
1982 if (attributeValue == Runtime.NONE) {
1983 continue;
1984 }
1985
1986 // Check that the attribute's name belongs to a valid attribute for this rule class.
1987 Integer attrIndex = getAttributeIndex(attributeName);
1988 if (attrIndex == null) {
1989 rule.reportError(
1990 String.format(
1991 "%s: no such attribute '%s' in '%s' rule", rule.getLabel(), attributeName, name),
1992 eventHandler);
1993 continue;
1994 }
1995 Attribute attr = getAttribute(attrIndex);
1996
gregce1d8d6dd2019-04-10 09:27:34 -07001997 if (attributeName.equals("licenses") && ignoreLicenses) {
1998 setRuleAttributeValue(rule, eventHandler, attr, License.NO_LICENSE, /*explicit=*/ false);
1999 definedAttrIndices.set(attrIndex);
2000 continue;
2001 }
2002
Mark Schalleree624452016-01-13 18:41:24 +00002003 // Convert the build-lang value to a native value, if necessary.
2004 Object nativeAttributeValue;
2005 if (attributeValues.valuesAreBuildLanguageTyped()) {
2006 try {
dannarkf24479d2018-06-21 11:55:44 -07002007 nativeAttributeValue =
nharmataf3e99412019-01-28 10:06:29 -08002008 convertFromBuildLangType(rule, attr, attributeValue, repositoryMapping, listInterner);
Mark Schalleree624452016-01-13 18:41:24 +00002009 } catch (ConversionException e) {
2010 rule.reportError(String.format("%s: %s", rule.getLabel(), e.getMessage()), eventHandler);
2011 continue;
2012 }
2013 } else {
2014 nativeAttributeValue = attributeValue;
2015 }
2016
nharmata65a173a2017-08-07 16:11:04 +02002017 boolean explicit = attributeValues.isExplicitlySpecified(attributeAccessor);
Mark Schalleree624452016-01-13 18:41:24 +00002018 setRuleAttributeValue(rule, eventHandler, attr, nativeAttributeValue, explicit);
2019 definedAttrIndices.set(attrIndex);
Mark Schalleree624452016-01-13 18:41:24 +00002020 }
2021 return definedAttrIndices;
2022 }
2023
2024 /** Populates attribute locations for attributes defined in {@code ast}. */
2025 private void populateAttributeLocations(Rule rule, FuncallExpression ast) {
2026 for (Argument.Passed arg : ast.getArguments()) {
2027 if (arg.isKeyword()) {
2028 String name = arg.getName();
2029 Integer attrIndex = getAttributeIndex(name);
2030 if (attrIndex != null) {
2031 rule.setAttributeLocation(attrIndex, arg.getValue().getLocation());
2032 }
2033 }
2034 }
2035 }
2036
2037 /**
2038 * Populates the attributes table of the new {@link Rule} with default values provided by this
Florian Weikertea6c82d2016-09-05 12:15:31 +00002039 * {@link RuleClass} and the {@code pkgBuilder}. This will only provide values for attributes that
2040 * haven't already been populated, using {@code definedAttrIndices} to determine whether an
Mark Schalleree624452016-01-13 18:41:24 +00002041 * attribute was populated.
2042 *
2043 * <p>Errors are reported on {@code eventHandler}.
2044 */
2045 private void populateDefaultRuleAttributeValues(
Florian Weikertea6c82d2016-09-05 12:15:31 +00002046 Rule rule, Package.Builder pkgBuilder, BitSet definedAttrIndices, EventHandler eventHandler)
2047 throws InterruptedException, CannotPrecomputeDefaultsException {
Mark Schalleree624452016-01-13 18:41:24 +00002048 // Set defaults; ensure that every mandatory attribute has a value. Use the default if none
2049 // is specified.
2050 List<Attribute> attrsWithComputedDefaults = new ArrayList<>();
2051 int numAttributes = getAttributeCount();
2052 for (int attrIndex = 0; attrIndex < numAttributes; ++attrIndex) {
2053 if (definedAttrIndices.get(attrIndex)) {
2054 continue;
2055 }
2056 Attribute attr = getAttribute(attrIndex);
2057 if (attr.isMandatory()) {
2058 rule.reportError(
2059 String.format(
2060 "%s: missing value for mandatory attribute '%s' in '%s' rule",
2061 rule.getLabel(),
2062 attr.getName(),
2063 name),
2064 eventHandler);
2065 }
2066
gregce1d8d6dd2019-04-10 09:27:34 -07002067 if (attr.getName().equals("licenses") && ignoreLicenses) {
2068 rule.setAttributeValue(attr, License.NO_LICENSE, /*explicit=*/ false);
2069 } else if (attr.hasComputedDefault()) {
Mark Schalleree624452016-01-13 18:41:24 +00002070 // Note that it is necessary to set all non-computed default values before calling
2071 // Attribute#getDefaultValue for computed default attributes. Computed default attributes
2072 // may have a condition predicate (i.e. the predicate returned by Attribute#getCondition)
2073 // that depends on non-computed default attribute values, and that condition predicate is
2074 // evaluated by the call to Attribute#getDefaultValue.
2075 attrsWithComputedDefaults.add(attr);
cparsonscaceacd2017-11-04 01:00:59 +01002076 } else if (attr.isLateBound()) {
2077 rule.setAttributeValue(attr, attr.getLateBoundDefault(), /*explicit=*/ false);
Mark Schalleree624452016-01-13 18:41:24 +00002078 } else {
2079 Object defaultValue = getAttributeNoncomputedDefaultValue(attr, pkgBuilder);
Mark Schalleree624452016-01-13 18:41:24 +00002080 rule.setAttributeValue(attr, defaultValue, /*explicit=*/ false);
2081 checkAllowedValues(rule, attr, eventHandler);
2082 }
2083 }
2084
2085 // Set computed default attribute values now that all other (i.e. non-computed) default values
2086 // have been set.
2087 for (Attribute attr : attrsWithComputedDefaults) {
Florian Weikertea6c82d2016-09-05 12:15:31 +00002088 // If Attribute#hasComputedDefault was true above, Attribute#getDefaultValue returns the
2089 // computed default function object or a Skylark computed default template. Note that we
2090 // cannot determine the exact value of the computed default function here because it may
2091 // depend on other attribute values that are configurable (i.e. they came from select({..})
2092 // expressions in the build language, and they require configuration data from the analysis
2093 // phase to be resolved). Instead, we're setting the attribute value to a reference to the
2094 // computed default function, or if #getDefaultValue is a Skylark computed default
2095 // template, setting the attribute value to a reference to the SkylarkComputedDefault
2096 // returned from SkylarkComputedDefaultTemplate#computePossibleValues.
2097 //
2098 // SkylarkComputedDefaultTemplate#computePossibleValues pre-computes all possible values the
2099 // function may evaluate to, and records them in a lookup table. By calling it here, with an
2100 // EventHandler, any errors that might occur during the function's evaluation can
2101 // be discovered and propagated here.
2102 Object valueToSet;
2103 Object defaultValue = attr.getDefaultValue(rule);
2104 if (defaultValue instanceof SkylarkComputedDefaultTemplate) {
2105 SkylarkComputedDefaultTemplate template = (SkylarkComputedDefaultTemplate) defaultValue;
2106 valueToSet = template.computePossibleValues(attr, rule, eventHandler);
schmitta4080da92019-05-20 13:12:46 -07002107 } else if (defaultValue instanceof ComputedDefault) {
2108 // Compute all possible values to verify that the ComputedDefault is well-defined. This was
2109 // previously done implicitly as part of visiting all labels to check for null-ness in
2110 // Rule.checkForNullLabels, but that was changed to skip non-label attributes to improve
2111 // performance.
2112 ((ComputedDefault) defaultValue).getPossibleValues(attr.getType(), rule);
2113 valueToSet = defaultValue;
Florian Weikertea6c82d2016-09-05 12:15:31 +00002114 } else {
2115 valueToSet = defaultValue;
2116 }
2117 rule.setAttributeValue(attr, valueToSet, /*explicit=*/ false);
Mark Schalleree624452016-01-13 18:41:24 +00002118 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002119 }
2120
2121 /**
2122 * Collects all labels used as keys for configurable attributes and places them into
2123 * the special implicit attribute that tracks them.
2124 */
2125 private static void populateConfigDependenciesAttribute(Rule rule) {
2126 RawAttributeMapper attributes = RawAttributeMapper.of(rule);
gregce749962a2019-03-08 12:47:34 -08002127 Attribute configDepsAttribute =
2128 attributes.getAttributeDefinition(CONFIG_SETTING_DEPS_ATTRIBUTE);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002129 if (configDepsAttribute == null) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002130 return;
2131 }
2132
felly7615e1a2019-05-16 03:45:26 -07002133 LinkedHashSet<Label> configLabels = new LinkedHashSet<>();
2134 for (Attribute attr : rule.getAttributes()) {
2135 SelectorList<?> selectorList = attributes.getSelectorList(attr.getName(), attr.getType());
2136 if (selectorList != null) {
2137 configLabels.addAll(selectorList.getKeyLabels());
2138 }
2139 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002140
2141 rule.setAttributeValue(configDepsAttribute, ImmutableList.copyOf(configLabels),
2142 /*explicit=*/false);
2143 }
2144
Nathan Harmatafcb17112016-04-13 16:56:58 +00002145 public void checkAttributesNonEmpty(
michajloc1062a42018-09-26 14:53:38 -07002146 RuleErrorConsumer ruleErrorConsumer, AttributeMap attributes) {
Nathan Harmatafcb17112016-04-13 16:56:58 +00002147 for (String attributeName : attributes.getAttributeNames()) {
2148 Attribute attr = attributes.getAttributeDefinition(attributeName);
2149 if (!attr.isNonEmpty()) {
2150 continue;
2151 }
2152 Object attributeValue = attributes.get(attributeName, attr.getType());
Francois-Rene Rideau93ed7f12015-10-20 15:39:33 +00002153
Nathan Harmatafcb17112016-04-13 16:56:58 +00002154 boolean isEmpty = false;
2155 if (attributeValue instanceof SkylarkList) {
michajloc1062a42018-09-26 14:53:38 -07002156 isEmpty = ((SkylarkList<?>) attributeValue).isEmpty();
Nathan Harmatafcb17112016-04-13 16:56:58 +00002157 } else if (attributeValue instanceof List<?>) {
2158 isEmpty = ((List<?>) attributeValue).isEmpty();
2159 } else if (attributeValue instanceof Map<?, ?>) {
2160 isEmpty = ((Map<?, ?>) attributeValue).isEmpty();
2161 }
Francois-Rene Rideau5e00ec62015-10-20 17:02:19 +00002162
Nathan Harmatafcb17112016-04-13 16:56:58 +00002163 if (isEmpty) {
2164 ruleErrorConsumer.attributeError(attr.getName(), "attribute must be non empty");
2165 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002166 }
2167 }
2168
2169 /**
2170 * Report an error for each label that appears more than once in a LABEL_LIST attribute
2171 * of the given rule.
2172 *
2173 * @param rule The rule.
2174 * @param eventHandler The eventHandler to use to report the duplicated deps.
2175 */
2176 private static void checkForDuplicateLabels(Rule rule, EventHandler eventHandler) {
2177 for (Attribute attribute : rule.getAttributes()) {
Lukacs Berkiffa73ad2015-09-18 11:40:12 +00002178 if (attribute.getType() == BuildType.LABEL_LIST) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002179 checkForDuplicateLabels(rule, attribute, eventHandler);
2180 }
2181 }
2182 }
2183
2184 /**
2185 * Reports an error against the specified rule if it's beneath third_party
2186 * but does not have a declared license.
2187 */
2188 private static void checkThirdPartyRuleHasLicense(Rule rule,
Han-Wen Nienhuys086e5f22015-04-21 11:39:59 +00002189 Package.Builder pkgBuilder, EventHandler eventHandler) {
gregce1d8d6dd2019-04-10 09:27:34 -07002190 if (rule.getRuleClassObject().ignoreLicenses()) {
Googlerfdb17eb2019-01-28 15:14:32 -08002191 // A package license is sufficient; ignore rules that don't include it.
2192 return;
2193 }
Brian Silvermand7d6d622016-03-17 09:53:39 +00002194 if (isThirdPartyPackage(rule.getLabel().getPackageIdentifier())) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002195 License license = rule.getLicense();
2196 if (license == null) {
2197 license = pkgBuilder.getDefaultLicense();
2198 }
lberki0d8d4cf2017-09-05 16:01:44 +02002199 if (!license.isSpecified()) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002200 rule.reportError("third-party rule '" + rule.getLabel() + "' lacks a license declaration "
2201 + "with one of the following types: notice, reciprocal, permissive, "
2202 + "restricted, unencumbered, by_exception_only",
2203 eventHandler);
2204 }
2205 }
2206 }
2207
2208 /**
2209 * Report an error for each label that appears more than once in the given attribute
2210 * of the given rule.
2211 *
2212 * @param rule The rule.
2213 * @param attribute The attribute to check. Must exist in rule and be of type LABEL_LIST.
2214 * @param eventHandler The eventHandler to use to report the duplicated deps.
2215 */
2216 private static void checkForDuplicateLabels(Rule rule, Attribute attribute,
2217 EventHandler eventHandler) {
Greg Estren14348c02015-04-16 16:26:19 +00002218 Set<Label> duplicates = AggregatingAttributeMapper.of(rule).checkForDuplicateLabels(attribute);
2219 for (Label label : duplicates) {
2220 rule.reportError(
2221 String.format("Label '%s' is duplicated in the '%s' attribute of rule '%s'",
2222 label, attribute.getName(), rule.getName()), eventHandler);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002223 }
2224 }
2225
2226 /**
2227 * Report an error if the rule has a timeout or size attribute that is not a
2228 * legal value. These attributes appear on all tests.
2229 *
2230 * @param rule the rule to check
2231 * @param eventHandler the eventHandler to use to report the duplicated deps
2232 */
2233 private static void checkForValidSizeAndTimeoutValues(Rule rule, EventHandler eventHandler) {
2234 if (rule.getRuleClassObject().hasAttr("size", Type.STRING)) {
2235 String size = NonconfigurableAttributeMapper.of(rule).get("size", Type.STRING);
2236 if (TestSize.getTestSize(size) == null) {
2237 rule.reportError(
2238 String.format("In rule '%s', size '%s' is not a valid size.", rule.getName(), size),
2239 eventHandler);
2240 }
2241 }
2242 if (rule.getRuleClassObject().hasAttr("timeout", Type.STRING)) {
2243 String timeout = NonconfigurableAttributeMapper.of(rule).get("timeout", Type.STRING);
2244 if (TestTimeout.getTestTimeout(timeout) == null) {
2245 rule.reportError(
2246 String.format(
2247 "In rule '%s', timeout '%s' is not a valid timeout.", rule.getName(), timeout),
2248 eventHandler);
2249 }
2250 }
2251 }
2252
2253 /**
2254 * Returns the default value for the specified rule attribute.
2255 *
Francois-Rene Rideau5dcdbf92015-02-19 18:36:17 +00002256 * <p>For most rule attributes, the default value is either explicitly specified
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002257 * in the attribute, or implicitly based on the type of the attribute, except
2258 * for some special cases (e.g. "licenses", "distribs") where it comes from
2259 * some other source, such as state in the package.
2260 *
Francois-Rene Rideau5dcdbf92015-02-19 18:36:17 +00002261 * <p>Precondition: {@code !attr.hasComputedDefault()}. (Computed defaults are
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002262 * evaluated in second pass.)
2263 */
2264 private static Object getAttributeNoncomputedDefaultValue(Attribute attr,
Han-Wen Nienhuys086e5f22015-04-21 11:39:59 +00002265 Package.Builder pkgBuilder) {
gregce82281ad2019-02-27 08:01:07 -08002266 // Starlark rules may define their own "licenses" attributes with different types -
2267 // we shouldn't trigger the special "licenses" on those cases.
2268 if (attr.getName().equals("licenses") && attr.getType() == BuildType.LICENSE) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002269 return pkgBuilder.getDefaultLicense();
2270 }
2271 if (attr.getName().equals("distribs")) {
2272 return pkgBuilder.getDefaultDistribs();
2273 }
2274 return attr.getDefaultValue(null);
2275 }
2276
2277 /**
Mark Schalleree624452016-01-13 18:41:24 +00002278 * Sets the value of attribute {@code attr} in {@code rule} to the native value {@code
2279 * nativeAttrVal}, and sets the value's explicitness to {@code explicit}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002280 *
Mark Schalleree624452016-01-13 18:41:24 +00002281 * <p>Handles the special case of the "visibility" attribute by also setting the rule's
2282 * visibility with {@link Rule#setVisibility}.
2283 *
2284 * <p>Checks that {@code nativeAttrVal} is an allowed value via {@link #checkAllowedValues}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002285 */
Mark Schalleree624452016-01-13 18:41:24 +00002286 private static void setRuleAttributeValue(
2287 Rule rule,
2288 EventHandler eventHandler,
2289 Attribute attr,
2290 Object nativeAttrVal,
2291 boolean explicit) {
2292 if (attr.getName().equals("visibility")) {
2293 @SuppressWarnings("unchecked")
2294 List<Label> attrList = (List<Label>) nativeAttrVal;
Francois-Rene Rideaucbebd632015-02-11 16:56:37 +00002295 if (!attrList.isEmpty()
2296 && ConstantRuleVisibility.LEGACY_PUBLIC_LABEL.equals(attrList.get(0))) {
Mark Schalleree624452016-01-13 18:41:24 +00002297 rule.reportError(
2298 rule.getLabel() + ": //visibility:legacy_public only allowed in package declaration",
2299 eventHandler);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002300 }
Yue Gan36a26572016-05-25 11:48:10 +00002301 try {
2302 rule.setVisibility(PackageFactory.getVisibility(rule.getLabel(), attrList));
2303 } catch (EvalException e) {
2304 rule.reportError(rule.getLabel() + " " + e.getMessage(), eventHandler);
2305 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002306 }
Mark Schalleree624452016-01-13 18:41:24 +00002307 rule.setAttributeValue(attr, nativeAttrVal, explicit);
Michael Staibff938b32015-08-27 19:22:59 +00002308 checkAllowedValues(rule, attr, eventHandler);
Mark Schalleree624452016-01-13 18:41:24 +00002309 }
2310
2311 /**
2312 * Converts the build-language-typed {@code buildLangValue} to a native value via {@link
laurentlb1d273cd2018-05-16 12:12:26 -07002313 * BuildType#selectableConvert}. Canonicalizes the value's order if it is a {@link List} type and
2314 * {@code attr.isOrderIndependent()} returns {@code true}.
Mark Schalleree624452016-01-13 18:41:24 +00002315 *
laurentlb1d273cd2018-05-16 12:12:26 -07002316 * <p>Throws {@link ConversionException} if the conversion fails, or if {@code buildLangValue} is
2317 * a selector expression but {@code attr.isConfigurable()} is {@code false}.
Mark Schalleree624452016-01-13 18:41:24 +00002318 */
dannarkf24479d2018-06-21 11:55:44 -07002319 private static Object convertFromBuildLangType(
2320 Rule rule,
2321 Attribute attr,
2322 Object buildLangValue,
nharmataf3e99412019-01-28 10:06:29 -08002323 ImmutableMap<RepositoryName, RepositoryName> repositoryMapping,
2324 Interner<ImmutableList<?>> listInterner)
Mark Schalleree624452016-01-13 18:41:24 +00002325 throws ConversionException {
dannarkf24479d2018-06-21 11:55:44 -07002326 LabelConversionContext context = new LabelConversionContext(rule.getLabel(), repositoryMapping);
2327 Object converted =
2328 BuildType.selectableConvert(
2329 attr.getType(),
2330 buildLangValue,
2331 new AttributeConversionContext(attr.getName(), rule.getRuleClass()),
2332 context);
Mark Schalleree624452016-01-13 18:41:24 +00002333
2334 if ((converted instanceof SelectorList<?>) && !attr.isConfigurable()) {
2335 throw new ConversionException(
2336 String.format("attribute \"%s\" is not configurable", attr.getName()));
2337 }
2338
laurentlb1d273cd2018-05-16 12:12:26 -07002339 if (converted instanceof List<?>) {
Mark Schalleree624452016-01-13 18:41:24 +00002340 if (attr.isOrderIndependent()) {
2341 @SuppressWarnings("unchecked")
2342 List<? extends Comparable<?>> list = (List<? extends Comparable<?>>) converted;
2343 converted = Ordering.natural().sortedCopy(list);
2344 }
nharmataf3e99412019-01-28 10:06:29 -08002345 // It's common for multiple rule instances in the same package to have the same value for some
2346 // attributes. As a concrete example, consider a package having several 'java_test' instances,
2347 // each with the same exact 'tags' attribute value.
2348 converted = listInterner.intern(ImmutableList.copyOf((List<?>) converted));
Mark Schalleree624452016-01-13 18:41:24 +00002349 }
2350
2351 return converted;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002352 }
2353
Michael Staibff938b32015-08-27 19:22:59 +00002354 /**
Michajlo Matijkiw7b7fce12016-09-20 19:52:07 +00002355 * Provides a {@link #toString()} description of the attribute being converted for
2356 * {@link BuildType#selectableConvert}. This is preferred over a raw string to avoid uselessly
2357 * constructing strings which are never used. A separate class instead of inline to avoid
2358 * accidental memory leaks.
2359 */
2360 private static class AttributeConversionContext {
2361 private final String attrName;
2362 private final String ruleClass;
2363
2364 AttributeConversionContext(String attrName, String ruleClass) {
2365 this.attrName = attrName;
2366 this.ruleClass = ruleClass;
2367 }
2368
2369 @Override
2370 public String toString() {
2371 return "attribute '" + attrName + "' in '" + ruleClass + "' rule";
2372 }
2373 }
2374
2375
2376 /**
Michael Staibff938b32015-08-27 19:22:59 +00002377 * Verifies that the rule has a valid value for the attribute according to its allowed values.
2378 *
2379 * <p>If the value for the given attribute on the given rule is invalid, an error will be recorded
2380 * in the given EventHandler.
2381 *
2382 * <p>If the rule is configurable, all of its potential values are evaluated, and errors for each
2383 * of the invalid values are reported.
2384 */
Mark Schalleree624452016-01-13 18:41:24 +00002385 private static void checkAllowedValues(
2386 Rule rule, Attribute attribute, EventHandler eventHandler) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002387 if (attribute.checkAllowedValues()) {
2388 PredicateWithMessage<Object> allowedValues = attribute.getAllowedValues();
Michael Staibff938b32015-08-27 19:22:59 +00002389 Iterable<?> values =
2390 AggregatingAttributeMapper.of(rule).visitAttribute(
2391 attribute.getName(), attribute.getType());
2392 for (Object value : values) {
2393 if (!allowedValues.apply(value)) {
Mark Schalleree624452016-01-13 18:41:24 +00002394 rule.reportError(
2395 String.format(
2396 "%s: invalid value in '%s' attribute: %s",
2397 rule.getLabel(),
2398 attribute.getName(),
2399 allowedValues.getErrorReason(value)),
2400 eventHandler);
Michael Staibff938b32015-08-27 19:22:59 +00002401 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002402 }
2403 }
2404 }
2405
Googler74558fc2016-05-06 21:47:42 +00002406 private static void checkAspectAllowedValues(
2407 Rule rule, EventHandler eventHandler) {
2408 for (Attribute attrOfRule : rule.getAttributes()) {
2409 for (Aspect aspect : attrOfRule.getAspects(rule)) {
2410 for (Attribute attrOfAspect : aspect.getDefinition().getAttributes().values()) {
2411 // By this point the AspectDefinition has been created and values assigned.
2412 if (attrOfAspect.checkAllowedValues()) {
2413 PredicateWithMessage<Object> allowedValues = attrOfAspect.getAllowedValues();
2414 Object value = attrOfAspect.getDefaultValue(rule);
2415 if (!allowedValues.apply(value)) {
gregce7deab0a2019-03-11 12:20:05 -07002416 if (RawAttributeMapper.of(rule).isConfigurable(attrOfAspect.getName())) {
2417 rule.reportError(
2418 String.format(
2419 "%s: attribute '%s' has a select() and aspect %s also declares "
2420 + "'%s'. Aspect attributes don't currently support select().",
2421 rule.getLabel(),
2422 attrOfAspect.getName(),
2423 aspect.getDefinition().getName(),
2424 rule.getLabel()),
2425 eventHandler);
2426 } else {
2427 rule.reportError(
2428 String.format(
2429 "%s: invalid value in '%s' attribute: %s",
2430 rule.getLabel(),
2431 attrOfAspect.getName(),
2432 allowedValues.getErrorReason(value)),
2433 eventHandler);
2434 }
Googler74558fc2016-05-06 21:47:42 +00002435 }
2436 }
2437 }
2438 }
2439 }
2440 }
2441
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002442 @Override
2443 public String toString() {
2444 return name;
2445 }
2446
2447 public boolean isDocumented() {
2448 return documented;
2449 }
2450
2451 public boolean isPublicByDefault() {
2452 return publicByDefault;
2453 }
2454
2455 /**
2456 * Returns true iff the outputs of this rule should be created beneath the
2457 * <i>bin</i> directory, false if beneath <i>genfiles</i>. For most rule
2458 * classes, this is a constant, but for genrule, it is a property of the
2459 * individual rule instance, derived from the 'output_to_bindir' attribute;
2460 * see Rule.hasBinaryOutput().
2461 */
Laurent Le Brunc2efe452015-04-08 16:27:21 +00002462 @VisibleForTesting
2463 public boolean hasBinaryOutput() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002464 return binaryOutput;
2465 }
2466
2467 /**
2468 * Returns this RuleClass's custom Skylark rule implementation.
2469 */
Francois-Rene Rideau95b0d0c2015-04-22 16:52:13 +00002470 @Nullable public BaseFunction getConfiguredTargetFunction() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002471 return configuredTargetFunction;
2472 }
2473
juliexxia1f332e02018-10-31 14:20:55 -07002474 @Nullable
2475 public BuildSetting getBuildSetting() {
2476 return buildSetting;
2477 }
2478
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002479 /**
Lukacs Berki0e1a9942015-06-18 08:53:18 +00002480 * Returns a function that computes the external bindings a repository function contributes to
2481 * the WORKSPACE file.
2482 */
2483 public Function<? super Rule, Map<String, Label>> getExternalBindingsFunction() {
2484 return externalBindingsFunction;
2485 }
2486
2487 /**
mstaibe5538ad2017-04-04 18:32:23 +00002488 * Returns a function that computes the options referenced by a rule.
2489 */
2490 public Function<? super Rule, ? extends Set<String>> getOptionReferenceFunction() {
2491 return optionReferenceFunction;
2492 }
2493
2494 /**
janakrd3fe5e72018-03-30 12:49:12 -07002495 * For Skylark rule classes, returns this RuleClass's rule definition environment's label, which
2496 * is never null. Is null for native rules' RuleClass objects.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002497 */
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00002498 @Nullable
janakrd3fe5e72018-03-30 12:49:12 -07002499 public Label getRuleDefinitionEnvironmentLabel() {
2500 return ruleDefinitionEnvironmentLabel;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002501 }
2502
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00002503 /**
janakrd3fe5e72018-03-30 12:49:12 -07002504 * Returns the hash code for the RuleClass's rule definition environment. Will be null for native
2505 * rules' RuleClass objects.
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00002506 */
2507 @Nullable
2508 public String getRuleDefinitionEnvironmentHashCode() {
2509 return ruleDefinitionEnvironmentHashCode;
2510 }
2511
Jon Brandveinead58ae2016-09-29 18:41:10 +00002512 /** Returns true if this RuleClass is a Skylark-defined RuleClass. */
Michajlo Matijkiwbc042c62015-10-29 13:22:52 +00002513 public boolean isSkylark() {
2514 return isSkylark;
2515 }
2516
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002517 /**
Jon Brandveinead58ae2016-09-29 18:41:10 +00002518 * Returns true if this RuleClass is Skylark-defined and is subject to analysis-time
2519 * tests.
2520 */
2521 public boolean isSkylarkTestable() {
2522 return skylarkTestable;
2523 }
2524
2525 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002526 * Returns true if this rule class outputs a default executable for every rule.
2527 */
dslomov2ce98442017-10-23 19:14:02 +02002528 public boolean isExecutableSkylark() {
2529 return isExecutableSkylark;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002530 }
Brian Silvermand7d6d622016-03-17 09:53:39 +00002531
cparsons55781c92018-10-17 12:03:08 -07002532 /** Returns true if this rule class is an analysis test (set by analysis_test = true). */
2533 public boolean isAnalysisTest() {
2534 return isAnalysisTest;
2535 }
2536
Googlerc2200fd2018-09-14 17:35:59 -07002537 /**
cparsons9d40c6b2019-02-25 12:24:40 -08002538 * Returns true if this rule class has at least one attribute with an analysis test transition. (A
2539 * starlark-defined transition using analysis_test_transition()).
2540 */
2541 public boolean hasAnalysisTestTransition() {
2542 return hasAnalysisTestTransition;
2543 }
2544
2545 /**
Googlerc2200fd2018-09-14 17:35:59 -07002546 * Returns true if this rule class has the _whitelist_function_transition attribute.
2547 */
2548 public boolean hasFunctionTransitionWhitelist() {
2549 return hasFunctionTransitionWhitelist;
2550 }
2551
gregce1d8d6dd2019-04-10 09:27:34 -07002552 /**
2553 * If true, no rule of this class ever declares a license regardless of what the rule's or
2554 * package's <code>licenses</code> attribute says.
2555 *
2556 * <p>This is useful for rule types that don't make sense for license checking.
2557 */
2558 public boolean ignoreLicenses() {
2559 return ignoreLicenses;
Googlerfdb17eb2019-01-28 15:14:32 -08002560 }
2561
cpeyserfb829992017-09-07 17:17:03 +02002562 public ImmutableSet<Label> getRequiredToolchains() {
John Catereca28402017-05-17 21:44:12 +02002563 return requiredToolchains;
2564 }
2565
jcater01bb1f92019-06-17 12:09:11 -07002566 public boolean useToolchainResolution() {
2567 return useToolchainResolution;
John Cater856b4dd2017-11-21 08:06:16 -08002568 }
2569
John Cateree45c662018-06-05 11:09:01 -07002570 public ExecutionPlatformConstraintsAllowed executionPlatformConstraintsAllowed() {
2571 return executionPlatformConstraintsAllowed;
2572 }
2573
2574 public ImmutableSet<Label> getExecutionPlatformConstraints() {
2575 return executionPlatformConstraints;
2576 }
2577
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -07002578 public OutputFile.Kind getOutputFileKind() {
2579 return outputFileKind;
2580 }
2581
Brian Silvermand7d6d622016-03-17 09:53:39 +00002582 public static boolean isThirdPartyPackage(PackageIdentifier packageIdentifier) {
2583 if (!packageIdentifier.getRepository().isMain()) {
2584 return false;
2585 }
2586
2587 if (!packageIdentifier.getPackageFragment().startsWith(THIRD_PARTY_PREFIX)) {
2588 return false;
2589 }
2590
2591 if (packageIdentifier.getPackageFragment().segmentCount() <= 1) {
2592 return false;
2593 }
2594
2595 return true;
2596 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002597}