...

Text file src/github.com/bazelbuild/rules_go/docs/go/core/bzlmod.md

Documentation: github.com/bazelbuild/rules_go/docs/go/core

     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## 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 as well as common remote execution platforms.
    34go_sdk.download(version = "1.20.3")
    35
    36# Alternately, download an SDK for a fixed OS/architecture.
    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).
    48As 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.
    49The 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
    53By default, Go SDK repositories are created with mangled names and are not expected to be referenced directly.
    54
    55For 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
    58The `go` tool of the SDK registered for the host is available via the `@rules_go//go` target.
    59Prefer running it via this target over running `go` directly to ensure that all developers use the same version.
    60The `@rules_go//go` target can be used in scripts executed via `bazel run`, but cannot be used in build actions.
    61Note that `go` command arguments starting with `-` require the use of the double dash separator with `bazel run`:
    62
    63```sh
    64bazel run @rules_go//go -- mod tidy -v
    65```
    66
    67If 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`.
    68Note that modules using this attribute cannot be added to registries such as the Bazel Central Registry (BCR).
    69If you have a use case that would require this, please explain it in an issue.
    70
    71### Configuring `nogo`
    72
    73The `nogo` tool is a static analyzer for Go code that is run as part of compilation.
    74It 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
    77go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
    78go_sdk.nogo(nogo = "//:my_nogo")
    79```
    80
    81By default, the `nogo` tool is executed for all Go targets in the main repository, but not any external repositories.
    82Each module can only provide at most one `go_sdk.nogo` tag and only the tag of the root module is honored.
    83
    84It 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
    87go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
    88go_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
   107Add the following to your top-level BUILD file:
   108
   109```starlark
   110load("@gazelle//:def.bzl", "gazelle")
   111
   112gazelle(name = "gazelle")
   113```
   114
   115If 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
   121Then, use `bazel run //:gazelle` to (re-)generate BUILD files.
   122
   123## External dependencies
   124
   125External 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.
   127For 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
   131Even 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`.
   132The `go_deps` extension parses this file directly, so external tooling such as `gazelle update-repos` is no longer needed.
   133
   134Register the `go.mod` file with the `go_deps` extension as follows:
   135
   136```starlark
   137go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
   138go_deps.from_file(go_mod = "//:go.mod")
   139
   140# All *direct* Go dependencies of the module have to be listed explicitly.
   141use_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
   150Bazel emits a warning if the `use_repo` statement is out of date or missing entirely (requires Bazel 6.2.0 or higher).
   151The warning contains a `buildozer` command to automatically fix the `MODULE.bazel` file (requires buildozer 6.1.1 or higher).
   152
   153Alternatively, you can specify a module extension tag to add an individual dependency:
   154
   155```starlark
   156go_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#### Depending on tools
   164
   165If 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):
   166
   1671. In a new subdirectory of your repository, create a `tools.go` file that imports the tools' main packages:
   168
   169    ```go
   170    //go:build tools
   171    // +build tools
   172
   173    package my_tools
   174
   175    import (
   176        _ "github.com/the/tool"
   177        _ "golang.org/x/tools/cmd/stringer"
   178    )
   179    ```
   180
   1812. Run `bazel run @rules_go//go mod tidy` to populate the `go.mod` file with the dependencies of the tools.
   182
   183Instead, 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)):
   184
   1852. 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.
   1863. Add `common --experimental_isolated_extension_usages` to your `.bazelrc` file to enable isolated usages of extensions.
   1874. Add an isolated usage of the `go_deps` extension to your module file:
   188
   189    ```starlark
   190    go_tool_deps = use_extension("@gazelle//:extensions.bzl", "go_deps", isolated = True)
   191    go_tool_deps.from_file(go_mod = "//tools:go.mod")
   192    ```
   193
   194### Managing `go.mod`
   195
   196An initial `go.mod` file can be created via
   197
   198```sh
   199bazel run @rules_go//go mod init github.com/example/project
   200```
   201
   202A dependency can be added via
   203
   204```sh
   205bazel run @rules_go//go get golang.org/x/text@v0.3.2
   206```
   207
   208### Overrides
   209
   210The root module can override certain aspects of the dependency resolution performed by the `go_deps` extension.
   211
   212#### `replace`
   213
   214[`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.
   215
   216```
   217replace(
   218    golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
   219    golang.org/x/mod => example.com/my/mod v1.4.5
   220)
   221```
   222
   223#### Gazelle directives
   224
   225Some external Go modules may require tweaking how Gazelle generates BUILD files for them via [Gazelle directives](https://github.com/bazelbuild/bazel-gazelle#directives).
   226The `go_deps` extension provides a dedicated `go_deps.gazelle_override` tag for this purpose:
   227
   228```starlark
   229go_deps.gazelle_override(
   230    directives = [
   231        "gazelle:go_naming_convention go_default_library",
   232    ],
   233    path = "github.com/stretchr/testify",
   234)
   235```
   236
   237If 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.
   238This will allow you to drop the `gazelle_override` tag and also makes the Go module usable in non-root Bazel modules.
   239
   240#### `go_deps.module_override`
   241
   242A `go_deps.module_override` can be used to apply patches to a Go module:
   243
   244```starlark
   245go_deps.module_override(
   246    patch_strip = 1,
   247    patches = [
   248        "//patches:testify.patch",
   249    ],
   250    path = "github.com/stretchr/testify",
   251)
   252```
   253
   254#### `go_deps.archive_override`
   255
   256A `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:
   257
   258```starlark
   259go_deps.archive_override(
   260    urls = [
   261        "https://github.com/bazelbuild/buildtools/archive/ae8e3206e815d086269eb208b01f300639a4b194.tar.gz",
   262    ],
   263    patch_strip = 1,
   264    patches = [
   265        "//patches:buildtools.patch",
   266    ],
   267    strip_prefix = "buildtools-ae8e3206e815d086269eb208b01f300639a4b194",
   268    path = "github.com/bazelbuild/buildtools",
   269    sha256 = "05d7c3d2bd3cc0b02d15672fefa0d6be48c7aebe459c1c99dced7ac5e598508f",
   270)
   271```
   272
   273### Not yet supported
   274
   275* Fetching dependencies from Git repositories
   276* `go.mod` `replace` directives referencing local files
   277* `go.mod` `exclude` directices

View as plain text