@@ -3,14 +3,318 @@ id: configurations
33title : Configurations
44---
55
6- For rule authors see also: [ Configurations] ( ../rule_authors/configurations.md )
7-
8- When building a target, buck always builds it in a particular "configuration."
9- The configuration typically includes information like the target os, target
10- arch, sanitizers, opt level, etc. One way to understand the effect that a
11- configuration has is via the ` cquery ` and ` uquery ` commands. The cquery command
12- will compute the appropriate configuration for a target and display a version of
13- that target's attributes with the configuration applied. The ` uquery ` command
6+ Build configurations are how Buck models building the same target in
7+ different ways. This can include (but is not limited to):
8+
9+ - Target architecture
10+ - Target OS
11+ - Optimization level/build mode
12+ - Compiler type/version
13+ - Language version (e.g. C++ standard version or Rust edition)
14+ - Sanitizers
15+ - Passing arbitrary flags to build tools
16+
17+ When building a target, Buck always builds it in a particular
18+ configuration. Build configurations are also sometimes called
19+ "platforms". While technically separate, those two concepts are almost
20+ identical.
21+
22+ Build configurations are [ composed] ( ../api/build/Configuration ) of a set
23+ of constraints and a set of values.
24+
25+ ## Configuration constraints
26+
27+ Configuration constraints are enum-like constructs. Here is an example
28+ definitions:
29+
30+ ``` python
31+ # //config/BUCK
32+
33+ constraint(
34+ name = " build_mode" ,
35+ default = " debug" ,
36+ values = [
37+ " debug" ,
38+ " release" ,
39+ ],
40+ )
41+ ```
42+
43+ Constraint values can also be grouped into larger logical pieces.
44+ Assuming that we have also defined other constraints:
45+
46+ ``` python
47+ config_setting(
48+ name = " dev" ,
49+ constraint_values = [
50+ " :build_mode[debug]" ,
51+ " :compiler[clang_21]" ,
52+ " :asan[enabled]" ,
53+ ],
54+ )
55+ ```
56+
57+ Note that the prelude defines some generic constraints, e.g. under
58+ ` prelude//os: ` and ` prelude//cpu: ` , which you might want to consider
59+ using for interoperability.
60+
61+ Once defined, this constraint can used in various ways, such as:
62+
63+ - Being passed on the command line to run a build in debug or release
64+ mode.
65+ - Being "selected on" so that building in debug vs release mode has
66+ different effects.
67+ - Being used for constraining compatibility (e.g. "this target can only
68+ be built in release mode" for a benchmark).
69+ - Being used to "transition" part of the build (e.g. "this target and
70+ its dependencies are always built in release mode, regardless of the
71+ dependent")
72+
73+ ## Configuration values
74+
75+ Configurations can also include values taken from the buckconfig:
76+
77+ ``` python
78+ config_setting(
79+ name = " fastmode_enabled" ,
80+ values = {
81+ " build.fastmode" : " true" ,
82+ },
83+ )
84+ ```
85+
86+ This setting will be satisfied if the associated buckconfig matches,
87+ i.e. if the user passes ` build.fastmode=true ` via the ` -c ` /` --config `
88+ CLI flag, or if the following is set in the cell's ` .buckconfig ` file:
89+
90+ ``` ini
91+ [build]
92+ fastmode = true
93+ ```
94+
95+ ## Using configuration: ` select() `
96+
97+ Configurations can be used to change the build behavior based on which
98+ value is currently active:
99+
100+ ``` cpp
101+ cxx_binary (
102+ name = "bin",
103+ srcs = ["main.cpp"],
104+ compiler_flags = select({
105+ "//config:build_mode[debug]": ["-O0", "-g"],
106+ "//config:build_mode[release]": ["-O3"],
107+ }),
108+ )
109+ ```
110+
111+ The above example is simplistic, and build mode compiler flags would
112+ typically be set at the toolchain level, rather than per-target, but it
113+ shows how build constraints can be used to change a build's behavior.
114+
115+ `select()` can appear in almost all attributes, and it can be composed
116+ with other collection types. For example, the following is valid:
117+
118+ ```python
119+ cxx_library(
120+ name = "lib",
121+ exported_deps = [
122+ "//common:lib",
123+ ] + select({
124+ "//config:os[linux]": ["//linux:lib"],
125+ "//config:os[mac]": ["//mac:lib"],
126+ # `DEFAULT` is a special value that is always available.
127+ # In this case, we do not link against any extra libraries.
128+ "DEFAULT": [],
129+ }),
130+ )
131+ ```
132+
133+ If multiple conditions of the `select()` match, then the select will be resolved
134+ to the "most refined" of the conditions that match. A set of constraints (as in
135+ a ` config_setting ` ) is said to "refine" another if it is a superset of that
136+ other's constraints. The "most refined" of a set is then the condition that
137+ refines all the others. If there is no "most refined" condition of the matching
138+ ones, it is an error.
139+
140+ Note that ` select() ` is resolved during configuration. This happens
141+ after the evaluation of the BUCK file is completed, and so Starlark code
142+ run during BUCK file evaluation does not have access to the resolved
143+ value. This can make it difficult to have macros that do extensive
144+ modification or inspection of attributes (which should be done in rules
145+ instead). However, some functions
146+ ([ ` select_map ` ] ( ../api/build/#select_map ) and
147+ [ ` select_test ` ] ( ../api/build/#select_map ) ) allow performing
148+ limited operations on these objects.
149+
150+ ## Using configuration: compatibility
151+
152+ Constraints can also be used to limit target compatibility. For example,
153+ assuming that our repo supports C++20, C++23 and C++26:
154+
155+ ``` python
156+ # Reflection is only available starting with C++26, so we require it.
157+ cxx_library(
158+ name = " uses_reflection" ,
159+ exported_headers = [" foo.h" ],
160+ target_compatible_with = [" //:cxx_standard[26]" ]
161+ )
162+
163+ # Deducing this is not available in C++20, so we make it incompatible.
164+ cxx_library(
165+ name = " uses_deducing_this" ,
166+ exported_headers = [" foo.h" ],
167+ target_compatible_with = select({
168+ " //:cxx_standard[20]" : [" prelude//:none" ],
169+ " DEFAULT" : [],
170+ })
171+ )
172+ ```
173+
174+ Target platform compatibility is transitive, all _ dependents_ of an incompatible
175+ target are incompatible. In other words, a node is compatible if and only if the
176+ node itself and all of its transitive dependencies are compatible.
177+
178+ When trying to build a target with the wrong configuration (we will see
179+ how shortly), the build will just fail (unless
180+ ` --skip-incompatible-targets ` is passed).
181+
182+ When trying to build a set of targets using a
183+ [ pattern] ( ./target_pattern ) ) (e.g. ` //some/package: ` or
184+ ` //some/package/... ` ), Buck will simply ignore incompatible targets.
185+
186+ See the [ reference
187+ documentation] ( ../api/build/Select/#target_compatible_with ) for more
188+ information.
189+
190+ ## Changing the build configuration
191+
192+ The build configuration is determined as follows:
193+
194+ 1 . A base platform is resolved:
195+ 1 . If the user passed ` --target-platforms ` via the CLI, use that.
196+ 2 . Else, if the target being built has a ` default_target_platform `
197+ attribute, use that. Note that since it is used to determine the
198+ configuration, it is one of the few attributes that are not
199+ ` select ` able.
200+ 3 . Else, use the default (` parser.target_platform_detector_spec ` in
201+ the ` .buckconfig ` file).
202+ 2 . [ Configuration modifiers] ( ./modifiers.md ) are applied. Those are a
203+ lightweight way to add ad-hoc constraints to an existing
204+ configuration (e.g. "build with the default configuration/platform,
205+ except with a different compiler").
206+ 3 . [ Configuration transitions] ( ./transitions.md ) are applied. Those
207+ allow changing the configuration of parts of the build graph based on
208+ arbitrary logic (e.g. "this part of the build graph should always be
209+ built in release mode").
210+
211+ The target platform resolution is not applied to all nodes in the graph.
212+ Once the top-level nodes have been configured via the target platform
213+ resolution, the configuration is propagated to dependencies (possibly
214+ altered by transitions).
215+
216+ For example:
217+
218+ ``` sh
219+ # Build this target with the default configuration.
220+ buck2 build :my_target
221+ # Build it with an entirely different configuration.
222+ buck2 build :my_target --target-platforms //my/other:platform
223+ # Build it with the default configuration, plus release mode.
224+ buck2 build :my_target? release
225+ ```
226+
227+ See the [ configurations for author] ( ../rule_authors/configurations.md )
228+ page for information on how to define a platform.
229+
230+ Other example:
231+
232+ ``` python
233+ java_binary(
234+ name = " cats" ,
235+ default_target_platform = " //platforms:windows-arm64-dev" ,
236+ deps = [" //libs:foo" ],
237+ )
238+
239+ java_binary(
240+ name = " dogs" ,
241+ default_target_platform = " //platforms:mac-x86-dev" ,
242+ deps = [" //libs:foo" ],
243+ )
244+
245+ java_library(
246+ name = " foo" ,
247+ deps = [
248+ " //libs:common" ,
249+ ] + select({
250+ " //constraints:x86" : [" //libs:x86" ],
251+ " //constraints:mac-arm64" : [" //libs:mac-arm64" ],
252+ " //constraints:windows-arm64" : [" //libs:win-arm64" ],
253+ " DEFAULT" : [" //libs:generic" ],
254+ })
255+ ```
256+
257+ When running `buck2 build // binaries:cats // binaries:dogs` , the
258+ `// binaries:cats` binary will be built in the `// platforms:windows- arm64- dev`
259+ configuration and the `// binaries:dogs` binary will be built in the
260+ `// platforms:mac- x86- dev` configuration.
261+
262+ Each of those binaries depend on `// libs:foo` , but they will get
263+ different versions of it as the binaries' configurations will each be
264+ passed down to their dependencies. For `// binaries:cats` , its resolved
265+ dependencies will include `// libs:win- arm64` and for `// binaries:dogs` ,
266+ it would contain `// libs:x86` .
267+
268+ Note that `// libs:common` will be built twice, once for each
269+ configuration.
270+
271+ When running `buck2 build // binaries:cats // binaries:dogs -- target- platforms
272+ // platforms:mac- x86- opt`, both ` // binaries:cats` and ` // binaries:dogs` will
273+ be built in the `// platforms:mac- x86- opt` configuration, use the same
274+ dependencies, which would only be built once.
275+
276+ # # Configurations and output paths
277+
278+ Since a target may appear within a build in multiple different configurations,
279+ output paths cannot be derived based on just targets (as multiple actions would
280+ map to the same outputs). For this reason, the target and the configuration are
281+ encoded into output paths. The configuration is currently represented as a hash
282+ of its values (a " hashed buck-out" ).
283+
284+ # # Target platform vs execution platform
285+
286+ Buck distinguishes two kinds of targets: " regular" ones, and the ones
287+ used as build tools. The rationale is that it is common to want
288+ different build configurations for those. For example, it is typical to
289+ want build tools (e.g. a compiler) to be built/ run in release mode, even
290+ when building debug targets.
291+
292+ For this reason, Buck requires both _target_ platforms and _execution_
293+ platforms to be defined. The execution platforms are specified via the
294+ `build.execution_platforms` value in `.buckconfig` .
295+
296+ # # Platform resolution
297+
298+ # # Queries
299+
300+ # ## Getting configuration constraints from its hash
301+
302+ Build configurations are uniquely identified by their hash , which is not
303+ human friendly.
304+
305+ To determine what constraints are part of a configuration, run `buck2
306+ cquery // ... ` sot that Buck will discover all existing configurations,
307+ then run `buck2 audit configurations` .
308+
309+ This will list all available configurations and print their composing
310+ contraints.
311+
312+ # ## `cquery` and `uquery`
313+
314+ One way to understand the effect that a configuration has is via the
315+ `cquery` and `uquery` commands. The `cquery` command will compute the
316+ appropriate configuration for a target and display a version of that
317+ target' s attributes with the configuration applied. The `uquery` command
14318will not apply a configuration.
15319
16320Here is a heavily trimmed version of the outputs of invoking `uquery` and
@@ -89,3 +393,16 @@ while the `nix` dependency is needed only for Linux. In `cquery` that
89393distinction has been resolved; because the target has been configured for Linux,
90394the `nix` dependency is present and indistinguishable from any other, while the
91395`common- path` dependency is gone.
396+
397+ # # Execution groups
398+
399+ Execution groups are a future feature that will allow a rule to perform
400+ execution platform resolution multiple times and then specify in which of the
401+ resolved platforms each action runs in .
402+
403+ # # See also
404+
405+ - [Configuration modifiers](./ modifiers.md)
406+ - [Configuration transitions](./ transitions.md)
407+ - [Configurations for rule authors](../ rule_authors/ configurations.md)
408+ - [Configuration transitions for rule authors](../ rule_authors/ configuration_transitions.md)
0 commit comments