blob: d83246871da6fe42479ccd6eabd6796e2fd8a19f [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
Florian Weikertea6c82d2016-09-05 12:15:31 +000017import static com.google.devtools.build.lib.packages.Attribute.attr;
Lukacs Berkiffa73ad2015-09-18 11:40:12 +000018import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
19import static com.google.devtools.build.lib.syntax.Type.BOOLEAN;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010020
21import com.google.common.annotations.VisibleForTesting;
Lukacs Berki0e1a9942015-06-18 08:53:18 +000022import com.google.common.base.Function;
23import com.google.common.base.Functions;
tomlua155b532017-11-08 20:12:47 +010024import com.google.common.base.Preconditions;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010025import com.google.common.base.Predicate;
26import com.google.common.base.Predicates;
27import com.google.common.collect.ImmutableList;
Lukacs Berki0e1a9942015-06-18 08:53:18 +000028import com.google.common.collect.ImmutableMap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010029import com.google.common.collect.ImmutableSet;
John Cater9a8d16e2017-07-05 16:12:07 -040030import com.google.common.collect.Iterables;
cpeyserd852e482017-09-07 22:16:06 +020031import com.google.common.collect.Lists;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010032import com.google.common.collect.Ordering;
gregcebe55e112018-01-30 11:04:53 -080033import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition;
mstaib860975a2018-04-26 15:00:52 -070034import com.google.devtools.build.lib.analysis.config.transitions.PatchTransition;
gregce74a895d2018-05-29 11:26:03 -070035import com.google.devtools.build.lib.analysis.config.transitions.SplitTransition;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000036import com.google.devtools.build.lib.cmdline.Label;
Lukacs Berkia6434362015-09-15 13:56:14 +000037import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
Brian Silvermand7d6d622016-03-17 09:53:39 +000038import com.google.devtools.build.lib.cmdline.PackageIdentifier;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010039import com.google.devtools.build.lib.events.EventHandler;
40import com.google.devtools.build.lib.events.Location;
Michajlo Matijkiw581f2c22016-07-25 20:12:16 +000041import com.google.devtools.build.lib.events.NullEventHandler;
Florian Weikertea6c82d2016-09-05 12:15:31 +000042import com.google.devtools.build.lib.packages.Attribute.SkylarkComputedDefaultTemplate;
43import com.google.devtools.build.lib.packages.Attribute.SkylarkComputedDefaultTemplate.CannotPrecomputeDefaultsException;
Lukacs Berkiffa73ad2015-09-18 11:40:12 +000044import com.google.devtools.build.lib.packages.BuildType.SelectorList;
Michael Staibb51251e2015-09-29 23:31:51 +000045import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy.MissingFragmentPolicy;
janakr6ff110e2018-03-21 21:44:27 -070046import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
nharmata65a173a2017-08-07 16:11:04 +020047import com.google.devtools.build.lib.packages.RuleFactory.AttributeValues;
mjhalupka49581922018-02-28 11:04:31 -080048import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
49import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010050import com.google.devtools.build.lib.syntax.Argument;
Francois-Rene Rideau95b0d0c2015-04-22 16:52:13 +000051import com.google.devtools.build.lib.syntax.BaseFunction;
Yue Gan36a26572016-05-25 11:48:10 +000052import com.google.devtools.build.lib.syntax.EvalException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010053import com.google.devtools.build.lib.syntax.FuncallExpression;
Francois-Rene Rideau0f7ba342015-08-31 16:16:21 +000054import com.google.devtools.build.lib.syntax.Runtime;
Francois-Rene Rideau93ed7f12015-10-20 15:39:33 +000055import com.google.devtools.build.lib.syntax.SkylarkList;
Lukacs Berkiffa73ad2015-09-18 11:40:12 +000056import com.google.devtools.build.lib.syntax.Type;
Mark Schalleree624452016-01-13 18:41:24 +000057import com.google.devtools.build.lib.syntax.Type.ConversionException;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010058import com.google.devtools.build.lib.util.StringUtil;
59import com.google.devtools.build.lib.vfs.PathFragment;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010060import java.util.ArrayList;
Googler72f3a102017-12-01 16:28:28 -080061import java.util.Arrays;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010062import java.util.BitSet;
63import java.util.Collection;
gregceda4c9592017-07-27 22:09:34 +020064import java.util.Collections;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010065import java.util.HashMap;
cpeyserfb829992017-09-07 17:17:03 +020066import java.util.HashSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010067import java.util.LinkedHashMap;
68import java.util.LinkedHashSet;
69import java.util.List;
70import java.util.Map;
mjhalupka49581922018-02-28 11:04:31 -080071import java.util.Objects;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010072import java.util.Set;
73import java.util.regex.Pattern;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010074import javax.annotation.Nullable;
75import javax.annotation.concurrent.Immutable;
76
77/**
78 * Instances of RuleClass encapsulate the set of attributes of a given "class" of rule, such as
79 * <code>cc_binary</code>.
80 *
janakrd3fe5e72018-03-30 12:49:12 -070081 * <p>This is an instance of the "meta-class" pattern for Rules: we achieve using <i>values</i> what
82 * subclasses achieve using <i>types</i>. (The "Design Patterns" book doesn't include this pattern,
83 * so think of it as something like a cross between a Flyweight and a State pattern. Like Flyweight,
84 * we avoid repeatedly storing data that belongs to many instances. Like State, we delegate from
85 * Rule to RuleClass for the specific behavior of that rule (though unlike state, a Rule object
86 * never changes its RuleClass). This avoids the need to declare one Java class per class of Rule,
87 * yet achieves the same behavior.)
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010088 *
89 * <p>The use of a metaclass also allows us to compute a mapping from Attributes to small integers
janakrd3fe5e72018-03-30 12:49:12 -070090 * 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 +010091 * dictionary for each rule instance using an array, which is much more compact than a hashtable.
92 *
93 * <p>Rule classes whose names start with "$" are considered "abstract"; since they are not valid
94 * identifiers, they cannot be named in the build language. However, they are useful for grouping
95 * related attributes which are inherited.
96 *
janakrd3fe5e72018-03-30 12:49:12 -070097 * <p>The exact values in this class are important. In particular:
98 *
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010099 * <ul>
janakrd3fe5e72018-03-30 12:49:12 -0700100 * <li>Changing an attribute from MANDATORY to OPTIONAL creates the potential for null-pointer
101 * exceptions in code that expects a value.
102 * <li>Attributes whose names are preceded by a "$" or a ":" are "hidden", and cannot be redefined
103 * in a BUILD file. They are a useful way of adding a special dependency. By convention,
104 * attributes starting with "$" are implicit dependencies, and those starting with a ":" are
105 * late-bound implicit dependencies, i.e. dependencies that can only be resolved when the
106 * configuration is known.
107 * <li>Attributes should not be introduced into the hierarchy higher then necessary.
108 * <li>The 'deps' and 'data' attributes are treated specially by the code that builds the runfiles
109 * tree. All targets appearing in these attributes appears beneath the ".runfiles" tree; in
110 * addition, "deps" may have rule-specific semantics.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100111 * </ul>
112 */
Janak Ramakrishnanc97ec7b2017-02-15 23:58:24 +0000113// Non-final only for mocking in tests. Do not subclass!
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100114@Immutable
janakrd3fe5e72018-03-30 12:49:12 -0700115@AutoCodec
Janak Ramakrishnanc97ec7b2017-02-15 23:58:24 +0000116public class RuleClass {
janakrd3fe5e72018-03-30 12:49:12 -0700117 @AutoCodec
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000118 static final Function<? super Rule, Map<String, Label>> NO_EXTERNAL_BINDINGS =
119 Functions.<Map<String, Label>>constant(ImmutableMap.<String, Label>of());
janakrd3fe5e72018-03-30 12:49:12 -0700120
121 @AutoCodec
mstaibe5538ad2017-04-04 18:32:23 +0000122 static final Function<? super Rule, Set<String>> NO_OPTION_REFERENCE =
123 Functions.<Set<String>>constant(ImmutableSet.<String>of());
Brian Silvermand7d6d622016-03-17 09:53:39 +0000124
nharmatab4060b62017-04-04 17:11:39 +0000125 public static final PathFragment THIRD_PARTY_PREFIX = PathFragment.create("third_party");
Brian Silvermand7d6d622016-03-17 09:53:39 +0000126
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100127 /**
128 * A constraint for the package name of the Rule instances.
129 */
130 public static class PackageNameConstraint implements PredicateWithMessage<Rule> {
131
132 public static final int ANY_SEGMENT = 0;
133
134 private final int pathSegment;
135
136 private final Set<String> values;
137
138 /**
139 * The pathSegment-th segment of the package must be one of the specified values.
140 * The path segment indexing starts from 1.
141 */
142 public PackageNameConstraint(int pathSegment, String... values) {
143 this.values = ImmutableSet.copyOf(values);
144 this.pathSegment = pathSegment;
145 }
146
147 @Override
148 public boolean apply(Rule input) {
149 PathFragment path = input.getLabel().getPackageFragment();
150 if (pathSegment == ANY_SEGMENT) {
151 return path.getFirstSegment(values) != PathFragment.INVALID_SEGMENT;
152 } else {
153 return path.segmentCount() >= pathSegment
154 && values.contains(path.getSegment(pathSegment - 1));
155 }
156 }
157
158 @Override
159 public String getErrorReason(Rule param) {
160 if (pathSegment == ANY_SEGMENT) {
Francois-Rene Rideaucbebd632015-02-11 16:56:37 +0000161 return param.getRuleClass() + " rules have to be under a "
162 + StringUtil.joinEnglishList(values, "or", "'") + " directory";
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100163 } else if (pathSegment == 1) {
164 return param.getRuleClass() + " rules are only allowed in "
165 + StringUtil.joinEnglishList(StringUtil.append(values, "//", ""), "or");
166 } else {
Francois-Rene Rideaucbebd632015-02-11 16:56:37 +0000167 return param.getRuleClass() + " rules are only allowed in packages which "
168 + StringUtil.ordinal(pathSegment) + " is " + StringUtil.joinEnglishList(values, "or");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100169 }
170 }
171
172 @VisibleForTesting
173 public int getPathSegment() {
174 return pathSegment;
175 }
176
177 @VisibleForTesting
178 public Collection<String> getValues() {
179 return values;
180 }
181 }
182
cparsonse2d200f2018-03-06 16:15:11 -0800183 /** A factory or builder class for rule implementations. */
184 public interface ConfiguredTargetFactory<
185 TConfiguredTarget, TContext, TActionConflictException extends Throwable> {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100186 /**
187 * Returns a fully initialized configured target instance using the given context.
Chris Parsons4dfb22c2016-05-23 17:39:42 +0000188 *
189 * @throws RuleErrorException if configured target creation could not be completed due to rule
cparsonse2d200f2018-03-06 16:15:11 -0800190 * errors
191 * @throws TActionConflictException if there were conflicts during action registration
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100192 */
cparsonse2d200f2018-03-06 16:15:11 -0800193 TConfiguredTarget create(TContext ruleContext)
194 throws InterruptedException, RuleErrorException, TActionConflictException;
Chris Parsons4dfb22c2016-05-23 17:39:42 +0000195
196 /**
cparsonse2d200f2018-03-06 16:15:11 -0800197 * Exception indicating that configured target creation could not be completed. General error
198 * messaging should be done via {@link RuleErrorConsumer}; this exception only interrupts
199 * configured target creation in cases where it can no longer continue.
Chris Parsons4dfb22c2016-05-23 17:39:42 +0000200 */
201 public static final class RuleErrorException extends Exception {}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100202 }
203
204 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100205 * For Bazel's constraint system: the attribute that declares the set of environments a rule
206 * supports, overriding the defaults for their respective groups.
207 */
208 public static final String RESTRICTED_ENVIRONMENT_ATTR = "restricted_to";
209
210 /**
211 * For Bazel's constraint system: the attribute that declares the set of environments a rule
212 * supports, appending them to the defaults for their respective groups.
213 */
214 public static final String COMPATIBLE_ENVIRONMENT_ATTR = "compatible_with";
215
216 /**
217 * For Bazel's constraint system: the implicit attribute used to store rule class restriction
218 * defaults as specified by {@link Builder#restrictedTo}.
219 */
220 public static final String DEFAULT_RESTRICTED_ENVIRONMENT_ATTR =
221 "$" + RESTRICTED_ENVIRONMENT_ATTR;
222
223 /**
224 * For Bazel's constraint system: the implicit attribute used to store rule class compatibility
225 * defaults as specified by {@link Builder#compatibleWith}.
226 */
227 public static final String DEFAULT_COMPATIBLE_ENVIRONMENT_ATTR =
228 "$" + COMPATIBLE_ENVIRONMENT_ATTR;
229
230 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100231 * A support class to make it easier to create {@code RuleClass} instances.
232 * This class follows the 'fluent builder' pattern.
233 *
234 * <p>The {@link #addAttribute} method will throw an exception if an attribute
235 * of that name already exists. Use {@link #overrideAttribute} in that case.
236 */
237 public static final class Builder {
Laurent Le Brun6ce51e12015-07-07 11:54:41 +0000238 private static final Pattern RULE_NAME_PATTERN = Pattern.compile("[A-Za-z_][A-Za-z0-9_]*");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100239
240 /**
241 * The type of the rule class, which determines valid names and required
242 * attributes.
243 */
244 public enum RuleClassType {
245 /**
246 * Abstract rules are intended for rule classes that are just used to
247 * factor out common attributes, and for rule classes that are used only
248 * internally. These rules cannot be instantiated by a BUILD file.
249 *
250 * <p>The rule name must contain a '$' and {@link
251 * TargetUtils#isTestRuleName} must return false for the name.
252 */
253 ABSTRACT {
254 @Override
255 public void checkName(String name) {
256 Preconditions.checkArgument(
Ulf Adams07dba942015-03-05 14:47:37 +0000257 (name.contains("$") && !TargetUtils.isTestRuleName(name)) || name.isEmpty());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100258 }
259
260 @Override
261 public void checkAttributes(Map<String, Attribute> attributes) {
262 // No required attributes.
263 }
264 },
265
266 /**
267 * Invisible rule classes should contain a dollar sign so that they cannot be instantiated
268 * by the user. They are different from abstract rules in that they can be instantiated
269 * at will.
270 */
271 INVISIBLE {
272 @Override
273 public void checkName(String name) {
274 Preconditions.checkArgument(name.contains("$"));
275 }
276
277 @Override
278 public void checkAttributes(Map<String, Attribute> attributes) {
279 // No required attributes.
280 }
281 },
282
283 /**
284 * Normal rules are instantiable by BUILD files. Their names must therefore
285 * obey the rules for identifiers in the BUILD language. In addition,
286 * {@link TargetUtils#isTestRuleName} must return false for the name.
287 */
288 NORMAL {
289 @Override
290 public void checkName(String name) {
Ulf Adams07dba942015-03-05 14:47:37 +0000291 Preconditions.checkArgument(
292 !TargetUtils.isTestRuleName(name) && RULE_NAME_PATTERN.matcher(name).matches(),
293 "Invalid rule name: %s", name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100294 }
295
296 @Override
297 public void checkAttributes(Map<String, Attribute> attributes) {
298 for (Attribute attribute : REQUIRED_ATTRIBUTES_FOR_NORMAL_RULES) {
299 Attribute presentAttribute = attributes.get(attribute.getName());
300 Preconditions.checkState(presentAttribute != null,
301 "Missing mandatory '%s' attribute in normal rule class.", attribute.getName());
302 Preconditions.checkState(presentAttribute.getType().equals(attribute.getType()),
Francois-Rene Rideaucbebd632015-02-11 16:56:37 +0000303 "Mandatory attribute '%s' in normal rule class has incorrect type (expected"
304 + " %s).", attribute.getName(), attribute.getType());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100305 }
306 }
307 },
308
309 /**
310 * Workspace rules can only be instantiated from a WORKSPACE file. Their names obey the
311 * rule for identifiers.
312 */
313 WORKSPACE {
314 @Override
315 public void checkName(String name) {
316 Preconditions.checkArgument(RULE_NAME_PATTERN.matcher(name).matches());
317 }
318
319 @Override
320 public void checkAttributes(Map<String, Attribute> attributes) {
321 // No required attributes.
322 }
323 },
324
325 /**
326 * Test rules are instantiable by BUILD files and are handled specially
327 * when run with the 'test' command. Their names must obey the rules
328 * for identifiers in the BUILD language and {@link
329 * TargetUtils#isTestRuleName} must return true for the name.
330 *
331 * <p>In addition, test rules must contain certain attributes. See {@link
332 * Builder#REQUIRED_ATTRIBUTES_FOR_TESTS}.
333 */
334 TEST {
335 @Override
336 public void checkName(String name) {
337 Preconditions.checkArgument(TargetUtils.isTestRuleName(name)
338 && RULE_NAME_PATTERN.matcher(name).matches());
339 }
340
341 @Override
342 public void checkAttributes(Map<String, Attribute> attributes) {
343 for (Attribute attribute : REQUIRED_ATTRIBUTES_FOR_TESTS) {
344 Attribute presentAttribute = attributes.get(attribute.getName());
345 Preconditions.checkState(presentAttribute != null,
346 "Missing mandatory '%s' attribute in test rule class.", attribute.getName());
347 Preconditions.checkState(presentAttribute.getType().equals(attribute.getType()),
Googleraa437e02017-09-14 09:52:47 +0200348 "Mandatory attribute '%s' in test rule class has incorrect type (expected %s).",
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100349 attribute.getName(), attribute.getType());
350 }
351 }
Mark Schaller4fa83ac2015-07-10 16:59:37 +0000352 },
353
354 /**
355 * Placeholder rules are only instantiated when packages which refer to non-native rule
356 * classes are deserialized. At this time, non-native rule classes can't be serialized. To
357 * prevent crashes on deserialization, when a package containing a rule with a non-native rule
358 * class is deserialized, the rule is assigned a placeholder rule class. This is compatible
359 * with our limited set of package serialization use cases.
360 *
361 * Placeholder rule class names obey the rule for identifiers.
362 */
363 PLACEHOLDER {
364 @Override
365 public void checkName(String name) {
366 Preconditions.checkArgument(RULE_NAME_PATTERN.matcher(name).matches(), name);
367 }
368
369 @Override
370 public void checkAttributes(Map<String, Attribute> attributes) {
371 // No required attributes; this rule class cannot have the wrong set of attributes now
372 // because, if it did, the rule class would have failed to build before the package
373 // referring to it was serialized.
374 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100375 };
376
377 /**
378 * Checks whether the given name is valid for the current rule class type.
379 *
380 * @throws IllegalArgumentException if the name is not valid
381 */
382 public abstract void checkName(String name);
383
384 /**
385 * Checks whether the given set of attributes contains all the required
386 * attributes for the current rule class type.
387 *
388 * @throws IllegalArgumentException if a required attribute is missing
389 */
390 public abstract void checkAttributes(Map<String, Attribute> attributes);
391 }
392
Googler72f3a102017-12-01 16:28:28 -0800393 /** A predicate that filters rule classes based on their names. */
mjhalupka49581922018-02-28 11:04:31 -0800394 @AutoCodec
Googler72f3a102017-12-01 16:28:28 -0800395 public static class RuleClassNamePredicate {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100396
mjhalupka49581922018-02-28 11:04:31 -0800397 private static final RuleClassNamePredicate UNSPECIFIED_INSTANCE =
398 new RuleClassNamePredicate(ImmutableSet.of(), PredicateType.UNSPECIFIED, null);
399
400 private final ImmutableSet<String> ruleClassNames;
401
402 private final PredicateType predicateType;
403
Googler72f3a102017-12-01 16:28:28 -0800404 private final Predicate<String> ruleClassNamePredicate;
405 private final Predicate<RuleClass> ruleClassPredicate;
406 // if non-null, used ONLY for checking overlap
407 @Nullable private final Set<?> overlappable;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100408
mjhalupka49581922018-02-28 11:04:31 -0800409 @VisibleForSerialization
410 enum PredicateType {
411 ONLY,
412 All_EXCEPT,
413 UNSPECIFIED
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100414 }
415
mjhalupka49581922018-02-28 11:04:31 -0800416 @VisibleForSerialization
417 RuleClassNamePredicate(
418 ImmutableSet<String> ruleClassNames, PredicateType predicateType, Set<?> overlappable) {
419 this.ruleClassNames = ruleClassNames;
420 this.predicateType = predicateType;
Googler72f3a102017-12-01 16:28:28 -0800421 this.overlappable = overlappable;
mjhalupka49581922018-02-28 11:04:31 -0800422
423 switch (predicateType) {
424 case All_EXCEPT:
425 Predicate<String> containing = only(ruleClassNames).asPredicateOfRuleClassName();
426 ruleClassNamePredicate =
427 new DescribedPredicate<>(
428 Predicates.not(containing), "all but " + containing.toString());
429 ruleClassPredicate =
430 new DescribedPredicate<>(
431 Predicates.compose(ruleClassNamePredicate, RuleClass::getName),
432 ruleClassNamePredicate.toString());
433 break;
434 case ONLY:
435 ruleClassNamePredicate =
436 new DescribedPredicate<>(
437 Predicates.in(ruleClassNames), StringUtil.joinEnglishList(ruleClassNames));
438 ruleClassPredicate =
439 new DescribedPredicate<>(
440 Predicates.compose(ruleClassNamePredicate, RuleClass::getName),
441 ruleClassNamePredicate.toString());
442 break;
443 case UNSPECIFIED:
444 ruleClassNamePredicate = Predicates.alwaysTrue();
445 ruleClassPredicate = Predicates.alwaysTrue();
446 break;
447 default:
448 // This shouldn't happen normally since the constructor is private and within this file.
449 throw new IllegalArgumentException(
450 "Predicate type was not specified when constructing a RuleClassNamePredicate.");
451 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100452 }
453
Googler72f3a102017-12-01 16:28:28 -0800454 public static RuleClassNamePredicate only(Iterable<String> ruleClassNamesAsIterable) {
455 ImmutableSet<String> ruleClassNames = ImmutableSet.copyOf(ruleClassNamesAsIterable);
mjhalupka49581922018-02-28 11:04:31 -0800456 return new RuleClassNamePredicate(ruleClassNames, PredicateType.ONLY, ruleClassNames);
Googler72f3a102017-12-01 16:28:28 -0800457 }
458
459 public static RuleClassNamePredicate only(String... ruleClasses) {
460 return only(Arrays.asList(ruleClasses));
461 }
462
463 public static RuleClassNamePredicate allExcept(String... ruleClasses) {
464 ImmutableSet<String> ruleClassNames = ImmutableSet.copyOf(ruleClasses);
465 Preconditions.checkState(!ruleClassNames.isEmpty(), "Use unspecified() instead");
mjhalupka49581922018-02-28 11:04:31 -0800466 return new RuleClassNamePredicate(ruleClassNames, PredicateType.All_EXCEPT, null);
Googler72f3a102017-12-01 16:28:28 -0800467 }
468
469 /**
470 * This is a special sentinel value which represents a "default" {@link
471 * RuleClassNamePredicate} which is unspecified. Note that a call to its {@link
472 * RuleClassNamePredicate#asPredicateOfRuleClass} produces {@code
473 * Predicates.<RuleClass>alwaysTrue()}, which is a sentinel value for other parts of bazel.
474 */
475 public static RuleClassNamePredicate unspecified() {
mjhalupka49581922018-02-28 11:04:31 -0800476 return UNSPECIFIED_INSTANCE;
Googler72f3a102017-12-01 16:28:28 -0800477 }
478
479 public final Predicate<String> asPredicateOfRuleClassName() {
480 return ruleClassNamePredicate;
481 }
482
483 public final Predicate<RuleClass> asPredicateOfRuleClass() {
484 return ruleClassPredicate;
485 }
486
487 /**
488 * Determines whether two {@code RuleClassNamePredicate}s should be considered incompatible as
489 * rule class predicate and rule class warning predicate.
490 *
491 * <p>Specifically, if both list sets of explicit rule class names to permit, those two sets
492 * must be disjoint, so the restriction only applies when both predicates have been created by
493 * {@link #only}.
494 */
495 boolean consideredOverlapping(RuleClassNamePredicate that) {
496 return this.overlappable != null
497 && that.overlappable != null
498 && !Collections.disjoint(this.overlappable, that.overlappable);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100499 }
500
501 @Override
502 public int hashCode() {
mjhalupka49581922018-02-28 11:04:31 -0800503 return Objects.hash(ruleClassNames, predicateType);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100504 }
505
506 @Override
Googler72f3a102017-12-01 16:28:28 -0800507 public boolean equals(Object obj) {
508 // NOTE: Specifically not checking equality of ruleClassPredicate.
509 // By construction, if the name predicates are equals, the rule class predicates are, too.
510 return obj instanceof RuleClassNamePredicate
mjhalupka49581922018-02-28 11:04:31 -0800511 && ruleClassNames.equals(((RuleClassNamePredicate) obj).ruleClassNames)
512 && predicateType.equals(((RuleClassNamePredicate) obj).predicateType);
gregceda4c9592017-07-27 22:09:34 +0200513 }
514
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100515 @Override
516 public String toString() {
Googler72f3a102017-12-01 16:28:28 -0800517 return ruleClassNamePredicate.toString();
518 }
519
520 /** A pass-through predicate, except that an explicit {@link #toString()} is provided. */
521 private static class DescribedPredicate<T> implements Predicate<T> {
522 private final Predicate<T> delegate; // the actual predicate
523 private final String description;
524
525 private DescribedPredicate(Predicate<T> delegate, String description) {
526 this.delegate = delegate;
527 this.description = description;
528 }
529
530 @Override
531 public boolean apply(T input) {
532 return delegate.apply(input);
533 }
534
535 @Override
536 public int hashCode() {
537 return delegate.hashCode();
538 }
539
540 @Override
541 public boolean equals(Object obj) {
542 return obj instanceof DescribedPredicate
543 && delegate.equals(((DescribedPredicate<?>) obj).delegate);
544 }
545
546 @Override
547 public String toString() {
548 return description;
549 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100550 }
551 }
552
janakrd3fe5e72018-03-30 12:49:12 -0700553 /** A RuleTransitionFactory which always returns the same transition. */
554 @AutoCodec.VisibleForSerialization
555 @AutoCodec
556 static final class FixedTransitionFactory implements RuleTransitionFactory {
mstaib860975a2018-04-26 15:00:52 -0700557 private final PatchTransition transition;
Michael Staib2a675202017-03-20 18:06:48 +0000558
janakrd3fe5e72018-03-30 12:49:12 -0700559 @AutoCodec.VisibleForSerialization
mstaib860975a2018-04-26 15:00:52 -0700560 FixedTransitionFactory(PatchTransition transition) {
Michael Staib2a675202017-03-20 18:06:48 +0000561 this.transition = transition;
562 }
563
564 @Override
mstaib860975a2018-04-26 15:00:52 -0700565 public PatchTransition buildTransitionFor(Rule rule) {
Michael Staib2a675202017-03-20 18:06:48 +0000566 return transition;
567 }
568 }
569
Googler7807b6c2017-03-14 10:57:43 +0000570 /** List of required attributes for normal rules, name and type. */
571 public static final ImmutableList<Attribute> REQUIRED_ATTRIBUTES_FOR_NORMAL_RULES =
572 ImmutableList.of(attr("tags", Type.STRING_LIST).build());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100573
Googler7807b6c2017-03-14 10:57:43 +0000574 /** List of required attributes for test rules, name and type. */
575 public static final ImmutableList<Attribute> REQUIRED_ATTRIBUTES_FOR_TESTS =
576 ImmutableList.of(
577 attr("tags", Type.STRING_LIST).build(),
578 attr("size", Type.STRING).build(),
579 attr("timeout", Type.STRING).build(),
580 attr("flaky", Type.BOOLEAN).build(),
581 attr("shard_count", Type.INTEGER).build(),
582 attr("local", Type.BOOLEAN).build());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100583
584 private String name;
585 private final RuleClassType type;
586 private final boolean skylark;
Jon Brandveinead58ae2016-09-29 18:41:10 +0000587 private boolean skylarkTestable = false;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100588 private boolean documented;
589 private boolean publicByDefault = false;
590 private boolean binaryOutput = true;
591 private boolean workspaceOnly = false;
dslomov2ce98442017-10-23 19:14:02 +0200592 private boolean isExecutableSkylark = false;
mstaibdf229582017-03-31 21:50:46 +0000593 private boolean isConfigMatcher = false;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100594 private ImplicitOutputsFunction implicitOutputsFunction = ImplicitOutputsFunction.NONE;
Michael Staib2a675202017-03-20 18:06:48 +0000595 private RuleTransitionFactory transitionFactory;
cparsonse2d200f2018-03-06 16:15:11 -0800596 private ConfiguredTargetFactory<?, ?, ?> configuredTargetFactory = null;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100597 private PredicateWithMessage<Rule> validityPredicate =
598 PredicatesWithMessage.<Rule>alwaysTrue();
599 private Predicate<String> preferredDependencyPredicate = Predicates.alwaysFalse();
Dmitry Lomovb91d3922017-01-09 20:12:57 +0000600 private AdvertisedProviderSet.Builder advertisedProviders = AdvertisedProviderSet.builder();
Francois-Rene Rideau95b0d0c2015-04-22 16:52:13 +0000601 private BaseFunction configuredTargetFunction = null;
Lukacs Berki0e1a9942015-06-18 08:53:18 +0000602 private Function<? super Rule, Map<String, Label>> externalBindingsFunction =
603 NO_EXTERNAL_BINDINGS;
mstaibe5538ad2017-04-04 18:32:23 +0000604 private Function<? super Rule, ? extends Set<String>> optionReferenceFunction =
605 NO_OPTION_REFERENCE;
janakrd3fe5e72018-03-30 12:49:12 -0700606 /** This field and the next are null iff the rule is native. */
607 @Nullable private Label ruleDefinitionEnvironmentLabel;
608
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000609 @Nullable private String ruleDefinitionEnvironmentHashCode = null;
Michael Staibb51251e2015-09-29 23:31:51 +0000610 private ConfigurationFragmentPolicy.Builder configurationFragmentPolicy =
611 new ConfigurationFragmentPolicy.Builder();
Florian Weikert3f53fbb2015-08-07 22:25:50 +0000612
Greg Estrenc04c88f2015-03-06 19:45:50 +0000613 private boolean supportsConstraintChecking = true;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100614
615 private final Map<String, Attribute> attributes = new LinkedHashMap<>();
cpeyserfb829992017-09-07 17:17:03 +0200616 private final Set<Label> requiredToolchains = new HashSet<>();
John Cater856b4dd2017-11-21 08:06:16 -0800617 private boolean supportsPlatforms = true;
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -0700618 private OutputFile.Kind outputFileKind = OutputFile.Kind.FILE;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100619
620 /**
621 * Constructs a new {@code RuleClassBuilder} using all attributes from all
622 * parent rule classes. An attribute cannot exist in more than one parent.
623 *
gregce64c36e12017-07-26 23:48:56 +0200624 * <p>The rule type affects the allowed names and the required
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100625 * attributes (see {@link RuleClassType}).
626 *
627 * @throws IllegalArgumentException if an attribute with the same name exists
628 * in more than one parent
629 */
630 public Builder(String name, RuleClassType type, boolean skylark, RuleClass... parents) {
631 this.name = name;
632 this.skylark = skylark;
633 this.type = type;
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000634 Preconditions.checkState(skylark || type != RuleClassType.PLACEHOLDER, name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100635 this.documented = type != RuleClassType.ABSTRACT;
636 for (RuleClass parent : parents) {
637 if (parent.getValidityPredicate() != PredicatesWithMessage.<Rule>alwaysTrue()) {
638 setValidityPredicate(parent.getValidityPredicate());
639 }
640 if (parent.preferredDependencyPredicate != Predicates.<String>alwaysFalse()) {
641 setPreferredDependencyPredicate(parent.preferredDependencyPredicate);
642 }
Michael Staibff66c192016-01-14 22:40:37 +0000643 configurationFragmentPolicy
644 .includeConfigurationFragmentsFrom(parent.getConfigurationFragmentPolicy());
Michael Staibb51251e2015-09-29 23:31:51 +0000645 configurationFragmentPolicy.setMissingFragmentPolicy(
646 parent.getConfigurationFragmentPolicy().getMissingFragmentPolicy());
Greg Estrenc04c88f2015-03-06 19:45:50 +0000647 supportsConstraintChecking = parent.supportsConstraintChecking;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100648
cpeyserd78b3742017-08-04 19:48:53 +0200649 addRequiredToolchains(parent.getRequiredToolchains());
John Cater856b4dd2017-11-21 08:06:16 -0800650 supportsPlatforms = parent.supportsPlatforms;
cpeyserd78b3742017-08-04 19:48:53 +0200651
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100652 for (Attribute attribute : parent.getAttributes()) {
653 String attrName = attribute.getName();
654 Preconditions.checkArgument(
655 !attributes.containsKey(attrName) || attributes.get(attrName) == attribute,
Googler2935d672015-03-12 01:25:11 +0000656 "Attribute %s is inherited multiple times in %s ruleclass",
657 attrName,
658 name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100659 attributes.put(attrName, attribute);
660 }
Lukacs Berkiac4f9422015-05-29 10:06:30 +0000661
Dmitry Lomovb91d3922017-01-09 20:12:57 +0000662 advertisedProviders.addParent(parent.getAdvertisedProviders());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100663 }
664 // TODO(bazel-team): move this testonly attribute setting to somewhere else
665 // preferably to some base RuleClass implementation.
666 if (this.type.equals(RuleClassType.TEST)) {
667 Attribute.Builder<Boolean> testOnlyAttr = attr("testonly", BOOLEAN).value(true)
668 .nonconfigurable("policy decision: this shouldn't depend on the configuration");
669 if (attributes.containsKey("testonly")) {
670 override(testOnlyAttr);
671 } else {
672 add(testOnlyAttr);
673 }
674 }
675 }
676
677 /**
678 * Checks that required attributes for test rules are present, creates the
679 * {@link RuleClass} object and returns it.
680 *
681 * @throws IllegalStateException if any of the required attributes is missing
682 */
683 public RuleClass build() {
tomlu72642a22017-10-18 06:23:14 +0200684 // For built-ins, name == key
685 return build(name, name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100686 }
687
tomlu72642a22017-10-18 06:23:14 +0200688 /** Same as {@link #build} except with setting the name and key parameters. */
689 public RuleClass build(String name, String key) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100690 Preconditions.checkArgument(this.name.isEmpty() || this.name.equals(name));
691 type.checkName(name);
692 type.checkAttributes(attributes);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100693 Preconditions.checkState(
694 (type == RuleClassType.ABSTRACT)
janakr6ff110e2018-03-21 21:44:27 -0700695 == (configuredTargetFactory == null && configuredTargetFunction == null),
696 "Bad combo for %s: %s %s %s",
697 name,
698 type,
699 configuredTargetFactory,
700 configuredTargetFunction);
Damien Martin-Guillerez653df882016-02-17 21:46:22 +0000701 if (!workspaceOnly) {
janakrd3fe5e72018-03-30 12:49:12 -0700702 if (skylark) {
703 assertSkylarkRuleClassHasImplementationFunction();
704 assertSkylarkRuleClassHasEnvironmentLabel();
705 }
Damien Martin-Guillerez653df882016-02-17 21:46:22 +0000706 Preconditions.checkState(externalBindingsFunction == NO_EXTERNAL_BINDINGS);
707 }
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000708 if (type == RuleClassType.PLACEHOLDER) {
709 Preconditions.checkNotNull(ruleDefinitionEnvironmentHashCode, this.name);
710 }
711 return new RuleClass(
712 name,
tomlu72642a22017-10-18 06:23:14 +0200713 key,
janakr6ff110e2018-03-21 21:44:27 -0700714 type,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000715 skylark,
Jon Brandveinead58ae2016-09-29 18:41:10 +0000716 skylarkTestable,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000717 documented,
718 publicByDefault,
719 binaryOutput,
720 workspaceOnly,
dslomov2ce98442017-10-23 19:14:02 +0200721 isExecutableSkylark,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000722 implicitOutputsFunction,
mstaibdf229582017-03-31 21:50:46 +0000723 isConfigMatcher,
Michael Staib2a675202017-03-20 18:06:48 +0000724 transitionFactory,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000725 configuredTargetFactory,
726 validityPredicate,
727 preferredDependencyPredicate,
Dmitry Lomovb91d3922017-01-09 20:12:57 +0000728 advertisedProviders.build(),
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000729 configuredTargetFunction,
730 externalBindingsFunction,
mstaibe5538ad2017-04-04 18:32:23 +0000731 optionReferenceFunction,
janakrd3fe5e72018-03-30 12:49:12 -0700732 ruleDefinitionEnvironmentLabel,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +0000733 ruleDefinitionEnvironmentHashCode,
734 configurationFragmentPolicy.build(),
735 supportsConstraintChecking,
John Catereca28402017-05-17 21:44:12 +0200736 requiredToolchains,
John Cater856b4dd2017-11-21 08:06:16 -0800737 supportsPlatforms,
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -0700738 outputFileKind,
janakrd3fe5e72018-03-30 12:49:12 -0700739 attributes.values());
740 }
741
742 private void assertSkylarkRuleClassHasImplementationFunction() {
743 Preconditions.checkState(
744 (type == RuleClassType.NORMAL || type == RuleClassType.TEST)
745 == (configuredTargetFunction != null),
746 "%s %s",
747 type,
748 configuredTargetFunction);
749 }
750
751 private void assertSkylarkRuleClassHasEnvironmentLabel() {
752 Preconditions.checkState(
753 (type == RuleClassType.NORMAL
754 || type == RuleClassType.TEST
755 || type == RuleClassType.PLACEHOLDER)
756 == (ruleDefinitionEnvironmentLabel != null),
757 "Concrete Skylark rule classes can't have null labels: %s %s",
758 ruleDefinitionEnvironmentLabel,
759 type);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100760 }
761
762 /**
Greg Estren693f17f2015-11-06 16:45:45 +0000763 * Declares that the implementation of the associated rule class requires the given
764 * fragments to be present in this rule's host and target configurations.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100765 *
Greg Estren693f17f2015-11-06 16:45:45 +0000766 * <p>The value is inherited by subclasses.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100767 */
Michael Staibb51251e2015-09-29 23:31:51 +0000768 public Builder requiresConfigurationFragments(Class<?>... configurationFragments) {
Michael Staibff66c192016-01-14 22:40:37 +0000769 configurationFragmentPolicy.requiresConfigurationFragments(
770 ImmutableSet.<Class<?>>copyOf(configurationFragments));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100771 return this;
772 }
773
Ulf Adams71423eb2015-08-06 11:51:17 +0000774 /**
Greg Estren693f17f2015-11-06 16:45:45 +0000775 * Declares that the implementation of the associated rule class requires the given
gregce614dc502017-12-20 17:24:46 -0800776 * fragments to be present in the given configuration that isn't the rule's configuration but
777 * is also readable by the rule.
778 *
779 * <p>You probably don't want to use this, because rules generally shouldn't read configurations
780 * other than their own. If you want to declare host config fragments, see
781 * {@link com.google.devtools.build.lib.analysis.config.ConfigAwareRuleClassBuilder}.
Greg Estren693f17f2015-11-06 16:45:45 +0000782 *
783 * <p>The value is inherited by subclasses.
784 */
gregcebe55e112018-01-30 11:04:53 -0800785 public Builder requiresConfigurationFragments(ConfigurationTransition transition,
gregce614dc502017-12-20 17:24:46 -0800786 Class<?>... configurationFragments) {
787 configurationFragmentPolicy.requiresConfigurationFragments(
788 transition,
Michael Staibff66c192016-01-14 22:40:37 +0000789 ImmutableSet.<Class<?>>copyOf(configurationFragments));
Greg Estren693f17f2015-11-06 16:45:45 +0000790 return this;
791 }
792
793 /**
Michael Staibff66c192016-01-14 22:40:37 +0000794 * Declares the configuration fragments that are required by this rule for the target
795 * configuration.
Greg Estren693f17f2015-11-06 16:45:45 +0000796 *
797 * <p>In contrast to {@link #requiresConfigurationFragments(Class...)}, this method takes the
Michael Staibff66c192016-01-14 22:40:37 +0000798 * Skylark module names of fragments instead of their classes.
Greg Estren693f17f2015-11-06 16:45:45 +0000799 */
Michael Staibff66c192016-01-14 22:40:37 +0000800 public Builder requiresConfigurationFragmentsBySkylarkModuleName(
801 Collection<String> configurationFragmentNames) {
802 configurationFragmentPolicy
803 .requiresConfigurationFragmentsBySkylarkModuleName(configurationFragmentNames);
804 return this;
805 }
806
807 /**
808 * Declares the configuration fragments that are required by this rule for the host
809 * configuration.
810 *
Michael Staibff66c192016-01-14 22:40:37 +0000811 */
gregce614dc502017-12-20 17:24:46 -0800812 /**
813 * Declares that the implementation of the associated rule class requires the given
814 * fragments to be present in the given configuration that isn't the rule's configuration but
815 * is also readable by the rule.
816 *
gregcebe55e112018-01-30 11:04:53 -0800817 * <p>In contrast to {@link #requiresConfigurationFragments(ConfigurationTransition, Class...)},
818 * this method takes Skylark module names of fragments instead of their classes.
gregce614dc502017-12-20 17:24:46 -0800819 * *
820 * <p>You probably don't want to use this, because rules generally shouldn't read configurations
821 * other than their own. If you want to declare host config fragments, see
822 * {@link com.google.devtools.build.lib.analysis.config.ConfigAwareRuleClassBuilder}.
823 *
824 * <p>The value is inherited by subclasses.
825 */
gregcebe55e112018-01-30 11:04:53 -0800826 public Builder requiresConfigurationFragmentsBySkylarkModuleName(
827 ConfigurationTransition transition, Collection<String> configurationFragmentNames) {
gregce614dc502017-12-20 17:24:46 -0800828 configurationFragmentPolicy.requiresConfigurationFragmentsBySkylarkModuleName(transition,
829 configurationFragmentNames);
Greg Estren693f17f2015-11-06 16:45:45 +0000830 return this;
831 }
832
Jon Brandveinead58ae2016-09-29 18:41:10 +0000833 public Builder setSkylarkTestable() {
834 Preconditions.checkState(skylark, "Cannot set skylarkTestable on a non-Skylark rule");
835 skylarkTestable = true;
836 return this;
837 }
838
Greg Estren693f17f2015-11-06 16:45:45 +0000839 /**
Ulf Adams71423eb2015-08-06 11:51:17 +0000840 * Sets the policy for the case where the configuration is missing required fragments (see
841 * {@link #requiresConfigurationFragments}).
842 */
843 public Builder setMissingFragmentPolicy(MissingFragmentPolicy missingFragmentPolicy) {
Michael Staibb51251e2015-09-29 23:31:51 +0000844 configurationFragmentPolicy.setMissingFragmentPolicy(missingFragmentPolicy);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100845 return this;
846 }
Florian Weikert3f8aac92015-09-07 12:06:02 +0000847
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100848 public Builder setUndocumented() {
849 documented = false;
850 return this;
851 }
852
853 public Builder publicByDefault() {
854 publicByDefault = true;
855 return this;
856 }
857
858 public Builder setWorkspaceOnly() {
859 workspaceOnly = true;
860 return this;
861 }
862
863 /**
864 * Determines the outputs of this rule to be created beneath the {@code
865 * genfiles} directory. By default, files are created beneath the {@code bin}
866 * directory.
867 *
868 * <p>This property is not inherited and this method should not be called by
869 * builder of {@link RuleClassType#ABSTRACT} rule class.
870 *
871 * @throws IllegalStateException if called for abstract rule class builder
872 */
873 public Builder setOutputToGenfiles() {
874 Preconditions.checkState(type != RuleClassType.ABSTRACT,
875 "Setting not inherited property (output to genrules) of abstract rule class '%s'", name);
876 this.binaryOutput = false;
877 return this;
878 }
879
880 /**
881 * Sets the implicit outputs function of the rule class. The default implicit
882 * outputs function is {@link ImplicitOutputsFunction#NONE}.
883 *
884 * <p>This property is not inherited and this method should not be called by
885 * builder of {@link RuleClassType#ABSTRACT} rule class.
886 *
887 * @throws IllegalStateException if called for abstract rule class builder
888 */
889 public Builder setImplicitOutputsFunction(
890 ImplicitOutputsFunction implicitOutputsFunction) {
891 Preconditions.checkState(type != RuleClassType.ABSTRACT,
892 "Setting not inherited property (implicit output function) of abstract rule class '%s'",
893 name);
894 this.implicitOutputsFunction = implicitOutputsFunction;
895 return this;
896 }
897
Cal Peyser19dda252017-01-11 23:37:05 +0000898 /**
gregce64c36e12017-07-26 23:48:56 +0200899 * Applies the given transition to all incoming edges for this rule class.
Cal Peyser19dda252017-01-11 23:37:05 +0000900 *
gregce74a895d2018-05-29 11:26:03 -0700901 * <p>This cannot be a {@link SplitTransition} because that requires coordination with the
902 * rule's parent: use {@link Attribute.Builder#cfg(ConfigurationTransition)} on the parent to
903 * declare splits.
904 *
gregce64c36e12017-07-26 23:48:56 +0200905 * <p>If you need the transition to depend on the rule it's being applied to, use
906 * {@link #cfg(RuleTransitionFactory)}.
Cal Peyser19dda252017-01-11 23:37:05 +0000907 */
mstaib860975a2018-04-26 15:00:52 -0700908 public Builder cfg(PatchTransition transition) {
gregce74a895d2018-05-29 11:26:03 -0700909 return cfg(new FixedTransitionFactory(transition));
Michael Staib2a675202017-03-20 18:06:48 +0000910 }
911
gregce64c36e12017-07-26 23:48:56 +0200912 /**
913 * Applies the given transition factory to all incoming edges for this rule class.
914 *
gregce74a895d2018-05-29 11:26:03 -0700915 * <p>Unlike{@link #cfg(PatchTransition)}, the factory can examine the rule when
gregcebe55e112018-01-30 11:04:53 -0800916 * deciding what transition to use.
gregce64c36e12017-07-26 23:48:56 +0200917 */
Michael Staib2a675202017-03-20 18:06:48 +0000918 public Builder cfg(RuleTransitionFactory transitionFactory) {
919 Preconditions.checkState(type != RuleClassType.ABSTRACT,
920 "Setting not inherited property (cfg) of abstract rule class '%s'", name);
gregcef19fcfe2017-06-02 16:04:07 -0400921 Preconditions.checkState(this.transitionFactory == null,
Michael Staib2a675202017-03-20 18:06:48 +0000922 "Property cfg has already been set");
923 Preconditions.checkNotNull(transitionFactory);
924 this.transitionFactory = transitionFactory;
Cal Peyser19dda252017-01-11 23:37:05 +0000925 return this;
926 }
927
cparsonse2d200f2018-03-06 16:15:11 -0800928 public Builder factory(ConfiguredTargetFactory<?, ?, ?> factory) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100929 this.configuredTargetFactory = factory;
930 return this;
931 }
932
933 public Builder setValidityPredicate(PredicateWithMessage<Rule> predicate) {
934 this.validityPredicate = predicate;
935 return this;
936 }
937
938 public Builder setPreferredDependencyPredicate(Predicate<String> predicate) {
939 this.preferredDependencyPredicate = predicate;
940 return this;
941 }
942
943 /**
944 * State that the rule class being built possibly supplies the specified provider to its direct
945 * dependencies.
946 *
947 * <p>When computing the set of aspects required for a rule, only the providers listed here are
948 * considered. The presence of a provider here does not mean that the rule <b>must</b> implement
949 * said provider, merely that it <b>can</b>. After the configured target is constructed from
950 * this rule, aspects will be filtered according to the set of actual providers.
951 *
952 * <p>This is here so that we can do the loading phase overestimation required for
953 * "blaze query", which does not have the configured targets available.
954 *
955 * <p>It's okay for the rule class eventually not to supply it (possibly based on analysis phase
956 * logic), but if a provider is not advertised but is supplied, aspects that require the it will
957 * not be evaluated for the rule.
958 */
959 public Builder advertiseProvider(Class<?>... providers) {
Dmitry Lomovb91d3922017-01-09 20:12:57 +0000960 for (Class<?> provider : providers) {
961 advertisedProviders.addNative(provider);
962 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100963 return this;
964 }
965
elenairinaaeb21bc2017-09-27 12:13:52 -0400966 public Builder advertiseSkylarkProvider(SkylarkProviderIdentifier... skylarkProviders) {
967 for (SkylarkProviderIdentifier skylarkProviderIdentifier : skylarkProviders) {
968 advertisedProviders.addSkylark(skylarkProviderIdentifier);
969 }
970 return this;
971 }
972
Lukacs Berki549bfce2016-04-22 15:29:12 +0000973 /**
974 * Set if the rule can have any provider. This is true for "alias" rules like
975 * <code>bind</code> .
976 */
977 public Builder canHaveAnyProvider() {
Dmitry Lomovb91d3922017-01-09 20:12:57 +0000978 advertisedProviders.canHaveAnyProvider();
Lukacs Berki549bfce2016-04-22 15:29:12 +0000979 return this;
980 }
981
dbabkina2823422018-05-02 02:42:53 -0700982 public Builder addAttribute(Attribute attribute) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100983 Preconditions.checkState(!attributes.containsKey(attribute.getName()),
984 "An attribute with the name '%s' already exists.", attribute.getName());
985 attributes.put(attribute.getName(), attribute);
dbabkina2823422018-05-02 02:42:53 -0700986 return this;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100987 }
988
989 private void overrideAttribute(Attribute attribute) {
990 String attrName = attribute.getName();
991 Preconditions.checkState(attributes.containsKey(attrName),
992 "No such attribute '%s' to override in ruleclass '%s'.", attrName, name);
993 Type<?> origType = attributes.get(attrName).getType();
994 Type<?> newType = attribute.getType();
995 Preconditions.checkState(origType.equals(newType),
996 "The type of the new attribute '%s' is different from the original one '%s'.",
997 newType, origType);
998 attributes.put(attrName, attribute);
999 }
1000
1001 /**
1002 * Builds attribute from the attribute builder and adds it to this rule
1003 * class.
1004 *
1005 * @param attr attribute builder
1006 */
1007 public <TYPE> Builder add(Attribute.Builder<TYPE> attr) {
1008 addAttribute(attr.build());
1009 return this;
1010 }
1011
1012 /**
1013 * Builds attribute from the attribute builder and overrides the attribute
1014 * with the same name.
1015 *
1016 * @throws IllegalArgumentException if the attribute does not override one of the same name
1017 */
1018 public <TYPE> Builder override(Attribute.Builder<TYPE> attr) {
1019 overrideAttribute(attr.build());
1020 return this;
1021 }
1022
1023 /**
1024 * Adds or overrides the attribute in the rule class. Meant for Skylark usage.
Florian Weikerte96b0b82015-09-25 11:35:11 +00001025 *
1026 * @throws IllegalArgumentException if the attribute overrides an existing attribute (will be
1027 * legal in the future).
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001028 */
1029 public void addOrOverrideAttribute(Attribute attribute) {
Florian Weikerte96b0b82015-09-25 11:35:11 +00001030 String name = attribute.getName();
1031 // Attributes may be overridden in the future.
1032 Preconditions.checkArgument(!attributes.containsKey(name),
1033 "There is already a built-in attribute '%s' which cannot be overridden", name);
1034 addAttribute(attribute);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001035 }
1036
Mark Schaller4fa83ac2015-07-10 16:59:37 +00001037 /** True if the rule class contains an attribute named {@code name}. */
1038 public boolean contains(String name) {
1039 return attributes.containsKey(name);
1040 }
1041
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001042 /**
1043 * Sets the rule implementation function. Meant for Skylark usage.
1044 */
Francois-Rene Rideau95b0d0c2015-04-22 16:52:13 +00001045 public Builder setConfiguredTargetFunction(BaseFunction func) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001046 this.configuredTargetFunction = func;
1047 return this;
1048 }
1049
Lukacs Berki0e1a9942015-06-18 08:53:18 +00001050 public Builder setExternalBindingsFunction(Function<? super Rule, Map<String, Label>> func) {
1051 this.externalBindingsFunction = func;
1052 return this;
1053 }
1054
janakrd3fe5e72018-03-30 12:49:12 -07001055 /** Sets the rule definition environment label and hash code. Meant for Skylark usage. */
1056 public Builder setRuleDefinitionEnvironmentLabelAndHashCode(Label label, String hashCode) {
1057 this.ruleDefinitionEnvironmentLabel = Preconditions.checkNotNull(label, this.name);
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001058 this.ruleDefinitionEnvironmentHashCode = Preconditions.checkNotNull(hashCode, this.name);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001059 return this;
1060 }
1061
1062 /**
1063 * Removes an attribute with the same name from this rule class.
1064 *
1065 * @throws IllegalArgumentException if the attribute with this name does
1066 * not exist
1067 */
1068 public <TYPE> Builder removeAttribute(String name) {
1069 Preconditions.checkState(attributes.containsKey(name), "No such attribute '%s' to remove.",
1070 name);
1071 attributes.remove(name);
1072 return this;
1073 }
1074
1075 /**
1076 * This rule class outputs a default executable for every rule with the same name as
1077 * the rules's. Only works for Skylark.
1078 */
dslomov2ce98442017-10-23 19:14:02 +02001079 public <TYPE> Builder setExecutableSkylark() {
1080 this.isExecutableSkylark = true;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001081 return this;
1082 }
1083
1084 /**
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -07001085 * Sets the kind of output files this rule creates.
1086 * DO NOT USE! This only exists to support the non-open-sourced {@code fileset} rule.
1087 * {@see OutputFile.Kind}.
1088 */
1089 public Builder setOutputFileKind(OutputFile.Kind outputFileKind) {
1090 this.outputFileKind = outputFileKind;
1091 return this;
1092 }
1093
1094
1095
1096 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001097 * Declares that instances of this rule are compatible with the specified environments,
1098 * in addition to the defaults declared by their environment groups. This can be overridden
1099 * by rule-specific declarations. See
1100 * {@link com.google.devtools.build.lib.analysis.constraints.ConstraintSemantics} for details.
1101 */
1102 public <TYPE> Builder compatibleWith(Label... environments) {
gregce614dc502017-12-20 17:24:46 -08001103 add(
1104 attr(DEFAULT_COMPATIBLE_ENVIRONMENT_ATTR, LABEL_LIST)
1105 .value(ImmutableList.copyOf(environments)));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001106 return this;
1107 }
1108
1109 /**
1110 * Declares that instances of this rule are restricted to the specified environments, i.e.
1111 * these override the defaults declared by their environment groups. This can be overridden
1112 * by rule-specific declarations. See
1113 * {@link com.google.devtools.build.lib.analysis.constraints.ConstraintSemantics} for details.
1114 *
1115 * <p>The input list cannot be empty.
1116 */
1117 public <TYPE> Builder restrictedTo(Label firstEnvironment, Label... otherEnvironments) {
1118 ImmutableList<Label> environments = ImmutableList.<Label>builder().add(firstEnvironment)
1119 .add(otherEnvironments).build();
gregce614dc502017-12-20 17:24:46 -08001120 add(
1121 attr(DEFAULT_RESTRICTED_ENVIRONMENT_ATTR, LABEL_LIST)
1122 .value(environments));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001123 return this;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001124 }
1125
1126 /**
Greg Estrenc04c88f2015-03-06 19:45:50 +00001127 * Exempts rules of this type from the constraint enforcement system. This should only be
1128 * applied to rules that are intrinsically incompatible with constraint checking (any
1129 * application of this method weakens the reach and strength of the system).
1130 *
1131 * @param reason user-informative message explaining the reason for exemption (not used)
1132 */
1133 public <TYPE> Builder exemptFromConstraintChecking(String reason) {
1134 Preconditions.checkState(this.supportsConstraintChecking);
1135 this.supportsConstraintChecking = false;
Greg Estren2ffc4fe2015-06-02 19:40:41 +00001136 attributes.remove(RuleClass.COMPATIBLE_ENVIRONMENT_ATTR);
1137 attributes.remove(RuleClass.RESTRICTED_ENVIRONMENT_ATTR);
Greg Estrenc04c88f2015-03-06 19:45:50 +00001138 return this;
1139 }
1140
1141 /**
mstaibdf229582017-03-31 21:50:46 +00001142 * Causes rules of this type to be evaluated with the parent's configuration, always, so that
1143 * rules which match against parts of the configuration will behave as expected.
1144 *
1145 * <p>This is only intended for use by {@code config_setting} - other rules should not use this!
1146 */
1147 public Builder setIsConfigMatcherForConfigSettingOnly() {
1148 this.isConfigMatcher = true;
1149 return this;
1150 }
1151
1152 /**
mstaibe5538ad2017-04-04 18:32:23 +00001153 * Causes rules of this type to implicitly reference the configuration fragments associated with
1154 * the options its attributes reference.
1155 *
1156 * <p>This is only intended for use by {@code config_setting} - other rules should not use this!
1157 */
1158 public Builder setOptionReferenceFunctionForConfigSettingOnly(
1159 Function<? super Rule, ? extends Set<String>> optionReferenceFunction) {
1160 this.optionReferenceFunction = Preconditions.checkNotNull(optionReferenceFunction);
1161 return this;
1162 }
1163
John Cater9a8d16e2017-07-05 16:12:07 -04001164 public Builder addRequiredToolchains(Iterable<Label> toolchainLabels) {
1165 Iterables.addAll(this.requiredToolchains, toolchainLabels);
John Catereca28402017-05-17 21:44:12 +02001166 return this;
1167 }
1168
cpeyserd852e482017-09-07 22:16:06 +02001169 public Builder addRequiredToolchains(Label... toolchainLabels) {
1170 Iterables.addAll(this.requiredToolchains, Lists.newArrayList(toolchainLabels));
1171 return this;
1172 }
1173
John Cater856b4dd2017-11-21 08:06:16 -08001174 public Builder supportsPlatforms(boolean flag) {
1175 this.supportsPlatforms = flag;
1176 return this;
1177 }
1178
mstaibe5538ad2017-04-04 18:32:23 +00001179 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001180 * Returns an Attribute.Builder object which contains a replica of the
1181 * same attribute in the parent rule if exists.
1182 *
1183 * @param name the name of the attribute
1184 */
1185 public Attribute.Builder<?> copy(String name) {
1186 Preconditions.checkArgument(attributes.containsKey(name),
1187 "Attribute %s does not exist in parent rule class.", name);
1188 return attributes.get(name).cloneBuilder();
1189 }
1190 }
1191
1192 private final String name; // e.g. "cc_library"
1193
tomlu72642a22017-10-18 06:23:14 +02001194 private final String key; // Just the name for native, label + name for skylark
1195
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001196 /**
1197 * The kind of target represented by this RuleClass (e.g. "cc_library rule").
1198 * Note: Even though there is partial duplication with the {@link RuleClass#name} field,
1199 * we want to store this as a separate field instead of generating it on demand in order to
1200 * avoid string duplication.
1201 */
1202 private final String targetKind;
1203
janakr6ff110e2018-03-21 21:44:27 -07001204 private final RuleClassType type;
Michajlo Matijkiwbc042c62015-10-29 13:22:52 +00001205 private final boolean isSkylark;
Jon Brandveinead58ae2016-09-29 18:41:10 +00001206 private final boolean skylarkTestable;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001207 private final boolean documented;
1208 private final boolean publicByDefault;
1209 private final boolean binaryOutput;
1210 private final boolean workspaceOnly;
dslomov2ce98442017-10-23 19:14:02 +02001211 private final boolean isExecutableSkylark;
mstaibdf229582017-03-31 21:50:46 +00001212 private final boolean isConfigMatcher;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001213
1214 /**
1215 * A (unordered) mapping from attribute names to small integers indexing into
1216 * the {@code attributes} array.
1217 */
Miguel Alcon Pintod7795f42015-10-23 21:55:52 +00001218 private final Map<String, Integer> attributeIndex;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001219
1220 /**
1221 * All attributes of this rule class (including inherited ones) ordered by
1222 * attributeIndex value.
1223 */
Eric Fellheimera954fae2015-08-27 19:37:52 +00001224 private final ImmutableList<Attribute> attributes;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001225
Michajlo Matijkiwcdd5b0e2015-12-09 18:17:44 +00001226 /** Names of the non-configurable attributes of this rule class. */
1227 private final ImmutableList<String> nonConfigurableAttributes;
1228
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001229 /**
1230 * The set of implicit outputs generated by a rule, expressed as a function
1231 * of that rule.
1232 */
1233 private final ImplicitOutputsFunction implicitOutputsFunction;
1234
1235 /**
Michael Staib2a675202017-03-20 18:06:48 +00001236 * A factory which will produce a configuration transition that should be applied on any edge of
1237 * the configured target graph that leads into a target of this rule class.
Cal Peyser19dda252017-01-11 23:37:05 +00001238 */
Michael Staib2a675202017-03-20 18:06:48 +00001239 private final RuleTransitionFactory transitionFactory;
Cal Peyser19dda252017-01-11 23:37:05 +00001240
cparsonse2d200f2018-03-06 16:15:11 -08001241 /** The factory that creates configured targets from this rule. */
1242 private final ConfiguredTargetFactory<?, ?, ?> configuredTargetFactory;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001243
1244 /**
1245 * The constraint the package name of the rule instance must fulfill
1246 */
1247 private final PredicateWithMessage<Rule> validityPredicate;
1248
1249 /**
1250 * See {@link #isPreferredDependency}.
1251 */
1252 private final Predicate<String> preferredDependencyPredicate;
1253
1254 /**
1255 * The list of transitive info providers this class advertises to aspects.
1256 */
Dmitry Lomovb91d3922017-01-09 20:12:57 +00001257 private final AdvertisedProviderSet advertisedProviders;
Lukacs Berki549bfce2016-04-22 15:29:12 +00001258
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001259 /**
1260 * The Skylark rule implementation of this RuleClass. Null for non Skylark executable RuleClasses.
1261 */
Francois-Rene Rideau95b0d0c2015-04-22 16:52:13 +00001262 @Nullable private final BaseFunction configuredTargetFunction;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001263
1264 /**
Lukacs Berki0e1a9942015-06-18 08:53:18 +00001265 * Returns the extra bindings a workspace function adds to the WORKSPACE file.
1266 */
1267 private final Function<? super Rule, Map<String, Label>> externalBindingsFunction;
1268
1269 /**
mstaibe5538ad2017-04-04 18:32:23 +00001270 * Returns the options referenced by this rule's attributes.
1271 */
1272 private final Function<? super Rule, ? extends Set<String>> optionReferenceFunction;
1273
1274 /**
janakrd3fe5e72018-03-30 12:49:12 -07001275 * The Skylark rule definition environment's label and hash code of this RuleClass. Null for non
1276 * Skylark executable RuleClasses.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001277 */
janakrd3fe5e72018-03-30 12:49:12 -07001278 @Nullable private final Label ruleDefinitionEnvironmentLabel;
1279
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001280 @Nullable private final String ruleDefinitionEnvironmentHashCode;
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -07001281 private final OutputFile.Kind outputFileKind;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001282
1283 /**
Michael Staibb51251e2015-09-29 23:31:51 +00001284 * The set of configuration fragments which are legal for this rule's implementation to access.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001285 */
Michael Staibb51251e2015-09-29 23:31:51 +00001286 private final ConfigurationFragmentPolicy configurationFragmentPolicy;
Greg Estrenc04c88f2015-03-06 19:45:50 +00001287
1288 /**
1289 * Determines whether instances of this rule should be checked for constraint compatibility
1290 * with their dependencies and the rules that depend on them. This should be true for
1291 * everything except for rules that are intrinsically incompatible with the constraint system.
1292 */
1293 private final boolean supportsConstraintChecking;
1294
cpeyserfb829992017-09-07 17:17:03 +02001295 private final ImmutableSet<Label> requiredToolchains;
John Cater856b4dd2017-11-21 08:06:16 -08001296 private final boolean supportsPlatforms;
John Catereca28402017-05-17 21:44:12 +02001297
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001298 /**
John Catereca28402017-05-17 21:44:12 +02001299 * Constructs an instance of RuleClass whose name is 'name', attributes are 'attributes'. The
1300 * {@code srcsAllowedFiles} determines which types of files are allowed as parameters to the
1301 * "srcs" attribute; rules are always allowed. For the "deps" attribute, there are four cases:
1302 *
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001303 * <ul>
John Catereca28402017-05-17 21:44:12 +02001304 * <li>if the parameter is a file, it is allowed if its file type is given in {@code
1305 * depsAllowedFiles},
1306 * <li>if the parameter is a rule and the rule class is accepted by {@code depsAllowedRules},
1307 * then it is allowed,
1308 * <li>if the parameter is a rule and the rule class is not accepted by {@code
1309 * depsAllowedRules}, but accepted by {@code depsAllowedRulesWithWarning}, then it is
1310 * allowed, but triggers a warning;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001311 * <li>all other parameters trigger an error.
1312 * </ul>
1313 *
John Catereca28402017-05-17 21:44:12 +02001314 * <p>The {@code depsAllowedRules} predicate should have a {@code toString} method which returns a
1315 * plain English enumeration of the allowed rule class names, if it does not allow all rule
1316 * classes.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001317 */
1318 @VisibleForTesting
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001319 RuleClass(
1320 String name,
tomlu72642a22017-10-18 06:23:14 +02001321 String key,
janakr6ff110e2018-03-21 21:44:27 -07001322 RuleClassType type,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001323 boolean isSkylark,
Jon Brandveinead58ae2016-09-29 18:41:10 +00001324 boolean skylarkTestable,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001325 boolean documented,
1326 boolean publicByDefault,
1327 boolean binaryOutput,
1328 boolean workspaceOnly,
dslomov2ce98442017-10-23 19:14:02 +02001329 boolean isExecutableSkylark,
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001330 ImplicitOutputsFunction implicitOutputsFunction,
mstaibdf229582017-03-31 21:50:46 +00001331 boolean isConfigMatcher,
Michael Staib2a675202017-03-20 18:06:48 +00001332 RuleTransitionFactory transitionFactory,
cparsonse2d200f2018-03-06 16:15:11 -08001333 ConfiguredTargetFactory<?, ?, ?> configuredTargetFactory,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001334 PredicateWithMessage<Rule> validityPredicate,
1335 Predicate<String> preferredDependencyPredicate,
Dmitry Lomovb91d3922017-01-09 20:12:57 +00001336 AdvertisedProviderSet advertisedProviders,
Francois-Rene Rideau95b0d0c2015-04-22 16:52:13 +00001337 @Nullable BaseFunction configuredTargetFunction,
Lukacs Berki0e1a9942015-06-18 08:53:18 +00001338 Function<? super Rule, Map<String, Label>> externalBindingsFunction,
mstaibe5538ad2017-04-04 18:32:23 +00001339 Function<? super Rule, ? extends Set<String>> optionReferenceFunction,
janakrd3fe5e72018-03-30 12:49:12 -07001340 @Nullable Label ruleDefinitionEnvironmentLabel,
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001341 String ruleDefinitionEnvironmentHashCode,
Michael Staibb51251e2015-09-29 23:31:51 +00001342 ConfigurationFragmentPolicy configurationFragmentPolicy,
Greg Estrenc04c88f2015-03-06 19:45:50 +00001343 boolean supportsConstraintChecking,
cpeyserfb829992017-09-07 17:17:03 +02001344 Set<Label> requiredToolchains,
John Cater856b4dd2017-11-21 08:06:16 -08001345 boolean supportsPlatforms,
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -07001346 OutputFile.Kind outputFileKind,
janakrd3fe5e72018-03-30 12:49:12 -07001347 Collection<Attribute> attributes) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001348 this.name = name;
tomlu72642a22017-10-18 06:23:14 +02001349 this.key = key;
janakr6ff110e2018-03-21 21:44:27 -07001350 this.type = type;
Michajlo Matijkiwbc042c62015-10-29 13:22:52 +00001351 this.isSkylark = isSkylark;
Googlerb448eef2017-05-02 21:50:24 +02001352 this.targetKind = name + Rule.targetKindSuffix();
Jon Brandveinead58ae2016-09-29 18:41:10 +00001353 this.skylarkTestable = skylarkTestable;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001354 this.documented = documented;
1355 this.publicByDefault = publicByDefault;
1356 this.binaryOutput = binaryOutput;
1357 this.implicitOutputsFunction = implicitOutputsFunction;
mstaibdf229582017-03-31 21:50:46 +00001358 this.isConfigMatcher = isConfigMatcher;
Michael Staib2a675202017-03-20 18:06:48 +00001359 this.transitionFactory = transitionFactory;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001360 this.configuredTargetFactory = configuredTargetFactory;
1361 this.validityPredicate = validityPredicate;
1362 this.preferredDependencyPredicate = preferredDependencyPredicate;
1363 this.advertisedProviders = advertisedProviders;
1364 this.configuredTargetFunction = configuredTargetFunction;
Lukacs Berki0e1a9942015-06-18 08:53:18 +00001365 this.externalBindingsFunction = externalBindingsFunction;
mstaibe5538ad2017-04-04 18:32:23 +00001366 this.optionReferenceFunction = optionReferenceFunction;
janakrd3fe5e72018-03-30 12:49:12 -07001367 this.ruleDefinitionEnvironmentLabel = ruleDefinitionEnvironmentLabel;
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00001368 this.ruleDefinitionEnvironmentHashCode = ruleDefinitionEnvironmentHashCode;
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -07001369 this.outputFileKind = outputFileKind;
Dmitry Lomov94387c22015-12-08 16:30:06 +00001370 validateNoClashInPublicNames(attributes);
Eric Fellheimera954fae2015-08-27 19:37:52 +00001371 this.attributes = ImmutableList.copyOf(attributes);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001372 this.workspaceOnly = workspaceOnly;
dslomov2ce98442017-10-23 19:14:02 +02001373 this.isExecutableSkylark = isExecutableSkylark;
Michael Staibb51251e2015-09-29 23:31:51 +00001374 this.configurationFragmentPolicy = configurationFragmentPolicy;
Greg Estrenc04c88f2015-03-06 19:45:50 +00001375 this.supportsConstraintChecking = supportsConstraintChecking;
cpeyserfb829992017-09-07 17:17:03 +02001376 this.requiredToolchains = ImmutableSet.copyOf(requiredToolchains);
John Cater856b4dd2017-11-21 08:06:16 -08001377 this.supportsPlatforms = supportsPlatforms;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001378
Michajlo Matijkiwcdd5b0e2015-12-09 18:17:44 +00001379 // Create the index and collect non-configurable attributes.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001380 int index = 0;
janakrd3fe5e72018-03-30 12:49:12 -07001381 attributeIndex = new HashMap<>(attributes.size());
Michajlo Matijkiwcdd5b0e2015-12-09 18:17:44 +00001382 ImmutableList.Builder<String> nonConfigurableAttributesBuilder = ImmutableList.builder();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001383 for (Attribute attribute : attributes) {
1384 attributeIndex.put(attribute.getName(), index++);
Michajlo Matijkiwcdd5b0e2015-12-09 18:17:44 +00001385 if (!attribute.isConfigurable()) {
1386 nonConfigurableAttributesBuilder.add(attribute.getName());
1387 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001388 }
Michajlo Matijkiwcdd5b0e2015-12-09 18:17:44 +00001389 this.nonConfigurableAttributes = nonConfigurableAttributesBuilder.build();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001390 }
1391
janakrd3fe5e72018-03-30 12:49:12 -07001392 private void validateNoClashInPublicNames(Iterable<Attribute> attributes) {
Dmitry Lomov94387c22015-12-08 16:30:06 +00001393 Map<String, Attribute> publicToPrivateNames = new HashMap<>();
1394 for (Attribute attribute : attributes) {
1395 String publicName = attribute.getPublicName();
1396 if (publicToPrivateNames.containsKey(publicName)) {
1397 throw new IllegalStateException(
1398 String.format(
1399 "Rule %s: Attributes %s and %s have an identical public name: %s",
1400 name,
1401 attribute.getName(),
1402 publicToPrivateNames.get(publicName).getName(),
1403 publicName));
1404 }
1405 publicToPrivateNames.put(publicName, attribute);
1406 }
1407 }
1408
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001409 /**
Michajlo Matijkiw6d471412016-08-09 20:35:45 +00001410 * Returns the default function for determining the set of implicit outputs generated by a given
1411 * rule. If not otherwise specified, this will be the implementation used by {@link Rule}s
1412 * created with this {@link RuleClass}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001413 *
Michajlo Matijkiw6d471412016-08-09 20:35:45 +00001414 * <p>Do not use this value to calculate implicit outputs for a rule, instead use
1415 * {@link Rule#getImplicitOutputsFunction()}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001416 *
Michajlo Matijkiw6d471412016-08-09 20:35:45 +00001417 * <p>An implicit output is an OutputFile that automatically comes into existence when a rule of
1418 * this class is declared, and whose name is derived from the name of the rule.
1419 *
1420 * <p>Implicit outputs are a widely-relied upon. All ".so", and "_deploy.jar" targets referenced
1421 * in BUILD files are examples.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001422 */
1423 @VisibleForTesting
Michajlo Matijkiw6d471412016-08-09 20:35:45 +00001424 public ImplicitOutputsFunction getDefaultImplicitOutputsFunction() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001425 return implicitOutputsFunction;
1426 }
1427
Michael Staib2a675202017-03-20 18:06:48 +00001428 public RuleTransitionFactory getTransitionFactory() {
1429 return transitionFactory;
Cal Peyser19dda252017-01-11 23:37:05 +00001430 }
1431
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001432 @SuppressWarnings("unchecked")
cparsonse2d200f2018-03-06 16:15:11 -08001433 public <CT, RC, ACE extends Throwable>
1434 ConfiguredTargetFactory<CT, RC, ACE> getConfiguredTargetFactory() {
1435 return (ConfiguredTargetFactory<CT, RC, ACE>) configuredTargetFactory;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001436 }
1437
1438 /**
1439 * Returns the class of rule that this RuleClass represents (e.g. "cc_library").
1440 */
1441 public String getName() {
1442 return name;
1443 }
1444
janakr6ff110e2018-03-21 21:44:27 -07001445 /** Returns the type of rule that this RuleClass represents. Only for use during serialization. */
1446 public RuleClassType getRuleClassType() {
1447 return type;
1448 }
1449
tomlu72642a22017-10-18 06:23:14 +02001450 /** Returns a unique key. Used for profiling purposes. */
1451 public String getKey() {
1452 return key;
1453 }
1454
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001455 /**
1456 * Returns the target kind of this class of rule (e.g. "cc_library rule").
1457 */
1458 String getTargetKind() {
1459 return targetKind;
1460 }
1461
1462 public boolean getWorkspaceOnly() {
1463 return workspaceOnly;
1464 }
1465
1466 /**
1467 * Returns true iff the attribute 'attrName' is defined for this rule class,
1468 * and has type 'type'.
1469 */
1470 public boolean hasAttr(String attrName, Type<?> type) {
1471 Integer index = getAttributeIndex(attrName);
1472 return index != null && getAttribute(index).getType() == type;
1473 }
1474
1475 /**
1476 * Returns the index of the specified attribute name. Use of indices allows
1477 * space-efficient storage of attribute values in rules, since hashtables are
1478 * not required. (The index mapping is specific to each RuleClass and an
1479 * attribute may have a different index in the parent RuleClass.)
1480 *
1481 * <p>Returns null if the named attribute is not defined for this class of Rule.
1482 */
1483 Integer getAttributeIndex(String attrName) {
1484 return attributeIndex.get(attrName);
1485 }
1486
1487 /**
1488 * Returns the attribute whose index is 'attrIndex'. Fails if attrIndex is
1489 * not in range.
1490 */
1491 Attribute getAttribute(int attrIndex) {
Eric Fellheimera954fae2015-08-27 19:37:52 +00001492 return attributes.get(attrIndex);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001493 }
1494
1495 /**
Michajlo Matijkiw0446c952015-10-28 19:59:00 +00001496 * Returns the attribute whose name is 'attrName'; fails with NullPointerException if not found.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001497 */
1498 public Attribute getAttributeByName(String attrName) {
Michajlo Matijkiw0446c952015-10-28 19:59:00 +00001499 Integer attrIndex = Preconditions.checkNotNull(getAttributeIndex(attrName),
1500 "Attribute %s does not exist", attrName);
1501 return attributes.get(attrIndex);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001502 }
1503
1504 /**
1505 * Returns the attribute whose name is {@code attrName}, or null if not
1506 * found.
1507 */
1508 Attribute getAttributeByNameMaybe(String attrName) {
1509 Integer i = getAttributeIndex(attrName);
Eric Fellheimera954fae2015-08-27 19:37:52 +00001510 return i == null ? null : attributes.get(i);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001511 }
1512
1513 /**
1514 * Returns the number of attributes defined for this rule class.
1515 */
1516 public int getAttributeCount() {
1517 return attributeIndex.size();
1518 }
1519
1520 /**
1521 * Returns an (immutable) list of all Attributes defined for this class of
1522 * rule, ordered by increasing index.
1523 */
1524 public List<Attribute> getAttributes() {
Eric Fellheimera954fae2015-08-27 19:37:52 +00001525 return attributes;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001526 }
1527
Michajlo Matijkiwcdd5b0e2015-12-09 18:17:44 +00001528 /** Returns set of non-configurable attribute names defined for this class of rule. */
1529 public List<String> getNonConfigurableAttributes() {
1530 return nonConfigurableAttributes;
1531 }
1532
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001533 public PredicateWithMessage<Rule> getValidityPredicate() {
1534 return validityPredicate;
1535 }
1536
1537 /**
1538 * Returns the set of advertised transitive info providers.
1539 *
1540 * <p>When computing the set of aspects required for a rule, only the providers listed here are
1541 * considered. The presence of a provider here does not mean that the rule <b>must</b> implement
1542 * said provider, merely that it <b>can</b>. After the configured target is constructed from this
1543 * rule, aspects will be filtered according to the set of actual providers.
1544 *
1545 * <p>This is here so that we can do the loading phase overestimation required for "blaze query",
1546 * which does not have the configured targets available.
Dmitry Lomovb91d3922017-01-09 20:12:57 +00001547 **/
1548 public AdvertisedProviderSet getAdvertisedProviders() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001549 return advertisedProviders;
1550 }
Lukacs Berki549bfce2016-04-22 15:29:12 +00001551 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001552 * For --compile_one_dependency: if multiple rules consume the specified target,
1553 * should we choose this one over the "unpreferred" options?
1554 */
1555 public boolean isPreferredDependency(String filename) {
1556 return preferredDependencyPredicate.apply(filename);
1557 }
1558
1559 /**
Michael Staibb51251e2015-09-29 23:31:51 +00001560 * Returns this rule's policy for configuration fragment access.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001561 */
Michael Staibb51251e2015-09-29 23:31:51 +00001562 public ConfigurationFragmentPolicy getConfigurationFragmentPolicy() {
1563 return configurationFragmentPolicy;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001564 }
1565
1566 /**
Greg Estrenc04c88f2015-03-06 19:45:50 +00001567 * Returns true if rules of this type can be used with the constraint enforcement system.
1568 */
1569 public boolean supportsConstraintChecking() {
1570 return supportsConstraintChecking;
1571 }
1572
1573 /**
mstaibdf229582017-03-31 21:50:46 +00001574 * Returns true if rules of this type should be evaluated with the parent's configuration so that
1575 * they can match on aspects of it.
1576 */
1577 public boolean isConfigMatcher() {
1578 return isConfigMatcher;
1579 }
1580
1581 /**
Mark Schalleree624452016-01-13 18:41:24 +00001582 * Creates a new {@link Rule} {@code r} where {@code r.getPackage()} is the {@link Package}
1583 * associated with {@code pkgBuilder}.
1584 *
1585 * <p>The created {@link Rule} will be populated with attribute values from {@code
1586 * attributeValues} or the default attribute values associated with this {@link RuleClass} and
1587 * {@code pkgBuilder}.
1588 *
Florian Weikertea6c82d2016-09-05 12:15:31 +00001589 * <p>The created {@link Rule} will also be populated with output files. These output files will
1590 * have been collected from the explicitly provided values of type {@link BuildType#OUTPUT} and
1591 * {@link BuildType#OUTPUT_LIST} as well as from the implicit outputs determined by this {@link
1592 * RuleClass} and the values in {@code attributeValues}.
Mark Schalleree624452016-01-13 18:41:24 +00001593 *
1594 * <p>This performs several validity checks. Invalid output file labels result in a thrown {@link
Florian Weikertea6c82d2016-09-05 12:15:31 +00001595 * LabelSyntaxException}. Computed default attributes that fail during precomputation result in a
1596 * {@link CannotPrecomputeDefaultsException}. All other errors are reported on {@code
1597 * eventHandler}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001598 */
nharmata65a173a2017-08-07 16:11:04 +02001599 <T> Rule createRule(
Mark Schalleree624452016-01-13 18:41:24 +00001600 Package.Builder pkgBuilder,
1601 Label ruleLabel,
nharmata65a173a2017-08-07 16:11:04 +02001602 AttributeValues<T> attributeValues,
Mark Schalleree624452016-01-13 18:41:24 +00001603 EventHandler eventHandler,
1604 @Nullable FuncallExpression ast,
1605 Location location,
1606 AttributeContainer attributeContainer)
Florian Weikertea6c82d2016-09-05 12:15:31 +00001607 throws LabelSyntaxException, InterruptedException, CannotPrecomputeDefaultsException {
Michajlo Matijkiw581f2c22016-07-25 20:12:16 +00001608 Rule rule = pkgBuilder.createRule(ruleLabel, this, location, attributeContainer);
1609 populateRuleAttributeValues(rule, pkgBuilder, attributeValues, eventHandler);
1610 checkAspectAllowedValues(rule, eventHandler);
1611 rule.populateOutputFiles(eventHandler, pkgBuilder);
1612 if (ast != null) {
1613 populateAttributeLocations(rule, ast);
1614 }
1615 checkForDuplicateLabels(rule, eventHandler);
1616 checkThirdPartyRuleHasLicense(rule, pkgBuilder, eventHandler);
1617 checkForValidSizeAndTimeoutValues(rule, eventHandler);
1618 rule.checkValidityPredicate(eventHandler);
Nathan Harmatacf738442016-06-28 14:52:21 +00001619 rule.checkForNullLabels();
1620 return rule;
1621 }
1622
1623 /**
1624 * Same as {@link #createRule}, except without some internal sanity checks.
1625 *
1626 * <p>Don't call this function unless you know what you're doing.
1627 */
nharmata65a173a2017-08-07 16:11:04 +02001628 <T> Rule createRuleUnchecked(
Nathan Harmatacf738442016-06-28 14:52:21 +00001629 Package.Builder pkgBuilder,
1630 Label ruleLabel,
nharmata65a173a2017-08-07 16:11:04 +02001631 AttributeValues<T> attributeValues,
Nathan Harmatacf738442016-06-28 14:52:21 +00001632 Location location,
Michajlo Matijkiw6d471412016-08-09 20:35:45 +00001633 AttributeContainer attributeContainer,
1634 ImplicitOutputsFunction implicitOutputsFunction)
nharmata59c16f62017-08-07 19:49:09 +02001635 throws InterruptedException, CannotPrecomputeDefaultsException {
Michajlo Matijkiw6d471412016-08-09 20:35:45 +00001636 Rule rule = pkgBuilder.createRule(
1637 ruleLabel,
1638 this,
1639 location,
1640 attributeContainer,
1641 implicitOutputsFunction);
Michajlo Matijkiw581f2c22016-07-25 20:12:16 +00001642 populateRuleAttributeValues(rule, pkgBuilder, attributeValues, NullEventHandler.INSTANCE);
nharmata59c16f62017-08-07 19:49:09 +02001643 rule.populateOutputFilesUnchecked(NullEventHandler.INSTANCE, pkgBuilder);
Mark Schalleree624452016-01-13 18:41:24 +00001644 return rule;
1645 }
1646
1647 /**
1648 * Populates the attributes table of the new {@link Rule} with the values in the {@code
1649 * attributeValues} map and with default values provided by this {@link RuleClass} and the {@code
1650 * pkgBuilder}.
1651 *
1652 * <p>Errors are reported on {@code eventHandler}.
1653 */
nharmata65a173a2017-08-07 16:11:04 +02001654 private <T> void populateRuleAttributeValues(
Mark Schalleree624452016-01-13 18:41:24 +00001655 Rule rule,
1656 Package.Builder pkgBuilder,
nharmata65a173a2017-08-07 16:11:04 +02001657 AttributeValues<T> attributeValues,
Florian Weikertea6c82d2016-09-05 12:15:31 +00001658 EventHandler eventHandler)
1659 throws InterruptedException, CannotPrecomputeDefaultsException {
Mark Schalleree624452016-01-13 18:41:24 +00001660 BitSet definedAttrIndices =
1661 populateDefinedRuleAttributeValues(rule, attributeValues, eventHandler);
1662 populateDefaultRuleAttributeValues(rule, pkgBuilder, definedAttrIndices, eventHandler);
1663 // Now that all attributes are bound to values, collect and store configurable attribute keys.
1664 populateConfigDependenciesAttribute(rule);
1665 }
1666
1667 /**
1668 * Populates the attributes table of the new {@link Rule} with the values in the {@code
1669 * attributeValues} map.
1670 *
1671 * <p>Handles the special cases of the attribute named {@code "name"} and attributes with value
1672 * {@link Runtime#NONE}.
1673 *
1674 * <p>Returns a bitset {@code b} where {@code b.get(i)} is {@code true} if this method set a
1675 * value for the attribute with index {@code i} in this {@link RuleClass}. Errors are reported
1676 * on {@code eventHandler}.
1677 */
nharmata65a173a2017-08-07 16:11:04 +02001678 private <T> BitSet populateDefinedRuleAttributeValues(
1679 Rule rule, AttributeValues<T> attributeValues, EventHandler eventHandler) {
Mark Schalleree624452016-01-13 18:41:24 +00001680 BitSet definedAttrIndices = new BitSet();
nharmata65a173a2017-08-07 16:11:04 +02001681 for (T attributeAccessor : attributeValues.getAttributeAccessors()) {
1682 String attributeName = attributeValues.getName(attributeAccessor);
1683 Object attributeValue = attributeValues.getValue(attributeAccessor);
Mark Schalleree624452016-01-13 18:41:24 +00001684 // Ignore all None values.
1685 if (attributeValue == Runtime.NONE) {
1686 continue;
1687 }
1688
1689 // Check that the attribute's name belongs to a valid attribute for this rule class.
1690 Integer attrIndex = getAttributeIndex(attributeName);
1691 if (attrIndex == null) {
1692 rule.reportError(
1693 String.format(
1694 "%s: no such attribute '%s' in '%s' rule", rule.getLabel(), attributeName, name),
1695 eventHandler);
1696 continue;
1697 }
1698 Attribute attr = getAttribute(attrIndex);
1699
1700 // Convert the build-lang value to a native value, if necessary.
1701 Object nativeAttributeValue;
1702 if (attributeValues.valuesAreBuildLanguageTyped()) {
1703 try {
1704 nativeAttributeValue = convertFromBuildLangType(rule, attr, attributeValue);
1705 } catch (ConversionException e) {
1706 rule.reportError(String.format("%s: %s", rule.getLabel(), e.getMessage()), eventHandler);
1707 continue;
1708 }
1709 } else {
1710 nativeAttributeValue = attributeValue;
1711 }
1712
nharmata65a173a2017-08-07 16:11:04 +02001713 boolean explicit = attributeValues.isExplicitlySpecified(attributeAccessor);
Mark Schalleree624452016-01-13 18:41:24 +00001714 setRuleAttributeValue(rule, eventHandler, attr, nativeAttributeValue, explicit);
1715 definedAttrIndices.set(attrIndex);
Mark Schalleree624452016-01-13 18:41:24 +00001716 }
1717 return definedAttrIndices;
1718 }
1719
1720 /** Populates attribute locations for attributes defined in {@code ast}. */
1721 private void populateAttributeLocations(Rule rule, FuncallExpression ast) {
1722 for (Argument.Passed arg : ast.getArguments()) {
1723 if (arg.isKeyword()) {
1724 String name = arg.getName();
1725 Integer attrIndex = getAttributeIndex(name);
1726 if (attrIndex != null) {
1727 rule.setAttributeLocation(attrIndex, arg.getValue().getLocation());
1728 }
1729 }
1730 }
1731 }
1732
1733 /**
1734 * Populates the attributes table of the new {@link Rule} with default values provided by this
Florian Weikertea6c82d2016-09-05 12:15:31 +00001735 * {@link RuleClass} and the {@code pkgBuilder}. This will only provide values for attributes that
1736 * haven't already been populated, using {@code definedAttrIndices} to determine whether an
Mark Schalleree624452016-01-13 18:41:24 +00001737 * attribute was populated.
1738 *
1739 * <p>Errors are reported on {@code eventHandler}.
1740 */
1741 private void populateDefaultRuleAttributeValues(
Florian Weikertea6c82d2016-09-05 12:15:31 +00001742 Rule rule, Package.Builder pkgBuilder, BitSet definedAttrIndices, EventHandler eventHandler)
1743 throws InterruptedException, CannotPrecomputeDefaultsException {
Mark Schalleree624452016-01-13 18:41:24 +00001744 // Set defaults; ensure that every mandatory attribute has a value. Use the default if none
1745 // is specified.
1746 List<Attribute> attrsWithComputedDefaults = new ArrayList<>();
1747 int numAttributes = getAttributeCount();
1748 for (int attrIndex = 0; attrIndex < numAttributes; ++attrIndex) {
1749 if (definedAttrIndices.get(attrIndex)) {
1750 continue;
1751 }
1752 Attribute attr = getAttribute(attrIndex);
1753 if (attr.isMandatory()) {
1754 rule.reportError(
1755 String.format(
1756 "%s: missing value for mandatory attribute '%s' in '%s' rule",
1757 rule.getLabel(),
1758 attr.getName(),
1759 name),
1760 eventHandler);
1761 }
1762
1763 if (attr.hasComputedDefault()) {
1764 // Note that it is necessary to set all non-computed default values before calling
1765 // Attribute#getDefaultValue for computed default attributes. Computed default attributes
1766 // may have a condition predicate (i.e. the predicate returned by Attribute#getCondition)
1767 // that depends on non-computed default attribute values, and that condition predicate is
1768 // evaluated by the call to Attribute#getDefaultValue.
1769 attrsWithComputedDefaults.add(attr);
cparsonscaceacd2017-11-04 01:00:59 +01001770 } else if (attr.isLateBound()) {
1771 rule.setAttributeValue(attr, attr.getLateBoundDefault(), /*explicit=*/ false);
Mark Schalleree624452016-01-13 18:41:24 +00001772 } else {
1773 Object defaultValue = getAttributeNoncomputedDefaultValue(attr, pkgBuilder);
Mark Schalleree624452016-01-13 18:41:24 +00001774 rule.setAttributeValue(attr, defaultValue, /*explicit=*/ false);
1775 checkAllowedValues(rule, attr, eventHandler);
1776 }
1777 }
1778
1779 // Set computed default attribute values now that all other (i.e. non-computed) default values
1780 // have been set.
1781 for (Attribute attr : attrsWithComputedDefaults) {
Florian Weikertea6c82d2016-09-05 12:15:31 +00001782 // If Attribute#hasComputedDefault was true above, Attribute#getDefaultValue returns the
1783 // computed default function object or a Skylark computed default template. Note that we
1784 // cannot determine the exact value of the computed default function here because it may
1785 // depend on other attribute values that are configurable (i.e. they came from select({..})
1786 // expressions in the build language, and they require configuration data from the analysis
1787 // phase to be resolved). Instead, we're setting the attribute value to a reference to the
1788 // computed default function, or if #getDefaultValue is a Skylark computed default
1789 // template, setting the attribute value to a reference to the SkylarkComputedDefault
1790 // returned from SkylarkComputedDefaultTemplate#computePossibleValues.
1791 //
1792 // SkylarkComputedDefaultTemplate#computePossibleValues pre-computes all possible values the
1793 // function may evaluate to, and records them in a lookup table. By calling it here, with an
1794 // EventHandler, any errors that might occur during the function's evaluation can
1795 // be discovered and propagated here.
1796 Object valueToSet;
1797 Object defaultValue = attr.getDefaultValue(rule);
1798 if (defaultValue instanceof SkylarkComputedDefaultTemplate) {
1799 SkylarkComputedDefaultTemplate template = (SkylarkComputedDefaultTemplate) defaultValue;
1800 valueToSet = template.computePossibleValues(attr, rule, eventHandler);
1801 } else {
1802 valueToSet = defaultValue;
1803 }
1804 rule.setAttributeValue(attr, valueToSet, /*explicit=*/ false);
Mark Schalleree624452016-01-13 18:41:24 +00001805 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001806 }
1807
1808 /**
1809 * Collects all labels used as keys for configurable attributes and places them into
1810 * the special implicit attribute that tracks them.
1811 */
1812 private static void populateConfigDependenciesAttribute(Rule rule) {
1813 RawAttributeMapper attributes = RawAttributeMapper.of(rule);
1814 Attribute configDepsAttribute = attributes.getAttributeDefinition("$config_dependencies");
1815 if (configDepsAttribute == null) {
1816 // Not currently compatible with Skylark rules.
1817 return;
1818 }
1819
1820 Set<Label> configLabels = new LinkedHashSet<>();
1821 for (Attribute attr : rule.getAttributes()) {
Lukacs Berkiffa73ad2015-09-18 11:40:12 +00001822 SelectorList<?> selectors = attributes.getSelectorList(attr.getName(), attr.getType());
Greg Estrena4fc8772015-04-13 19:58:23 +00001823 if (selectors != null) {
Lukacs Berkia88755c2016-01-22 16:40:37 +00001824 configLabels.addAll(selectors.getKeyLabels());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001825 }
1826 }
1827
1828 rule.setAttributeValue(configDepsAttribute, ImmutableList.copyOf(configLabels),
1829 /*explicit=*/false);
1830 }
1831
Nathan Harmatafcb17112016-04-13 16:56:58 +00001832 public void checkAttributesNonEmpty(
1833 Rule rule, RuleErrorConsumer ruleErrorConsumer, AttributeMap attributes) {
1834 for (String attributeName : attributes.getAttributeNames()) {
1835 Attribute attr = attributes.getAttributeDefinition(attributeName);
1836 if (!attr.isNonEmpty()) {
1837 continue;
1838 }
1839 Object attributeValue = attributes.get(attributeName, attr.getType());
Francois-Rene Rideau93ed7f12015-10-20 15:39:33 +00001840
Nathan Harmatafcb17112016-04-13 16:56:58 +00001841 boolean isEmpty = false;
1842 if (attributeValue instanceof SkylarkList) {
1843 isEmpty = ((SkylarkList) attributeValue).isEmpty();
1844 } else if (attributeValue instanceof List<?>) {
1845 isEmpty = ((List<?>) attributeValue).isEmpty();
1846 } else if (attributeValue instanceof Map<?, ?>) {
1847 isEmpty = ((Map<?, ?>) attributeValue).isEmpty();
1848 }
Francois-Rene Rideau5e00ec62015-10-20 17:02:19 +00001849
Nathan Harmatafcb17112016-04-13 16:56:58 +00001850 if (isEmpty) {
1851 ruleErrorConsumer.attributeError(attr.getName(), "attribute must be non empty");
1852 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001853 }
1854 }
1855
1856 /**
1857 * Report an error for each label that appears more than once in a LABEL_LIST attribute
1858 * of the given rule.
1859 *
1860 * @param rule The rule.
1861 * @param eventHandler The eventHandler to use to report the duplicated deps.
1862 */
1863 private static void checkForDuplicateLabels(Rule rule, EventHandler eventHandler) {
1864 for (Attribute attribute : rule.getAttributes()) {
Lukacs Berkiffa73ad2015-09-18 11:40:12 +00001865 if (attribute.getType() == BuildType.LABEL_LIST) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001866 checkForDuplicateLabels(rule, attribute, eventHandler);
1867 }
1868 }
1869 }
1870
1871 /**
1872 * Reports an error against the specified rule if it's beneath third_party
1873 * but does not have a declared license.
1874 */
1875 private static void checkThirdPartyRuleHasLicense(Rule rule,
Han-Wen Nienhuys086e5f22015-04-21 11:39:59 +00001876 Package.Builder pkgBuilder, EventHandler eventHandler) {
Brian Silvermand7d6d622016-03-17 09:53:39 +00001877 if (isThirdPartyPackage(rule.getLabel().getPackageIdentifier())) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001878 License license = rule.getLicense();
1879 if (license == null) {
1880 license = pkgBuilder.getDefaultLicense();
1881 }
lberki0d8d4cf2017-09-05 16:01:44 +02001882 if (!license.isSpecified()) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001883 rule.reportError("third-party rule '" + rule.getLabel() + "' lacks a license declaration "
1884 + "with one of the following types: notice, reciprocal, permissive, "
1885 + "restricted, unencumbered, by_exception_only",
1886 eventHandler);
1887 }
1888 }
1889 }
1890
1891 /**
1892 * Report an error for each label that appears more than once in the given attribute
1893 * of the given rule.
1894 *
1895 * @param rule The rule.
1896 * @param attribute The attribute to check. Must exist in rule and be of type LABEL_LIST.
1897 * @param eventHandler The eventHandler to use to report the duplicated deps.
1898 */
1899 private static void checkForDuplicateLabels(Rule rule, Attribute attribute,
1900 EventHandler eventHandler) {
Greg Estren14348c02015-04-16 16:26:19 +00001901 Set<Label> duplicates = AggregatingAttributeMapper.of(rule).checkForDuplicateLabels(attribute);
1902 for (Label label : duplicates) {
1903 rule.reportError(
1904 String.format("Label '%s' is duplicated in the '%s' attribute of rule '%s'",
1905 label, attribute.getName(), rule.getName()), eventHandler);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001906 }
1907 }
1908
1909 /**
1910 * Report an error if the rule has a timeout or size attribute that is not a
1911 * legal value. These attributes appear on all tests.
1912 *
1913 * @param rule the rule to check
1914 * @param eventHandler the eventHandler to use to report the duplicated deps
1915 */
1916 private static void checkForValidSizeAndTimeoutValues(Rule rule, EventHandler eventHandler) {
1917 if (rule.getRuleClassObject().hasAttr("size", Type.STRING)) {
1918 String size = NonconfigurableAttributeMapper.of(rule).get("size", Type.STRING);
1919 if (TestSize.getTestSize(size) == null) {
1920 rule.reportError(
1921 String.format("In rule '%s', size '%s' is not a valid size.", rule.getName(), size),
1922 eventHandler);
1923 }
1924 }
1925 if (rule.getRuleClassObject().hasAttr("timeout", Type.STRING)) {
1926 String timeout = NonconfigurableAttributeMapper.of(rule).get("timeout", Type.STRING);
1927 if (TestTimeout.getTestTimeout(timeout) == null) {
1928 rule.reportError(
1929 String.format(
1930 "In rule '%s', timeout '%s' is not a valid timeout.", rule.getName(), timeout),
1931 eventHandler);
1932 }
1933 }
1934 }
1935
1936 /**
1937 * Returns the default value for the specified rule attribute.
1938 *
Francois-Rene Rideau5dcdbf92015-02-19 18:36:17 +00001939 * <p>For most rule attributes, the default value is either explicitly specified
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001940 * in the attribute, or implicitly based on the type of the attribute, except
1941 * for some special cases (e.g. "licenses", "distribs") where it comes from
1942 * some other source, such as state in the package.
1943 *
Francois-Rene Rideau5dcdbf92015-02-19 18:36:17 +00001944 * <p>Precondition: {@code !attr.hasComputedDefault()}. (Computed defaults are
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001945 * evaluated in second pass.)
1946 */
1947 private static Object getAttributeNoncomputedDefaultValue(Attribute attr,
Han-Wen Nienhuys086e5f22015-04-21 11:39:59 +00001948 Package.Builder pkgBuilder) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001949 if (attr.getName().equals("licenses")) {
1950 return pkgBuilder.getDefaultLicense();
1951 }
1952 if (attr.getName().equals("distribs")) {
1953 return pkgBuilder.getDefaultDistribs();
1954 }
1955 return attr.getDefaultValue(null);
1956 }
1957
1958 /**
Mark Schalleree624452016-01-13 18:41:24 +00001959 * Sets the value of attribute {@code attr} in {@code rule} to the native value {@code
1960 * nativeAttrVal}, and sets the value's explicitness to {@code explicit}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001961 *
Mark Schalleree624452016-01-13 18:41:24 +00001962 * <p>Handles the special case of the "visibility" attribute by also setting the rule's
1963 * visibility with {@link Rule#setVisibility}.
1964 *
1965 * <p>Checks that {@code nativeAttrVal} is an allowed value via {@link #checkAllowedValues}.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001966 */
Mark Schalleree624452016-01-13 18:41:24 +00001967 private static void setRuleAttributeValue(
1968 Rule rule,
1969 EventHandler eventHandler,
1970 Attribute attr,
1971 Object nativeAttrVal,
1972 boolean explicit) {
1973 if (attr.getName().equals("visibility")) {
1974 @SuppressWarnings("unchecked")
1975 List<Label> attrList = (List<Label>) nativeAttrVal;
Francois-Rene Rideaucbebd632015-02-11 16:56:37 +00001976 if (!attrList.isEmpty()
1977 && ConstantRuleVisibility.LEGACY_PUBLIC_LABEL.equals(attrList.get(0))) {
Mark Schalleree624452016-01-13 18:41:24 +00001978 rule.reportError(
1979 rule.getLabel() + ": //visibility:legacy_public only allowed in package declaration",
1980 eventHandler);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001981 }
Yue Gan36a26572016-05-25 11:48:10 +00001982 try {
1983 rule.setVisibility(PackageFactory.getVisibility(rule.getLabel(), attrList));
1984 } catch (EvalException e) {
1985 rule.reportError(rule.getLabel() + " " + e.getMessage(), eventHandler);
1986 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001987 }
Mark Schalleree624452016-01-13 18:41:24 +00001988 rule.setAttributeValue(attr, nativeAttrVal, explicit);
Michael Staibff938b32015-08-27 19:22:59 +00001989 checkAllowedValues(rule, attr, eventHandler);
Mark Schalleree624452016-01-13 18:41:24 +00001990 }
1991
1992 /**
1993 * Converts the build-language-typed {@code buildLangValue} to a native value via {@link
laurentlb1d273cd2018-05-16 12:12:26 -07001994 * BuildType#selectableConvert}. Canonicalizes the value's order if it is a {@link List} type and
1995 * {@code attr.isOrderIndependent()} returns {@code true}.
Mark Schalleree624452016-01-13 18:41:24 +00001996 *
laurentlb1d273cd2018-05-16 12:12:26 -07001997 * <p>Throws {@link ConversionException} if the conversion fails, or if {@code buildLangValue} is
1998 * a selector expression but {@code attr.isConfigurable()} is {@code false}.
Mark Schalleree624452016-01-13 18:41:24 +00001999 */
2000 private static Object convertFromBuildLangType(Rule rule, Attribute attr, Object buildLangValue)
2001 throws ConversionException {
Michajlo Matijkiw7b7fce12016-09-20 19:52:07 +00002002 Object converted = BuildType.selectableConvert(
2003 attr.getType(),
2004 buildLangValue,
2005 new AttributeConversionContext(attr.getName(), rule.getRuleClass()),
2006 rule.getLabel());
Mark Schalleree624452016-01-13 18:41:24 +00002007
2008 if ((converted instanceof SelectorList<?>) && !attr.isConfigurable()) {
2009 throw new ConversionException(
2010 String.format("attribute \"%s\" is not configurable", attr.getName()));
2011 }
2012
laurentlb1d273cd2018-05-16 12:12:26 -07002013 if (converted instanceof List<?>) {
Mark Schalleree624452016-01-13 18:41:24 +00002014 if (attr.isOrderIndependent()) {
2015 @SuppressWarnings("unchecked")
2016 List<? extends Comparable<?>> list = (List<? extends Comparable<?>>) converted;
2017 converted = Ordering.natural().sortedCopy(list);
2018 }
2019 converted = ImmutableList.copyOf((List<?>) converted);
2020 }
2021
2022 return converted;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002023 }
2024
Michael Staibff938b32015-08-27 19:22:59 +00002025 /**
Michajlo Matijkiw7b7fce12016-09-20 19:52:07 +00002026 * Provides a {@link #toString()} description of the attribute being converted for
2027 * {@link BuildType#selectableConvert}. This is preferred over a raw string to avoid uselessly
2028 * constructing strings which are never used. A separate class instead of inline to avoid
2029 * accidental memory leaks.
2030 */
2031 private static class AttributeConversionContext {
2032 private final String attrName;
2033 private final String ruleClass;
2034
2035 AttributeConversionContext(String attrName, String ruleClass) {
2036 this.attrName = attrName;
2037 this.ruleClass = ruleClass;
2038 }
2039
2040 @Override
2041 public String toString() {
2042 return "attribute '" + attrName + "' in '" + ruleClass + "' rule";
2043 }
2044 }
2045
2046
2047 /**
Michael Staibff938b32015-08-27 19:22:59 +00002048 * Verifies that the rule has a valid value for the attribute according to its allowed values.
2049 *
2050 * <p>If the value for the given attribute on the given rule is invalid, an error will be recorded
2051 * in the given EventHandler.
2052 *
2053 * <p>If the rule is configurable, all of its potential values are evaluated, and errors for each
2054 * of the invalid values are reported.
2055 */
Mark Schalleree624452016-01-13 18:41:24 +00002056 private static void checkAllowedValues(
2057 Rule rule, Attribute attribute, EventHandler eventHandler) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002058 if (attribute.checkAllowedValues()) {
2059 PredicateWithMessage<Object> allowedValues = attribute.getAllowedValues();
Michael Staibff938b32015-08-27 19:22:59 +00002060 Iterable<?> values =
2061 AggregatingAttributeMapper.of(rule).visitAttribute(
2062 attribute.getName(), attribute.getType());
2063 for (Object value : values) {
2064 if (!allowedValues.apply(value)) {
Mark Schalleree624452016-01-13 18:41:24 +00002065 rule.reportError(
2066 String.format(
2067 "%s: invalid value in '%s' attribute: %s",
2068 rule.getLabel(),
2069 attribute.getName(),
2070 allowedValues.getErrorReason(value)),
2071 eventHandler);
Michael Staibff938b32015-08-27 19:22:59 +00002072 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002073 }
2074 }
2075 }
2076
Googler74558fc2016-05-06 21:47:42 +00002077 private static void checkAspectAllowedValues(
2078 Rule rule, EventHandler eventHandler) {
2079 for (Attribute attrOfRule : rule.getAttributes()) {
2080 for (Aspect aspect : attrOfRule.getAspects(rule)) {
2081 for (Attribute attrOfAspect : aspect.getDefinition().getAttributes().values()) {
2082 // By this point the AspectDefinition has been created and values assigned.
2083 if (attrOfAspect.checkAllowedValues()) {
2084 PredicateWithMessage<Object> allowedValues = attrOfAspect.getAllowedValues();
2085 Object value = attrOfAspect.getDefaultValue(rule);
2086 if (!allowedValues.apply(value)) {
2087 rule.reportError(
2088 String.format(
2089 "%s: invalid value in '%s' attribute: %s",
2090 rule.getLabel(),
2091 attrOfAspect.getName(),
2092 allowedValues.getErrorReason(value)),
2093 eventHandler);
2094 }
2095 }
2096 }
2097 }
2098 }
2099 }
2100
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002101 @Override
2102 public String toString() {
2103 return name;
2104 }
2105
2106 public boolean isDocumented() {
2107 return documented;
2108 }
2109
2110 public boolean isPublicByDefault() {
2111 return publicByDefault;
2112 }
2113
2114 /**
2115 * Returns true iff the outputs of this rule should be created beneath the
2116 * <i>bin</i> directory, false if beneath <i>genfiles</i>. For most rule
2117 * classes, this is a constant, but for genrule, it is a property of the
2118 * individual rule instance, derived from the 'output_to_bindir' attribute;
2119 * see Rule.hasBinaryOutput().
2120 */
Laurent Le Brunc2efe452015-04-08 16:27:21 +00002121 @VisibleForTesting
2122 public boolean hasBinaryOutput() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002123 return binaryOutput;
2124 }
2125
2126 /**
2127 * Returns this RuleClass's custom Skylark rule implementation.
2128 */
Francois-Rene Rideau95b0d0c2015-04-22 16:52:13 +00002129 @Nullable public BaseFunction getConfiguredTargetFunction() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002130 return configuredTargetFunction;
2131 }
2132
2133 /**
Lukacs Berki0e1a9942015-06-18 08:53:18 +00002134 * Returns a function that computes the external bindings a repository function contributes to
2135 * the WORKSPACE file.
2136 */
2137 public Function<? super Rule, Map<String, Label>> getExternalBindingsFunction() {
2138 return externalBindingsFunction;
2139 }
2140
2141 /**
mstaibe5538ad2017-04-04 18:32:23 +00002142 * Returns a function that computes the options referenced by a rule.
2143 */
2144 public Function<? super Rule, ? extends Set<String>> getOptionReferenceFunction() {
2145 return optionReferenceFunction;
2146 }
2147
2148 /**
janakrd3fe5e72018-03-30 12:49:12 -07002149 * For Skylark rule classes, returns this RuleClass's rule definition environment's label, which
2150 * is never null. Is null for native rules' RuleClass objects.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002151 */
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00002152 @Nullable
janakrd3fe5e72018-03-30 12:49:12 -07002153 public Label getRuleDefinitionEnvironmentLabel() {
2154 return ruleDefinitionEnvironmentLabel;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002155 }
2156
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00002157 /**
janakrd3fe5e72018-03-30 12:49:12 -07002158 * Returns the hash code for the RuleClass's rule definition environment. Will be null for native
2159 * rules' RuleClass objects.
Janak Ramakrishnan9b12f9c2016-05-20 16:33:02 +00002160 */
2161 @Nullable
2162 public String getRuleDefinitionEnvironmentHashCode() {
2163 return ruleDefinitionEnvironmentHashCode;
2164 }
2165
Jon Brandveinead58ae2016-09-29 18:41:10 +00002166 /** Returns true if this RuleClass is a Skylark-defined RuleClass. */
Michajlo Matijkiwbc042c62015-10-29 13:22:52 +00002167 public boolean isSkylark() {
2168 return isSkylark;
2169 }
2170
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002171 /**
Jon Brandveinead58ae2016-09-29 18:41:10 +00002172 * Returns true if this RuleClass is Skylark-defined and is subject to analysis-time
2173 * tests.
2174 */
2175 public boolean isSkylarkTestable() {
2176 return skylarkTestable;
2177 }
2178
2179 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002180 * Returns true if this rule class outputs a default executable for every rule.
2181 */
dslomov2ce98442017-10-23 19:14:02 +02002182 public boolean isExecutableSkylark() {
2183 return isExecutableSkylark;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002184 }
Brian Silvermand7d6d622016-03-17 09:53:39 +00002185
cpeyserfb829992017-09-07 17:17:03 +02002186 public ImmutableSet<Label> getRequiredToolchains() {
John Catereca28402017-05-17 21:44:12 +02002187 return requiredToolchains;
2188 }
2189
John Cater856b4dd2017-11-21 08:06:16 -08002190 public boolean supportsPlatforms() {
2191 return supportsPlatforms;
2192 }
2193
Dmitry Lomov5b1ce4d2018-05-30 04:34:08 -07002194 @Nullable
2195 public OutputFile.Kind getOutputFileKind() {
2196 return outputFileKind;
2197 }
2198
Brian Silvermand7d6d622016-03-17 09:53:39 +00002199 public static boolean isThirdPartyPackage(PackageIdentifier packageIdentifier) {
2200 if (!packageIdentifier.getRepository().isMain()) {
2201 return false;
2202 }
2203
2204 if (!packageIdentifier.getPackageFragment().startsWith(THIRD_PARTY_PREFIX)) {
2205 return false;
2206 }
2207
2208 if (packageIdentifier.getPackageFragment().segmentCount() <= 1) {
2209 return false;
2210 }
2211
2212 return true;
2213 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002214}