blob: 3cfb94113635721430d362cee3c72e0ef3495022 [file] [log] [blame] [view]
gregcec44a87b2018-06-08 12:07:03 -07001---
2layout: documentation
Greg Estrenc0816752020-02-20 13:04:29 -08003title: Configurable build attributes
daroberts223aebd2021-02-18 17:53:30 -08004category: getting-started
gregcec44a87b2018-06-08 12:07:03 -07005---
6
Googler458daaa2021-01-08 18:55:00 -08007# Configurable Build Attributes
gregcec44a87b2018-06-08 12:07:03 -07008
laurentlb79b94312018-11-07 05:18:59 -08009**_Configurable attributes_**, commonly known as [`select()`](
10be/functions.html#select), is a Bazel feature that lets users toggle the values
Googler2ebf3bd2021-05-21 09:35:36 -070011of build rule attributes at the command line.
gregcec44a87b2018-06-08 12:07:03 -070012
brandjoneadd5f62018-10-02 12:05:44 -070013This can be used, for example, for a multiplatform library that automatically
14chooses the appropriate implementation for the architecture, or for a
15feature-configurable binary that can be customized at build time.
gregcec44a87b2018-06-08 12:07:03 -070016
17## Example
18
brandjoneadd5f62018-10-02 12:05:44 -070019```python
20# myapp/BUILD
21
gregcec44a87b2018-06-08 12:07:03 -070022cc_binary(
23 name = "mybinary",
24 srcs = ["main.cc"],
25 deps = select({
26 ":arm_build": [":arm_lib"],
27 ":x86_debug_build": [":x86_dev_lib"],
brandjoneadd5f62018-10-02 12:05:44 -070028 "//conditions:default": [":generic_lib"],
29 }),
gregcec44a87b2018-06-08 12:07:03 -070030)
31
32config_setting(
33 name = "arm_build",
brandjoneadd5f62018-10-02 12:05:44 -070034 values = {"cpu": "arm"},
gregcec44a87b2018-06-08 12:07:03 -070035)
36
37config_setting(
38 name = "x86_debug_build",
39 values = {
brandjoneadd5f62018-10-02 12:05:44 -070040 "cpu": "x86",
41 "compilation_mode": "dbg",
42 },
gregcec44a87b2018-06-08 12:07:03 -070043)
44```
45
46This declares a `cc_binary` that "chooses" its deps based on the flags at the
47command line. Specficially, `deps` becomes:
48
49<table>
50 <tr style="background: #E9E9E9; font-weight: bold">
51 <td>Command</td>
52 <td>deps =</td>
53 </tr>
54 <tr>
55 <td><code>bazel build //myapp:mybinary --cpu=arm</code></td>
56 <td><code>[":arm_lib"]</code></td>
57 </tr>
58 <tr>
Thid1a8a902018-12-21 15:43:24 -080059 <td><code>bazel build //myapp:mybinary -c dbg --cpu=x86</code></td>
gregcec44a87b2018-06-08 12:07:03 -070060 <td><code>[":x86_dev_lib"]</code></td>
61 </tr>
62 <tr>
63 <td><code>bazel build //myapp:mybinary --cpu=ppc</code></td>
64 <td><code>[":generic_lib"]</code></td>
65 </tr>
66 <tr>
67 <td><code>bazel build //myapp:mybinary -c dbg --cpu=ppc</code></td>
68 <td><code>[":generic_lib"]</code></td>
69 </tr>
70</table>
Greg Estrene821cfa2020-02-20 09:34:56 -080071
brandjoneadd5f62018-10-02 12:05:44 -070072`select()` serves as a placeholder for a value that will be chosen based on
gregce8e8dcc82020-08-25 08:30:28 -070073*configuration conditions*, which are labels referencing [`config_setting`](be/general.html#config_setting)
74targets. By using `select()` in a configurable attribute, the attribute
75effectively adopts different values when different conditions hold.
gregcec44a87b2018-06-08 12:07:03 -070076
77Matches must be unambiguous: either exactly one condition must match or, if
78multiple conditions match, one's `values` must be a strict superset of all
brandjoneadd5f62018-10-02 12:05:44 -070079others'. For example, `values = {"cpu": "x86", "compilation_mode": "dbg"}` is an
80unambiguous specialization of `values = {"cpu": "x86"}`. The built-in condition
gregce8e8dcc82020-08-25 08:30:28 -070081[`//conditions:default`](#the-default-condition) automatically matches when
82nothing else does.
gregcec44a87b2018-06-08 12:07:03 -070083
gregce8e8dcc82020-08-25 08:30:28 -070084While this example uses `deps`, `select()` works just as well on `srcs`,
85`resources`, `cmd`, and most other attributes. Only a small number of attributes
86are *non-configurable*, and these are clearly annotated. For example,
87`config_setting`'s own
brandjoneadd5f62018-10-02 12:05:44 -070088[`values`](be/general.html#config_setting.values) attribute is non-configurable.
89
gregce8e8dcc82020-08-25 08:30:28 -070090## `select()` and dependencies
91
92Certain attributes change the build parameters for all transitive dependencies
93under a target. For example, `genrule`'s `tools` changes `--cpu` to the CPU of
94the machine running Bazel (which, thanks to cross-compilation, may be different
95than the CPU the target is built for). This is known as a
aiuto4e9a77e2021-06-15 08:55:11 -070096[configuration transition](https://docs.bazel.build/versions/main/glossary.html#transition).
gregce8e8dcc82020-08-25 08:30:28 -070097
98Given
99
100```python
101#myapp/BUILD
102
103config_setting(
104 name = "arm_cpu",
105 values = {"cpu": "arm"},
106)
107
108config_setting(
109 name = "x86_cpu",
110 values = {"cpu": "x86"},
111)
112
113genrule(
114 name = "my_genrule",
115 srcs = select({
116 ":arm_cpu": ["g_arm.src"],
117 ":x86_cpu": ["g_x86.src"],
Googlerd63925b2021-02-05 10:57:50 -0800118 }),
gregce8e8dcc82020-08-25 08:30:28 -0700119 tools = select({
120 ":arm_cpu": [":tool1"],
121 ":x86_cpu": [":tool2"],
122 }),
123)
124
125cc_binary(
126 name = "tool1",
127 srcs = select({
128 ":arm_cpu": ["armtool.cc"],
129 ":x86_cpu": ["x86tool.cc"],
130 }),
131)
132```
133
134running
135
136```sh
137$ bazel build //myapp:my_genrule --cpu=arm
138```
139
140on an `x86` developer machine binds the build to `g_arm.src`, `tool1`, and
141`x86tool.cc`. Both of the `select`s attached to `my_genrule` use `my_genrule`'s
142build parameters, which include `--cpu=arm`. The `tools` attribute changes
143`--cpu` to `x86` for `tool1` and its transitive dependencies. The `select` on
144`tool1` uses `tool1`'s build parameters, which include `--cpu=x86`.
gregcec44a87b2018-06-08 12:07:03 -0700145
Greg Estrenc0816752020-02-20 13:04:29 -0800146## Configuration conditions
gregcec44a87b2018-06-08 12:07:03 -0700147
148Each key in a configurable attribute is a label reference to a
Greg Estren12b06b22020-09-11 10:58:43 -0700149[`config_setting`](be/general.html#config_setting) or
150[`constraint_value`](be/platform.html#constraint_value).
151
152`config_setting` is just a collection of
gregce8e8dcc82020-08-25 08:30:28 -0700153expected command line flag settings. By encapsulating these in a target, it's
154easy to maintain "standard" conditions users can reference from multiple places.
gregcec44a87b2018-06-08 12:07:03 -0700155
Greg Estren12b06b22020-09-11 10:58:43 -0700156`constraint_value` provides support for [multi-platform behavior](#platforms).
157
gregce8e8dcc82020-08-25 08:30:28 -0700158
159### Built-in flags
160
161Flags like `--cpu` are built into Bazel: the build tool natively understands
162them for all builds in all projects. These are specified with
163[`config_setting`](be/general.html#config_setting)'s
164[`values`](be/general.html#config_setting.values) attribute:
gregcec44a87b2018-06-08 12:07:03 -0700165
brandjoneadd5f62018-10-02 12:05:44 -0700166```python
gregcec44a87b2018-06-08 12:07:03 -0700167config_setting(
168 name = "meaningful_condition_name",
169 values = {
gregce8e8dcc82020-08-25 08:30:28 -0700170 "flag1": "value1",
171 "flag2": "value2",
gregcec44a87b2018-06-08 12:07:03 -0700172 ...
brandjoneadd5f62018-10-02 12:05:44 -0700173 },
gregcec44a87b2018-06-08 12:07:03 -0700174)
175```
176
gregce8e8dcc82020-08-25 08:30:28 -0700177`flagN` is a flag name (without `--`, so `"cpu"` instead of `"--cpu"`). `valueN`
178is the expected value for that flag. `:meaningful_condition_name` matches if
179*every* entry in `values` matches. Order is irrelevant.
gregcec44a87b2018-06-08 12:07:03 -0700180
gregce8e8dcc82020-08-25 08:30:28 -0700181`valueN` is parsed as if it was set on the command line. This means:
gregcec44a87b2018-06-08 12:07:03 -0700182
gregce8e8dcc82020-08-25 08:30:28 -0700183* `values = { "compilation_mode": "opt" }` matches `bazel build -c opt`
184* `values = { "force_pic": "true" }` matches `bazel build --force_pic=1`
185* `values = { "force_pic": "0" }` matches `bazel build --noforce_pic`
gregcec44a87b2018-06-08 12:07:03 -0700186
gregce8e8dcc82020-08-25 08:30:28 -0700187`config_setting` only supports flags that affect target behavior. For example,
188[`--show_progress`](user-manual.html#flag--show_progress) isn't allowed because
189it only affects how Bazel reports progress to the user. Targets can't use that
190flag to construct their results. The exact set of supported flags isn't
191documented. In practice, most flags that "make sense" work.
gregcec44a87b2018-06-08 12:07:03 -0700192
gregce8e8dcc82020-08-25 08:30:28 -0700193### Custom flags
gregcec44a87b2018-06-08 12:07:03 -0700194
gregce8e8dcc82020-08-25 08:30:28 -0700195You can model your own project-specific flags with
196[Starlark build
gregcecd2209a2020-10-13 11:17:01 -0700197settings][BuildSettings]. Unlike built-in flags, these are defined as build
198targets, so Bazel references them with target labels.
gregce8e8dcc82020-08-25 08:30:28 -0700199
200These are triggered with [`config_setting`](be/general.html#config_setting)'s
201[`flag_values`](be/general.html#config_setting.flag_values)
202attribute:
203
204```python
205config_setting(
206 name = "meaningful_condition_name",
207 flag_values = {
208 "//myflags:flag1": "value1",
209 "//myflags:flag2": "value2",
210 ...
211 },
212)
213```
214
aiuto4e9a77e2021-06-15 08:55:11 -0700215Behavior is the same as for [built-in flags](#built-in-flags). See [here](https://github.com/bazelbuild/examples/tree/HEAD/rules/starlark_configurations/select_on_build_setting)
gregce8e8dcc82020-08-25 08:30:28 -0700216for a working example.
217
218[`--define`](command-line-reference.html#flag--define)
219is an alternative legacy syntax for custom flags (for example
220`--define foo=bar`). This can be expressed either in the
221[values](be/general.html#config_setting.values) attribute
222(`values = {"define": "foo=bar"}`) or the
223[define_values](be/general.html#config_setting.define_values) attribute
224(`define_values = {"foo": "bar"}`). `--define` is only supported for backwards
225compatibility. Prefer Starlark build settings whenever possible.
226
227`values`, `flag_values`, and `define_values` evaluate independently. The
228`config_setting` matches if all values across all of them match.
229
230## The default condition
gregcec44a87b2018-06-08 12:07:03 -0700231
232The built-in condition `//conditions:default` matches when no other condition
233matches.
234
235Because of the "exactly one match" rule, a configurable attribute with no match
gregce8e8dcc82020-08-25 08:30:28 -0700236and no default condition emits a `"no matching conditions"` error. This can
237protect against silent failures from unexpected settings:
gregcec44a87b2018-06-08 12:07:03 -0700238
brandjoneadd5f62018-10-02 12:05:44 -0700239```python
gregce8e8dcc82020-08-25 08:30:28 -0700240# myapp/BUILD
brandjoneadd5f62018-10-02 12:05:44 -0700241
gregcec44a87b2018-06-08 12:07:03 -0700242config_setting(
gregce8e8dcc82020-08-25 08:30:28 -0700243 name = "x86_cpu",
244 values = {"cpu": "x86"},
gregcec44a87b2018-06-08 12:07:03 -0700245)
246
247cc_library(
gregce8e8dcc82020-08-25 08:30:28 -0700248 name = "x86_only_lib",
gregcec44a87b2018-06-08 12:07:03 -0700249 srcs = select({
gregce8e8dcc82020-08-25 08:30:28 -0700250 ":x86_cpu": ["lib.cc"],
brandjoneadd5f62018-10-02 12:05:44 -0700251 }),
gregcec44a87b2018-06-08 12:07:03 -0700252)
253```
254
255```sh
gregce8e8dcc82020-08-25 08:30:28 -0700256$ bazel build //myapp:x86_only_lib --cpu=arm
gregcec44a87b2018-06-08 12:07:03 -0700257ERROR: Configurable attribute "srcs" doesn't match this configuration (would
258a default condition help?).
259Conditions checked:
gregce8e8dcc82020-08-25 08:30:28 -0700260 //myapp:x86_cpu
gregcec44a87b2018-06-08 12:07:03 -0700261```
262
gregce8e8dcc82020-08-25 08:30:28 -0700263For even clearer errors, you can set custom messages with `select()`'s
264[`no_match_error`](#custom-error-messages) attribute.
gregcec44a87b2018-06-08 12:07:03 -0700265
266## Platforms
267
268While the ability to specify multiple flags on the command line provides
brandjoneadd5f62018-10-02 12:05:44 -0700269flexibility, it can also be burdensome to individually set each one every time
270you want to build a target.
271 [Platforms](platforms.html)
Greg Estren12b06b22020-09-11 10:58:43 -0700272let you consolidate these into simple bundles.
gregcec44a87b2018-06-08 12:07:03 -0700273
brandjoneadd5f62018-10-02 12:05:44 -0700274```python
275# myapp/BUILD
276
gregcec44a87b2018-06-08 12:07:03 -0700277sh_binary(
brandjoneadd5f62018-10-02 12:05:44 -0700278 name = "my_rocks",
gregcec44a87b2018-06-08 12:07:03 -0700279 srcs = select({
brandjoneadd5f62018-10-02 12:05:44 -0700280 ":basalt": ["pyroxene.sh"],
281 ":marble": ["calcite.sh"],
282 "//conditions:default": ["feldspar.sh"],
283 }),
gregcec44a87b2018-06-08 12:07:03 -0700284)
285
286config_setting(
287 name = "basalt",
288 constraint_values = [
brandjoneadd5f62018-10-02 12:05:44 -0700289 ":black",
gregcec44a87b2018-06-08 12:07:03 -0700290 ":igneous",
brandjoneadd5f62018-10-02 12:05:44 -0700291 ],
gregcec44a87b2018-06-08 12:07:03 -0700292)
293
294config_setting(
295 name = "marble",
296 constraint_values = [
297 ":white",
brandjoneadd5f62018-10-02 12:05:44 -0700298 ":metamorphic",
299 ],
gregcec44a87b2018-06-08 12:07:03 -0700300)
301
brandjoneadd5f62018-10-02 12:05:44 -0700302# constraint_setting acts as an enum type, and constraint_value as an enum value.
gregcec44a87b2018-06-08 12:07:03 -0700303constraint_setting(name = "color")
304constraint_value(name = "black", constraint_setting = "color")
305constraint_value(name = "white", constraint_setting = "color")
306constraint_setting(name = "texture")
307constraint_value(name = "smooth", constraint_setting = "texture")
308constraint_setting(name = "type")
309constraint_value(name = "igneous", constraint_setting = "type")
310constraint_value(name = "metamorphic", constraint_setting = "type")
311
312platform(
313 name = "basalt_platform",
314 constraint_values = [
315 ":black",
brandjoneadd5f62018-10-02 12:05:44 -0700316 ":igneous",
317 ],
gregcec44a87b2018-06-08 12:07:03 -0700318)
319
320platform(
321 name = "marble_platform",
322 constraint_values = [
323 ":white",
brandjoneadd5f62018-10-02 12:05:44 -0700324 ":smooth",
325 ":metamorphic",
326 ],
gregcec44a87b2018-06-08 12:07:03 -0700327)
328```
329
brandjoneadd5f62018-10-02 12:05:44 -0700330The platform can be specified on the command line. It activates the
331`config_setting`s that contain a subset of the platform's `constraint_values`,
332allowing those `config_setting`s to match in `select()` expressions.
gregcec44a87b2018-06-08 12:07:03 -0700333
brandjoneadd5f62018-10-02 12:05:44 -0700334For example, in order to set the `srcs` attribute of `my_rocks` to `calcite.sh`,
Googlera1a29ec2021-02-26 12:19:25 -0800335you can simply run
gregcec44a87b2018-06-08 12:07:03 -0700336
337```sh
brandjoneadd5f62018-10-02 12:05:44 -0700338bazel build //my_app:my_rocks --platforms=//myapp:marble_platform
gregcec44a87b2018-06-08 12:07:03 -0700339```
340
341Without platforms, this might look something like
342
343```sh
brandjoneadd5f62018-10-02 12:05:44 -0700344bazel build //my_app:my_rocks --define color=white --define texture=smooth --define type=metamorphic
gregcec44a87b2018-06-08 12:07:03 -0700345```
brandjoneadd5f62018-10-02 12:05:44 -0700346
Greg Estren12b06b22020-09-11 10:58:43 -0700347`select()` can also directly read `constraint_value`s:
348
349```python
350constraint_setting(name = "type")
351constraint_value(name = "igneous", constraint_setting = "type")
352constraint_value(name = "metamorphic", constraint_setting = "type")
353sh_binary(
354 name = "my_rocks",
355 srcs = select({
356 ":igneous": ["igneous.sh"],
357 ":metamorphic" ["metamorphic.sh"],
358 }),
359)
360```
361
362This saves the need for boilerplate `config_setting`s when you only need to
363check against single values.
364
365Platforms are still under development. See the
366[documentation](platforms-intro.html) for details.
gregcec44a87b2018-06-08 12:07:03 -0700367
gregce8e8dcc82020-08-25 08:30:28 -0700368## Combining `select()`s
gregcec44a87b2018-06-08 12:07:03 -0700369
370`select` can appear multiple times in the same attribute:
371
brandjoneadd5f62018-10-02 12:05:44 -0700372```python
gregcec44a87b2018-06-08 12:07:03 -0700373sh_binary(
brandjoneadd5f62018-10-02 12:05:44 -0700374 name = "my_target",
375 srcs = ["always_include.sh"] +
376 select({
377 ":armeabi_mode": ["armeabi_src.sh"],
378 ":x86_mode": ["x86_src.sh"],
379 }) +
380 select({
381 ":opt_mode": ["opt_extras.sh"],
382 ":dbg_mode": ["dbg_extras.sh"],
383 }),
gregcec44a87b2018-06-08 12:07:03 -0700384)
385```
386
Greg Estrened0f7d02019-07-17 13:07:25 -0700387`select` cannot appear inside another `select`. If you need to nest `selects`
gregce8e8dcc82020-08-25 08:30:28 -0700388and your attribute takes other targets as values, use an intermediate target:
gregcec44a87b2018-06-08 12:07:03 -0700389
brandjoneadd5f62018-10-02 12:05:44 -0700390```python
391sh_binary(
392 name = "my_target",
gregcec44a87b2018-06-08 12:07:03 -0700393 srcs = ["always_include.sh"],
394 deps = select({
395 ":armeabi_mode": [":armeabi_lib"],
396 ...
brandjoneadd5f62018-10-02 12:05:44 -0700397 }),
gregcec44a87b2018-06-08 12:07:03 -0700398)
399
400sh_library(
401 name = "armeabi_lib",
402 srcs = select({
brandjoneadd5f62018-10-02 12:05:44 -0700403 ":opt_mode": ["armeabi_with_opt.sh"],
gregcec44a87b2018-06-08 12:07:03 -0700404 ...
brandjoneadd5f62018-10-02 12:05:44 -0700405 }),
gregcec44a87b2018-06-08 12:07:03 -0700406)
407```
408
gregce8e8dcc82020-08-25 08:30:28 -0700409If you need a `select` to match when multiple conditions match, consider [AND
Greg Estrened0f7d02019-07-17 13:07:25 -0700410chaining](#and-chaining).
gregcec44a87b2018-06-08 12:07:03 -0700411
Greg Estrenc0816752020-02-20 13:04:29 -0800412## OR chaining
gregcec44a87b2018-06-08 12:07:03 -0700413
414Consider the following:
415
brandjoneadd5f62018-10-02 12:05:44 -0700416```python
417sh_binary(
418 name = "my_target",
gregcec44a87b2018-06-08 12:07:03 -0700419 srcs = ["always_include.sh"],
420 deps = select({
421 ":config1": [":standard_lib"],
422 ":config2": [":standard_lib"],
423 ":config3": [":standard_lib"],
424 ":config4": [":special_lib"],
brandjoneadd5f62018-10-02 12:05:44 -0700425 }),
gregcec44a87b2018-06-08 12:07:03 -0700426)
427```
428
gregce8e8dcc82020-08-25 08:30:28 -0700429Most conditions evaluate to the same dep. But this syntax is hard to read and
430maintain. It would be nice to not have to repeat `[":standard_lib"]` multiple
431times.
gregcec44a87b2018-06-08 12:07:03 -0700432
gregce8e8dcc82020-08-25 08:30:28 -0700433One option is to predefine the value as a BUILD variable:
gregcec44a87b2018-06-08 12:07:03 -0700434
435```python
436STANDARD_DEP = [":standard_lib"]
437
brandjoneadd5f62018-10-02 12:05:44 -0700438sh_binary(
439 name = "my_target",
gregcec44a87b2018-06-08 12:07:03 -0700440 srcs = ["always_include.sh"],
441 deps = select({
442 ":config1": STANDARD_DEP,
443 ":config2": STANDARD_DEP,
444 ":config3": STANDARD_DEP,
445 ":config4": [":special_lib"],
brandjoneadd5f62018-10-02 12:05:44 -0700446 }),
gregcec44a87b2018-06-08 12:07:03 -0700447)
448```
449
gregce8e8dcc82020-08-25 08:30:28 -0700450This makes it easier to manage the dependency. But it still causes unnecessary
gregcec44a87b2018-06-08 12:07:03 -0700451duplication.
452
Greg Estrened0f7d02019-07-17 13:07:25 -0700453For more direct support, use one of the following:
Greg Estren016e2172019-01-29 13:28:48 -0800454
455### <a name="selects-with-or"></a>`selects.with_or`
456
Greg Estrened0f7d02019-07-17 13:07:25 -0700457The
arostovtsev414f3c82021-04-16 11:11:39 -0700458[with_or](https://github.com/bazelbuild/bazel-skylib/blob/main/docs/selects_doc.md#selectswith_or)
Greg Estrened0f7d02019-07-17 13:07:25 -0700459macro in [Skylib](https://github.com/bazelbuild/bazel-skylib)'s
arostovtsev414f3c82021-04-16 11:11:39 -0700460[`selects`](https://github.com/bazelbuild/bazel-skylib/blob/main/docs/selects_doc.md)
Greg Estrened0f7d02019-07-17 13:07:25 -0700461module supports `OR`ing conditions directly inside a `select`:
gregcec44a87b2018-06-08 12:07:03 -0700462
brandjoneadd5f62018-10-02 12:05:44 -0700463```python
cparsons7e10a4d2019-08-29 16:29:41 -0700464load("@bazel_skylib//lib:selects.bzl", "selects")
gregcec44a87b2018-06-08 12:07:03 -0700465```
466
brandjoneadd5f62018-10-02 12:05:44 -0700467```python
468sh_binary(
469 name = "my_target",
gregcec44a87b2018-06-08 12:07:03 -0700470 srcs = ["always_include.sh"],
471 deps = selects.with_or({
472 (":config1", ":config2", ":config3"): [":standard_lib"],
473 ":config4": [":special_lib"],
brandjoneadd5f62018-10-02 12:05:44 -0700474 }),
gregcec44a87b2018-06-08 12:07:03 -0700475)
476```
477
Greg Estrened0f7d02019-07-17 13:07:25 -0700478### <a name="selects-config-setting-or-group"></a>`selects.config_setting_group`
gregcec44a87b2018-06-08 12:07:03 -0700479
Greg Estren016e2172019-01-29 13:28:48 -0800480
Greg Estrened0f7d02019-07-17 13:07:25 -0700481The
arostovtsev414f3c82021-04-16 11:11:39 -0700482[config_setting_group](https://github.com/bazelbuild/bazel-skylib/blob/main/docs/selects_doc.md#selectsconfig_setting_group)
Greg Estrened0f7d02019-07-17 13:07:25 -0700483macro in [Skylib](https://github.com/bazelbuild/bazel-skylib)'s
arostovtsev414f3c82021-04-16 11:11:39 -0700484[`selects`](https://github.com/bazelbuild/bazel-skylib/blob/main/docs/selects_doc.md)
Greg Estrened0f7d02019-07-17 13:07:25 -0700485module supports `OR`ing multiple `config_setting`s:
Greg Estren016e2172019-01-29 13:28:48 -0800486
487```python
cparsons7e10a4d2019-08-29 16:29:41 -0700488load("@bazel_skylib//lib:selects.bzl", "selects")
Greg Estrened0f7d02019-07-17 13:07:25 -0700489```
Greg Estren016e2172019-01-29 13:28:48 -0800490
Greg Estrened0f7d02019-07-17 13:07:25 -0700491
492```python
493config_setting(
494 name = "config1",
495 values = {"cpu": "arm"},
496)
497config_setting(
498 name = "config2",
499 values = {"compilation_mode": "dbg"},
500)
501selects.config_setting_group(
502 name = "config1_or_2",
503 match_any = [":config1", ":config2"],
504)
Greg Estren016e2172019-01-29 13:28:48 -0800505sh_binary(
506 name = "my_target",
507 srcs = ["always_include.sh"],
508 deps = select({
Greg Estrened0f7d02019-07-17 13:07:25 -0700509 ":config1_or_2": [":standard_lib"],
510 "//conditions:default": [":other_lib"],
Greg Estren016e2172019-01-29 13:28:48 -0800511 }),
512)
513```
514
gregce8e8dcc82020-08-25 08:30:28 -0700515Unlike `selects.with_or`, different targets can share `:config1_or_2` across
516different attributes.
Greg Estren016e2172019-01-29 13:28:48 -0800517
gregce8e8dcc82020-08-25 08:30:28 -0700518It's an error for multiple conditions to match unless one is an unambiguous
519"specialization" of the others. See [here](#example) for details.
Greg Estren016e2172019-01-29 13:28:48 -0800520
gregce8e8dcc82020-08-25 08:30:28 -0700521## AND chaining
Greg Estrened0f7d02019-07-17 13:07:25 -0700522
gregce8e8dcc82020-08-25 08:30:28 -0700523If you need a `select` branch to match when multiple conditions match, use the
Greg Estrened0f7d02019-07-17 13:07:25 -0700524[Skylib](https://github.com/bazelbuild/bazel-skylib) macro
arostovtsev414f3c82021-04-16 11:11:39 -0700525[config_setting_group](https://github.com/bazelbuild/bazel-skylib/blob/main/docs/selects_doc.md#selectsconfig_setting_group):
Greg Estrened0f7d02019-07-17 13:07:25 -0700526
527```python
528config_setting(
529 name = "config1",
530 values = {"cpu": "arm"},
531)
532config_setting(
533 name = "config2",
534 values = {"compilation_mode": "dbg"},
535)
536selects.config_setting_group(
537 name = "config1_and_2",
538 match_all = [":config1", ":config2"],
539)
540sh_binary(
541 name = "my_target",
542 srcs = ["always_include.sh"],
543 deps = select({
544 ":config1_and_2": [":standard_lib"],
545 "//conditions:default": [":other_lib"],
Matt Mackay552f0e722020-11-12 20:01:36 -0800546 }),
Greg Estrened0f7d02019-07-17 13:07:25 -0700547)
548```
549
gregce8e8dcc82020-08-25 08:30:28 -0700550Unlike OR chaining, existing `config_setting`s can't be directly `AND`ed
551inside a `select`. You have to explicitly wrap them in a `config_setting_group`.
gregcec44a87b2018-06-08 12:07:03 -0700552
Greg Estrenc0816752020-02-20 13:04:29 -0800553## Custom error messages
gregcec44a87b2018-06-08 12:07:03 -0700554
gregce8e8dcc82020-08-25 08:30:28 -0700555By default, when no condition matches, the target the `select()` is attached to
556fails with the error:
gregcec44a87b2018-06-08 12:07:03 -0700557
558```sh
559ERROR: Configurable attribute "deps" doesn't match this configuration (would
560a default condition help?).
561Conditions checked:
562 //tools/cc_target_os:darwin
563 //tools/cc_target_os:android
564```
565
gregce8e8dcc82020-08-25 08:30:28 -0700566This can be customized with the [`no_match_error`](be/functions.html#select)
567attribute:
gregcec44a87b2018-06-08 12:07:03 -0700568
brandjoneadd5f62018-10-02 12:05:44 -0700569```python
gregcec44a87b2018-06-08 12:07:03 -0700570cc_library(
571 name = "my_lib",
brandjoneadd5f62018-10-02 12:05:44 -0700572 deps = select(
573 {
574 "//tools/cc_target_os:android": [":android_deps"],
575 "//tools/cc_target_os:windows": [":windows_deps"],
576 },
577 no_match_error = "Please build with an Android or Windows toolchain",
578 ),
gregcec44a87b2018-06-08 12:07:03 -0700579)
580```
581
582```sh
gregce8e8dcc82020-08-25 08:30:28 -0700583$ bazel build //myapp:my_lib
gregcec44a87b2018-06-08 12:07:03 -0700584ERROR: Configurable attribute "deps" doesn't match this configuration: Please
585build with an Android or Windows toolchain
586```
587
Greg Estrenc0816752020-02-20 13:04:29 -0800588## <a name="rules"></a>Rules compatibility
laurentlbdc702ce2018-08-17 06:52:20 -0700589Rule implementations receive the *resolved values* of configurable
gregcec44a87b2018-06-08 12:07:03 -0700590attributes. For example, given:
591
brandjoneadd5f62018-10-02 12:05:44 -0700592```python
gregce8e8dcc82020-08-25 08:30:28 -0700593# myapp/BUILD
brandjoneadd5f62018-10-02 12:05:44 -0700594
laurentlbdc702ce2018-08-17 06:52:20 -0700595some_rule(
brandjoneadd5f62018-10-02 12:05:44 -0700596 name = "my_target",
gregcec44a87b2018-06-08 12:07:03 -0700597 some_attr = select({
598 ":foo_mode": [":foo"],
599 ":bar_mode": [":bar"],
brandjoneadd5f62018-10-02 12:05:44 -0700600 }),
gregcec44a87b2018-06-08 12:07:03 -0700601)
602```
603
604```sh
gregce8e8dcc82020-08-25 08:30:28 -0700605$ bazel build //myapp/my_target --define mode=foo
gregcec44a87b2018-06-08 12:07:03 -0700606```
607
laurentlbdc702ce2018-08-17 06:52:20 -0700608Rule implementation code sees `ctx.attr.some_attr` as `[":foo"]`.
gregcec44a87b2018-06-08 12:07:03 -0700609
laurentlbdc702ce2018-08-17 06:52:20 -0700610Macros can accept `select()` clauses and pass them through to native
gregcec44a87b2018-06-08 12:07:03 -0700611rules. But *they cannot directly manipulate them*. For example, there's no way
laurentlbdc702ce2018-08-17 06:52:20 -0700612for a macro to convert
gregcec44a87b2018-06-08 12:07:03 -0700613
brandjoneadd5f62018-10-02 12:05:44 -0700614```python
615select({"foo": "val"}, ...)
gregcec44a87b2018-06-08 12:07:03 -0700616```
617
618to
619
brandjoneadd5f62018-10-02 12:05:44 -0700620```python
621select({"foo": "val_with_suffix"}, ...)
gregcec44a87b2018-06-08 12:07:03 -0700622```
623
624This is for two reasons.
625
626First, macros that need to know which path a `select` will choose *cannot work*
glukasiknuro61d663a2020-05-27 11:48:16 -0700627because macros are evaluated in Bazel's [loading phase](guide.html#loading-phase),
laurentlb79b94312018-11-07 05:18:59 -0800628which occurs before flag values are known.
gregcec44a87b2018-06-08 12:07:03 -0700629This is a core Bazel design restriction that's unlikely to change any time soon.
630
631Second, macros that just need to iterate over *all* `select` paths, while
632technically feasible, lack a coherent UI. Further design is necessary to change
633this.
634
Greg Estrenc0816752020-02-20 13:04:29 -0800635## <a name="query"></a>Bazel query and cquery
gregce8e8dcc82020-08-25 08:30:28 -0700636Bazel [`query`](query-how-to.html) operates over Bazel's
aiuto4e9a77e2021-06-15 08:55:11 -0700637[loading phase](https://docs.bazel.build/versions/main/glossary.html#loading-phase).
gregce8e8dcc82020-08-25 08:30:28 -0700638This means it doesn't know what command line flags a target uses since those
639flags aren't evaluated until later in the build (in the
aiuto4e9a77e2021-06-15 08:55:11 -0700640[analysis phase](https://docs.bazel.build/versions/main/glossary.html#analysis-phase)).
gregce8e8dcc82020-08-25 08:30:28 -0700641So it can't determine which `select()` branches are chosen.
gregcec44a87b2018-06-08 12:07:03 -0700642
Grzegorz Lukasika8048182021-03-17 07:28:58 -0700643Bazel [`cquery`](cquery.html) operates after Bazel's analysis phase, so it has
gregce8e8dcc82020-08-25 08:30:28 -0700644all this information and can accurately resolve `select()`s.
645
646Consider:
gregcec44a87b2018-06-08 12:07:03 -0700647
brandjoneadd5f62018-10-02 12:05:44 -0700648```python
gregce8e8dcc82020-08-25 08:30:28 -0700649load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
650```
651```python
652# myapp/BUILD
653
654string_flag(
655 name = "dog_type",
656 build_setting_default = "cat"
657)
brandjoneadd5f62018-10-02 12:05:44 -0700658
gregcec44a87b2018-06-08 12:07:03 -0700659cc_library(
660 name = "my_lib",
661 deps = select({
662 ":long": [":foo_dep"],
663 ":short": [":bar_dep"],
brandjoneadd5f62018-10-02 12:05:44 -0700664 }),
gregcec44a87b2018-06-08 12:07:03 -0700665)
brandjoneadd5f62018-10-02 12:05:44 -0700666
gregcec44a87b2018-06-08 12:07:03 -0700667config_setting(
brandjoneadd5f62018-10-02 12:05:44 -0700668 name = "long",
gregce8e8dcc82020-08-25 08:30:28 -0700669 flag_values = {":dog_type": "dachshund"},
gregcec44a87b2018-06-08 12:07:03 -0700670)
brandjoneadd5f62018-10-02 12:05:44 -0700671
gregcec44a87b2018-06-08 12:07:03 -0700672config_setting(
brandjoneadd5f62018-10-02 12:05:44 -0700673 name = "short",
gregce8e8dcc82020-08-25 08:30:28 -0700674 flag_values = {":dog_type": "pug"},
gregcec44a87b2018-06-08 12:07:03 -0700675)
676```
brandjoneadd5f62018-10-02 12:05:44 -0700677
Gautam Korlam82552dd2021-01-05 22:08:27 -0800678`query` overapproximates `:my_lib`'s dependencies:
gregcec44a87b2018-06-08 12:07:03 -0700679
680```sh
gregce8e8dcc82020-08-25 08:30:28 -0700681$ bazel query 'deps(//myapp:my_lib)'
682//myapp:my_lib
683//myapp:foo_dep
684//myapp:bar_dep
685```
gregcec44a87b2018-06-08 12:07:03 -0700686
gregce8e8dcc82020-08-25 08:30:28 -0700687while `cquery` shows its exact dependencies:
688
689```sh
690$ bazel cquery 'deps(//myapp:my_lib)' --//myapp:dog_type=pug
691//myapp:my_lib
692//myapp:bar_dep
gregcec44a87b2018-06-08 12:07:03 -0700693```
694
695## FAQ
696
Greg Estrene821cfa2020-02-20 09:34:56 -0800697### <a name="macros-select"></a>Why doesn't select() work in macros?
laurentlb6b6b84a2018-10-05 14:14:29 -0700698select() *does* work in rules! See [Rules compatibility](#rules) for
gregcec44a87b2018-06-08 12:07:03 -0700699details.
700
701The key issue this question usually means is that select() doesn't work in
laurentlbdc702ce2018-08-17 06:52:20 -0700702*macros*. These are different than *rules*. See the
gregcec44a87b2018-06-08 12:07:03 -0700703documentation on [rules](skylark/rules.html) and [macros](skylark/macros.html)
704to understand the difference.
705Here's an end-to-end example:
706
laurentlbdc702ce2018-08-17 06:52:20 -0700707Define a rule and macro:
gregcec44a87b2018-06-08 12:07:03 -0700708
brandjoneadd5f62018-10-02 12:05:44 -0700709```python
gregce8e8dcc82020-08-25 08:30:28 -0700710# myapp/defs.bzl
gregcec44a87b2018-06-08 12:07:03 -0700711
712# Rule implementation: when an attribute is read, all select()s have already
713# been resolved. So it looks like a plain old attribute just like any other.
714def _impl(ctx):
brandjoneadd5f62018-10-02 12:05:44 -0700715 name = ctx.attr.name
716 allcaps = ctx.attr.my_config_string.upper() # This works fine on all values.
717 print("My name is " + name + " with custom message: " + allcaps)
gregcec44a87b2018-06-08 12:07:03 -0700718
laurentlbdc702ce2018-08-17 06:52:20 -0700719# Rule declaration:
gregcec44a87b2018-06-08 12:07:03 -0700720my_custom_bazel_rule = rule(
721 implementation = _impl,
brandjoneadd5f62018-10-02 12:05:44 -0700722 attrs = {"my_config_string": attr.string()},
gregcec44a87b2018-06-08 12:07:03 -0700723)
724
laurentlbdc702ce2018-08-17 06:52:20 -0700725# Macro declaration:
gregcec44a87b2018-06-08 12:07:03 -0700726def my_custom_bazel_macro(name, my_config_string):
brandjoneadd5f62018-10-02 12:05:44 -0700727 allcaps = my_config_string.upper() # This line won't work with select(s).
728 print("My name is " + name + " with custom message: " + allcaps)
gregcec44a87b2018-06-08 12:07:03 -0700729```
730
731Instantiate the rule and macro:
732
brandjoneadd5f62018-10-02 12:05:44 -0700733```python
gregce8e8dcc82020-08-25 08:30:28 -0700734# myapp/BUILD
brandjoneadd5f62018-10-02 12:05:44 -0700735
gregce8e8dcc82020-08-25 08:30:28 -0700736load("//myapp:defs.bzl", "my_custom_bazel_rule")
737load("//myapp:defs.bzl", "my_custom_bazel_macro")
gregcec44a87b2018-06-08 12:07:03 -0700738
739my_custom_bazel_rule(
740 name = "happy_rule",
741 my_config_string = select({
742 "//tools/target_cpu:x86": "first string",
743 "//tools/target_cpu:ppc": "second string",
744 }),
745)
746
747my_custom_bazel_macro(
748 name = "happy_macro",
749 my_config_string = "fixed string",
750)
751
752my_custom_bazel_macro(
753 name = "sad_macro",
754 my_config_string = select({
755 "//tools/target_cpu:x86": "first string",
756 "//tools/target_cpu:ppc": "other string",
757 }),
758)
759```
760
761Building fails because `sad_macro` can't process the `select()`:
762
763```sh
gregce8e8dcc82020-08-25 08:30:28 -0700764$ bazel build //myapp:all
765ERROR: /myworkspace/myapp/BUILD:17:1: Traceback
gregcec44a87b2018-06-08 12:07:03 -0700766 (most recent call last):
gregce8e8dcc82020-08-25 08:30:28 -0700767File "/myworkspace/myapp/BUILD", line 17
gregcec44a87b2018-06-08 12:07:03 -0700768my_custom_bazel_macro(name = "sad_macro", my_config_stri..."}))
gregce8e8dcc82020-08-25 08:30:28 -0700769File "/myworkspace/myapp/defs.bzl", line 4, in
gregcec44a87b2018-06-08 12:07:03 -0700770 my_custom_bazel_macro
771my_config_string.upper()
772type 'select' has no method upper().
gregce8e8dcc82020-08-25 08:30:28 -0700773ERROR: error loading package 'myapp': Package 'myapp' contains errors.
gregcec44a87b2018-06-08 12:07:03 -0700774```
775
Googlera1a29ec2021-02-26 12:19:25 -0800776Building succeeds when you comment out `sad_macro`:
gregcec44a87b2018-06-08 12:07:03 -0700777
778```sh
779# Comment out sad_macro so it doesn't mess up the build.
gregce8e8dcc82020-08-25 08:30:28 -0700780$ bazel build //myapp:all
781DEBUG: /myworkspace/myapp/defs.bzl:5:3: My name is happy_macro with custom message: FIXED STRING.
782DEBUG: /myworkspace/myapp/hi.bzl:15:3: My name is happy_rule with custom message: FIRST STRING.
gregcec44a87b2018-06-08 12:07:03 -0700783```
784
785This is impossible to change because *by definition* macros are evaluated before
786Bazel reads the build's command line flags. That means there isn't enough
787information to evaluate select()s.
788
789Macros can, however, pass `select()`s as opaque blobs to rules:
790
brandjoneadd5f62018-10-02 12:05:44 -0700791```python
gregce8e8dcc82020-08-25 08:30:28 -0700792# myapp/defs.bzl
brandjoneadd5f62018-10-02 12:05:44 -0700793
gregcec44a87b2018-06-08 12:07:03 -0700794def my_custom_bazel_macro(name, my_config_string):
brandjoneadd5f62018-10-02 12:05:44 -0700795 print("Invoking macro " + name)
796 my_custom_bazel_rule(
797 name = name + "_as_target",
798 my_config_string = my_config_string,
799 )
gregcec44a87b2018-06-08 12:07:03 -0700800```
801
802```sh
gregce8e8dcc82020-08-25 08:30:28 -0700803$ bazel build //myapp:sad_macro_less_sad
804DEBUG: /myworkspace/myapp/defs.bzl:23:3: Invoking macro sad_macro_less_sad.
805DEBUG: /myworkspace/myapp/defs.bzl:15:3: My name is sad_macro_less_sad with custom message: FIRST STRING.
gregcec44a87b2018-06-08 12:07:03 -0700806```
807
Greg Estrene821cfa2020-02-20 09:34:56 -0800808### <a name="boolean-select"></a>Why does select() always return true?
laurentlbdc702ce2018-08-17 06:52:20 -0700809Because *macros* (but not rules) by definition
gregce8e8dcc82020-08-25 08:30:28 -0700810[can't evaluate `select()`s](#macros-select), any attempt to do so
Ray Loyzagaca591462020-01-02 06:26:58 -0800811usually produces an error:
gregcec44a87b2018-06-08 12:07:03 -0700812
813```sh
gregce8e8dcc82020-08-25 08:30:28 -0700814ERROR: /myworkspace/myapp/BUILD:17:1: Traceback
gregcec44a87b2018-06-08 12:07:03 -0700815 (most recent call last):
gregce8e8dcc82020-08-25 08:30:28 -0700816File "/myworkspace/myapp/BUILD", line 17
gregcec44a87b2018-06-08 12:07:03 -0700817my_custom_bazel_macro(name = "sad_macro", my_config_stri..."}))
gregce8e8dcc82020-08-25 08:30:28 -0700818File "/myworkspace/myapp/defs.bzl", line 4, in
gregcec44a87b2018-06-08 12:07:03 -0700819 my_custom_bazel_macro
820my_config_string.upper()
821type 'select' has no method upper().
822```
823
824Booleans are a special case that fail silently, so you should be particularly
825vigilant with them:
826
827```sh
gregce8e8dcc82020-08-25 08:30:28 -0700828$ cat myapp/defs.bzl
gregcec44a87b2018-06-08 12:07:03 -0700829def my_boolean_macro(boolval):
830 print("TRUE" if boolval else "FALSE")
831
gregce8e8dcc82020-08-25 08:30:28 -0700832$ cat myapp/BUILD
833load("//myapp:defs.bzl", "my_boolean_macro")
gregcec44a87b2018-06-08 12:07:03 -0700834my_boolean_macro(
835 boolval = select({
836 "//tools/target_cpu:x86": True,
837 "//tools/target_cpu:ppc": False,
838 }),
839)
840
gregce8e8dcc82020-08-25 08:30:28 -0700841$ bazel build //myapp:all --cpu=x86
842DEBUG: /myworkspace/myapp/defs.bzl:4:3: TRUE.
843$ bazel build //mypro:all --cpu=ppc
844DEBUG: /myworkspace/myapp/defs.bzl:4:3: TRUE.
gregcec44a87b2018-06-08 12:07:03 -0700845```
846
laurentlbdc702ce2018-08-17 06:52:20 -0700847This happens because macros don't understand the contents of `select()`.
gregcec44a87b2018-06-08 12:07:03 -0700848So what they're really evaluting is the `select()` object itself. According to
849[Pythonic](https://docs.python.org/release/2.5.2/lib/truth.html) design
850standards, all objects aside from a very small number of exceptions
851automatically return true.
Greg Estrene821cfa2020-02-20 09:34:56 -0800852### <a name="inspectable-select"></a>Can I read select() like a dict?
gregce8e8dcc82020-08-25 08:30:28 -0700853Macros [can't](#macros-select) evaluate select(s) because macros evaluate before
854Bazel knows what the build's command line parameters are. Can they at least read
855the `select()`'s dictionary to, for example, add a suffix to each value?
gregcec44a87b2018-06-08 12:07:03 -0700856
gregce8e8dcc82020-08-25 08:30:28 -0700857Conceptually this is possible, but it isn't yet a Bazel feature.
gregcec44a87b2018-06-08 12:07:03 -0700858What you *can* do today is prepare a straight dictionary, then feed it into a
859`select()`:
860
861```sh
gregce8e8dcc82020-08-25 08:30:28 -0700862$ cat myapp/defs.bzl
gregcec44a87b2018-06-08 12:07:03 -0700863def selecty_genrule(name, select_cmd):
864 for key in select_cmd.keys():
865 select_cmd[key] += " WITH SUFFIX"
866 native.genrule(
867 name = name,
868 outs = [name + ".out"],
869 srcs = [],
870 cmd = "echo " + select(select_cmd + {"//conditions:default": "default"})
871 + " > $@"
872 )
873
gregce8e8dcc82020-08-25 08:30:28 -0700874$ cat myapp/BUILD
gregcec44a87b2018-06-08 12:07:03 -0700875selecty_genrule(
876 name = "selecty",
877 select_cmd = {
878 "//tools/target_cpu:x86": "x86 mode",
879 },
880)
881
882$ bazel build //testapp:selecty --cpu=x86 && cat bazel-genfiles/testapp/selecty.out
883x86 mode WITH SUFFIX
884```
885
886If you'd like to support both `select()` and native types, you can do this:
887
888```sh
gregce8e8dcc82020-08-25 08:30:28 -0700889$ cat myapp/defs.bzl
gregcec44a87b2018-06-08 12:07:03 -0700890def selecty_genrule(name, select_cmd):
brandjoneadd5f62018-10-02 12:05:44 -0700891 cmd_suffix = ""
892 if type(select_cmd) == "string":
893 cmd_suffix = select_cmd + " WITH SUFFIX"
894 elif type(select_cmd) == "dict":
895 for key in select_cmd.keys():
896 select_cmd[key] += " WITH SUFFIX"
897 cmd_suffix = select(select_cmd + {"//conditions:default": "default"})
gregcec44a87b2018-06-08 12:07:03 -0700898
brandjoneadd5f62018-10-02 12:05:44 -0700899 native.genrule(
900 name = name,
901 outs = [name + ".out"],
902 srcs = [],
903 cmd = "echo " + cmd_suffix + "> $@",
904 )
gregcec44a87b2018-06-08 12:07:03 -0700905```
John Cater7780b752019-01-16 12:14:35 -0800906
Greg Estrene821cfa2020-02-20 09:34:56 -0800907### <a name="bind-select"></a>Why doesn't select() work with bind()?
John Cater7780b752019-01-16 12:14:35 -0800908
909Because [`bind()`](be/workspace.html#bind) is a WORKSPACE rule, not a BUILD rule.
910
911Workspace rules do not have a specific configuration, and aren't evaluated in
912the same way as BUILD rules. Therefore, a `select()` in a `bind()` can't
913actually evaluate to any specific branch.
914
915Instead, you should use [`alias()`](be/general.html#alias), with a `select()` in
916the `actual` attribute, to perform this type of run-time determination. This
917works correctly, since `alias()` is a BUILD rule, and is evaluated with a
918specific configuration.
919
920You can even have a `bind()` target point to an `alias()`, if needed.
921
922```sh
923$ cat WORKSPACE
gregce8e8dcc82020-08-25 08:30:28 -0700924workspace(name = "myapp")
John Cater7780b752019-01-16 12:14:35 -0800925bind(name = "openssl", actual = "//:ssl")
926http_archive(name = "alternative", ...)
927http_archive(name = "boringssl", ...)
928
929$ cat BUILD
930config_setting(
931 name = "alt_ssl",
932 define_values = {
933 "ssl_library": "alternative",
934 },
935)
936
937alias(
938 name = "ssl",
939 actual = select({
940 "//:alt_ssl": "@alternative//:ssl",
941 "//conditions:default": "@boringssl//:ssl",
942 }),
943)
944```
945
946With this setup, you can pass `--define ssl_library=alternative`, and any target
947that depends on either `//:ssl` or `//external:ssl` will see the alternative
948located at `@alternative//:ssl`.
gregce8d551782020-04-16 11:18:15 -0700949
950### Why doesn't my select() choose what I expect?
gregce8e8dcc82020-08-25 08:30:28 -0700951If `//myapp:foo` has a `select()` that doesn't choose the condition you expect,
952use [cquery](cquery.html) and `bazel config` to debug:
gregce8d551782020-04-16 11:18:15 -0700953
gregce8e8dcc82020-08-25 08:30:28 -0700954If `//myapp:foo` is the top-level target you're building, run:
gregce8d551782020-04-16 11:18:15 -0700955
956```sh
gregce8e8dcc82020-08-25 08:30:28 -0700957$ bazel cquery //myapp:foo <desired build flags>
958//myapp:foo (12e23b9a2b534a)
gregce8d551782020-04-16 11:18:15 -0700959```
960
gregce8e8dcc82020-08-25 08:30:28 -0700961If you're building some other target `//bar` that depends on
962//myapp:foo somewhere in its subgraph, run:
gregce8d551782020-04-16 11:18:15 -0700963
964```sh
gregce8e8dcc82020-08-25 08:30:28 -0700965$ bazel cquery 'somepath(//bar, //myapp:foo)' <desired build flags>
966//bar:bar (3ag3193fee94a2)
967//bar:intermediate_dep (12e23b9a2b534a)
968//myapp:foo (12e23b9a2b534a)
gregce8d551782020-04-16 11:18:15 -0700969```
970
gregce8e8dcc82020-08-25 08:30:28 -0700971The `(12e23b9a2b534a)` next to `//myapp:foo` is a *hash* of the
972configuration that resolves `//myapp:foo`'s `select()`. You can inspect its
973values with `bazel config`:
gregce8d551782020-04-16 11:18:15 -0700974
975```sh
976$ bazel config 12e23b9a2b534a
977BuildConfiguration 12e23b9a2b534a
978Fragment com.google.devtools.build.lib.analysis.config.CoreOptions {
979 cpu: darwin
980 compilation_mode: fastbuild
981 ...
982}
983Fragment com.google.devtools.build.lib.rules.cpp.CppOptions {
984 linkopt: [-Dfoo=bar]
985 ...
986}
987...
988```
989
gregce8e8dcc82020-08-25 08:30:28 -0700990Then compare this output against the settings expected by each `config_setting`.
gregce8d551782020-04-16 11:18:15 -0700991
gregce8e8dcc82020-08-25 08:30:28 -0700992`//myapp:foo` may exist in different configurations in the same build. See the
993[cquery docs](cquery.html) for guidance on using `somepath` to get the right
994one.
juliexxiad3f0e012020-10-08 14:01:37 -0700995
996Caution: To prevent restarting the Bazel server, invoke `bazel config` with the
997same command line flags as the `bazel cquery`. The `config` command relies on
998the configuration nodes from the still-running server of the previous command.
gregcecd2209a2020-10-13 11:17:01 -0700999
1000[BuildSettings]: skylark/config.html#user-defined-build-settings