blob: 6ad0617071e30aa20afe3210774657cc128214f0 [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;
Ulf Adams37590dc2016-10-14 11:52:00 +000032import com.google.common.collect.ImmutableSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010033import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
34import com.google.devtools.build.lib.analysis.config.RunUnder;
35import com.google.devtools.build.lib.analysis.constraints.EnvironmentRule;
Lukacs Berki6e91eb92015-09-21 09:12:37 +000036import com.google.devtools.build.lib.cmdline.Label;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010037import com.google.devtools.build.lib.packages.Attribute;
38import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel;
39import com.google.devtools.build.lib.packages.Attribute.LateBoundLabelList;
40import com.google.devtools.build.lib.packages.AttributeMap;
41import com.google.devtools.build.lib.packages.Rule;
42import com.google.devtools.build.lib.packages.RuleClass;
43import com.google.devtools.build.lib.packages.RuleClass.Builder;
44import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
45import com.google.devtools.build.lib.packages.TestSize;
Lukacs Berkiffa73ad2015-09-18 11:40:12 +000046import com.google.devtools.build.lib.syntax.Type;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010047import com.google.devtools.build.lib.util.FileTypeSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010048import java.util.List;
49
50/**
51 * Rule class definitions used by (almost) every rule.
52 */
53public class BaseRuleClasses {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010054 private static final Attribute.ComputedDefault testonlyDefault =
55 new Attribute.ComputedDefault() {
56 @Override
57 public Object getDefault(AttributeMap rule) {
58 return rule.getPackageDefaultTestOnly();
59 }
60 };
61
62 private static final Attribute.ComputedDefault deprecationDefault =
63 new Attribute.ComputedDefault() {
64 @Override
65 public Object getDefault(AttributeMap rule) {
66 return rule.getPackageDefaultDeprecation();
67 }
68 };
69
70 /**
71 * Implementation for the :action_listener attribute.
72 */
Carmi Grushkoeaaa9d0d2015-11-17 01:54:45 +000073 @VisibleForTesting
74 static final LateBoundLabelList<BuildConfiguration> ACTION_LISTENER =
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010075 new LateBoundLabelList<BuildConfiguration>() {
76 @Override
Lukacs Berki0dbe07f2016-04-19 10:22:08 +000077 public List<Label> resolve(Rule rule, AttributeMap attributes,
Greg Estren33ec1912016-02-10 15:57:58 +000078 BuildConfiguration configuration) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010079 // action_listeners are special rules; they tell the build system to add extra_actions to
80 // existing rules. As such they need an edge to every ConfiguredTarget with the limitation
81 // that they only run on the target configuration and should not operate on action_listeners
82 // and extra_actions themselves (to avoid cycles).
83 return configuration.getActionListeners();
84 }
85 };
86
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010087 /**
88 * Implementation for the :run_under attribute.
89 */
Lukacs Berki8f460f32016-06-29 09:14:10 +000090 public static final LateBoundLabel<BuildConfiguration> RUN_UNDER =
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010091 new LateBoundLabel<BuildConfiguration>() {
92 @Override
Lukacs Berki0dbe07f2016-04-19 10:22:08 +000093 public Label resolve(Rule rule, AttributeMap attributes,
Greg Estren33ec1912016-02-10 15:57:58 +000094 BuildConfiguration configuration) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010095 RunUnder runUnder = configuration.getRunUnder();
96 return runUnder == null ? null : runUnder.getLabel();
97 }
98 };
99
100 /**
101 * A base rule for all test rules.
102 */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100103 public static final class TestBaseRule implements RuleDefinition {
104 @Override
105 public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
106 return builder
107 .add(attr("size", STRING).value("medium").taggable()
108 .nonconfigurable("policy decision: should be consistent across configurations"))
109 .add(attr("timeout", STRING).taggable()
110 .nonconfigurable("policy decision: should be consistent across configurations")
111 .value(new Attribute.ComputedDefault() {
112 @Override
113 public Object getDefault(AttributeMap rule) {
114 TestSize size = TestSize.getTestSize(rule.get("size", Type.STRING));
115 if (size != null) {
116 String timeout = size.getDefaultTimeout().toString();
117 if (timeout != null) {
118 return timeout;
119 }
120 }
121 return "illegal";
122 }
123 }))
124 .add(attr("flaky", BOOLEAN).value(false).taggable()
125 .nonconfigurable("policy decision: should be consistent across configurations"))
126 .add(attr("shard_count", INTEGER).value(-1))
127 .add(attr("local", BOOLEAN).value(false).taggable()
128 .nonconfigurable("policy decision: should be consistent across configurations"))
Greg Estren547295a2016-08-18 22:01:29 +0000129 .add(attr("args", STRING_LIST))
Lukacs Berki8f460f32016-06-29 09:14:10 +0000130 // Input files for every test action
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100131 .add(attr("$test_runtime", LABEL_LIST).cfg(HOST).value(ImmutableList.of(
Luis Fernando Pino Duque18d13222016-02-08 14:55:28 +0000132 env.getToolsLabel("//tools/test:runtime"))))
Lukacs Berki8f460f32016-06-29 09:14:10 +0000133 // Input files for test actions collecting code coverage
134 .add(attr("$coverage_support", LABEL)
135 .cfg(HOST)
136 .value(env.getLabel("//tools/defaults:coverage_support")))
137 // Used in the one-per-build coverage report generation action.
138 .add(attr("$coverage_report_generator", LABEL)
139 .cfg(HOST)
140 .value(env.getLabel("//tools/defaults:coverage_report_generator"))
141 .singleArtifact())
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100142
143 // The target itself and run_under both run on the same machine. We use the DATA config
144 // here because the run_under acts like a data dependency (e.g. no LIPO optimization).
Ulf Adams0d815d652015-09-14 08:50:29 +0000145 .add(attr(":run_under", LABEL).cfg(DATA).value(RUN_UNDER)
Greg Estren875c7a72015-09-24 19:57:54 +0000146 .skipPrereqValidatorCheck())
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100147 .build();
148 }
Googler58505032015-03-19 16:12:34 +0000149
150 @Override
151 public Metadata getMetadata() {
152 return RuleDefinition.Metadata.builder()
153 .name("$test_base_rule")
154 .type(RuleClassType.ABSTRACT)
155 .build();
156 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100157 }
158
159 /**
160 * Share common attributes across both base and Skylark base rules.
161 */
162 public static RuleClass.Builder commonCoreAndSkylarkAttributes(RuleClass.Builder builder) {
163 return builder
Vladimir Moskvada574922016-10-05 16:36:49 +0000164 .add(attr("name", STRING)
165 .nonconfigurable("Rule name"))
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100166 // The visibility attribute is special: it is a nodep label, and loading the
167 // necessary package groups is handled by {@link LabelVisitor#visitTargetVisibility}.
168 // Package groups always have the null configuration so that they are not duplicated
169 // needlessly.
170 .add(attr("visibility", NODEP_LABEL_LIST).orderIndependent().cfg(HOST)
171 .nonconfigurable("special attribute integrated more deeply into Bazel's core logic"))
172 .add(attr("deprecation", STRING).value(deprecationDefault)
173 .nonconfigurable("Used in core loading phase logic with no access to configs"))
174 .add(attr("tags", STRING_LIST).orderIndependent().taggable()
175 .nonconfigurable("low-level attribute, used in TargetUtils without configurations"))
Greg Estrenff476142016-02-08 21:03:33 +0000176 .add(attr("generator_name", STRING).undocumented("internal")
177 .nonconfigurable("static structure of a rule"))
178 .add(attr("generator_function", STRING).undocumented("internal")
179 .nonconfigurable("static structure of a rule"))
180 .add(attr("generator_location", STRING).undocumented("internal")
181 .nonconfigurable("static structure of a rule"))
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100182 .add(attr("testonly", BOOLEAN).value(testonlyDefault)
183 .nonconfigurable("policy decision: rules testability should be consistent"))
Manuel Klimek6d9fb362015-04-30 12:50:55 +0000184 .add(attr("features", STRING_LIST).orderIndependent())
Laurent Le Brund83e8482015-07-13 14:34:44 +0000185 .add(attr(":action_listener", LABEL_LIST).cfg(HOST).value(ACTION_LISTENER))
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100186 .add(attr(RuleClass.COMPATIBLE_ENVIRONMENT_ATTR, LABEL_LIST)
187 .allowedRuleClasses(EnvironmentRule.RULE_NAME)
188 .cfg(Attribute.ConfigurationTransition.HOST)
Greg Estrena7651722016-05-02 18:54:18 +0000189 .allowedFileTypes(FileTypeSet.NO_FILE)
Greg Estren9d837842016-12-01 21:36:59 +0000190 .dontCheckConstraints()
Greg Estrena7651722016-05-02 18:54:18 +0000191 .nonconfigurable("special logic for constraints and select: see ConstraintSemantics")
192 )
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100193 .add(attr(RuleClass.RESTRICTED_ENVIRONMENT_ATTR, LABEL_LIST)
194 .allowedRuleClasses(EnvironmentRule.RULE_NAME)
195 .cfg(Attribute.ConfigurationTransition.HOST)
Greg Estrena7651722016-05-02 18:54:18 +0000196 .allowedFileTypes(FileTypeSet.NO_FILE)
Greg Estren9d837842016-12-01 21:36:59 +0000197 .dontCheckConstraints()
Greg Estrena7651722016-05-02 18:54:18 +0000198 .nonconfigurable("special logic for constraints and select: see ConstraintSemantics")
199 );
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100200 }
201
202 /**
203 * Common parts of rules.
204 */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100205 public static final class BaseRule implements RuleDefinition {
206 @Override
207 public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
208 return commonCoreAndSkylarkAttributes(builder)
209 // The name attribute is handled specially, so it does not appear here.
210 //
211 // Aggregates the labels of all {@link ConfigRuleClasses} rules this rule uses (e.g.
212 // keys for configurable attributes). This is specially populated in
213 // {@RuleClass#populateRuleAttributeValues}.
214 //
215 // This attribute is not needed for actual builds. Its main purpose is so query's
216 // proto/XML output includes the labels of config dependencies, so, e.g., depserver
217 // reverse dependency lookups remain accurate. These can't just be added to the
218 // attribute definitions proto/XML queries already output because not all attributes
219 // contain labels.
220 //
221 // Builds and Blaze-interactive queries don't need this because they find dependencies
222 // through direct Rule label visitation, which already factors these in.
223 .add(attr("$config_dependencies", LABEL_LIST)
224 .nonconfigurable("not intended for actual builds"))
225 .add(attr("licenses", LICENSE)
226 .nonconfigurable("Used in core loading phase logic with no access to configs"))
227 .add(attr("distribs", DISTRIBUTIONS)
228 .nonconfigurable("Used in core loading phase logic with no access to configs"))
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100229 .build();
230 }
Googler58505032015-03-19 16:12:34 +0000231
232 @Override
233 public Metadata getMetadata() {
234 return RuleDefinition.Metadata.builder()
235 .name("$base_rule")
236 .type(RuleClassType.ABSTRACT)
237 .build();
238 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100239 }
240
241 /**
242 * Common ancestor class for all rules.
243 */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100244 public static final class RuleBase implements RuleDefinition {
245 @Override
246 public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
247 return builder
248 .add(attr("deps", LABEL_LIST).legacyAllowAnyFileType())
Greg Estren9d837842016-12-01 21:36:59 +0000249 .add(attr("data", LABEL_LIST).cfg(DATA)
250 .allowedFileTypes(FileTypeSet.ANY_FILE)
251 .dontCheckConstraints())
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100252 .build();
253 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100254
Googler58505032015-03-19 16:12:34 +0000255 @Override
256 public Metadata getMetadata() {
257 return RuleDefinition.Metadata.builder()
258 .name("$rule")
259 .type(RuleClassType.ABSTRACT)
260 .ancestors(BaseRule.class)
261 .build();
262 }
263 }
Ulf Adams37590dc2016-10-14 11:52:00 +0000264
265 public static final ImmutableSet<String> ALLOWED_RULE_CLASSES =
266 ImmutableSet.of("filegroup", "genrule", "Fileset");
267
268 /** A base rule for all binary rules. */
269 public static final class BinaryBaseRule implements RuleDefinition {
270 @Override
271 public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
272 return builder
273 .add(attr("args", STRING_LIST))
274 .add(attr("output_licenses", LICENSE))
275 .add(
276 attr("$is_executable", BOOLEAN)
277 .value(true)
278 .nonconfigurable("Called from RunCommand.isExecutable, which takes a Target"))
279 .build();
280 }
281
282 @Override
283 public Metadata getMetadata() {
284 return RuleDefinition.Metadata.builder()
285 .name("$binary_base_rule")
286 .type(RuleClassType.ABSTRACT)
287 .build();
288 }
289 }
290
291 /** Rule class for rules in error. */
292 public static final class ErrorRule implements RuleDefinition {
293 @Override
294 public RuleClass build(Builder builder, RuleDefinitionEnvironment env) {
295 return builder.publicByDefault().build();
296 }
297
298 @Override
299 public Metadata getMetadata() {
300 return RuleDefinition.Metadata.builder()
301 .name("$error_rule")
302 .type(RuleClassType.ABSTRACT)
303 .ancestors(BaseRuleClasses.BaseRule.class)
304 .build();
305 }
306 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100307}