github.com/bazelbuild/rules_go@v0.47.2-0.20240515105122-e7ddb9ea474e/docs/go/core/bzlmod.md (about) 1 # Go with Bzlmod 2 3 This 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. 4 Usages 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 8 Add the following lines to your `MODULE.bazel` file: 9 10 ```starlark 11 bazel_dep(name = "rules_go", version = "0.39.1") 12 bazel_dep(name = "gazelle", version = "0.31.0") 13 ``` 14 15 The latest versions are always listed on https://registry.bazel.build/. 16 17 If 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 20 bazel_dep(name = "rules_go", version = "0.39.1", repo_name = "io_bazel_rules_go") 21 bazel_dep(name = "gazelle", version = "0.31.0", repo_name = "bazel_gazelle") 22 ``` 23 24 ## Go SDKs 25 26 rules_go automatically downloads and registers a recent Go SDK, so unless a particular version is required, no manual steps are required. 27 28 To register a particular version of the Go SDK, use the `go_sdk` module extension: 29 30 ```starlark 31 go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk") 32 33 # Download an SDK for the host OS & architecture as well as common remote execution platforms. 34 go_sdk.download(version = "1.20.3") 35 36 # Alternately, download an SDK for a fixed OS/architecture. 37 go_sdk.download( 38 version = "1.20.3", 39 goarch = "amd64", 40 goos = "linux", 41 ) 42 43 # Register the Go SDK installed on the host. 44 go_sdk.host() 45 ``` 46 47 You 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). 48 As long as you specify the `version` of an SDK, it will be downloaded lazily, that is, only when it is actually needed during a particular build. 49 The 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. 50 51 ### Using a Go SDK 52 53 By default, Go SDK repositories are created with mangled names and are not expected to be referenced directly. 54 55 For build actions, toolchain resolution is used to select the appropriate SDK for a given target. 56 [`go_cross_binary`](rules.md#go_cross_binary) can be used to influence the outcome of the resolution. 57 58 The `go` tool of the SDK registered for the host is available via the `@rules_go//go` target. 59 Prefer running it via this target over running `go` directly to ensure that all developers use the same version. 60 The `@rules_go//go` target can be used in scripts executed via `bazel run`, but cannot be used in build actions. 61 Note that `go` command arguments starting with `-` require the use of the double dash separator with `bazel run`: 62 63 ```sh 64 bazel run @rules_go//go -- mod tidy -v 65 ``` 66 67 If 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`. 68 Note that modules using this attribute cannot be added to registries such as the Bazel Central Registry (BCR). 69 If you have a use case that would require this, please explain it in an issue. 70 71 ### Configuring `nogo` 72 73 The `nogo` tool is a static analyzer for Go code that is run as part of compilation. 74 It is configured via an instance of the [`nogo`](/go/nogo.rst) rule, which can then be registered with the `go_sdk` extension: 75 76 ```starlark 77 go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk") 78 go_sdk.nogo(nogo = "//:my_nogo") 79 ``` 80 81 By default, the `nogo` tool is executed for all Go targets in the main repository, but not any external repositories. 82 Each module can only provide at most one `go_sdk.nogo` tag and only the tag of the root module is honored. 83 84 It is also possible to include only or exclude particular packages from `nogo` analysis, using syntax that matches the `visibility` attribute on rules: 85 86 ```starlark 87 go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk") 88 go_sdk.nogo( 89 nogo = "//:my_nogo", 90 includes = [ 91 "//:__subpackages__", 92 "@my_own_go_dep//logic:__pkg__", 93 ], 94 excludes = [ 95 "//third_party:__subpackages__", 96 ], 97 ) 98 ``` 99 100 ### Not yet supported 101 102 * `go_local_sdk` 103 * `go_wrap_sdk` 104 105 ## Generating BUILD files 106 107 Add the following to your top-level BUILD file: 108 109 ```starlark 110 load("@gazelle//:def.bzl", "gazelle") 111 112 gazelle(name = "gazelle") 113 ``` 114 115 If 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: 116 117 ```starlark 118 # gazelle:prefix github.com/example/project 119 ``` 120 121 Then, use `bazel run //:gazelle` to (re-)generate BUILD files. 122 123 ## External dependencies 124 125 External Go dependencies are managed by the `go_deps` module extension provided by Gazelle. 126 `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. 127 For 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. 128 129 ### Specifying external dependencies 130 131 Even 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`. 132 The `go_deps` extension parses this file directly, so external tooling such as `gazelle update-repos` is no longer needed. 133 134 Register the `go.mod` file with the `go_deps` extension as follows: 135 136 ```starlark 137 go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps") 138 go_deps.from_file(go_mod = "//:go.mod") 139 140 # All *direct* Go dependencies of the module have to be listed explicitly. 141 use_repo( 142 go_deps, 143 "com_github_gogo_protobuf", 144 "com_github_golang_mock", 145 "com_github_golang_protobuf", 146 "org_golang_x_net", 147 ) 148 ``` 149 150 Bazel emits a warning if the `use_repo` statement is out of date or missing entirely (requires Bazel 6.2.0 or higher). 151 The warning contains a `buildozer` command to automatically fix the `MODULE.bazel` file (requires buildozer 6.1.1 or higher). 152 153 Alternatively, you can specify a module extension tag to add an individual dependency: 154 155 ```starlark 156 go_deps.module( 157 path = "google.golang.org/grpc", 158 sum = "h1:fPVVDxY9w++VjTZsYvXWqEf9Rqar/e+9zYfxKK+W+YU=", 159 version = "v1.50.0", 160 ) 161 ``` 162 163 #### Specifying Workspaces 164 165 The `go.work` functionality is supported by the `go_deps` module extension in Gazelle. 166 167 ```starlark 168 go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps") 169 go_deps.from_file(go_work = "//:go.work") 170 171 # All *direct* Go dependencies of all `go.mod` files referenced by the `go.work` file have to be listed explicitly. 172 use_repo( 173 go_deps, 174 "com_github_gogo_protobuf", 175 "com_github_golang_mock", 176 "com_github_golang_protobuf", 177 "org_golang_x_net", 178 ) 179 ``` 180 181 Limitations: 182 * `go.work` is supported exclusively in the root module. 183 * Dependencies that are indirect and depend on a go module specified in `go.work` will have that dependency diverge from the one in `go.work`. More details can be found here: https://github.com/bazelbuild/bazel-gazelle/issues/1797. 184 185 #### Depending on tools 186 187 If you need to depend on Go modules that are only used as tools, you can use the [`tools.go` technique](https://github.com/golang/go/issues/25922#issuecomment-1038394599): 188 189 1. In a new subdirectory of your repository, create a `tools.go` file that imports the tools' main packages: 190 191 ```go 192 //go:build tools 193 // +build tools 194 195 package my_tools 196 197 import ( 198 _ "github.com/the/tool" 199 _ "golang.org/x/tools/cmd/stringer" 200 ) 201 ``` 202 203 2. Run `bazel run @rules_go//go mod tidy` to populate the `go.mod` file with the dependencies of the tools. 204 205 Instead, if you want the tools' dependencies to be resolved independently of the dependencies of your regular code ([experimental](https://github.com/bazelbuild/bazel/issues/20186)): 206 207 2. Run `bazel run @rules_go//go mod init` in the directory containing the `tools.go` file to create a new `go.mod` file and then run `bazel run @rules_go//go mod tidy` in that directory. 208 3. Add `common --experimental_isolated_extension_usages` to your `.bazelrc` file to enable isolated usages of extensions. 209 4. Add an isolated usage of the `go_deps` extension to your module file: 210 211 ```starlark 212 go_tool_deps = use_extension("@gazelle//:extensions.bzl", "go_deps", isolate = True) 213 go_tool_deps.from_file(go_mod = "//tools:go.mod") 214 ``` 215 216 ### Managing `go.mod` 217 218 An initial `go.mod` file can be created via 219 220 ```sh 221 bazel run @rules_go//go mod init github.com/example/project 222 ``` 223 224 A dependency can be added via 225 226 ```sh 227 bazel run @rules_go//go get golang.org/x/text@v0.3.2 228 ``` 229 230 ### Environment variables 231 232 Environment variables (such as `GOPROXY` and `GOPRIVATE`) required for fetching Go dependencies can be set as follows: 233 234 ```starlark 235 go_deps.config( 236 go_env = { 237 "GOPRIVATE": "...", 238 }, 239 ) 240 ``` 241 242 Variables set in this way are used by `go_deps` as well as `@rules_go//go`, with other variables inheriting their value from the host environment. 243 `go_env` does *not* affect Go build actions. 244 245 ### Overrides 246 247 The root module can override certain aspects of the dependency resolution performed by the `go_deps` extension. 248 249 #### `replace` 250 251 [`replace` directives](https://go.dev/ref/mod#go-mod-file-replace) in `go.mod` can be used to replace particular or all versions of dependencies with other versions or entirely different modules. 252 253 ``` 254 replace( 255 golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5 256 golang.org/x/mod => example.com/my/mod v1.4.5 257 example.org/hello => ../../../fixtures/hello 258 ) 259 ``` 260 261 #### Gazelle directives 262 263 Some external Go modules may require tweaking how Gazelle generates BUILD files for them via [Gazelle directives](https://github.com/bazelbuild/bazel-gazelle#directives). 264 The `go_deps` extension provides a dedicated `go_deps.gazelle_override` tag for this purpose: 265 266 ```starlark 267 go_deps.gazelle_override( 268 directives = [ 269 "gazelle:go_naming_convention go_default_library", 270 ], 271 path = "github.com/stretchr/testify", 272 ) 273 ``` 274 275 If 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. 276 This will allow you to drop the `gazelle_override` tag and also makes the Go module usable in non-root Bazel modules. 277 278 #### `go_deps.module_override` 279 280 A `go_deps.module_override` can be used to apply patches to a Go module: 281 282 ```starlark 283 go_deps.module_override( 284 patch_strip = 1, 285 patches = [ 286 "//patches:testify.patch", 287 ], 288 path = "github.com/stretchr/testify", 289 ) 290 ``` 291 292 #### `go_deps.archive_override` 293 294 A `go_deps.archive_override` can be used to replace a Go module with an archive fetched from a URL and is very similar to the `archive_override` for Bazel modules: 295 296 ```starlark 297 go_deps.archive_override( 298 urls = [ 299 "https://github.com/bazelbuild/buildtools/archive/ae8e3206e815d086269eb208b01f300639a4b194.tar.gz", 300 ], 301 patch_strip = 1, 302 patches = [ 303 "//patches:buildtools.patch", 304 ], 305 strip_prefix = "buildtools-ae8e3206e815d086269eb208b01f300639a4b194", 306 path = "github.com/bazelbuild/buildtools", 307 sha256 = "05d7c3d2bd3cc0b02d15672fefa0d6be48c7aebe459c1c99dced7ac5e598508f", 308 ) 309 ``` 310 311 ### Not yet supported 312 313 * Fetching dependencies from Git repositories 314 * `go.mod` `exclude` directices