Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for --@io_bazel_rules_go//go/toolchain:sdk_version flag. #3260

Merged
merged 1 commit into from
Aug 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions go/private/BUILD.sdk.bazel
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
load("@{rules_go_repo_name}//go/private/rules:binary.bzl", "go_tool_binary")
load("@{rules_go_repo_name}//go/private/rules:sdk.bzl", "package_list")
load("@{rules_go_repo_name}//go:def.bzl", "declare_toolchains", "go_sdk")
load("@bazel_skylib//lib:selects.bzl", "selects")

package(default_visibility = ["//visibility:public"])

Expand Down Expand Up @@ -58,10 +59,60 @@ package_list(
root_file = "ROOT",
)

sdk_version_label = "@{rules_go_repo_name}//go/toolchain:sdk_version"

config_setting(
name = "match_all_versions",
flag_values = {
sdk_version_label: "",
},
)

config_setting(
name = "match_major_version",
flag_values = {
sdk_version_label: "{major_version}",
},
)

config_setting(
name = "match_major_minor_version",
flag_values = {
sdk_version_label: "{major_version}.{minor_version}",
},
)

config_setting(
name = "match_patch_version",
flag_values = {
sdk_version_label: "{major_version}.{minor_version}.{patch_version}",
},
)

# If prerelease version is "", this will be the same as ":match_patch_version", but that's fine since we use match_any in config_setting_group.
config_setting(
name = "match_prerelease_version",
flag_values = {
sdk_version_label: "{major_version}.{minor_version}.{patch_version}{prerelease_suffix}",
},
)

selects.config_setting_group(
name = "sdk_version_setting",
match_any = [
":match_all_versions",
":match_major_version",
":match_major_minor_version",
":match_patch_version",
":match_prerelease_version",
],
)

declare_toolchains(
builder = ":builder",
host = "{goos}_{goarch}",
sdk = ":go_sdk",
sdk_version_setting = ":sdk_version_setting",
)

filegroup(
Expand Down
3 changes: 2 additions & 1 deletion go/private/go_toolchain.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ go_toolchain = rule(
provides = [platform_common.ToolchainInfo],
)

def declare_toolchains(host, sdk, builder):
def declare_toolchains(host, sdk, builder, sdk_version_setting):
"""Declares go_toolchain and toolchain targets for each platform."""

# keep in sync with generate_toolchain_names
Expand Down Expand Up @@ -139,5 +139,6 @@ def declare_toolchains(host, sdk, builder):
"@io_bazel_rules_go//go/toolchain:" + host_goarch,
],
target_compatible_with = constraints,
target_settings = [sdk_version_setting],
toolchain = ":" + impl_name,
)
36 changes: 31 additions & 5 deletions go/private/sdk.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ MIN_SUPPORTED_VERSION = (1, 14, 0)
def _go_host_sdk_impl(ctx):
goroot = _detect_host_sdk(ctx)
platform = _detect_sdk_platform(ctx, goroot)
_sdk_build_file(ctx, platform)
version = _detect_sdk_version(ctx, goroot)
_sdk_build_file(ctx, platform, version)
_local_sdk(ctx, goroot)

_go_host_sdk = repository_rule(
Expand All @@ -53,7 +54,6 @@ def _go_download_sdk_impl(ctx):
fail("goos set but goarch not set")
goos, goarch = ctx.attr.goos, ctx.attr.goarch
platform = goos + "_" + goarch
_sdk_build_file(ctx, platform)

version = ctx.attr.version
sdks = ctx.attr.sdks
Expand Down Expand Up @@ -100,6 +100,9 @@ def _go_download_sdk_impl(ctx):
filename, sha256 = sdks[platform]
_remote_sdk(ctx, [url.format(filename) for url in ctx.attr.urls], ctx.attr.strip_prefix, sha256)

detected_version = _detect_sdk_version(ctx, ".")
_sdk_build_file(ctx, platform, detected_version)

if not ctx.attr.sdks and not ctx.attr.version:
# Returning this makes Bazel print a message that 'version' must be
# specified for a reproducible build.
Expand Down Expand Up @@ -134,7 +137,8 @@ def go_download_sdk(name, register_toolchains = True, **kwargs):
def _go_local_sdk_impl(ctx):
goroot = ctx.attr.path
platform = _detect_sdk_platform(ctx, goroot)
_sdk_build_file(ctx, platform)
version = _detect_sdk_version(ctx, goroot)
_sdk_build_file(ctx, platform, version)
_local_sdk(ctx, goroot)

_go_local_sdk = repository_rule(
Expand Down Expand Up @@ -164,7 +168,8 @@ def _go_wrap_sdk_impl(ctx):
root_file = Label(ctx.attr.root_files[platform])
goroot = str(ctx.path(root_file).dirname)
platform = _detect_sdk_platform(ctx, goroot)
_sdk_build_file(ctx, platform)
version = _detect_sdk_version(ctx, goroot)
_sdk_build_file(ctx, platform, version)
_local_sdk(ctx, goroot)

_go_wrap_sdk = repository_rule(
Expand Down Expand Up @@ -226,9 +231,16 @@ def _local_sdk(ctx, path):
for entry in ["src", "pkg", "bin", "lib"]:
ctx.symlink(path + "/" + entry, entry)

def _sdk_build_file(ctx, platform):
def _sdk_build_file(ctx, platform, version):
ctx.file("ROOT")
goos, _, goarch = platform.partition("_")

pv = _parse_version(version)
if pv == None or len(pv) < 3:
fail("error parsing sdk version: " + version)
major, minor, patch = pv[0], pv[1], pv[2]
prerelease = pv[3] if len(pv) > 3 else ""

ctx.template(
"BUILD.bazel",
Label("//go/private:BUILD.sdk.bazel"),
Expand All @@ -238,6 +250,10 @@ def _sdk_build_file(ctx, platform):
"{goarch}": goarch,
"{exe}": ".exe" if goos == "windows" else "",
"{rules_go_repo_name}": "io_bazel_rules_go",
"{major_version}": str(major),
"{minor_version}": str(minor),
"{patch_version}": str(patch),
"{prerelease_suffix}": prerelease,
},
)

Expand Down Expand Up @@ -321,6 +337,16 @@ def _detect_sdk_platform(ctx, goroot):
fail("Could not detect SDK platform: found multiple platforms %s in %s" % (platforms, path))
return platforms[0]

def _detect_sdk_version(ctx, goroot):
path = goroot + "/VERSION"
version_contents = ctx.read(path)

# VERSION file has version prefixed by go, eg. go1.18.3
version = version_contents[2:]
if _parse_version(version) == None:
fail("Could not parse SDK version from version file (%s): %s" % (path, version_contents))
return version

def _parse_versions_json(data):
"""Parses version metadata returned by golang.org.

Expand Down
6 changes: 6 additions & 0 deletions go/toolchain/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
load(
":toolchains.bzl",
"declare_constraints",
Expand All @@ -8,6 +9,11 @@ package(default_visibility = ["//visibility:public"])

declare_constraints()

string_flag(
name = "sdk_version",
build_setting_default = "",
)

filegroup(
name = "all_rules",
srcs = glob(["*.bzl"]),
Expand Down
10 changes: 10 additions & 0 deletions go/toolchains.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ 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"``.
JamesMBartlett marked this conversation as resolved.
Show resolved Hide resolved
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``.

The toolchain
~~~~~~~~~~~~~

Expand Down
14 changes: 7 additions & 7 deletions tests/bcr/bcr.patch
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ index 9a364815..2eb6349d 100644

def _go_toolchain_impl(ctx):
sdk = ctx.attr.sdk[GoSDK]
@@ -115,8 +115,8 @@ def declare_toolchains(host, sdk, builder):
@@ -115,8 +115,8 @@ def declare_toolchains(host, sdk, builder, sdk_version_setting):
impl_name = toolchain_name + "-impl"

cgo_constraints = (
Expand All @@ -44,7 +44,7 @@ index 9a364815..2eb6349d 100644
)
constraints = [c for c in p.constraints if c not in cgo_constraints]

@@ -135,8 +135,8 @@ def declare_toolchains(host, sdk, builder):
@@ -135,8 +135,8 @@ def declare_toolchains(host, sdk, builder, sdk_version_setting):
name = toolchain_name,
toolchain_type = GO_TOOLCHAIN,
exec_compatible_with = [
Expand All @@ -54,7 +54,7 @@ index 9a364815..2eb6349d 100644
+ "@rules_go//go/toolchain:" + host_goarch,
],
target_compatible_with = constraints,
toolchain = ":" + impl_name,
target_settings = [sdk_version_setting],
diff --git a/go/private/nogo.bzl b/go/private/nogo.bzl
index 1d3491bb..efb4594f 100644
--- a/go/private/nogo.bzl
Expand Down Expand Up @@ -128,15 +128,15 @@ diff --git a/go/private/sdk.bzl b/go/private/sdk.bzl
index ee53cb0b..768b174d 100644
--- a/go/private/sdk.bzl
+++ b/go/private/sdk.bzl
@@ -237,7 +237,7 @@ def _sdk_build_file(ctx, platform):
@@ -249,7 +249,7 @@ def _sdk_build_file(ctx, platform, version):
"{goos}": goos,
"{goarch}": goarch,
"{exe}": ".exe" if goos == "windows" else "",
- "{rules_go_repo_name}": "io_bazel_rules_go",
+ "{rules_go_repo_name}": "rules_go",
},
)

"{major_version}": str(major),
"{minor_version}": str(minor),
"{patch_version}": str(patch),
diff --git a/go/toolchain/toolchains.bzl b/go/toolchain/toolchains.bzl
index b4e070cf..6a342da7 100644
--- a/go/toolchain/toolchains.bzl
Expand Down
47 changes: 42 additions & 5 deletions tests/core/go_download_sdk/go_download_sdk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ func Test(t *testing.T) {

func Test(t *testing.T) {
for _, test := range []struct {
desc, rule, wantVersion string
desc, rule string
optToWantVersion map[string]string
}{
{
desc: "version",
Expand All @@ -68,7 +69,7 @@ go_download_sdk(
)

`,
wantVersion: "go1.16",
optToWantVersion: map[string]string{"": "go1.16"},
}, {
desc: "custom_archives",
rule: `
Expand All @@ -84,7 +85,33 @@ go_download_sdk(
},
)
`,
wantVersion: "go1.16",
optToWantVersion: map[string]string{"": "go1.16"},
},
{
desc: "multiple_sdks",
rule: `
load("@io_bazel_rules_go//go:deps.bzl", "go_download_sdk")

go_download_sdk(
name = "go_sdk",
version = "1.16",
)
go_download_sdk(
name = "go_sdk_1_17",
version = "1.17",
)
go_download_sdk(
name = "go_sdk_1_17_1",
version = "1.17.1",
)
`,
optToWantVersion: map[string]string{
"": "go1.16",
"--@io_bazel_rules_go//go/toolchain:sdk_version=1": "go1.16",
"--@io_bazel_rules_go//go/toolchain:sdk_version=1.17": "go1.17",
"--@io_bazel_rules_go//go/toolchain:sdk_version=1.17.0": "go1.17",
"--@io_bazel_rules_go//go/toolchain:sdk_version=1.17.1": "go1.17.1",
},
},
} {
t.Run(test.desc, func(t *testing.T) {
Expand Down Expand Up @@ -115,8 +142,18 @@ go_register_toolchains()
}
}()

if err := bazel_testing.RunBazel("test", "//:version_test", "--test_arg=-version="+test.wantVersion); err != nil {
t.Fatal(err)
for opt, wantVersion := range test.optToWantVersion {
args := []string{
"test",
"//:version_test",
"--test_arg=-version=" + wantVersion,
}
if opt != "" {
args = append(args, opt)
}
if err := bazel_testing.RunBazel(args...); err != nil {
t.Fatal(err)
}
}
})
}
Expand Down