Skip to main content

Pre-built binary

We recommend that developers execute a pre-compiled binary.
  1. You could create a custom workflow for your repository to build the binary when needed, for the right architectures, and then publish it somewhere that your developers use. Consider creating a tools/gazelle redirect in the repo to make it easy to locate - see run tools installed by bazel
  2. Much easier: use the aspect gazelle task in the free Aspect CLI, which runs the pre-built aspect-gazelle binaries, no compilation required. See the aspect gazelle task for setup and the built-in language extensions. This includes the ability to write extensions in Starlark, which we’ll explore extensively.

Using aspect_gazelle_prebuilt

The prebuilt binary is distributed as a Bazel module, so wiring it up is two snippets. The aspect_gazelle_prebuilt README documents how to wire up the aspect_gazelle() macro and all its options. Add the dependency to MODULE.bazel:
Then declare a gazelle target, conventionally at //tools/gazelle, selecting the languages your repo uses:
Omit languages entirely to get the default set (visibility_extension, proto, starlark, python, js). The valid language keys are buf, cc, go, js, kotlin, orion, proto, python, starlark, and visibility_extension. That target is what aspect gazelle runs by default. Crucially, this is the binary that interprets the Starlark (.axl) extensions we write later in the course — building from source (below) cannot run them. Enabling the go language requires some extra repo_config and go_deps wiring — see the aspect_gazelle_prebuilt README for the details. Why prefer the prebuilt binary over building from source?
  • No Go toolchain download and no first-run compile — developers fetch a cached artifact instead.
  • It bundles all the common, well-written language extensions, including support for the orion Gazelle language for writing your own extensions in Starlark/AXL.
  • It avoids the bootstrapping trap: a broken BUILD file referenced by your gazelle binary’s load statements can otherwise prevent gazelle from compiling, and therefore from fixing that file.

Building from source

Drawbacks of building from source

  • Bootstrapping trap — broken BUILD files referenced (even transitively) by load statements prevent Gazelle from compiling, so it can’t fix the very files it needs to run.
  • Slow cold starts — Bazel adds latency for analysis-cache rebuilds and external-repo fetches; a prebuilt artifact skips both.
  • Rebuild on every extension change — any edit to a first-party Go extension forces all developers to recompile the binary.
  • cgo portability — the Go toolchain is hermetic under Bazel but cgo is not (without extra work). Extensions that need it (such as rules_python) may not compile on all developer machines. See this PR.
  • Unnecessary Go toolchain — repos without Go code still pull down the Go toolchain and all its complexity.

Checking on CI

CI steps should verify that the repository is “gazelle-clean” in case developers haven’t run the tool. Pass with_check = True to aspect_gazelle() to generate a companion <name>.check target that runs Gazelle in diff mode — it makes no changes, prints a diff of what would change, and exits non-zero if any BUILD file is stale:
Aspect Workflows has this feature built-in! Check out Aspect Workflows