blob: 48a855b354a4bc19e6a4bfb2ec8c81614912cb26 [file] [log] [blame]
rosicad2e02542018-08-21 13:18:43 -07001# Copyright 2018 The Bazel Authors. All rights reserved.
2#
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
15""" A library of functions creating structs for CcToolchainConfigInfo."""
16
17def _check_is_none_or_right_type(obj, obj_of_right_type, parameter_name, method_name):
18 if obj != None:
19 _check_right_type(obj, obj_of_right_type, parameter_name, method_name)
20
21def _check_right_type(obj, obj_of_right_type, parameter_name, method_name):
22 if type(obj) != type(obj_of_right_type):
23 fail("{} parameter of {} should be a {}, found {}."
24 .format(parameter_name, method_name, type(obj_of_right_type), type(obj)))
25
26def _check_is_nonempty_string(obj, parameter_name, method_name):
27 _check_right_type(obj, "", parameter_name, method_name)
28 if obj == "":
29 fail("{} parameter of {} must be a nonempty string."
30 .format(parameter_name, method_name))
31
32def _check_is_nonempty_list(obj, parameter_name, method_name):
33 _check_right_type(obj, [], parameter_name, method_name)
34 if len(obj) == 0:
35 fail("{} parameter of {} must be a nonempty list."
36 .format(parameter_name, method_name))
37
38EnvEntryInfo = provider(fields = ["key", "value", "type_name"])
39
40def env_entry(key, value):
41 """ A key/value pair to be added as an environment variable.
42
43 The returned EnvEntry provider finds its use in EnvSet creation through
44 the env_entries parameter of env_set(); EnvSet groups environment variables
45 that need to be expanded for specific actions.
46 The value of this pair is expanded in the same way as is described in
47 flag_group. The key remains an unexpanded string literal.
48
49 Args:
50 key: a string literal representing the name of the variable.
51 value: the value to be expanded.
52
53 Returns:
54 An EnvEntryInfo provider.
55 """
56 _check_is_nonempty_string(key, "key", "env_entry")
57 _check_is_nonempty_string(value, "value", "env_entry")
58 return EnvEntryInfo(key = key, value = value, type_name = "env_entry")
59
60VariableWithValueInfo = provider(fields = ["name", "value", "type_name"])
61
62def variable_with_value(name, value):
63 """ Represents equality check between a variable and a certain value.
64
65 The returned provider finds its use through flag_group.expand_if_equal,
66 making the expansion of the flag_group conditional on the value of the
67 variable.
68
69 Args:
70 name: name of the variable.
71 value: the value the variable should be compared against.
72
73 Returns:
74 A VariableWithValueInfo provider.
75 """
76 _check_is_nonempty_string(name, "name", "variable_with_value")
77 _check_is_nonempty_string(value, "value", "variable_with_value")
78 return VariableWithValueInfo(
79 name = name,
80 value = value,
81 type_name = "variable_with_value",
82 )
83
84MakeVariableInfo = provider(fields = ["name", "value", "type_name"])
85
86def make_variable(name, value):
87 """ A make variable that is made accessible to rules."""
88 _check_is_nonempty_string(name, "name", "make_variable")
89 _check_is_nonempty_string(value, "value", "make_variable")
90 return MakeVariableInfo(
91 name = name,
92 value = value,
93 type_name = "make_variable",
94 )
95
96FeatureSetInfo = provider(fields = ["features", "type_name"])
97
98def feature_set(features = []):
99 """ A set of features.
100
101 Used to support logical 'and' when specifying feature requirements in a
102 feature.
103
104 Args:
105 features: A list of unordered feature names.
106
107 Returns:
108 A FeatureSetInfo provider.
109 """
110 _check_right_type(features, [], "features", "feature_set")
111 return FeatureSetInfo(features = features, type_name = "feature_set")
112
113WithFeatureSetInfo = provider(fields = ["features", "not_features", "type_name"])
114
115def with_feature_set(features = [], not_features = []):
116 """ A set of positive and negative features.
117
118 This stanza will evaluate to true when every 'feature' is enabled, and
119 every 'not_feature' is not enabled.
120
121 Args:
122 features: A list of feature names that need to be enabled.
123 not_features: A list of feature names that need to not be enabled.
124
125 Returns:
126 A WithFeatureSetInfo provider.
127 """
128 _check_right_type(features, [], "features", "with_feature_set")
129 _check_right_type(not_features, [], "not_features", "with_feature_set")
130 return WithFeatureSetInfo(
131 features = features,
132 not_features = not_features,
133 type_name = "with_feature_set",
134 )
135
136EnvSetInfo = provider(fields = ["actions", "env_entries", "with_features", "type_name"])
137
138def env_set(actions, env_entries = [], with_features = []):
139 """ Groups a set of environment variables to apply for certain actions.
140
141 EnvSet providers are passed to feature() and action_config(), to be applied to
142 the actions they are specified for.
143
144 Args:
145 actions: A list of actions this env set applies to; each env set must
146 specify at least one action.
147 env_entries: A list of EnvEntry - the environment variables applied
148 via this env set.
149 with_features: A list of feature sets defining when this env set gets
150 applied. The env set will be applied when any one of the feature
151 sets evaluate to true. (That is, when when every 'feature' is
152 enabled, and every 'not_feature' is not enabled.)
153 If 'with_features' is omitted, the env set will be applied
154 unconditionally for every action specified.
155
156 Returns:
157 An EnvSetInfo provider.
158 """
159 _check_is_nonempty_list(actions, "actions", "env_set")
160 _check_right_type(env_entries, [], "env_entries", "env_set")
161 _check_right_type(with_features, [], "with_features", "env_set")
162 return EnvSetInfo(
163 actions = actions,
164 env_entries = env_entries,
165 with_features = with_features,
166 type_name = "env_set",
167 )
168
169FlagGroupInfo = provider(fields = [
170 "flags",
171 "flag_groups",
172 "iterate_over",
173 "expand_if_available",
174 "expand_if_not_available",
175 "expand_if_true",
176 "expand_if_false",
177 "expand_if_equal",
178 "type_name",
179])
180
181def flag_group(
182 flags = [],
183 flag_groups = [],
184 iterate_over = None,
185 expand_if_available = None,
186 expand_if_not_available = None,
187 expand_if_true = None,
188 expand_if_false = None,
189 expand_if_equal = None):
190 """ A group of flags. Supports parametrization via variable expansion.
191
192 To expand a variable of list type, flag_group has to be annotated with
193 `iterate_over` message. Then all nested flags or flag_groups will be
194 expanded repeatedly for each element of the list.
195 For example:
196 flag_group(
197 iterate_over = 'include_path',
198 flags = ['-I', '%{include_path}'],
199 )
200 ... will get expanded to -I /to/path1 -I /to/path2 ... for each
201 include_path /to/pathN.
202
203 To expand a variable of structure type, use dot-notation, e.g.:
204 flag_group(
205 iterate_over = "libraries_to_link",
206 flag_groups = [
207 flag_group(
208 iterate_over = "libraries_to_link.libraries",
209 flags = ["-L%{libraries_to_link.libraries.directory}"],
210 )
211 ]
212 )
213
214 Flag groups can be nested; if they are, the flag group must only contain
215 other flag groups (no flags) so the order is unambiguously specified.
216 In order to expand a variable of nested lists, 'iterate_over' can be used.
217 For example:
218 flag_group (
219 iterate_over = 'object_files',
220 flag_groups = [
221 flag_group (
222 flags = ['--start-lib'],
223 ),
224 flag_group (
225 iterate_over = 'object_files',
226 flags = ['%{object_files}'],
227 ),
228 flag_group (
229 flags = ['--end-lib'],
230 )
231 ]
232 )
233 ... will get expanded to
234 --start-lib a1.o a2.o ... --end-lib --start-lib b1.o b2.o .. --end-lib
235 with %{object_files} being a variable of nested list type
236 [['a1.o', 'a2.o', ...], ['b1.o', 'b2.o', ...], ...].
237
238 Args:
239 flags: a string list, representing flags. Only one of flags and
240 flag_groups can be set, as to avoid ambiguity.
241 flag_groups: a list of FlagGroup entries. Only one of flags and
242 flag_groups can be set, as to avoid ambiguity.
243 iterate_over: a string, representing a variable of list type.
244 expand_if_available: A build variable that needs to be available
245 in order to expand the flag_group.
246 expand_if_not_available: A build variable that needs to be
247 unavailable in order for this flag_group to be expanded.
248 expand_if_true: if set, this variable needs to evaluate to True in
249 order for the flag_group to be expanded.
250 expand_if_false: if set, this variable needs to evalate to False in
251 order for the flag_group to be expanded.
252 expand_if_equal: a VariableWithValue, the flag_group is expanded in
253 case of equality.
254
255 Returns:
256 A FlagGroupInfo provider.
257 """
258
259 _check_right_type(flags, [], "flags", "flag_group")
260 _check_right_type(flag_groups, [], "flag_groups", "flag_group")
261 if len(flags) > 0 and len(flag_groups) > 0:
262 fail("flag_group must not contain both a flag and another flag_group.")
263 if len(flags) == 0 and len(flag_groups) == 0:
264 fail("flag_group must contain either a list of flags or a list of flag_groups.")
265 _check_is_none_or_right_type(expand_if_true, "string", "expand_if_true", "flag_group")
266 _check_is_none_or_right_type(expand_if_false, "string", "expand_if_false", "flag_group")
267 _check_is_none_or_right_type(expand_if_available, "string", "expand_if_available", "flag_group")
268 _check_is_none_or_right_type(
269 expand_if_not_available,
270 "string",
271 "expand_if_not_available",
272 "flag_group",
273 )
274 _check_is_none_or_right_type(iterate_over, "string", "iterate_over", "flag_group")
275
276 return FlagGroupInfo(
277 flags = flags,
278 flag_groups = flag_groups,
279 iterate_over = iterate_over,
280 expand_if_available = expand_if_available,
281 expand_if_not_available = expand_if_not_available,
282 expand_if_true = expand_if_true,
283 expand_if_false = expand_if_false,
284 expand_if_equal = expand_if_equal,
285 type_name = "flag_group",
286 )
287
288FlagSetInfo = provider(fields = [
289 "actions",
290 "with_features",
291 "flag_groups",
292 "type_name",
293])
294
295def flag_set(
rosica38f54512018-12-04 01:22:56 -0800296 actions = [],
rosicad2e02542018-08-21 13:18:43 -0700297 with_features = [],
298 flag_groups = []):
299 """ A set of flags to be expanded in the command line for specific actions.
300
301 Args:
302 actions: The actions this flag set applies to; each flag set must
303 specify at least one action.
304 with_features: A list of feature sets defining when this flag set gets
305 applied. The flag set will be applied when any one of the feature
306 sets evaluate to true. (That is, when when every 'feature' is
307 enabled, and every 'not_feature' is not enabled.)
308 If 'with_feature' is omitted, the flag set will be applied
309 unconditionally for every action specified.
310 flag_groups: A FlagGroup list - the flags applied via this flag set.
311
312 Returns:
313 A FlagSetInfo provider.
314 """
rosica38f54512018-12-04 01:22:56 -0800315 _check_right_type(actions, [], "actions", "flag_set")
rosicad2e02542018-08-21 13:18:43 -0700316 _check_right_type(with_features, [], "with_features", "flag_set")
317 _check_right_type(flag_groups, [], "flag_groups", "flag_set")
318 return FlagSetInfo(
319 actions = actions,
320 with_features = with_features,
321 flag_groups = flag_groups,
322 type_name = "flag_set",
323 )
324
325FeatureInfo = provider(fields = [
326 "name",
327 "enabled",
328 "flag_sets",
329 "env_sets",
330 "requires",
331 "implies",
332 "provides",
333 "type_name",
334])
335
336def feature(
337 name,
338 enabled = False,
339 flag_sets = [],
340 env_sets = [],
341 requires = [],
342 implies = [],
343 provides = []):
344 """ Contains all flag specifications for one feature.
345
346 Args:
347 name: The feature's name. It is possible to introduce a feature without
348 a change to Bazel by adding a 'feature' section to the toolchain
349 and adding the corresponding string as feature in the BUILD file.
350 enabled: If 'True', this feature is enabled unless a rule type
351 explicitly marks it as unsupported.
352 flag_sets: A FlagSet list - If the given feature is enabled, the flag
353 sets will be applied for the actions are specified for.
354 env_sets: an EnvSet list - If the given feature is enabled, the env
355 sets will be applied for the actions they are specified for.
356 requires: A list of feature sets defining when this feature is
357 supported by the toolchain. The feature is supported if any of the
358 feature sets fully apply, that is, when all features of a feature
359 set are enabled.
360 If 'requires' is omitted, the feature is supported independently of
361 which other features are enabled.
362 Use this for example to filter flags depending on the build mode
363 enabled (opt / fastbuild / dbg).
364 implies: A string list of features or action configs that are
365 automatically enabled when this feature is enabled. If any of the
366 implied features or action configs cannot be enabled, this feature
367 will (silently) not be enabled either.
368 provides: A list of names this feature conflicts with.
369 A feature cannot be enabled if:
370 - 'provides' contains the name of a different feature or action
371 config that we want to enable.
372 - 'provides' contains the same value as a 'provides' in a
373 different feature or action config that we want to enable.
374 Use this in order to ensure that incompatible features cannot be
375 accidentally activated at the same time, leading to hard to
376 diagnose compiler errors.
377
378 Returns:
379 A FeatureInfo provider.
380 """
381 _check_right_type(enabled, True, "enabled", "feature")
382 _check_right_type(flag_sets, [], "flag_sets", "feature")
383 _check_right_type(env_sets, [], "env_sets", "feature")
384 _check_right_type(requires, [], "requires", "feature")
385 _check_right_type(provides, [], "provides", "feature")
386 _check_right_type(implies, [], "implies", "feature")
387 return FeatureInfo(
388 name = name,
389 enabled = enabled,
390 flag_sets = flag_sets,
391 env_sets = env_sets,
392 requires = requires,
393 implies = implies,
394 provides = provides,
395 type_name = "feature",
396 )
397
398ToolPathInfo = provider(fields = ["name", "path", "type_name"])
399
400def tool_path(name, path):
401 """ Tool locations.
402
403 Args:
404 name: Name of the tool.
405 path: Location of the tool; Can be absolute path (in case of non hermetic
406 toolchain), or path relative to the cc_toolchain's package.
407
408 Returns:
409 A ToolPathInfo provider.
410
411 Deprecated:
412 Prefer specifying an ActionConfig for the action that needs the tool.
413 TODO(b/27903698) migrate to ActionConfig.
414 """
415 _check_is_nonempty_string(name, "name", "tool_path")
416 _check_is_nonempty_string(path, "path", "tool_path")
417 return ToolPathInfo(name = name, path = path, type_name = "tool_path")
418
419ToolInfo = provider(fields = ["path", "with_features", "execution_requirements", "type_name"])
420
421def tool(path, with_features = [], execution_requirements = []):
422 """ Describes a tool associated with a crosstool action config.
423
424 Args:
425 path: Location of the tool; Can be absolute path (in case of non hermetic
426 toolchain), or path relative to the cc_toolchain's package.
427 with_features: A list of feature sets defining when this tool is
428 applicable. The tool will used when any one of the feature sets
429 evaluate to true. (That is, when when every 'feature' is enabled,
430 and every 'not_feature' is not enabled.)
431 If 'with_feature' is omitted, the tool will apply for any feature
432 configuration.
433 execution_requirements: Requirements on the execution environment for
434 the execution of this tool, to be passed as out-of-band "hints" to
435 the execution backend.
436 Ex. "requires-darwin"
437
438 Returns:
439 A ToolInfo provider.
440 """
441 _check_is_nonempty_string(path, "path", "tool")
442 _check_right_type(with_features, [], "with_features", "tool")
443 _check_right_type(execution_requirements, [], "execution_requirements", "tool")
444 return ToolInfo(
445 path = path,
446 with_features = with_features,
447 execution_requirements = execution_requirements,
448 type_name = "tool",
449 )
450
451ActionConfigInfo = provider(fields = [
452 "config_name",
453 "action_name",
454 "enabled",
455 "tools",
456 "flag_sets",
457 "implies",
458 "type_name",
459])
460
461def action_config(
462 action_name,
rosica292f9092019-01-18 07:35:32 -0800463 enabled = False,
rosicad2e02542018-08-21 13:18:43 -0700464 tools = [],
465 flag_sets = [],
466 implies = []):
467 """ Configuration of a Bazel action.
468
469 An action config corresponds to a Bazel action, and allows selection of
470 a tool based on activated features.
471 Action config activation occurs by the same semantics as features: a
472 feature can 'require' or 'imply' an action config in the same way that it
473 would another feature.
474
475 Args:
476 action_name: The name of the Bazel action that this config applies to,
477 ex. 'c-compile' or 'c-module-compile'.
478 enabled: If 'True', this action is enabled unless a rule type
479 explicitly marks it as unsupported.
480 tools: The tool applied to the action will be the first Tool with a
481 feature set that matches the feature configuration. An error will
482 be thrown if no tool matches a provided feature configuration - for
483 that reason, it's a good idea to provide a default tool with an
484 empty feature set.
485 flag_sets: If the given action config is enabled, the flag sets will be
486 applied to the corresponding action.
487 implies: A list of features or action configs that are automatically
488 enabled when this action config is enabled. If any of the implied
489 features or action configs cannot be enabled, this action config
490 will (silently) not be enabled either.
491
492 Returns:
493 An ActionConfigInfo provider.
494 """
495 _check_is_nonempty_string(action_name, "name", "action_config")
496 _check_right_type(enabled, True, "enabled", "action_config")
497 _check_right_type(tools, [], "tools", "action_config")
498 _check_right_type(flag_sets, [], "flag_sets", "action_config")
499 _check_right_type(implies, [], "implies", "action_config")
500 return ActionConfigInfo(
501 action_name = action_name,
502 enabled = enabled,
503 tools = tools,
504 flag_sets = flag_sets,
505 implies = implies,
506 type_name = "action_config",
507 )
508
509ArtifactNamePatternInfo = provider(fields = [
510 "category_name",
511 "prefix",
512 "extension",
513 "type_name",
514])
515
516def artifact_name_pattern(category_name, prefix, extension):
517 """ The name for an artifact of a given category of input or output artifacts to an action.
518
519 Args:
520 category_name: The category of artifacts that this selection applies
521 to. This field is compared against a list of categories defined
522 in bazel. Example categories include "linked_output" or
523 "debug_symbols". An error is thrown if no category is matched.
524 prefix: The prefix for creating the artifact for this selection.
525 Together with the extension it is used to create an artifact name
526 based on the target name.
527 extension: The extension for creating the artifact for this selection.
528 Together with the prefix it is used to create an artifact name
529 based on the target name.
530
531 Returns:
532 An ArtifactNamePatternInfo provider
533 """
534 _check_is_nonempty_string(category_name, "category_name", "artifact_name_pattern")
rosica53c32a82018-10-23 06:06:13 -0700535 _check_is_none_or_right_type(prefix, "", "prefix", "artifact_name_pattern")
536 _check_is_none_or_right_type(extension, "", "extension", "artifact_name_pattern")
rosicad2e02542018-08-21 13:18:43 -0700537 return ArtifactNamePatternInfo(
538 category_name = category_name,
539 prefix = prefix,
540 extension = extension,
541 type_name = "artifact_name_pattern",
542 )