Skip to main content

Bazel Build System

Overview

Michelangelo uses Bazel (version 7.4.1, see .bazelversion) for building all Go binaries, generating proto bindings, and running tests. Bazel's hermetic, reproducible builds mean that bazel build produces the same output regardless of what is installed on your machine — no implicit toolchain dependencies.

Key Files

FilePurpose
MODULE.bazelDependency declarations (Bazel modules)
BUILD.bazel (root)Workspace-level rules, Gazelle config, nogo linting setup
go/BUILD.bazelGo workspace build targets
proto/BUILD.bazelProto workspace build targets

Each subdirectory that contains Go packages or proto definitions has its own BUILD.bazel file managed by Gazelle.

Gazelle

Gazelle auto-generates and updates BUILD.bazel files for Go packages and proto targets. Run it after adding or removing Go files or proto files:

tools/gazelle

Never manually edit Go or proto BUILD targets — Gazelle owns them and will overwrite manual changes on the next run. Non-Go, non-proto targets (custom rules, macros) can be added to BUILD.bazel files alongside Gazelle-managed targets, but must be placed in sections that Gazelle will not touch.

Common Commands

# Build a specific target
bazel build //go/cmd/apiserver

# Run a binary
bazel run //go/cmd/apiserver

# Build all proto targets
bazel build //proto/...

# Run all Go and proto tests (matches CI)
bazel test //go/... //proto/... --build_tests_only

# Update Bazel module dependencies
bazel mod tidy

Go + Bazel Together

Go modules and Bazel modules are separate dependency systems that must be kept in sync. After changing Go dependencies with go mod tidy, also run:

bazel mod tidy

from the repo root. See Managing Go Dependencies for the full workflow.

macOS Note

If Bazel fails with C++ toolchain errors on macOS, set the following environment variables before running Bazel commands:

export CC=clang
export CXX=clang++

Adding these to your shell profile (.zshrc or .bashrc) avoids having to set them for each session.