3.2 Project Configuration
A command like bazel test --config=ci //... looks like one request, but a maintainer knows it is carrying a whole project contract. Which rc files were loaded? Did a local override sneak in? Does --config=ci set the same flags on every machine? Are stamped release artifacts supposed to rebuild? Is the action environment still reading the developer's shell? Project configuration is the layer where undocumented team knowledge becomes files, flags, and repeatable defaults.
In a Bazel repo, configuration is part of the build's identity, not merely a set of options passed to Bazel. Flags feed action keys, select branches, toolchain decisions, hermeticity policy, release metadata, and CI behavior. Level 2 taught why the graph, cache, and sandbox care about declared inputs in 2.3 Hermeticity & Sandboxing and 2.4 Caching & Incrementality. This section turns that model into maintainer work: decide where policy lives, keep it consistent across environments, and make drift diagnosable before it becomes a cache-miss mystery.
Configuration Is A Control Plane
The section follows workflow order, not strict numeric order: first the files and wrappers that shape an invocation, then the flags that become build identity, then the maturity of the configuration surface itself.
The section starts with the files that shape every invocation before any BUILD target is analyzed. 3.2.1 .bazelrc Hierarchy is the anchor article because .bazelrc is where most project policy becomes executable. Read it as the answer to "who set this flag, and who is allowed to override it?"
3.2.2 .bazelignore covers a different kind of configuration: not flags, but repository discovery. It belongs here because broad target patterns, generated BUILD maintenance, and migration work all get noisy when Bazel walks directories that are present in the checkout but outside the intended package tree.
3.2.8 tools/bazel Wrapper sits even lower than rc files. Read it when the project needs setup before Bazel can interpret normal flags. The boundary matters: wrappers prepare the launcher environment, while ordinary build policy should return to .bazelrc and the flag surface.
Flags Are Inputs, Not Preferences
The middle of the section is about the flags themselves. 3.2.4 Command Line Flags gives the maintainer's first map of the flag surface. Read it less as a flag catalog and more as the diagnostic article for "what options did this invocation really carry, and why did changing them change the build?"
3.2.3 Stamping & Build Metadata is the release-metadata case study. Its role in the sequence is to show that "just add version info" is also configuration ownership: decide when metadata belongs in artifacts, which builds should carry it, and why the release versioning story later continues in H.11.3 Release Identity.
3.2.6 Hermeticity Settings turns the theory from 2.3 Hermeticity & Sandboxing into shared defaults. This article is the bridge from "Bazel should be reproducible" to "the workspace rc should enforce the baseline that makes reproducibility plausible."
If two developers use different rc layers, compiler flags, action environments,
or stamping modes, they have requested different builds even when the sources
match. That difference may be deliberate, as with --config=release, or
accidental, as with a home rc that changes one laptop's compiler flags. Shared
defaults therefore need both technical meaning and clear ownership.
Some Configuration Is Temporary, Some Is Future Shape
Two articles teach how to judge the maturity of the configuration surface itself. 3.2.5 Flag Lifecycle is the risk-label article: use it before copying a flag from docs, blog posts, or old rc files into shared policy. It also points naturally toward M4 Bazel Version Upgrades.
3.2.7 Project Specifications & Flag Sets is intentionally extra and forward-looking. You do not need it to operate a Bazel 8-era repository, but it names the direction: project configuration wants to become more scoped, enforceable, and explicit than a convention spread across rc files, user habits, and CI wrappers.
This control plane prepares 3.3 Configurable Builds & Platform Basics, where
select() and platforms consume configuration during analysis. Stable,
inspectable invocation policy keeps those graph choices from depending on
undocumented local defaults.
Trace Configuration From The Invocation
If you are setting up or repairing a real repository, start with 3.2.1 .bazelrc Hierarchy, then read 3.2.4 Command Line Flags and 3.2.6 Hermeticity Settings. That path gives you the daily maintainer loop: put shared policy in the right rc layer, understand the first flags that affect outputs and cache keys, and lock down the most common host-environment leaks.
Read 3.2.2 .bazelignore when broad target patterns or Gazelle keep walking into directories that should not be part of the Bazel package tree. Read 3.2.3 Stamping & Build Metadata when release artifacts need version or git metadata. Read 3.2.8 tools/bazel Wrapper only when the problem happens before Bazel can interpret normal flags: wrong launcher, mirror routing, or environment setup below .bazelrc.
Keep 3.2.5 Flag Lifecycle close when copying advice from docs, blog posts, or old rc files. It tells you whether a flag is stable policy, migration preview, or experimental risk. Treat 3.2.7 Project Specifications & Flag Sets as a preview of where the ecosystem is heading, not as the default mechanism every repo should adopt today.
When a build differs between a laptop and CI, do not start by changing BUILD files. First use --announce_rc to expose rc contributions, canonicalize the explicit option lists you want to compare, then check whether stamping, the action environment, or a wrapper changed the invocation.
Project configuration turns an individual invocation into repeatable, reviewable repository policy. Keep launcher setup, rc ownership, build-affecting flags, and host-environment inputs explicit enough that developers and CI can explain when two requests are intentionally different.
Sections in this chapter · 8
Layered configuration files that control default flags for every Bazel invocation.
Directories Bazel should skip when scanning for BUILD files.
Injecting build-time information like git commit hashes into compiled outputs.
Key build flags plus --announce_rc and bazel canonicalize-flags for exposing rc contributions and comparing explicit option lists without shorthand.
How Bazel flags evolve: experimental → incompatible → default → removed.
Shared .bazelrc policy for action environment, sandbox networking, and hermetic toolchains.
A forward-looking feature grouping flags into named sets associated with formal project definitions.
Intercepting Bazel invocations with a project-level wrapper script for environment setup, mirror routing, and enforcing Bazelisk usage.