The Go toolchain is at the heart of the Go rules, and is the mechanism used to customize the behavior of the core Go rules.
Contents
The Go toolchain consists of three main layers: the SDK, the toolchain, and the context.
The Go SDK (more commonly known as the Go distribution) is a directory tree containing sources for the Go toolchain and standard library and pre-compiled binaries for the same. You can download this from by visiting the Go website and downloading a binary distribution.
There are several Bazel rules for obtaining and configuring a Go SDK:
- go_download_sdk: downloads a toolchain for a specific version of Go for a specific operating system and architecture.
- go_host_sdk: uses the toolchain installed on the system where Bazel is
run. The toolchain's location is specified with the
GOROOT
or by runninggo env GOROOT
. - go_local_sdk: like go_host_sdk, but uses the toolchain in a specific directory on the host system.
- go_wrap_sdk: configures a toolchain downloaded with another Bazel repository rule.
By default, if none of the above rules are used, the go_register_toolchains
function creates a repository named @go_sdk
using go_download_sdk, using
a recent version of Go for the host operating system and architecture.
SDKs are specific to a host platform (e.g., linux_amd64
) and a version of
Go. They may target all platforms that Go supports. The Go SDK is naturally
cross compiling.
By default, all go_binary
, go_test
, etc. rules will use the first declared
Go SDK. If you would like to build a target using a specific Go SDK version, first
ensure that you have declared a Go SDK of that version using one of the above rules
(go_download_sdk, go_host_sdk, go_local_sdk, go_wrap_sdk). Then you
can specify the sdk version to build with when running a bazel build
by passing
the flag --@io_bazel_rules_go//go/toolchain:sdk_version="version"
where
"version"
is the SDK version you would like to build with, eg. "1.18.3"
.
The SDK version can omit the patch, or include a prerelease part, eg. "1"
,
"1.18"
, "1.18.0"
, and "1.19.0beta1"
are all valid values for sdk_version
.
When go_host_sdk
is used, "version"
can be set to host
to refer to the host Go SDK.
It can also be set remote
to match any non-host version.
The workspace rules above declare Bazel toolchains with go_toolchain
implementations for each target platform that Go supports. Wrappers around
the rules register these toolchains automatically. Bazel will select a
registered toolchain automatically based on the execution and target platforms,
specified with --host_platform
and --platforms
, respectively.
The workspace rules define the toolchains in a separate repository from the SDK. For example, if the SDK repository is @go_sdk, the toolchains will be defined in @go_sdk_toolchains. The @go_sdk_toolchains repository must be eagerly fetched in order to register the toolchain, but fetching the @go_sdk repository may be delayed until the toolchain is needed to build something. To activate lazily fetching the SDK, you must provide a version attribute to the workspace rule that defines the SDK (go_download_sdk, go_host_sdk, go_local_sdk, go_wrap_sdk, or go_register_toolchains). The value must match the actual version of the SDK; rules_go will validate this when the toolchain is used.
The toolchain itself should be considered opaque. You should only access its contents through the context.
The context is the type you need if you are writing custom rules that need to be compatible with rules_go. It provides information about the SDK, the toolchain, and the standard library. It also provides a convenient way to declare mode-specific files, and to create actions for compiling, linking, and more.
This is an example of normal usage for the other examples to be compared against. This will download and use a specific version of Go for the host platform.
# WORKSPACE
load("@io_bazel_rules_go//go:deps.bzl", "go_rules_dependencies", "go_register_toolchains")
go_rules_dependencies()
go_register_toolchains(version = "1.23.1")
You can use the Go SDK that's installed on the system where Bazel is running. This may result in faster builds, since there's no need to download an SDK, but builds won't be reproducible across systems with different SDKs installed.
# WORKSPACE
load("@io_bazel_rules_go//go:deps.bzl", "go_rules_dependencies", "go_register_toolchains")
go_rules_dependencies()
go_register_toolchains(version = "host")
If you download the SDK through another repository rule, you can configure
it with go_wrap_sdk
. It must still be named go_sdk
, but this is a
temporary limitation that will be removed in the future.
# WORKSPACE
load("@io_bazel_rules_go//go:deps.bzl", "go_rules_dependencies", "go_register_toolchains", "go_wrap_sdk")
unknown_download_sdk(
name = "go",
...,
)
go_wrap_sdk(
name = "go_sdk",
root_file = "@go//:README.md",
)
go_rules_dependencies()
go_register_toolchains()
If you are writing a new Bazel rule that uses the Go toolchain, you need to do several things to ensure you have full access to the toolchain and common dependencies.
- Declare a dependency on a toolchain of type
@io_bazel_rules_go//go:toolchain
. Bazel will select an appropriate, registered toolchain automatically. - Declare an implicit attribute named
_go_context_data
that defaults to@io_bazel_rules_go//:go_context_data
. This target gathers configuration information and several common dependencies. - Use the
go_context
function to gain access to the context. This is your main interface to the Go toolchain.
load("@io_bazel_rules_go//go:def.bzl", "go_context")
def _my_rule_impl(ctx):
go = go_context(ctx)
...
my_rule = rule(
implementation = _my_rule_impl,
attrs = {
...
"_go_context_data": attr.label(
default = "@io_bazel_rules_go//:go_context_data",
),
},
toolchains = ["@io_bazel_rules_go//go:toolchain"],
)
Installs the Go toolchains. If version is specified, it sets the
SDK version to use (for example, "1.15.5"
).
Name | Type | Default value |
version | string | mandatory value |
Specifies the version of Go to download if one has not been declared. If a toolchain was already declared with go_download_sdk or a similar rule, this parameter may not be set. Normally this is set to a Go version like If |
||
nogo | label | None |
The nogo attribute refers to a nogo rule that builds a binary
used for static analysis. The nogo binary will be used alongside the
Go compiler when building packages. |
||
experiments | string_list | [] |
Go experiments to enable via GOEXPERIMENT. |
This downloads a Go SDK for use in toolchains.
Name | Type | Default value |
name | string | mandatory value |
A unique name for this SDK. This should almost always be go_sdk if
you want the SDK to be used by toolchains. |
||
goos | string | None |
The operating system the binaries in the SDK are intended to run on. By default, this is detected automatically, but if you're building on an unusual platform, or if you're using remote execution and the execution platform is different than the host, you may need to specify this explictly. | ||
goarch | string | None |
The architecture the binaries in the SDK are intended to run on. By default, this is detected automatically, but if you're building on an unusual platform, or if you're using remote execution and the execution platform is different than the host, you may need to specify this explictly. | ||
version | string | latest Go version |
The version of Go to download, for example 1.12.5 . If unspecified,
go_download_sdk will list available versions of Go from golang.org, then
pick the highest version. If version is specified but sdks is
unspecified, go_download_sdk will list available versions on golang.org
to determine the correct file name and SHA-256 sum.
If version is specified, the SDK will be fetched only when the build uses a Go toolchain and
toolchain resolution results in this SDK being chosen. Otherwise it will be fetched unconditionally. |
||
urls | string_list | [https://dl.google.com/go/{}] |
A list of mirror urls to the binary distribution of a Go SDK. These must contain the {}
used to substitute the sdk filename being fetched (using .format.
It defaults to the official repository This attribute is seldom used. It is only needed for downloading Go from an alternative location (for example, an internal mirror). |
||
strip_prefix | string | "go" |
A directory prefix to strip from the extracted files.
Used with urls . |
||
sdks | string_list_dict | see description |
This consists of a set of mappings from the host platform tuple to a list of filename and sha256 for that file. The filename is combined the urls to produce the final download urls to use. This option is seldom used. It is only needed for downloading a modified Go distribution (with a different SHA-256 sum) or a version of Go not supported by rules_go (for example, a beta or release candidate). |
||
patches | label_list | [] |
A list of files that are to be applied to go sdk. By default, it uses the Bazel-native patch implementation which doesn't support fuzz match and binary patch, but Bazel will fall back to use patch command line tool if patch_tool attribute is specified. | ||
patch_strip | int | 0 |
The number of leading slashes to be stripped from the file name in thepatches. |
Example:
load(
"@io_bazel_rules_go//go:deps.bzl",
"go_download_sdk",
"go_register_toolchains",
"go_rules_dependencies",
)
go_download_sdk(
name = "go_sdk",
goos = "linux",
goarch = "amd64",
version = "1.18.1",
sdks = {
# NOTE: In most cases the whole sdks attribute is not needed.
# There are 2 "common" reasons you might want it:
#
# 1. You need to use an modified GO SDK, or an unsupported version
# (for example, a beta or release candidate)
#
# 2. You want to avoid the dependency on the index file for the
# SHA-256 checksums. In this case, You can get the expected
# filenames and checksums from https://go.dev/dl/
"linux_amd64": ("go1.18.1.linux-amd64.tar.gz", "b3b815f47ababac13810fc6021eb73d65478e0b2db4b09d348eefad9581a2334"),
"darwin_amd64": ("go1.18.1.darwin-amd64.tar.gz", "3703e9a0db1000f18c0c7b524f3d378aac71219b4715a6a4c5683eb639f41a4d"),
},
patch_strip = 1,
patches = [
"//patches:cgo_issue_fix.patch",
]
)
go_rules_dependencies()
go_register_toolchains()
This detects and configures the host Go SDK for use in toolchains.
If the GOROOT
environment variable is set, the SDK in that directory is
used. Otherwise, go env GOROOT
is used.
Name | Type | Default value |
name | string | mandatory value |
A unique name for this SDK. This should almost always be go_sdk if you want the SDK
to be used by toolchains. |
||
version | string | None |
The version of Go installed on the host. If specified, go_host_sdk will create its repository only when the build uses a Go toolchain and toolchain resolution results in this SDK being chosen. Otherwise it will be created unconditionally. | ||
experiments | string_list | [] |
Go experiments to enable via GOEXPERIMENT. |
This prepares a local path to use as the Go SDK in toolchains.
Name | Type | Default value |
name | string | mandatory value |
A unique name for this SDK. This should almost always be go_sdk if you want the SDK
to be used by toolchains. |
||
path | string | "" |
The local path to a pre-installed Go SDK. The path must contain the go binary, the tools it invokes and the standard library sources. | ||
version | string | None |
The version of the Go SDK. If specified, go_local_sdk will create its repository only when the build uses a Go toolchain and toolchain resolution results in this SDK being chosen. Otherwise it will be created unconditionally. | ||
experiments | string_list | [] |
Go experiments to enable via GOEXPERIMENT. |
This configures an SDK that was downloaded or located with another repository rule.
Name | Type | Default value |
name | string | mandatory value |
A unique name for this SDK. This should almost always be go_sdk if you want the SDK
to be used by toolchains. |
||
root_file | label | None |
A Bazel label referencing a file in the root directory of the SDK. Used to determine the GOROOT for the SDK. This attribute and root_files cannot be both provided. | ||
root_files | string_dict | None |
A set of mappings from the host platform to a Bazel label referencing a file in the SDK's root directory. This attribute and root_file cannot be both provided. | ||
version | string | None |
The version of the Go SDK. If specified, go_wrap_sdk will create its repository only when the build uses a Go toolchain and toolchain resolution results in this SDK being chosen. Otherwise it will be created unconditionally. | ||
experiments | string_list | [] |
Go experiments to enable via GOEXPERIMENT. |
Example:
load(
"@io_bazel_rules_go//go:deps.bzl",
"go_register_toolchains",
"go_rules_dependencies",
"go_wrap_sdk",
)
go_wrap_sdk(
name = "go_sdk",
root_file = "@other_repo//go:README.md",
)
go_rules_dependencies()
go_register_toolchains()
This declares a toolchain that may be used with toolchain type
"@io_bazel_rules_go//go:toolchain"
.
Normally, go_toolchain
rules are declared and registered in repositories
configured with go_download_sdk, go_host_sdk, go_local_sdk, or
go_wrap_sdk. You usually won't need to declare these explicitly.
Name | Type | Default value |
name | string | mandatory value |
A unique name for the toolchain. | ||
goos | string | mandatory value |
The target operating system. Must be a standard GOOS value. |
||
goarch | string | mandatory value |
The target architecture. Must be a standard GOARCH value. |
||
sdk | label | mandatory value |
The SDK this toolchain is based on. The target must provide GoSDK. This is usually a `go_sdk`_ rule. | ||
link_flags | string_list | [] |
Flags passed to the Go external linker. | ||
cgo_link_flags | string_list | [] |
Flags passed to the external linker (if it is used). |
This collects the information needed to form and return a GoContext from a rule ctx. It uses the attributes and the toolchains.
def _my_rule_impl(ctx):
go = go_context(ctx)
...
Name | Type | Default value |
ctx | ctx | mandatory value |
The Bazel ctx object for the current rule. |
GoContext
is never returned by a rule, instead you build one using
go_context(ctx)
in the top of any custom starlark rule that wants to interact
with the go rules. It provides all the information needed to create go actions,
and create or interact with the other go providers.
When you get a GoContext
from a context it exposes a number of fields
and methods.
All methods take the GoContext
as the only positional argument. All other
arguments must be passed as keyword arguments. This allows us to re-order and
deprecate individual parameters over time.
Name | Type |
toolchain | ToolchainInfo |
The underlying toolchain. This should be considered an opaque type subject to change. | |
sdk | GoSDK |
The SDK in use. This may be used to access sources, packages, and tools. | |
mode | Mode |
Controls the compilation setup affecting things like enabling profilers and sanitizers. See compilation modes for more information about the allowed values. | |
stdlib | GoStdLib |
The standard library and tools to use in this build mode. This may be the pre-compiled standard library that comes with the SDK, or it may be compiled in a different directory for this mode. | |
actions | ctx.actions |
The actions structure from the Bazel context, which has all the methods for building new bazel actions. | |
cc_toolchain_files | list of File |
The files you need to add to the inputs of an action in order to use the cc toolchain. | |
env | dict of string to string |
Environment variables to pass to actions. Includes GOARCH , GOOS ,
GOROOT , GOROOT_FINAL , CGO_ENABLED , and PATH . |
Name | Type |
root | string |
Prefer go.env["GOROOT"]. Path of the effective GOROOT. If stdlib is set,
this is the same as go.stdlib.root_file.dirname . Otherwise, this is the same as
go.sdk.root_file.dirname . |
|
go | File |
Prefer go.sdk.go. The main "go" binary used to run go sdk tools. | |
package_list | File |
Prefer go.sdk.package_list. A file that contains the package list of the standard library. | |
tags | list of string |
Prefer go.mode.tags. List of build tags used to filter source files. |
- Action generators
- Helpers
This emits actions to compile Go code into an archive. It supports embedding, cgo dependencies, coverage, and assembling and packing .s files.
It returns a GoArchive.
Name | Type | Default value |
go | GoContext | mandatory value |
This must be the same GoContext object you got this function from. | ||
source | GoSource | mandatory value |
The GoSource that should be compiled into an archive. |
This emits actions to compile and link Go code into a binary. It supports embedding, cgo dependencies, coverage, and assembling and packing .s files.
It returns a tuple containing GoArchive, the output executable file, and
a runfiles
object.
Name | Type | Default value |
go | GoContext | mandatory value |
This must be the same GoContext object you got this function from. | ||
name | string | "" |
The base name of the generated binaries. Required if executable is not given. | ||
source | GoSource | mandatory value |
The GoSource that should be compiled and linked. | ||
test_archives | list GoArchiveData | [] |
List of archives for libraries under test. See link. | ||
gc_linkopts | string_list | [] |
Go link options. | ||
version_file | File | None |
Version file used for link stamping. See link. | ||
info_file | File | None |
Info file used for link stamping. See link. | ||
executable | File | None |
Optional output file to write. If not set, binary will generate an output
file name based on name , the target platform, and the link mode. |
The link function adds an action that runs go tool link
on a library.
It does not return anything.
Name | Type | Default value |
go | GoContext | mandatory value |
This must be the same GoContext object you got this function from. | ||
archive | GoArchive | mandatory value |
The library to link. | ||
test_archives | GoArchiveData list | [] |
List of archives for libraries under test. These are excluded from linking if transitive dependencies of archive have the same package paths. This is useful for linking external test archives that depend internal test archives. | ||
executable | File | mandatory value |
The binary to produce. | ||
gc_linkopts | string_list | [] |
Basic link options, these may be adjusted by the mode. | ||
version_file | File | None |
Version file used for link stamping. | ||
info_file | File | None |
Info file used for link stamping. |
This creates a new Args object, using the ctx.actions.args
method. The
object is pre-populated with standard arguments used by all the go toolchain
builders.
Name | Type | Default value |
go | GoContext | mandatory value |
This must be the same GoContext object you got this function from. |
This is the equivalent of ctx.actions.declare_file
. It uses the
current build mode to make the filename unique between configurations.
Name | Type | Default value |
go | GoContext | mandatory value |
This must be the same GoContext object you got this function from. | ||
path | string | "" |
A path for this file, including the basename of the file. | ||
ext | string | "" |
The extension to use for the file. | ||
name | string | "" |
A name to use for this file. If path is not present, this becomes a prefix to the path. If this is not set, the current rule name is used in it's place. |
This is used to build a GoSource object for a given GoLibrary in the current build mode.
Name | Type | Default value |
go | GoContext | mandatory value |
This must be the same GoContext object you got this function from. | ||
attr | ctx.attr | mandatory value |
The attributes of the target being analyzed. For most rules, this should be
As an exception, |
||
library | GoLibrary | mandatory value |
The GoLibrary that you want to build a GoSource object for in the current build mode. | ||
coverage_instrumented | bool | mandatory value |
This controls whether cover is enabled for this specific library in this mode. This should generally be the value of ctx.coverage_instrumented() |
This creates a new GoLibrary. You can add extra fields to the go library by providing extra named parameters to this function, they will be visible to the resolver when it is invoked.
Name | Type | Default value |
go | GoContext | mandatory value |
This must be the same GoContext object you got this function from. | ||
resolver | function | None |
This is the function that gets invoked when converting from a GoLibrary to a GoSource. The function's signature must be def _stdlib_library_to_source(go, attr, source, merge) attr is the attributes of the rule being processed source is the dictionary of GoSource fields being generated merge is a helper you can call to merge |
||
importable | bool | mandatory value |
This controls whether the GoLibrary is supposed to be importable. This is generally only false for the "main" libraries that are built just before linking. |