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