blob: 817f4d163e5e80a64e6115b9f586cf3ca38a4442 [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.analysis;
16
17import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.DATA;
18import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST;
19import static com.google.devtools.build.lib.packages.Attribute.attr;
Lukacs Berkiffa73ad2015-09-18 11:40:12 +000020import static com.google.devtools.build.lib.packages.BuildType.DISTRIBUTIONS;
21import static com.google.devtools.build.lib.packages.BuildType.LABEL;
22import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
23import static com.google.devtools.build.lib.packages.BuildType.LICENSE;
24import static com.google.devtools.build.lib.packages.BuildType.NODEP_LABEL_LIST;
25import static com.google.devtools.build.lib.syntax.Type.BOOLEAN;
26import static com.google.devtools.build.lib.syntax.Type.INTEGER;
27import static com.google.devtools.build.lib.syntax.Type.STRING;
28import static com.google.devtools.build.lib.syntax.Type.STRING_LIST;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010029
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +000030import com.google.common.annotations.VisibleForTesting;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010031import com.google.common.collect.ImmutableList;
gregce490b0952017-07-06 18:44:38 -040032import com.google.common.collect.ImmutableMap;
Ulf Adams37590dc2016-10-14 11:52:00 +000033import com.google.common.collect.ImmutableSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010034import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
gregce490b0952017-07-06 18:44:38 -040035import com.google.devtools.build.lib.analysis.config.DynamicTransitionMapper;
36import com.google.devtools.build.lib.analysis.config.HostTransition;
37import com.google.devtools.build.lib.analysis.config.PatchTransition;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010038import com.google.devtools.build.lib.analysis.config.RunUnder;
39import com.google.devtools.build.lib.analysis.constraints.EnvironmentRule;
ulfjackab21d182017-08-10 15:36:14 +020040import com.google.devtools.build.lib.analysis.test.TestConfiguration;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000041import com.google.devtools.build.lib.cmdline.Label;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010042import com.google.devtools.build.lib.packages.Attribute;
43import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel;
44import com.google.devtools.build.lib.packages.Attribute.LateBoundLabelList;
gregce490b0952017-07-06 18:44:38 -040045import com.google.devtools.build.lib.packages.Attribute.Transition;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010046import com.google.devtools.build.lib.packages.AttributeMap;
47import com.google.devtools.build.lib.packages.Rule;
48import com.google.devtools.build.lib.packages.RuleClass;
49import com.google.devtools.build.lib.packages.RuleClass.Builder;
50import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
51import com.google.devtools.build.lib.packages.TestSize;
Lukacs Berkiffa73ad2015-09-18 11:40:12 +000052import com.google.devtools.build.lib.syntax.Type;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010053import com.google.devtools.build.lib.util.FileTypeSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010054import java.util.List;
55
56/**
57 * Rule class definitions used by (almost) every rule.
58 */
59public class BaseRuleClasses {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010060 private static final Attribute.ComputedDefault testonlyDefault =
61 new Attribute.ComputedDefault() {
62 @Override
63 public Object getDefault(AttributeMap rule) {
64 return rule.getPackageDefaultTestOnly();
65 }
66 };
67
68 private static final Attribute.ComputedDefault deprecationDefault =
69 new Attribute.ComputedDefault() {
70 @Override
71 public Object getDefault(AttributeMap rule) {
72 return rule.getPackageDefaultDeprecation();
73 }
74 };
75
76 /**
77 * Implementation for the :action_listener attribute.
78 */
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +000079 @VisibleForTesting
80 static final LateBoundLabelList<BuildConfiguration> ACTION_LISTENER =
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010081 new LateBoundLabelList<BuildConfiguration>() {
82 @Override
Lukacs Berki0dbe07f2016-04-19 10:22:08 +000083 public List<Label> resolve(Rule rule, AttributeMap attributes,
Greg Estren33ec1912016-02-10 15:57:58 +000084 BuildConfiguration configuration) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010085 // action_listeners are special rules; they tell the build system to add extra_actions to
86 // existing rules. As such they need an edge to every ConfiguredTarget with the limitation
87 // that they only run on the target configuration and should not operate on action_listeners
88 // and extra_actions themselves (to avoid cycles).
89 return configuration.getActionListeners();
90 }
91 };
92
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010093 /**
94 * Implementation for the :run_under attribute.
95 */
Lukacs Berki8f460f32016-06-29 09:14:10 +000096 public static final LateBoundLabel<BuildConfiguration> RUN_UNDER =
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010097 new LateBoundLabel<BuildConfiguration>() {
98 @Override
Lukacs Berki0dbe07f2016-04-19 10:22:08 +000099 public Label resolve(Rule rule, AttributeMap attributes,
Greg Estren33ec1912016-02-10 15:57:58 +0000100 BuildConfiguration configuration) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100101 RunUnder runUnder = configuration.getRunUnder();
102 return runUnder == null ? null : runUnder.getLabel();
103 }
104 };
105
106 /**
107 * A base rule for all test rules.
108 */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100109 public static final class TestBaseRule implements RuleDefinition {
110 @Override
111 public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
112 return builder
tomlua08bb892017-08-03 03:23:48 +0200113 .requiresConfigurationFragments(TestConfiguration.class)
114 .add(
115 attr("size", STRING)
116 .value("medium")
117 .taggable()
118 .nonconfigurable("policy decision: should be consistent across configurations"))
119 .add(
120 attr("timeout", STRING)
121 .taggable()
122 .nonconfigurable("policy decision: should be consistent across configurations")
123 .value(
124 new Attribute.ComputedDefault() {
125 @Override
126 public Object getDefault(AttributeMap rule) {
127 TestSize size = TestSize.getTestSize(rule.get("size", Type.STRING));
128 if (size != null) {
129 String timeout = size.getDefaultTimeout().toString();
130 if (timeout != null) {
131 return timeout;
132 }
133 }
134 return "illegal";
135 }
136 }))
137 .add(
138 attr("flaky", BOOLEAN)
139 .value(false)
140 .taggable()
141 .nonconfigurable("policy decision: should be consistent across configurations"))
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100142 .add(attr("shard_count", INTEGER).value(-1))
tomlua08bb892017-08-03 03:23:48 +0200143 .add(
144 attr("local", BOOLEAN)
145 .value(false)
146 .taggable()
147 .nonconfigurable("policy decision: should be consistent across configurations"))
Greg Estren547295a2016-08-18 22:01:29 +0000148 .add(attr("args", STRING_LIST))
Lukacs Berki8f460f32016-06-29 09:14:10 +0000149 // Input files for every test action
tomlua08bb892017-08-03 03:23:48 +0200150 .add(
151 attr("$test_runtime", LABEL_LIST)
152 .cfg(HOST)
153 .value(ImmutableList.of(env.getToolsLabel("//tools/test:runtime"))))
Lukacs Berki8f460f32016-06-29 09:14:10 +0000154 // Input files for test actions collecting code coverage
tomlua08bb892017-08-03 03:23:48 +0200155 .add(
156 attr("$coverage_support", LABEL)
157 .value(env.getLabel("//tools/defaults:coverage_support")))
Lukacs Berki8f460f32016-06-29 09:14:10 +0000158 // Used in the one-per-build coverage report generation action.
tomlua08bb892017-08-03 03:23:48 +0200159 .add(
160 attr("$coverage_report_generator", LABEL)
161 .cfg(HOST)
162 .value(env.getLabel("//tools/defaults:coverage_report_generator"))
163 .singleArtifact())
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100164
165 // The target itself and run_under both run on the same machine. We use the DATA config
166 // here because the run_under acts like a data dependency (e.g. no LIPO optimization).
tomlua08bb892017-08-03 03:23:48 +0200167 .add(attr(":run_under", LABEL).cfg(DATA).value(RUN_UNDER).skipPrereqValidatorCheck())
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100168 .build();
169 }
Googler58505032015-03-19 16:12:34 +0000170
171 @Override
172 public Metadata getMetadata() {
173 return RuleDefinition.Metadata.builder()
174 .name("$test_base_rule")
175 .type(RuleClassType.ABSTRACT)
lberki3c1c8e92017-07-13 12:25:47 +0200176 .ancestors(RootRule.class, MakeVariableExpandingRule.class)
Googler58505032015-03-19 16:12:34 +0000177 .build();
178 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100179 }
180
181 /**
182 * Share common attributes across both base and Skylark base rules.
183 */
184 public static RuleClass.Builder commonCoreAndSkylarkAttributes(RuleClass.Builder builder) {
cpeyser03755ea2017-08-28 22:43:32 +0200185 return builder
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100186 // The visibility attribute is special: it is a nodep label, and loading the
187 // necessary package groups is handled by {@link LabelVisitor#visitTargetVisibility}.
188 // Package groups always have the null configuration so that they are not duplicated
189 // needlessly.
cpeyser03755ea2017-08-28 22:43:32 +0200190 .add(attr("visibility", NODEP_LABEL_LIST).orderIndependent().cfg(HOST)
191 .nonconfigurable("special attribute integrated more deeply into Bazel's core logic"))
192 .add(attr("deprecation", STRING).value(deprecationDefault)
193 .nonconfigurable("Used in core loading phase logic with no access to configs"))
194 .add(attr("tags", STRING_LIST).orderIndependent().taggable()
195 .nonconfigurable("low-level attribute, used in TargetUtils without configurations"))
196 .add(attr("generator_name", STRING).undocumented("internal")
197 .nonconfigurable("static structure of a rule"))
198 .add(attr("generator_function", STRING).undocumented("internal")
199 .nonconfigurable("static structure of a rule"))
200 .add(attr("generator_location", STRING).undocumented("internal")
201 .nonconfigurable("static structure of a rule"))
202 .add(attr("testonly", BOOLEAN).value(testonlyDefault)
203 .nonconfigurable("policy decision: rules testability should be consistent"))
Manuel Klimek6d9fb362015-04-30 12:50:55 +0000204 .add(attr("features", STRING_LIST).orderIndependent())
Laurent Le Brund83e8482015-07-13 14:34:44 +0000205 .add(attr(":action_listener", LABEL_LIST).cfg(HOST).value(ACTION_LISTENER))
cpeyser03755ea2017-08-28 22:43:32 +0200206 .add(attr(RuleClass.COMPATIBLE_ENVIRONMENT_ATTR, LABEL_LIST)
207 .allowedRuleClasses(EnvironmentRule.RULE_NAME)
208 .cfg(Attribute.ConfigurationTransition.HOST)
209 .allowedFileTypes(FileTypeSet.NO_FILE)
210 .dontCheckConstraints()
211 .nonconfigurable("special logic for constraints and select: see ConstraintSemantics")
212 )
213 .add(attr(RuleClass.RESTRICTED_ENVIRONMENT_ATTR, LABEL_LIST)
214 .allowedRuleClasses(EnvironmentRule.RULE_NAME)
215 .cfg(Attribute.ConfigurationTransition.HOST)
216 .allowedFileTypes(FileTypeSet.NO_FILE)
217 .dontCheckConstraints()
218 .nonconfigurable("special logic for constraints and select: see ConstraintSemantics")
219 );
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100220 }
221
Googler015e5952017-02-14 09:45:30 +0000222 public static RuleClass.Builder nameAttribute(RuleClass.Builder builder) {
223 return builder.add(attr("name", STRING).nonconfigurable("Rule name"));
224 }
225
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100226 /**
Googler015e5952017-02-14 09:45:30 +0000227 * Ancestor of every rule.
228 *
229 * <p>Adds the name attribute to every rule.
230 */
231 public static final class RootRule implements RuleDefinition {
232
233 @Override
234 public RuleClass build(Builder builder, RuleDefinitionEnvironment environment) {
235 return nameAttribute(builder).build();
236 }
237
238 @Override
239 public Metadata getMetadata() {
240 return RuleDefinition.Metadata.builder()
241 .name("$root_rule")
242 .type(RuleClassType.ABSTRACT)
243 .build();
244 }
245 }
246
247 /**
248 * Common parts of some rules.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100249 */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100250 public static final class BaseRule implements RuleDefinition {
251 @Override
252 public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
253 return commonCoreAndSkylarkAttributes(builder)
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100254 // Aggregates the labels of all {@link ConfigRuleClasses} rules this rule uses (e.g.
255 // keys for configurable attributes). This is specially populated in
256 // {@RuleClass#populateRuleAttributeValues}.
257 //
258 // This attribute is not needed for actual builds. Its main purpose is so query's
259 // proto/XML output includes the labels of config dependencies, so, e.g., depserver
260 // reverse dependency lookups remain accurate. These can't just be added to the
261 // attribute definitions proto/XML queries already output because not all attributes
262 // contain labels.
263 //
264 // Builds and Blaze-interactive queries don't need this because they find dependencies
265 // through direct Rule label visitation, which already factors these in.
266 .add(attr("$config_dependencies", LABEL_LIST)
267 .nonconfigurable("not intended for actual builds"))
268 .add(attr("licenses", LICENSE)
269 .nonconfigurable("Used in core loading phase logic with no access to configs"))
270 .add(attr("distribs", DISTRIBUTIONS)
271 .nonconfigurable("Used in core loading phase logic with no access to configs"))
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100272 .build();
273 }
Googler58505032015-03-19 16:12:34 +0000274
275 @Override
276 public Metadata getMetadata() {
277 return RuleDefinition.Metadata.builder()
278 .name("$base_rule")
279 .type(RuleClassType.ABSTRACT)
Googler015e5952017-02-14 09:45:30 +0000280 .ancestors(RootRule.class)
Googler58505032015-03-19 16:12:34 +0000281 .build();
282 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100283 }
284
285 /**
lberki3c1c8e92017-07-13 12:25:47 +0200286 * A rule that contains a {@code variables=} attribute to allow referencing Make variables.
287 */
288 public static final class MakeVariableExpandingRule implements RuleDefinition {
289 @Override
290 public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
291 return builder
292 /* <!-- #BLAZE_RULE($make_variable_expanding_rule).ATTRIBUTE(toolchains) -->
293 The set of toolchains that supply <a href="${link make-variables}">"Make variables"</a>
294 that this target can use in some of its attributes. Some rules have toolchains whose Make
295 variables they can use by default.
296 <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
297 .add(attr("toolchains", LABEL_LIST)
298 .allowedFileTypes(FileTypeSet.NO_FILE)
dslomov375f95b2017-08-21 12:52:41 +0200299 .mandatoryProviders(ImmutableList.of(MakeVariableInfo.PROVIDER.id())))
lberki3c1c8e92017-07-13 12:25:47 +0200300 .build();
301 }
302
303 @Override
304 public Metadata getMetadata() {
305 return RuleDefinition.Metadata.builder()
306 .name("$make_variable_expanding_rule")
307 .type(RuleClassType.ABSTRACT)
308 .build();
309 }
310 }
311
312 /**
Googler015e5952017-02-14 09:45:30 +0000313 * Common ancestor class for some rules.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100314 */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100315 public static final class RuleBase implements RuleDefinition {
316 @Override
317 public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
318 return builder
319 .add(attr("deps", LABEL_LIST).legacyAllowAnyFileType())
Greg Estren9d837842016-12-01 21:36:59 +0000320 .add(attr("data", LABEL_LIST).cfg(DATA)
321 .allowedFileTypes(FileTypeSet.ANY_FILE)
322 .dontCheckConstraints())
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100323 .build();
324 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100325
Googler58505032015-03-19 16:12:34 +0000326 @Override
327 public Metadata getMetadata() {
328 return RuleDefinition.Metadata.builder()
329 .name("$rule")
330 .type(RuleClassType.ABSTRACT)
331 .ancestors(BaseRule.class)
332 .build();
333 }
334 }
Ulf Adams37590dc2016-10-14 11:52:00 +0000335
336 public static final ImmutableSet<String> ALLOWED_RULE_CLASSES =
337 ImmutableSet.of("filegroup", "genrule", "Fileset");
338
339 /** A base rule for all binary rules. */
340 public static final class BinaryBaseRule implements RuleDefinition {
341 @Override
342 public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
343 return builder
344 .add(attr("args", STRING_LIST))
345 .add(attr("output_licenses", LICENSE))
346 .add(
347 attr("$is_executable", BOOLEAN)
348 .value(true)
349 .nonconfigurable("Called from RunCommand.isExecutable, which takes a Target"))
350 .build();
351 }
352
353 @Override
354 public Metadata getMetadata() {
355 return RuleDefinition.Metadata.builder()
356 .name("$binary_base_rule")
357 .type(RuleClassType.ABSTRACT)
lberki3c1c8e92017-07-13 12:25:47 +0200358 .ancestors(RootRule.class, MakeVariableExpandingRule.class)
Ulf Adams37590dc2016-10-14 11:52:00 +0000359 .build();
360 }
361 }
362
363 /** Rule class for rules in error. */
364 public static final class ErrorRule implements RuleDefinition {
365 @Override
366 public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
367 return builder.publicByDefault().build();
368 }
369
370 @Override
371 public Metadata getMetadata() {
372 return RuleDefinition.Metadata.builder()
373 .name("$error_rule")
374 .type(RuleClassType.ABSTRACT)
375 .ancestors(BaseRuleClasses.BaseRule.class)
376 .build();
377 }
378 }
gregce490b0952017-07-06 18:44:38 -0400379
380 /**
381 * Declares the implementations for {@link Attribute.ConfigurationTransition} enums.
382 *
383 * <p>We can't put this in {@link Attribute} because that's in the {@code lib.packages} package,
384 * which has no access to configuration classes.
385 *
386 * <p>New transitions should extend {@link PatchTransition}, which avoids the need for this map.
387 */
388 public static final ImmutableMap<Transition, Transition> DYNAMIC_TRANSITIONS_MAP =
389 ImmutableMap.of(
390 Attribute.ConfigurationTransition.NONE, DynamicTransitionMapper.SELF,
391 Attribute.ConfigurationTransition.NULL, DynamicTransitionMapper.SELF,
392 Attribute.ConfigurationTransition.HOST, HostTransition.INSTANCE
393 // Attribute.ConfigurationTransition.DATA is skipped because it's C++-specific.
394 // The C++ rule definitions handle its mapping.
395 );
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100396}