Refresh configurable attributes doc.
Highlights:
- Update outdated "Starlark flags not yet supported" refs
- Convert "--define" examples to Starlark flags when possible
- Overhaul "native vs. user-defined" core config_setting description
- Use more consistent package naming for examples
- Remove "Short keys" section, which is considered bad practice (creates too much indirection which makes it hard to know what relies on what).
For https://github.com/bazelbuild/bazel/issues/11967
PiperOrigin-RevId: 328335077
diff --git a/site/docs/configurable-attributes.md b/site/docs/configurable-attributes.md
index efed273..ddede2b 100644
--- a/site/docs/configurable-attributes.md
+++ b/site/docs/configurable-attributes.md
@@ -69,156 +69,193 @@
</table>
`select()` serves as a placeholder for a value that will be chosen based on
-*configuration conditions*. These conditions are labels that refer to
-[`config_setting`](be/general.html#config_setting) targets. By using `select()`
-in a configurable attribute, the attribute effectively takes on different values
-when different conditions hold.
+*configuration conditions*, which are labels referencing [`config_setting`](be/general.html#config_setting)
+targets. By using `select()` in a configurable attribute, the attribute
+effectively adopts different values when different conditions hold.
Matches must be unambiguous: either exactly one condition must match or, if
multiple conditions match, one's `values` must be a strict superset of all
others'. For example, `values = {"cpu": "x86", "compilation_mode": "dbg"}` is an
unambiguous specialization of `values = {"cpu": "x86"}`. The built-in condition
-[`//conditions:default`](#defaults) automatically matches when nothing else
-does.
+[`//conditions:default`](#the-default-condition) automatically matches when
+nothing else does.
-This example uses `deps`. But `select()` works just as well on `srcs`,
-`resources`, `cmd`, or practically any other attribute. Only a small number of
-attributes are *non-configurable*, and those are clearly annotated; for
-instance, `config_setting`'s own
+While this example uses `deps`, `select()` works just as well on `srcs`,
+`resources`, `cmd`, and most other attributes. Only a small number of attributes
+are *non-configurable*, and these are clearly annotated. For example,
+`config_setting`'s own
[`values`](be/general.html#config_setting.values) attribute is non-configurable.
-Certain attributes, like the `tools` of a `genrule`, have the effect of changing
-the build parameters (such as the cpu) for all targets that transitively appear
-beneath them. This will affect how conditions are matched within those targets
-but not within the attribute that causes the change. That is, a `select` in the
-`tools` attribute of a `genrule` will work the same as a `select` in the `srcs`.
+## `select()` and dependencies
+
+Certain attributes change the build parameters for all transitive dependencies
+under a target. For example, `genrule`'s `tools` changes `--cpu` to the CPU of
+the machine running Bazel (which, thanks to cross-compilation, may be different
+than the CPU the target is built for). This is known as a
+[configuration transition](https://docs.bazel.build/versions/master/glossary.html#transition).
+
+Given
+
+```python
+#myapp/BUILD
+
+config_setting(
+ name = "arm_cpu",
+ values = {"cpu": "arm"},
+)
+
+config_setting(
+ name = "x86_cpu",
+ values = {"cpu": "x86"},
+)
+
+genrule(
+ name = "my_genrule",
+ srcs = select({
+ ":arm_cpu": ["g_arm.src"],
+ ":x86_cpu": ["g_x86.src"],
+ tools = select({
+ ":arm_cpu": [":tool1"],
+ ":x86_cpu": [":tool2"],
+ }),
+)
+
+cc_binary(
+ name = "tool1",
+ srcs = select({
+ ":arm_cpu": ["armtool.cc"],
+ ":x86_cpu": ["x86tool.cc"],
+ }),
+)
+```
+
+running
+
+```sh
+$ bazel build //myapp:my_genrule --cpu=arm
+```
+
+on an `x86` developer machine binds the build to `g_arm.src`, `tool1`, and
+`x86tool.cc`. Both of the `select`s attached to `my_genrule` use `my_genrule`'s
+build parameters, which include `--cpu=arm`. The `tools` attribute changes
+`--cpu` to `x86` for `tool1` and its transitive dependencies. The `select` on
+`tool1` uses `tool1`'s build parameters, which include `--cpu=x86`.
## Configuration conditions
Each key in a configurable attribute is a label reference to a
-[`config_setting`](be/general.html#config_setting) target. This is just a
-collection of expected command line flag settings. By encapsulating these in a
-target, it's easy to maintain "standard" conditions that can be referenced
-across targets and BUILD files.
+[`config_setting`](be/general.html#config_setting). This is just a collection of
+expected command line flag settings. By encapsulating these in a target, it's
+easy to maintain "standard" conditions users can reference from multiple places.
-The core `config_setting` syntax is:
+
+### Built-in flags
+
+Flags like `--cpu` are built into Bazel: the build tool natively understands
+them for all builds in all projects. These are specified with
+[`config_setting`](be/general.html#config_setting)'s
+[`values`](be/general.html#config_setting.values) attribute:
```python
config_setting(
name = "meaningful_condition_name",
values = {
- "flag1": "expected_value1",
- "flag2": "expected_value2",
+ "flag1": "value1",
+ "flag2": "value2",
...
},
)
```
-`flagN` is an arbitrary Bazel command line flag. `value` is the expected value
-for that flag. A `config_setting` matches when *all* of its flags match (order
-is irrelevant).
+`flagN` is a flag name (without `--`, so `"cpu"` instead of `"--cpu"`). `valueN`
+is the expected value for that flag. `:meaningful_condition_name` matches if
+*every* entry in `values` matches. Order is irrelevant.
-`values` entries use the same parsing logic as at the actual command line. This
-means:
+`valueN` is parsed as if it was set on the command line. This means:
-* `values = { "compilation_mode": "opt" }` matches `bazel build -c opt ...`
-* `values = { "java_header_compilation": "true" }` matches `bazel build
---java_header_compilation=1 ...`
-* `values = { "java_header_compilation": "0" }` matches `bazel build
---nojava_header_compilation ...`
+* `values = { "compilation_mode": "opt" }` matches `bazel build -c opt`
+* `values = { "force_pic": "true" }` matches `bazel build --force_pic=1`
+* `values = { "force_pic": "0" }` matches `bazel build --noforce_pic`
-`config_setting` only works with flags that affect build rule output. For
-example, [`--show_progress`](user-manual.html#flag--show_progress) isn't allowed
-because this only affects how Bazel reports progress to the user.
+`config_setting` only supports flags that affect target behavior. For example,
+[`--show_progress`](user-manual.html#flag--show_progress) isn't allowed because
+it only affects how Bazel reports progress to the user. Targets can't use that
+flag to construct their results. The exact set of supported flags isn't
+documented. In practice, most flags that "make sense" work.
-`config_setting` semantics are intentionally simple. For example, there's no
-direct support for `OR` chaining (although a
-[convenience function](#or-chaining) provides this). Consider writing
-macros for complicated flag logic.
+### Custom flags
-## Defaults
+You can model your own project-specific flags with
+[Starlark build
+settings](skylark/config.html#user-defined-build-settings). Unlike built-in
+flags, these are defined as build targets, so Bazel references them with target
+labels.
+
+These are triggered with [`config_setting`](be/general.html#config_setting)'s
+[`flag_values`](be/general.html#config_setting.flag_values)
+attribute:
+
+```python
+config_setting(
+ name = "meaningful_condition_name",
+ flag_values = {
+ "//myflags:flag1": "value1",
+ "//myflags:flag2": "value2",
+ ...
+ },
+)
+```
+
+Behavior is the same as for [built-in flags](#built-in-flags). See [here](https://github.com/bazelbuild/examples/tree/master/rules/starlark_configurations/select_on_build_setting)
+for a working example.
+
+[`--define`](command-line-reference.html#flag--define)
+is an alternative legacy syntax for custom flags (for example
+`--define foo=bar`). This can be expressed either in the
+[values](be/general.html#config_setting.values) attribute
+(`values = {"define": "foo=bar"}`) or the
+[define_values](be/general.html#config_setting.define_values) attribute
+(`define_values = {"foo": "bar"}`). `--define` is only supported for backwards
+compatibility. Prefer Starlark build settings whenever possible.
+
+`values`, `flag_values`, and `define_values` evaluate independently. The
+`config_setting` matches if all values across all of them match.
+
+## The default condition
The built-in condition `//conditions:default` matches when no other condition
matches.
Because of the "exactly one match" rule, a configurable attribute with no match
-and no default condition triggers a `"no matching conditions"` error. This can
-protect against silent failures from unexpected build flags:
+and no default condition emits a `"no matching conditions"` error. This can
+protect against silent failures from unexpected settings:
```python
-# foo/BUILD
+# myapp/BUILD
config_setting(
- name = "foobar",
- values = {"define": "foo=bar"},
+ name = "x86_cpu",
+ values = {"cpu": "x86"},
)
cc_library(
- name = "my_lib",
+ name = "x86_only_lib",
srcs = select({
- ":foobar": ["foobar_lib.cc"],
+ ":x86_cpu": ["lib.cc"],
}),
)
```
```sh
-$ bazel build //foo:my_lib --define foo=baz
+$ bazel build //myapp:x86_only_lib --cpu=arm
ERROR: Configurable attribute "srcs" doesn't match this configuration (would
a default condition help?).
Conditions checked:
- //foo:foobar
+ //myapp:x86_cpu
```
-`select()` can include a [`no_match_error`](#custom-error-messages) for custom
-failure messages.
-
-## Custom keys
-
-Since `config_setting` currently only supports built-in Bazel flags, the level
-of custom conditioning it can support is limited. For example, there's no Bazel
-flag for `IncludeSpecialProjectFeatureX`.
-
-Plans for [truly custom flags](
-https://docs.google.com/document/d/1vc8v-kXjvgZOdQdnxPTaV0rrLxtP2XwnD2tAZlYJOqw/edit?usp=sharing)
-are underway. In the meantime, [`--define`](command-line-reference.html#flag--define) is
-the best approach for these purposes.
-`--define` is a bit awkward to use and wasn't originally designed for this
-purpose. We recommend using it sparingly until true custom flags are available.
-For example, don't use `--define` to specify multiple variants of top-level
-binary. Just use multiple targets instead.
-
-To trigger an arbitrary condition with `--define`, write
-
-```python
-config_setting(
- name = "bar",
- values = {"define": "foo=bar"},
-)
-
-config_setting(
- name = "baz",
- values = {"define": "foo=baz"},
-)
-```
-
-and run `$ bazel build //my:target --define foo=baz`.
-
-The `values` attribute can't contain multiple `define`s. This is
-because each instance has the same dictionary key. To solve this, use
-`define_values`:
-
-```python
-config_setting(
- name = "bar_and_baz",
- define_values = {
- "foo": "bar", # matches --define foo=bar
- "baz": "bat", # matches --define baz=bat
- },
-)
-```
-
-When `define`s appear in both `values` and `define_values`, all must match for
-the `config_setting` to match.
+For even clearer errors, you can set custom messages with `select()`'s
+[`no_match_error`](#custom-error-messages) attribute.
## Platforms
@@ -304,89 +341,7 @@
Platforms are still under development. See the [documentation](platforms.html)
and [roadmap](https://bazel.build/roadmaps/platforms.html) for details.
-## Short keys
-
-Since configuration keys are target labels, their names can get long and
-unwieldy. This can be mitigated with local variable definitions:
-
-Before:
-
-```python
-sh_binary(
- name = "my_target",
- srcs = select({
- "//my/project/my/team/configs:config1": ["my_target_1.sh"],
- "//my/project/my/team/configs:config2": ["my_target_2.sh"],
- }),
-)
-```
-
-After:
-
-```python
-CONFIG1="//my/project/my/team/configs:config1"
-CONFIG2="//my/project/my/team/configs:config2"
-
-sh_binary(
- name = "my_target",
- srcs = select({
- CONFIG1: ["my_target_1.sh"],
- CONFIG2: ["my_target_2.sh"],
- })
-)
-```
-
-
-For more complex expressions, you can use [macros](skylark/macros.md):
-
-Before:
-
-```python
-# foo/BUILD
-
-genrule(
- name = "my_target",
- srcs = [],
- outs = ["my_target.out"],
- cmd = select({
- "//my/project/my/team/configs/config1": "echo custom val: this > $@",
- "//my/project/my/team/configs/config2": "echo custom val: that > $@",
- "//conditions:default": "echo default output > $@",
- }),
-)
-```
-
-After:
-
-```python
-# foo/genrule_select.bzl
-
-def select_echo(input_dict):
- echo_cmd = "echo %s > $@"
- out_dict = {"//conditions:default": echo_cmd % "default output"}
- for (key, val) in input_dict.items():
- cmd = echo_cmd % ("custom val: " + val)
- out_dict["//my/project/my/team/configs/config" + key] = cmd
- return select(out_dict)
-```
-
-```python
-# foo/BUILD
-
-load("//foo:genrule_select.bzl", "select_echo")
-
-genrule(
- name = "my_target",
- srcs = [],
- outs = ["my_target.out"],
- cmd = select_echo({
- "1": "this",
- "2": "that",
- }),
-)
-```
-
-## Multiple `select` functions
+## Combining `select()`s
`select` can appear multiple times in the same attribute:
@@ -406,7 +361,7 @@
```
`select` cannot appear inside another `select`. If you need to nest `selects`
-use an intermediate target:
+and your attribute takes other targets as values, use an intermediate target:
```python
sh_binary(
@@ -427,10 +382,7 @@
)
```
-Note that this approach doesn't work for non-deps attributes (like
-[genrule:cmd](be/general.html#genrule.cmd)).
-
-If you just need a `select` to match when multiple conditions match, see [AND
+If you need a `select` to match when multiple conditions match, consider [AND
chaining](#and-chaining).
## OR chaining
@@ -450,11 +402,11 @@
)
```
-Most conditions evaluate to the same dep. But this syntax is verbose, hard to
-maintain, and refactoring-unfriendly. It would be nice to not have to repeat
-`[":standard_lib"]` over and over.
+Most conditions evaluate to the same dep. But this syntax is hard to read and
+maintain. It would be nice to not have to repeat `[":standard_lib"]` multiple
+times.
-One option is to predefine the declaration as a BUILD variable:
+One option is to predefine the value as a BUILD variable:
```python
STANDARD_DEP = [":standard_lib"]
@@ -471,7 +423,7 @@
)
```
-This makes it easier to manage the dependency. But it still adds unnecessary
+This makes it easier to manage the dependency. But it still causes unnecessary
duplication.
For more direct support, use one of the following:
@@ -479,9 +431,9 @@
### <a name="selects-with-or"></a>`selects.with_or`
The
-[with_or](https://github.com/bazelbuild/bazel-skylib/blob/master/docs/selects_doc.md#selectswith_or)
+[with_or](https://g3doc.corp.google.com/third_party/bazel_skylib/g3doc/selects_doc.md#selectswith-or)
macro in [Skylib](https://github.com/bazelbuild/bazel-skylib)'s
-[`selects`](https://github.com/bazelbuild/bazel-skylib/blob/master/docs/selects_doc.md)
+[`selects`](https://g3doc.corp.google.com/third_party/bazel_skylib/g3doc/selects_doc.md)
module supports `OR`ing conditions directly inside a `select`:
```python
@@ -536,21 +488,17 @@
)
```
-Unlike `selects.with_or`, different rules can `select` on `:config1_or_2`
-with different values.
+Unlike `selects.with_or`, different targets can share `:config1_or_2` across
+different attributes.
-Note that it's an error for multiple conditions to match unless one is a
-"specialization" of the other. See [select()](be/functions.html#select)
-documentation for details.
+It's an error for multiple conditions to match unless one is an unambiguous
+"specialization" of the others. See [here](#example) for details.
-## And chaining
+## AND chaining
-If you need a `select` path to match when multiple conditions match, use the
+If you need a `select` branch to match when multiple conditions match, use the
[Skylib](https://github.com/bazelbuild/bazel-skylib) macro
[config_setting_group](https://github.com/bazelbuild/bazel-skylib/blob/master/docs/selects_doc.md#selectsconfig_setting_group):
-
-```python
-load("@bazel_skylib//lib:selects.bzl", "selects")
```
```python
@@ -576,13 +524,13 @@
)
```
-Unlike OR chaining, existing `config_setting`s can't be `AND`ed together
-directly inside a `select`: you have to explicitly declare the
-`config_setting_group`.
+Unlike OR chaining, existing `config_setting`s can't be directly `AND`ed
+inside a `select`. You have to explicitly wrap them in a `config_setting_group`.
## Custom error messages
-By default, when no condition matches, the owning target fails with the error:
+By default, when no condition matches, the target the `select()` is attached to
+fails with the error:
```sh
ERROR: Configurable attribute "deps" doesn't match this configuration (would
@@ -592,7 +540,8 @@
//tools/cc_target_os:android
```
-This can be customized with [`no_match_error`](be/functions.html#select):
+This can be customized with the [`no_match_error`](be/functions.html#select)
+attribute:
```python
cc_library(
@@ -608,7 +557,7 @@
```
```sh
-$ bazel build //foo:my_lib
+$ bazel build //myapp:my_lib
ERROR: Configurable attribute "deps" doesn't match this configuration: Please
build with an Android or Windows toolchain
```
@@ -618,7 +567,7 @@
attributes. For example, given:
```python
-# myproject/BUILD
+# myapp/BUILD
some_rule(
name = "my_target",
@@ -630,7 +579,7 @@
```
```sh
-$ bazel build //myproject/my_target --define mode=foo
+$ bazel build //myapp/my_target --define mode=foo
```
Rule implementation code sees `ctx.attr.some_attr` as `[":foo"]`.
@@ -661,21 +610,28 @@
this.
## <a name="query"></a>Bazel query and cquery
-Bazel `query` operates over Bazel's [loading phase](
-guide.html#loading-phase). This means it doesn't know what command line
-flags will be applied to a target since those flags aren't evaluated until later
-in the build (during the [analysis phase](user-manual.html#analysis-phase)). So
-the [`query`](query.html) command can't accurately determine which path a
-configurable attribute will follow.
+Bazel [`query`](query-how-to.html) operates over Bazel's
+[loading phase](https://docs.bazel.build/versions/master/glossary.html#loading-phase).
+This means it doesn't know what command line flags a target uses since those
+flags aren't evaluated until later in the build (in the
+[analysis phase](https://docs.bazel.build/versions/master/glossary.html#analysis-phase)).
+So it can't determine which `select()` branches are chosen.
-[Bazel `cquery`](cquery.html) has the advantage of being able to parse build
-flags and operating post-analysis phase so it correctly resolves configurable
-attributes. It doesn't have full feature parity with query but supports most
-major functionality and is actively being worked on.
-Querying the following build file...
+Bazel [`cquery`](cquery.html) opeates after Bazel's analysis phase, so it has
+all this information and can accurately resolve `select()`s.
+
+Consider:
```python
-# myproject/BUILD
+load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
+```
+```python
+# myapp/BUILD
+
+string_flag(
+ name = "dog_type",
+ build_setting_default = "cat"
+)
cc_library(
name = "my_lib",
@@ -687,26 +643,30 @@
config_setting(
name = "long",
- values = {"define": "dog=dachshund"},
+ flag_values = {":dog_type": "dachshund"},
)
config_setting(
name = "short",
- values = {"define": "dog=pug"},
+ flag_values = {":dog_type": "pug"},
)
```
-...would return the following results.
+`query` overapproximtes `:my_lib`'s dependencies:
```sh
-$ bazel query 'deps(//myproject:my_lib)'
-//myproject:my_lib
-//myproject:foo_dep
-//myproject:bar_dep
+$ bazel query 'deps(//myapp:my_lib)'
+//myapp:my_lib
+//myapp:foo_dep
+//myapp:bar_dep
+```
-$ bazel cquery 'deps(//myproject:my_lib)' --define dog=pug
-//myproject:my_lib
-//myproject:bar_dep
+while `cquery` shows its exact dependencies:
+
+```sh
+$ bazel cquery 'deps(//myapp:my_lib)' --//myapp:dog_type=pug
+//myapp:my_lib
+//myapp:bar_dep
```
## FAQ
@@ -724,7 +684,7 @@
Define a rule and macro:
```python
-# myproject/defs.bzl
+# myapp/defs.bzl
# Rule implementation: when an attribute is read, all select()s have already
# been resolved. So it looks like a plain old attribute just like any other.
@@ -748,10 +708,10 @@
Instantiate the rule and macro:
```python
-# myproject/BUILD
+# myapp/BUILD
-load("//myproject:defs.bzl", "my_custom_bazel_rule")
-load("//myproject:defs.bzl", "my_custom_bazel_macro")
+load("//myapp:defs.bzl", "my_custom_bazel_rule")
+load("//myapp:defs.bzl", "my_custom_bazel_macro")
my_custom_bazel_rule(
name = "happy_rule",
@@ -778,25 +738,25 @@
Building fails because `sad_macro` can't process the `select()`:
```sh
-$ bazel build //myproject:all
-ERROR: /myworkspace/myproject/BUILD:17:1: Traceback
+$ bazel build //myapp:all
+ERROR: /myworkspace/myapp/BUILD:17:1: Traceback
(most recent call last):
-File "/myworkspace/myproject/BUILD", line 17
+File "/myworkspace/myapp/BUILD", line 17
my_custom_bazel_macro(name = "sad_macro", my_config_stri..."}))
-File "/myworkspace/myproject/defs.bzl", line 4, in
+File "/myworkspace/myapp/defs.bzl", line 4, in
my_custom_bazel_macro
my_config_string.upper()
type 'select' has no method upper().
-ERROR: error loading package 'myproject': Package 'myproject' contains errors.
+ERROR: error loading package 'myapp': Package 'myapp' contains errors.
```
Building succeeds when we comment out `sad_macro`:
```sh
# Comment out sad_macro so it doesn't mess up the build.
-$ bazel build //myproject:all
-DEBUG: /myworkspace/myproject/defs.bzl:5:3: My name is happy_macro with custom message: FIXED STRING.
-DEBUG: /myworkspace/myproject/hi.bzl:15:3: My name is happy_rule with custom message: FIRST STRING.
+$ bazel build //myapp:all
+DEBUG: /myworkspace/myapp/defs.bzl:5:3: My name is happy_macro with custom message: FIXED STRING.
+DEBUG: /myworkspace/myapp/hi.bzl:15:3: My name is happy_rule with custom message: FIRST STRING.
```
This is impossible to change because *by definition* macros are evaluated before
@@ -806,7 +766,7 @@
Macros can, however, pass `select()`s as opaque blobs to rules:
```python
-# myproject/defs.bzl
+# myapp/defs.bzl
def my_custom_bazel_macro(name, my_config_string):
print("Invoking macro " + name)
@@ -817,22 +777,22 @@
```
```sh
-$ bazel build //myproject:sad_macro_less_sad
-DEBUG: /myworkspace/myproject/defs.bzl:23:3: Invoking macro sad_macro_less_sad.
-DEBUG: /myworkspace/myproject/defs.bzl:15:3: My name is sad_macro_less_sad with custom message: FIRST STRING.
+$ bazel build //myapp:sad_macro_less_sad
+DEBUG: /myworkspace/myapp/defs.bzl:23:3: Invoking macro sad_macro_less_sad.
+DEBUG: /myworkspace/myapp/defs.bzl:15:3: My name is sad_macro_less_sad with custom message: FIRST STRING.
```
### <a name="boolean-select"></a>Why does select() always return true?
Because *macros* (but not rules) by definition
-[can't evaluate select(s)](#macros-select), any attempt to do so
+[can't evaluate `select()`s](#macros-select), any attempt to do so
usually produces an error:
```sh
-ERROR: /myworkspace/myproject/BUILD:17:1: Traceback
+ERROR: /myworkspace/myapp/BUILD:17:1: Traceback
(most recent call last):
-File "/myworkspace/myproject/BUILD", line 17
+File "/myworkspace/myapp/BUILD", line 17
my_custom_bazel_macro(name = "sad_macro", my_config_stri..."}))
-File "/myworkspace/myproject/defs.bzl", line 4, in
+File "/myworkspace/myapp/defs.bzl", line 4, in
my_custom_bazel_macro
my_config_string.upper()
type 'select' has no method upper().
@@ -842,12 +802,12 @@
vigilant with them:
```sh
-$ cat myproject/defs.bzl
+$ cat myapp/defs.bzl
def my_boolean_macro(boolval):
print("TRUE" if boolval else "FALSE")
-$ cat myproject/BUILD
-load("//myproject:defs.bzl", "my_boolean_macro")
+$ cat myapp/BUILD
+load("//myapp:defs.bzl", "my_boolean_macro")
my_boolean_macro(
boolval = select({
"//tools/target_cpu:x86": True,
@@ -855,10 +815,10 @@
}),
)
-$ bazel build //myproject:all --cpu=x86
-DEBUG: /myworkspace/myproject/defs.bzl:4:3: TRUE.
-$ bazel build //myproject:all --cpu=ppc
-DEBUG: /myworkspace/myproject/defs.bzl:4:3: TRUE.
+$ bazel build //myapp:all --cpu=x86
+DEBUG: /myworkspace/myapp/defs.bzl:4:3: TRUE.
+$ bazel build //mypro:all --cpu=ppc
+DEBUG: /myworkspace/myapp/defs.bzl:4:3: TRUE.
```
This happens because macros don't understand the contents of `select()`.
@@ -867,19 +827,16 @@
standards, all objects aside from a very small number of exceptions
automatically return true.
### <a name="inspectable-select"></a>Can I read select() like a dict?
-Fine. Macros [can't](#macros-select) evaluate select(s) because
-macros are evaluated before Bazel knows what the command line flags are.
+Macros [can't](#macros-select) evaluate select(s) because macros evaluate before
+Bazel knows what the build's command line parameters are. Can they at least read
+the `select()`'s dictionary to, for example, add a suffix to each value?
-Can macros at least read the `select()`'s dictionary, say, to add an extra
-suffix to each branch?
-
-Conceptually this is possible. But this isn't yet implemented and is not
-currently prioritized.
+Conceptually this is possible, but it isn't yet a Bazel feature.
What you *can* do today is prepare a straight dictionary, then feed it into a
`select()`:
```sh
-$ cat myproject/defs.bzl
+$ cat myapp/defs.bzl
def selecty_genrule(name, select_cmd):
for key in select_cmd.keys():
select_cmd[key] += " WITH SUFFIX"
@@ -891,7 +848,7 @@
+ " > $@"
)
-$ cat myproject/BUILD
+$ cat myapp/BUILD
selecty_genrule(
name = "selecty",
select_cmd = {
@@ -906,7 +863,7 @@
If you'd like to support both `select()` and native types, you can do this:
```sh
-$ cat myproject/defs.bzl
+$ cat myapp/defs.bzl
def selecty_genrule(name, select_cmd):
cmd_suffix = ""
if type(select_cmd) == "string":
@@ -941,7 +898,7 @@
```sh
$ cat WORKSPACE
-workspace(name = "myproject")
+workspace(name = "myapp")
bind(name = "openssl", actual = "//:ssl")
http_archive(name = "alternative", ...)
http_archive(name = "boringssl", ...)
@@ -968,29 +925,29 @@
located at `@alternative//:ssl`.
### Why doesn't my select() choose what I expect?
-If `//my:target` has a `select()` that doesn't choose the condition you expect,
-you can debug with [cquery](cquery.html) and `bazel config`:
+If `//myapp:foo` has a `select()` that doesn't choose the condition you expect,
+use [cquery](cquery.html) and `bazel config` to debug:
-If `//my:target` is what you're building, run:
+If `//myapp:foo` is the top-level target you're building, run:
```sh
-$ bazel cquery //my:target <desired build flags>
-//my:target (12e23b9a2b534a)
+$ bazel cquery //myapp:foo <desired build flags>
+//myapp:foo (12e23b9a2b534a)
```
-Alternatively, if you're building some other target `//foo` that depends on
-`//my:target` somewhere in its subgraph, run:
+If you're building some other target `//bar` that depends on
+//myapp:foo somewhere in its subgraph, run:
```sh
-$ bazel cquery 'somepath(//foo, //my:target)' <desired build flags>
-//foo:foo (3ag3193fee94a2)
-//foo:intermediate_dep (12e23b9a2b534a)
-//my:target (12e23b9a2b534a)
+$ bazel cquery 'somepath(//bar, //myapp:foo)' <desired build flags>
+//bar:bar (3ag3193fee94a2)
+//bar:intermediate_dep (12e23b9a2b534a)
+//myapp:foo (12e23b9a2b534a)
```
-The "`(12e23b9a2b534a)`" that appears next to `//my:target` is a *hash* of the
-configuration that resolves the `select()`. You can inspect its values with
-`bazel config`:
+The `(12e23b9a2b534a)` next to `//myapp:foo` is a *hash* of the
+configuration that resolves `//myapp:foo`'s `select()`. You can inspect its
+values with `bazel config`:
```sh
$ bazel config 12e23b9a2b534a
@@ -1007,8 +964,8 @@
...
```
-Then compare this output against the settings that match the `config_setting`s.
+Then compare this output against the settings expected by each `config_setting`.
-It's possible for `//my:target` to exist in multiple configurations in the same
-build. See the [cquery docs](cquery.html) for guidance on using `somepath` to
-get the right one.
+`//myapp:foo` may exist in different configurations in the same build. See the
+[cquery docs](cquery.html) for guidance on using `somepath` to get the right
+one.