0.1.4 Output Root
After your first bazel build, Bazel normally creates convenience symlinks
at a writable repository root. They point into its output directory
hierarchy1, and their names or presence can be configured.
Bazel keeps build artifacts outside the source tree2, and the symlinks provide
quick access to find them.
The Convenience Symlinks
With the default symlink prefix, four symlinks normally appear alongside
MODULE.bazel (0.1.2 Repository Root) and your BUILD.bazel files1:
my-project/
├── MODULE.bazel
├── BUILD.bazel
├── app/
│ ├── BUILD.bazel
│ └── main.cc
├── bazel-bin → ... ← compiled outputs
├── bazel-my-project → ... ← execution root
├── bazel-out → ... ← configuration output tree
└── bazel-testlogs → ... ← test logs
| Symlink | Contents |
|---|---|
bazel-bin/ | Compiled binaries, libraries, and generated files for the current build configuration. |
bazel-my-project/ | The execution root — the working directory where build actions run. Named after the project directory. |
bazel-testlogs/ | Test logs and results (test.log, test.xml) for the current configuration. |
bazel-out/ | The output path containing configuration-specific subtrees for this repository. bazel-bin is a shortcut into one configuration's bin/ directory inside it. |
Bazel does not use these convenience symlinks internally1. Their destinations are Bazel-managed state outside your source tree.
Path Mirroring
Output paths mirror the package structure (0.1.3 Package): the package part of the label becomes the subdirectory under Bazel's output trees. Most targets have one main output location. Tests are the common exception: Bazel builds the test program under bazel-bin/, then writes execution artifacts such as logs and XML under bazel-testlogs/1.
The diagram below shows one runnable example, reproduced by the output-path-mirroring snippet. The sample files are representative, not exhaustive: real output directories often include helper files such as params files or test metadata.
One test target can have a built test executable in bazel-bin/ and a separate per-target artifact directory in bazel-testlogs/1, so "one label -> one final file" does not describe tests.
Configurations Inside bazel-out
Inside bazel-out/, Bazel creates a subdirectory for each build configuration — a combination of target platform, compilation mode, and other settings1:
bazel-out/
├── k8-fastbuild/
│ ├── bin/ ← compiled outputs (BINDIR)
│ └── testlogs/ ← test results
├── k8-opt/
│ ├── bin/
│ └── testlogs/
└── _tmp/
└── actions/ ← stdout/stderr from build actions
The bazel-bin and bazel-testlogs symlinks point to one configuration at a time: the configuration of your most recent top-level build or test. Change flags such as -c opt, build for a different platform, or switch to a top-level target with a different configuration, and those symlinks may point somewhere else. Older outputs still remain in bazel-out/.
If you need the full picture, look in bazel-out/. It keeps one subtree per configuration, while bazel-bin and bazel-testlogs are just shortcuts into one of them.
Why Outputs Live Outside the Source Tree
Keeping generated state separate prevents outputs from masquerading as inputs and lets several configurations coexist without overwriting source files3. Edit files under the repository tree, but treat bazel-* entries as generated views managed by Bazel.
When you need an exact managed path, ask Bazel with the commands in 1.1.7 bazel info. Before deleting generated state, read 1.1.6 bazel clean to see what the cleanup commands actually remove. You do not need to understand the action cache or server lifecycle just to find a freshly built artifact.
Gitignoring Output Directories
The convenience symlinks should be excluded from version control:
/bazel-*
This catches all four convenience symlinks: bazel-bin, bazel-out, bazel-testlogs, and bazel-<project-name>1.
Bazel keeps generated outputs outside your source tree and exposes convenience symlinks (bazel-bin, bazel-out, bazel-testlogs, bazel-<project-name>) at the repository root. Package paths mirror into the output trees, so a label helps predict where to look. bazel-bin holds built outputs for the active configuration, while test execution artifacts appear under bazel-testlogs. Treat every /bazel-* entry as generated state and keep it out of version control.
Check your understanding · 2 questions
1.Match each convenience symlink to what it points at:
Drag each answer onto the matching prompt, or click an answer and then click a prompt
2.True or false: how Bazel manages output directories.
Choose True or False for each sentence
Footnotes
-
Output Directory Layout — Convenience symlinks, layout diagram, and configuration directory structure ↩1 ↩2 ↩3 ↩4 ↩5 ↩6 ↩7
-
Bazel 101 Training (Part 6): Create a repository — Bazel never writes outputs into the source tree ↩
-
Output Directory Layout — separation of source and generated state and configuration-specific output trees ↩