-
-
Notifications
You must be signed in to change notification settings - Fork 549
Intro examples for auto-configured builds / PROJECT.scl #635
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
Merged
gregestren
merged 10 commits into
bazelbuild:main
from
gregestren:auto-configured-builds
Oct 17, 2025
+507
−1
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
0453c27
Intro examples for auto-configured builds / PROJECT.scl
gregestren 14154a8
Formatting fixes.
gregestren 23f0a1e
More formatting fixes.
gregestren 78ed98e
Respond to review comments.
gregestren 2e5a22c
Further emphasize Bazel 9.0 need.
gregestren b75e8fa
Further wrap code blocks.
gregestren 4bbf525
Update command.
gregestren 17bcdc3
More README tweaks.
gregestren 7df6812
Exclude from CI
gregestren 9ea0408
Typo fix.
gregestren File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| platform( | ||
| name = "myplatform", | ||
| constraint_values = [ | ||
| "@platforms//os:linux", | ||
| "@platforms//cpu:arm", | ||
| ], | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| bazel_dep(name = "platforms", version = "1.0.0") | ||
| bazel_dep(name = "bazel_skylib", version = "1.8.2") | ||
|
|
||
| local_repository = use_repo_rule("@bazel_tools//tools/build_defs/repo:local.bzl", "local_repository") | ||
| local_repository(name = "custom_flags", path = "custom_flags_impl") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,178 @@ | ||
| ## Auto-configured builds examples | ||
| **Requirements: Bazel 9.0 or newer.** | ||
|
|
||
| *Auto-configured builds* is a Bazel 9.0+ feature that lets project owners declare which build flags should apply to their project's targets. | ||
|
|
||
| This makes it possible to write | ||
|
|
||
| $ bazel test //foo/... | ||
|
|
||
| and bazel automatically adds whatever flags are appropriate for `foo`'s builds. | ||
|
|
||
| This is similar to [bazelrc](https://bazel.build/run/bazelrc) with the crucial difference that bazelrc files are *user-registered*, not *project-registered*. That means `bazelrc`-added flags depend on who does the build and which `bazelrcs` they've registered, not which targets they're building. | ||
|
|
||
| The features described here make it easier for *anyone* to write `$ bazel test //foo/...` - a project dev, external contributor, library maintainer, IDE, AI agent, or CI system - and consistently get the same results with the same flags regardless of how they've set up their workspace or if they've ever built the project before. Project owners can then ensure everyone builds with correct, project-approved flags. | ||
|
|
||
| More info at https://github.com/bazelbuild/bazel/issues/24839. | ||
|
|
||
| ### `PROJECT.scl` | ||
| Flag settings are declared in a file called `PROJECT.scl`. This lives in your source repository next to your `BUILD` files. | ||
|
|
||
| `$ bazel test //foo/bar/baz:all` looks for a `PROJECT.scl` in `foo/bar/baz/` to find the project's flag settings. If that file doesn't exist, it looks in `foo/bar/`, then `foo/`, and so on until it either finds a match or determines the project has no flag settings. | ||
gregestren marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| This also applies to `bazel build` and `bazel cquery`. | ||
|
|
||
| ### Project-wide settings with warnings for unexpected flags | ||
| [warn](warn) is an example that sets two sets of flags for a project. The first set, `default_config`, triggers by default. The second, `debug_config`, can be set with `--scl_config=debug_config`. If the user sets any other flags, bazel emits a warning that the build is non-canonical. | ||
|
|
||
| *Default flags:* | ||
| ```sh | ||
| $ bazel build //warn:all | ||
| INFO: Reading project settings from //warn:PROJECT.scl. | ||
| INFO: Applying flags from the config 'default_config' defined in //warn:PROJECT.scl: [--platforms=//:myplatform, | ||
| --compilation_mode=opt, --@custom_flags//:project_flag="custom flag value"] | ||
| INFO: Found 2 targets... | ||
| INFO: Build completed successfully, 3 total actions | ||
| ``` | ||
|
|
||
| *Non-default supported flags:* | ||
| ```sh | ||
| $ bazel build //warn:all --scl_config=debug_config | ||
| INFO: Reading project settings from //warn:PROJECT.scl. | ||
| INFO: Applying flags from the config 'debug_config' defined in //warn:PROJECT.scl: [--platforms=//:myplatform, | ||
| --compilation_mode=dbg, --@custom_flags//:project_flag="debug value"] | ||
| INFO: Found 2 targets... | ||
| INFO: Build completed successfully, 3 total actions | ||
| ``` | ||
|
|
||
| *Unexpected flags:* | ||
| ```sh | ||
| $ bazel build //warn:all --copt=abc | ||
| INFO: Reading project settings from //warn:PROJECT.scl. | ||
| WARNING: This build uses a project file (//warn:PROJECT.scl), but also sets output-affecting flags in the command | ||
| line or user bazelrc: ['--copt=abc']. Please consider removing these flags. | ||
| INFO: Applying flags from the config 'default_config' defined in //warn:PROJECT.scl: [--platforms=//:myplatform, | ||
| --compilation_mode=opt, --@custom_flags//:project_flag="custom flag value" | ||
| INFO: Found 2 targets... | ||
| INFO: Build completed successfully, 3 total actions | ||
| ``` | ||
|
|
||
| ### Project-wide settings with incompatible flag checks | ||
| [compatible](compatible) is an example that sets two sets of flags for a project. It lets the user set other, unrelated flags with a warning but fails the build if the user sets contradictory flags. | ||
|
|
||
| *Default flags:* | ||
| ```sh | ||
| $ bazel build //compatible:all | ||
| INFO: Reading project settings from //compatible:PROJECT.scl. | ||
| INFO: Applying flags from the config 'default_config' defined in //compatible:PROJECT.scl: | ||
| [--platforms=//:myplatform, --compilation_mode=opt, --@custom_flags//:project_flag="custom flag value"] | ||
| INFO: Found 2 targets... | ||
| INFO: Build completed successfully, 3 total actions | ||
| ``` | ||
|
|
||
| *Unexpected non-conflicting flag:* | ||
| ```sh | ||
| $ bazel build //compatible:all --copt=abc | ||
| INFO: Reading project settings from //compatible:PROJECT.scl. | ||
| WARNING: This build uses a project file (//compatible:PROJECT.scl), but also sets output-affecting flags in | ||
| the command line or user bazelrc: ['--copt=abc']. Please consider removing these flags. | ||
| INFO: Applying flags from the config 'default_config' defined in //compatible:PROJECT.scl: | ||
| [--platforms=//:myplatform, --compilation_mode=opt, --@custom_flags//:project_flag="custom flag value"] | ||
| INFO: Build completed successfully, 3 total actions | ||
| ``` | ||
|
|
||
| *Unexpected conflicting flag:* | ||
| ```sh | ||
| $ bazel build //compatible:all --compilation_mode=fastbuild | ||
| INFO: Reading project settings from //compatible:PROJECT.scl. | ||
| ERROR: Cannot parse options: This build uses a project file (//compatible:PROJECT.scl) that does not allow | ||
| conflicting flags in the command line or user bazelrc. Found ['--compilation_mode=fastbuild']. Please remove | ||
| these flags or disable project file resolution via --noenforce_project_configs. | ||
| ERROR: Build did NOT complete successfully | ||
| ``` | ||
|
|
||
| ### Project-wide settings with strict checks | ||
| [strict](strict) is an example that sets two sets of flags for a project. It fails the build if the user sets any flags to any values different than the project settings. This is the strictest form of flag checking. It ensures all builds use pre-approved, canonical flags. | ||
|
|
||
| *Default flags:* | ||
| ```sh | ||
| $ bazel build //strict:all | ||
| INFO: Reading project settings from //strict:PROJECT.scl. | ||
| INFO: Applying flags from the config 'default_config' defined in //strict:PROJECT.scl: [--platforms=//:myplatform, | ||
| --compilation_mode=opt, --@custom_flags//:project_flag="custom flag value"] | ||
| INFO: Found 2 targets... | ||
| INFO: Build completed successfully, 3 total actions | ||
| ``` | ||
|
|
||
| *Unexpected non-conflicting flag:* | ||
| ```sh | ||
| $ bazel build //strict:all --copt=abc | ||
| INFO: Reading project settings from //strict:PROJECT.scl. | ||
| ERROR: Cannot parse options: This build uses a project file (//strict:PROJECT.scl) that does not allow | ||
| output-affeccting flags in the command line or user bazelrc. Found ['--copt=abc']. Please remove these flags or | ||
| disable project file resolution via --noenforce_project_configs. | ||
| ERROR: Build did NOT complete successfully | ||
| ``` | ||
|
|
||
| ### Per-target flag settings | ||
| [target_specific](target_specific) sets different default flags for different targets. This example applies the [warn](warn) enforcement policy. | ||
|
|
||
| *`//target_specific:one`:* | ||
| ```sh | ||
| $ bazel build //target_specific:one | ||
| INFO: Reading project settings from //target_specific:PROJECT.scl. | ||
| INFO: Applying flags from the config 'default_config_for_target_one' defined in //target_specific:PROJECT.scl: | ||
| [--platforms=//:myplatform, --@custom_flags//:project_flag="settings for target one"] | ||
| INFO: Found 1 target... | ||
| INFO: Build completed successfully, 1 total action | ||
| ``` | ||
|
|
||
| *`//target_specific:two`:* | ||
| ```sh | ||
| $ bazel build //target_specific:two | ||
| INFO: Reading project settings from //target_specific:PROJECT.scl. | ||
| INFO: Applying flags from the config 'default_config_for_target_two' defined in //target_specific:PROJECT.scl: | ||
| [--platforms=//:myplatform, --@custom_flags//:project_flag="settings for target two"] | ||
| INFO: Found 1 target... | ||
| INFO: Build completed successfully, 1 total action | ||
| ``` | ||
|
|
||
| **Note:** `$ bazel build //target_specific:all` fails because no common set of flags applies to both targets. You can resolve this either by explicitly setting `--scl_config` or disabling project flags with `--noenforce_project_configs`. Comment on https://github.com/bazelbuild/bazel/issues/24839 if you're interested in more automatic behavior. | ||
|
|
||
| ### Aliases | ||
| [alias](alias) is a project with different disjoint directories. You can refer them all to the same souce of flag truth with `PROJECT.scl` aliases. | ||
|
|
||
| *Main project definition in `alias/project_main`:* | ||
| ```sh | ||
| $ bazel build //alias/project_main:main | ||
| INFO: Reading project settings from //alias/project_main:PROJECT.scl. | ||
| INFO: Applying flags from the config 'default_config' defined in //alias/project_main:PROJECT.scl: | ||
| [--platforms=//:myplatform, --compilation_mode=opt, --@custom_flags//:project_flag="custom flag value"] | ||
| INFO: Found 1 target... | ||
| INFO: Build completed successfully, 1 total action | ||
| ``` | ||
|
|
||
| *`alias/project_lib` is a different directory but part of the same project:* | ||
| ```sh | ||
| $ cat alias/project_lib/PROJECT.scl | ||
| project = { | ||
| "actual": "//alias/project_main:PROJECT.scl", | ||
| } | ||
| ``` | ||
|
|
||
| ```sh | ||
| $ bazel build //alias/project_lib:lib | ||
| INFO: Reading project settings from //alias/project_main:PROJECT.scl. | ||
| INFO: Applying flags from the config 'default_config' defined in //alias/project_main:PROJECT.scl: | ||
| [--platforms=//:myplatform, --compilation_mode=opt, --@custom_flags//:project_flag="custom flag value"] | ||
| INFO: Found 1 target... | ||
| INFO: Build completed successfully, 1 total action | ||
| ``` | ||
|
|
||
| **Note:** In this example both directories have the same parent directory. You can alternatively move the project definition to `alias/PROJECT.scl` for the same effect. This also requires an `alias/BUILD` file, which may be empty. | ||
|
|
||
| ### Questions? | ||
| This is an evolving feature. These examples don't cover everything. | ||
|
|
||
| Comment at https://github.com/bazelbuild/bazel/issues/24839 with more questions and requests. | ||
|
|
||
6 changes: 6 additions & 0 deletions
6
configurations/auto_configured_builds/alias/project_lib/BUILD
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| genrule( | ||
| name = "lib", | ||
| srcs = [], | ||
| outs = ["lib.out"], | ||
| cmd = "echo lib > $@", | ||
| ) |
5 changes: 5 additions & 0 deletions
5
configurations/auto_configured_builds/alias/project_lib/PROJECT.scl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # This package is part of the //alias/project_main project. Use that | ||
| # package's PROJECT.scl. | ||
| project = { | ||
| "actual": "//alias/project_main:PROJECT.scl", | ||
| } |
6 changes: 6 additions & 0 deletions
6
configurations/auto_configured_builds/alias/project_main/BUILD
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| genrule( | ||
| name = "main", | ||
| srcs = [], | ||
| outs = ["main.out"], | ||
| cmd = "echo main > $@", | ||
| ) |
35 changes: 35 additions & 0 deletions
35
configurations/auto_configured_builds/alias/project_main/PROJECT.scl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| # A project file that automatically sets build flags for all targets in the | ||
| # project and warns if the user sets any other flags. | ||
| load( | ||
| "@bazel_tools//src/main/protobuf/project:project_proto.scl", | ||
| "buildable_unit_pb2", | ||
| "project_pb2", | ||
| ) | ||
|
|
||
| project = project_pb2.Project.create( | ||
| # "WARN" means bazel emits a warning if the user sets flags to different | ||
| # values than they're set here. This can be used as a signal to determine if | ||
| # the project is built canonically. | ||
| # | ||
| # "WARN" is the default value. You can omit the below line and keep the same behavior. | ||
| enforcement_policy = "WARN", | ||
gregestren marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| buildable_units = [ | ||
| # Since this buildable unit sets "is_default = True", these flags apply | ||
| # to any target in this package or its subpackages by default. You can | ||
| # also request these flags explicitly with "--scl_config=default_config". | ||
| buildable_unit_pb2.BuildableUnit.create( | ||
| name = "default_config", | ||
| flags = [ | ||
| "--platforms=//:myplatform", | ||
| "--compilation_mode=opt", | ||
| '--@custom_flags//:project_flag="custom flag value"', | ||
| ], | ||
| is_default = True, | ||
| # If a build sets an unknown --scl_config value or omits | ||
| # --scl_config on a project with no default config, bazel errors | ||
| # with a summary of valid configurations. The "description" field | ||
| # tells bazel how to describe this configuration. | ||
| description = "this project's default flags", | ||
| ), | ||
| ], | ||
| ) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| genrule( | ||
| name = "one", | ||
| srcs = [], | ||
| outs = ["one.out"], | ||
| cmd = "echo one > $@", | ||
| ) | ||
|
|
||
| genrule( | ||
| name = "two", | ||
| srcs = [], | ||
| outs = ["two.out"], | ||
| cmd = "echo two > $@", | ||
| ) |
50 changes: 50 additions & 0 deletions
50
configurations/auto_configured_builds/compatible/PROJECT.scl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| # A project file that automatically sets build flags for all targets in the | ||
| # project and fails if the users set any flags that conflict with the project's | ||
| # flags. | ||
| # | ||
| # For example: | ||
| # --compilation_mode=dbg conflicts with --compilation_mode=opt | ||
| # --compilation_mode=dbg does not conflict with --//some:unrelated_flag=1 | ||
| load( | ||
| "@bazel_tools//src/main/protobuf/project:project_proto.scl", | ||
| "buildable_unit_pb2", | ||
| "project_pb2", | ||
| ) | ||
|
|
||
| project = project_pb2.Project.create( | ||
| # "COMPATIBLE" means bazel errors if the user sets flags that conflict with | ||
| # project's flags. However, bazel permits other user flags that don't | ||
| # directly conflict. See top of this file for examples. | ||
| enforcement_policy = "COMPATIBLE", | ||
| buildable_units = [ | ||
| # Since this buildable unit sets "is_default = True", these flags apply | ||
| # to any target in this package or its subpackages by default. You can | ||
| # also request these flags explicitly with "--scl_config=default_config". | ||
| buildable_unit_pb2.BuildableUnit.create( | ||
| name = "default_config", | ||
| flags = [ | ||
| "--platforms=//:myplatform", | ||
| "--compilation_mode=opt", | ||
| '--@custom_flags//:project_flag="custom flag value"', | ||
| ], | ||
| is_default = True, | ||
| # If a build sets an unknown --scl_config value or omits | ||
| # --scl_config on a project with no default config, bazel errors | ||
| # with a summary of valid configurations. The "description" field | ||
| # tells bazel how to describe this configuration. | ||
| description = "this project's default flags", | ||
| ), | ||
|
|
||
| # A different flag configuration. Since this doesn't set "is_default | ||
| # True", you have to request it explicitly with "--scl_config=debug_config". | ||
| buildable_unit_pb2.BuildableUnit.create( | ||
| name = "debug_config", | ||
| flags = [ | ||
| "--platforms=//:myplatform", | ||
| "--compilation_mode=dbg", | ||
| '--@custom_flags//:project_flag="debug value"', | ||
| ], | ||
| description = "debug configuration for developers", | ||
| ), | ||
| ], | ||
| ) |
11 changes: 11 additions & 0 deletions
11
configurations/auto_configured_builds/custom_flags_impl/BUILD
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| load("@bazel_skylib//rules:common_settings.bzl", "string_flag") | ||
|
|
||
| string_flag( | ||
| name = "project_flag", | ||
| build_setting_default = "default value", | ||
| ) | ||
|
|
||
| string_flag( | ||
| name = "some_unrelated_flag", | ||
| build_setting_default = "default value", | ||
| ) |
1 change: 1 addition & 0 deletions
1
configurations/auto_configured_builds/custom_flags_impl/MODULE.bazel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| #bazel_dep(name = "bazel_skylib", version = "1.8.2") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| genrule( | ||
| name = "one", | ||
| srcs = [], | ||
| outs = ["one.out"], | ||
| cmd = "echo one > $@", | ||
| ) | ||
|
|
||
| genrule( | ||
| name = "two", | ||
| srcs = [], | ||
| outs = ["two.out"], | ||
| cmd = "echo two > $@", | ||
| ) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.