Skip to content

Add documentation for modifiers #848

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions docs/concepts/modifiers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
id: modifiers
title: Configuration modifiers
---

Configuration modifiers (or just "modifiers" for short) are a feature
that lets users add ad-hoc [configuration
constraints](../rule_authors/configurations) to individual
directories, target definitions and individual `buck2` invocations.

## Adding modifiers to a project

To add support for modifiers in your project, simply call `set_cfg_constructor` in your root `PACKAGE` file.

See the [dedicated how-to](../users/how_tos/modifiers_setup) for more
information.

## Modifiers in `PACKAGE` files

Modifiers can be specified per-directory. In that case, they are used as
the default build configurations defined in that directory.

See the [dedicated how-to](../users/how_tos/modifiers_package) for more
information.

## Modifiers on targets

Modifiers can be added to individual targets. This can be used as an
alternative to the missing [per-target
transitions](../rule_authors/configurations#per-target-transition).

See the [dedicated how-to](../users/how_tos/modifiers_target) for more
information.

## Modifiers on the CLI

Custom modifiers can be specified on the CLI to build a target with a
specific build configuration. For example, this can be used to build a
target with a non-default compiler, or to run a test using a specific
sanitizer.

See the [dedicated how-to](../users/how_tos/modifiers_cli) for more
information.

## More information

Official documentation on modifiers is sparse at the moment, so you
might be interested in the following documents:

- [The original RFC](../rfcs/cfg-modifiers/modifiers.pdf)
- [The @ configuration CLI RFC](../rfcs/drafts/configuration-at-syntax)
4 changes: 1 addition & 3 deletions docs/users/how_tos/compilation_database.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
---
id: compilation_database
title: Compilation databases
title: Generate C++ compilation databases
---

# Generating compilation databases

You can generate compilation databases for consumption by tools such as clangd
and clang-tidy by running the following BXL script:

Expand Down
29 changes: 29 additions & 0 deletions docs/users/how_tos/modifiers_cli.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
id: modifiers_cli
title: Specify configuration modifiers from the CLI
---

Modifiers can be specified on the command line to override the values
set in `PACKAGE` files or on targets directly. To do so, pass constraint
targets via the `-m`/`--modifiers` flag:

```sh
# Assuming that `//constraints:BUCK` contains the appropriate constraint
# definitions.
buck build :my_target -m //constraints:debug
buck build :my_target -m //constraints:release
```

Aliases can be used as shorthands (see the [setup how-to](./modifiers_setup) for more
information):

```sh
buck build :my_target -m debug
```

The following shorthand syntax is planned, but is currently
unimplemented:

```sh
buck2 build :my_target?debug
```
27 changes: 27 additions & 0 deletions docs/users/how_tos/modifiers_package.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
id: package_modifiers
title: Add configuration modifiers to entire directories
---

Modifiers can be set in [`PACKAGE` files](../../rule_authors/package)
using the prelude's `set_cfg_modifiers`. In this case they will be
applied to all targets affected by that `PACKAGE` file.

For example, assuming that `root//build:debug` is an existing constraint
value and [modifiers have been setup](./modifiers_setup), the following
will apply it by default to all targets defined in that `PACKAGE`'s
directory:

```python
load("@prelude//cfg/modifier/set_cfg_modifiers.bzl", "set_cfg_modifiers")

set_cfg_modifiers([
"root//build:debug",
])
```

`set_cfg_modifiers` takes 2 arguments:

- `cfg_modifiers`, a list of modifiers to set.
- `extra_cfg_modifiers_per_rule`, a dictionary mapping rule names to
lists of modifiers that should be applied only for that rule.
93 changes: 93 additions & 0 deletions docs/users/how_tos/modifiers_setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
---
id: modifiers_setup
title: Setup configuration modifiers
---

To start using configuration modifiers, all you need to do is call
`set_cfg_constructor` from a `PACKAGE` file.

Start by adding the following to your root `PACKAGE` file:

```python
load("@prelude//cfg/modifier:cfg_constructor.bzl", "cfg_constructor_post_constraint_analysis", "cfg_constructor_pre_constraint_analysis")
load("@prelude//cfg/modifier:common.bzl", "MODIFIER_METADATA_KEY")

native.set_cfg_constructor(
stage0 = cfg_constructor_pre_constraint_analysis,
stage1 = cfg_constructor_post_constraint_analysis,
key = MODIFIER_METADATA_KEY,
aliases = struct(),
extra_data = struct(),
)
```

`set_cfg_constructor` is a Buck2 builtin used to setup configuration
modifiers. It supports a few configuration points:

- `stage0` and `stage1` are used to resolve modifiers from the [target
platform](../../rule_authors/configurations) (which is now considered
deprecated) and the modifiers set in the nearest `PACKAGE` file, on
the target, and on the CLI. You _can_ override those, but the
functions provided by the prelude basically do what you would expect.
- `key` is used to fetch modifiers defined on `metadata` attributes. It
is only supported for legacy reasons, so you should not have to worry
about it.
- `aliases` contains modifier aliases to modifier modifiers. Populate it
to make aliases available from the CLI.
- `extra_data` is used for logging/validation by Meta's internal
modifier implementation.

As you can see, `aliases` is the the only value that one would commonly
want to configure, and it might make sense to call `set_cfg_constructor`
with different `aliases` values in different `PACKAGE` files, if some
aliases only make sense in specific projects (e.g. because they have
custom configuration constraints).

The following is an example of exposing custom aliases for build
constraints. We create a `build_mode` constraint with 2 values (`debug`
and `release`), which would most likely be `select`ed in a toolchain
definition.

`BUCK`:

```python
constraint_setting(name = "build_mode")

constraint_value(
name = "debug",
constraint_setting = ":build_mode",
)

constraint_value(
name = "release",
constraint_setting = ":build_mode",
)
```

`PACKAGE`:

```python

load("@prelude//cfg/modifier:cfg_constructor.bzl", "cfg_constructor_post_constraint_analysis", "cfg_constructor_pre_constraint_analysis")
load("@prelude//cfg/modifier:common.bzl", "MODIFIER_METADATA_KEY")

native.set_cfg_constructor(
stage0 = cfg_constructor_pre_constraint_analysis,
stage1 = cfg_constructor_post_constraint_analysis,
key = MODIFIER_METADATA_KEY,
aliases = struct(
debug = "//build:debug",
release = "//build:release",
),
extra_data = struct(),
)
```

Now, assuming that `:my_target` exists and is affected by the
`build_mode` constraint, we can build it in debug and release mode
from the command line using the `-m`/`--modifier` flag:

```sh
buck2 build :my_target -m debug
buck2 build :my_target -m release
```
55 changes: 55 additions & 0 deletions docs/users/how_tos/modifiers_target.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
id: modifiers_target
title: Add configuration modifiers to a specific target
---

Modifiers can be added to individual targets via the `modifiers`
attribute which is exposed by all rules (this is handled by Buck2
itself, so rule authors do not have to add it themselves).

For example, lets assume that we have a `release_package` rule that
references various `dep`s and packages them, and that our [`PACKAGE`
file defaults our build mode to debug](./modifiers_package). We could
add the `release` modifier to our artifact target to build all
dependencies in release mode rather than debug:

```python
release_package(
name = "my_package",
binaries = [
":my_cxx_bin",
":my_rust_bin",
],
modifiers = [
"//constraints:debug",
],
)
```

As another example, imagine that we have a constraint that controls
whether we use real or simulated IO:

```python
constraint_setting(name = "io_mode")

constraint_value(
name = "real_io",
constraint_setting = ":io_mode",
)

constraint_value(
name = "simulated_io",
constraint_setting = ":io_mode",
)
```

The default IO mode would be `real_io`, but we would like to override it
for a specific test:

```python
go_test(
name = "simulated_io_test",
srcs = ["test.go"],
modifiers = ["//constraints:simulated_io"],
)
```
12 changes: 12 additions & 0 deletions website/sidebars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export const sidebars: SidebarsConfig = {
'concepts/isolation_dir',
'concepts/buckconfig',
'concepts/configurations',
'concepts/modifiers',
'concepts/glossary',
],
},
Expand All @@ -82,6 +83,17 @@ export const sidebars: SidebarsConfig = {
{ type: 'autogenerated' as const, dirName: 'users/commands' },
],
},
{
type: 'category' as const,
label: 'How-tos',
items: [
'users/how_tos/modifiers_setup',
'users/how_tos/modifiers_package',
'users/how_tos/modifiers_target',
'users/how_tos/modifiers_cli',
'users/how_tos/compilation_database',
],
},
'users/cheat_sheet',
{
type: 'category' as const,
Expand Down
Loading