select() Awareness
extraselect() is the first bit of BUILD-file syntax that looks like real conditional logic. In Level 0, the right mental model is intentionally small: this attribute depends on the build configuration, and Bazel will choose one value later. It is not a top-level if statement, and it does not turn the BUILD file into a script.1,2
cc_binary(
name = "mybinary",
deps = select({
":arm_build": [":arm_lib"],
"//conditions:default": [":generic_lib"],
}),
)
config_setting(
name = "arm_build",
values = {"cpu": "arm"},
)
When you see syntax like this, read the whole attribute as "Bazel will substitute one branch here for the active configuration." The keys are labels naming config_setting or constraint_value targets, and //conditions:default is the fallback when nothing else matches.2,3 In other words, select() does not create a second control-flow language inside BUILD files. It gives one attribute a configuration-dependent value.
Why This Still Fits A Declarative BUILD File
BUILD files still forbid top-level if and for statements, even though they allow limited expressions such as list comprehensions and if expressions.1 select() fits that design because it lives inside an attribute value. It describes alternatives in the graph instead of executing a branch while the file is being loaded.1,2
That is the useful connection to 0.3.3 Attributes & Semantic Roles. deps, srcs, or cmd still mean the same thing they meant before. select() only says that the value of that attribute varies by configuration.2 So a line like deps = select({...}) is still a declaration: "this target's dependencies depend on which build configuration is active."
What You Need To Recognize For Now
At this stage, you do not need to learn the full configuration system. The practical reading skill is simpler:
- spot which attribute is wrapped in
select() - scan the named conditions
- look for
//conditions:default - treat the chosen branch as "resolved later"
The deeper questions come later: which flags make a config_setting match, how platforms relate to constraint_value, why macros can pass select() through but cannot inspect the chosen branch themselves, and which query tools can show the resolved result.2 Those topics belong when configuration becomes explicit in 3.2 Project Configuration and, more specifically, when configurable attributes return in 3.3.1 Configurable Attributes (select()).
For Level 0, select() is mostly a recognition pattern. When you meet it in a BUILD file, read it as "this attribute has configuration-dependent values." Do not try to mentally execute the branches like ordinary program flow. Just identify the attribute, note the fallback, and keep reading.
1.Where does select() appear in a BUILD file?
2.What does //conditions:default mean in a select()?
3.Does select() make a BUILD file imperative (like an if/else script)?
Footnotes
-
BUILD files — BUILD-file restrictions, sequential declaration model, and the distinction between allowed expressions and forbidden top-level control flow ↩1 ↩2 ↩3
-
Configurable Build Attributes —
select()as a configurable attribute placeholder,config_settingconditions,//conditions:default, and the loading-versus-analysis split behind later resolution ↩1 ↩2 ↩3 ↩4 ↩5 -
BUILD globals reference —
select()parameter contract: condition keys areconfig_settingorconstraint_valuelabels, with optionalno_match_error↩