xref: /aosp_15_r20/external/bazelbuild-rules_go/docs/go/core/bzlmod.md (revision 9bb1b549b6a84214c53be0924760be030e66b93a)
1# Go with Bzlmod
2
3This document describes how to use rules_go and Gazelle with Bazel's new external dependency subsystem [Bzlmod](https://bazel.build/external/overview#bzlmod), which is meant to replace `WORKSPACE` files eventually.
4Usages of rules_go and Gazelle in `BUILD` files are not affected by this; refer to the existing documentation on rules and configuration options for them.
5
6## Setup
7
8Add the following lines to your `MODULE.bazel` file:
9
10```starlark
11bazel_dep(name = "rules_go", version = "0.39.1")
12bazel_dep(name = "gazelle", version = "0.31.0")
13```
14
15The latest versions are always listed on https://registry.bazel.build/.
16
17If you have WORKSPACE dependencies that reference rules_go and/or Gazelle, you can still use the legacy repository names for the two repositories:
18
19```starlark
20bazel_dep(name = "rules_go", version = "0.39.1", repo_name = "io_bazel_rules_go")
21bazel_dep(name = "gazelle", version = "0.31.0", repo_name = "bazel_gazelle")
22```
23
24## Registering Go SDKs
25
26rules_go automatically downloads and registers a recent Go SDK, so unless a particular version is required, no manual steps are required.
27
28To register a particular version of the Go SDK, use the `go_sdk` module extension:
29
30```starlark
31go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
32
33# Download an SDK for the host OS & architecture.
34go_sdk.download(version = "1.20.3")
35
36# Alternately, download an SDK for a fixed OS/architecture, e.g. for remote execution.
37go_sdk.download(
38    version = "1.20.3",
39    goarch = "amd64",
40    goos = "linux",
41)
42
43# Register the Go SDK installed on the host.
44go_sdk.host()
45```
46
47You can register multiple Go SDKs and select which one to use on a per-target basis using [`go_cross_binary`](rules.md#go_cross_binary).
48The usual rules of [toolchain resolution](https://bazel.build/extending/toolchains#toolchain-resolution) apply, with SDKs registered in the root module taking precedence over those registered in dependencies.
49
50### Using a Go SDK
51
52By default, Go SDK repositories are created with mangled names and are not expected to be referenced directly.
53
54For build actions, toolchain resolution is used to select the appropriate SDK for a given target.
55[`go_cross_binary`](rules.md#go_cross_binary) can be used to influence the outcome of the resolution.
56
57The `go` tool of the SDK registered for the host is available via the `@rules_go//go` target.
58Prefer running it via this target over running `go` directly to ensure that all developers use the same version.
59The `@rules_go//go` target can be used in scripts executed via `bazel run`, but cannot be used in build actions.
60Note that `go` command arguments starting with `-` require the use of the double dash separator with `bazel run`:
61
62```sh
63bazel run @rules_go//go -- mod tidy -v
64```
65
66If you really do need direct access to a Go SDK, you can provide the `name` attribute on the `go_sdk.download` or `go_sdk.host` tag and then bring the repository with that name into scope via `use_repo`.
67Note that modules using this attribute cannot be added to registries such as the Bazel Central Registry (BCR).
68If you have a use case that would require this, please explain it in an issue.
69
70### Not yet supported
71
72* `go_local_sdk`
73* `go_wrap_sdk`
74* nogo ([#3529](https://github.com/bazelbuild/rules_go/issues/3529))
75
76## Generating BUILD files
77
78Add the following to your top-level BUILD file:
79
80```starlark
81load("@gazelle//:def.bzl", "gazelle")
82
83gazelle(name = "gazelle")
84```
85
86If there is no `go.mod` file in the same directory as your top-level BUILD file, also add the following [Gazelle directive](https://github.com/bazelbuild/bazel-gazelle#directives) to that BUILD file to supply Gazelle with your Go module's path:
87
88```starlark
89# gazelle:prefix github.com/example/project
90```
91
92Then, use `bazel run //:gazelle` to (re-)generate BUILD files.
93
94## External dependencies
95
96External Go dependencies are managed by the `go_deps` module extension provided by Gazelle.
97`go_deps` performs [Minimal Version Selection](https://go.dev/ref/mod#minimal-version-selection) on all transitive Go dependencies of all Bazel modules, so compared to the old WORKSPACE setup, every Bazel module only needs to declare its own Go dependencies.
98For every major version of a Go module, there will only ever be a single version in the entire build, just as in regular Go module builds.
99
100### Specifying external dependencies
101
102Even though this is not a strict requirement, for interoperability with Go tooling that isn't Bazel-aware, it is recommended to manage Go dependencies via `go.mod`.
103The `go_deps` extension parses this file directly, so external tooling such as `gazelle update-repos` is no longer needed.
104
105Register the `go.mod` file with the `go_deps` extension as follows:
106
107```starlark
108go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
109go_deps.from_file(go_mod = "//:go.mod")
110
111# All *direct* Go dependencies of the module have to be listed explicitly.
112use_repo(
113    go_deps,
114    "com_github_gogo_protobuf",
115    "com_github_golang_mock",
116    "com_github_golang_protobuf",
117    "org_golang_x_net",
118)
119```
120
121Bazel emits a warning if the `use_repo` statement is out of date or missing entirely (requires Bazel 6.2.0 or higher).
122The warning contains a `buildozer` command to automatically fix the `MODULE.bazel` file (requires buildozer 6.1.1 or higher).
123
124Alternatively, you can specify a module extension tag to add an individual dependency.
125This can be useful for dependencies of generated code that `go mod tidy` would remove. (There is [ongoing work](https://github.com/bazelbuild/bazel-gazelle/pull/1495) to provide a Bazel-aware version of `tidy`.)
126
127```starlark
128go_deps.module(
129    path = "google.golang.org/grpc",
130    sum = "h1:fPVVDxY9w++VjTZsYvXWqEf9Rqar/e+9zYfxKK+W+YU=",
131    version = "v1.50.0",
132)
133```
134
135### Managing `go.mod`
136
137An initial `go.mod` file can be created via
138
139```sh
140bazel run @rules_go//go mod init github.com/example/project
141```
142
143A dependency can be added via
144
145```sh
146bazel run @rules_go//go get golang.org/x/text@v0.3.2
147```
148
149### Overrides
150
151The root module can override certain aspects of the dependency resolution performed by the `go_deps` extension.
152
153#### `replace`
154
155[`replace` directives](https://go.dev/ref/mod#go-mod-file-replace) in `go.mod` can be used to replace particular versions of dependencies with other versions or entirely different modules.
156At the moment the only supported form is:
157
158```
159replace(
160    golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
161)
162```
163
164#### Gazelle directives
165
166Some external Go modules may require tweaking how Gazelle generates BUILD files for them via [Gazelle directives](https://github.com/bazelbuild/bazel-gazelle#directives).
167The `go_deps` extension provides a dedicated `go_deps.gazelle_override` tag for this purpose:
168
169```starlark
170go_deps.gazelle_override(
171    directives = [
172        "gazelle:go_naming_convention go_default_library",
173    ],
174    path = "github.com/stretchr/testify",
175)
176```
177
178If you need to use a `gazelle_override` to get a public Go module to build with Bazel, consider contributing the directives to the [public registry for default Gazelle overrides](https://github.com/bazelbuild/bazel-gazelle/blob/master/internal/bzlmod/default_gazelle_overrides.bzl) via a PR.
179This will allow you to drop the `gazelle_override` tag and also makes the Go module usable in non-root Bazel modules.
180
181### Not yet supported
182
183* Fetching dependencies from Git repositories or via HTTP
184* `go.mod` `replace` directives matching all versions of a module
185* `go.mod` `replace` directives referencing local files
186* `go.mod` `exclude` directices
187