go_sdk extension: create `go_host_compatible_sdk` repository (#3543)
See issue 1469 on https://github.com/bazelbuild/bazel-gazelle
Co-authored-by: Fabian Meumertzheim <fabian@meumertzhe.im>
diff --git a/go/private/extensions.bzl b/go/private/extensions.bzl
index dd1166e..03d3fea 100644
--- a/go/private/extensions.bzl
+++ b/go/private/extensions.bzl
@@ -1,6 +1,25 @@
-load("//go/private:sdk.bzl", "go_download_sdk_rule", "go_host_sdk_rule", "go_multiple_toolchains")
+load("//go/private:sdk.bzl", "detect_host_platform", "go_download_sdk_rule", "go_host_sdk_rule", "go_multiple_toolchains")
load("//go/private:repositories.bzl", "go_rules_dependencies")
+def host_compatible_toolchain_impl(ctx):
+ ctx.file("BUILD.bazel")
+ ctx.file("defs.bzl", content = """
+HOST_COMPATIBLE_SDK = Label({})
+""".format(repr(ctx.attr.toolchain)))
+
+host_compatible_toolchain = repository_rule(
+ implementation = host_compatible_toolchain_impl,
+ attrs = {
+ # We cannot use attr.label for the `toolchain` attribute since the module extension cannot
+ # refer to the repositories it creates by their apparent repository names.
+ "toolchain": attr.string(
+ doc = "The apparent label of a `ROOT` file in the repository of a host compatible toolchain created by the `go_sdk` extension",
+ mandatory = True,
+ ),
+ },
+ doc = "An external repository to expose the first host compatible toolchain",
+)
+
_download_tag = tag_class(
attrs = {
"name": attr.string(),
@@ -33,6 +52,11 @@
else:
multi_version_module[module.name] = False
+ # We remember the first host compatible toolchain declared by the download and host tags.
+ # The order follows bazel's iteration over modules (the toolchains declared by the root module are considered first).
+ # We know that at least `go_default_sdk` (which is declared by the `rules_go` module itself) is host compatible.
+ first_host_compatible_toolchain = None
+ host_detected_goos, host_detected_goarch = detect_host_platform(ctx)
toolchains = []
for module in ctx.modules:
for index, download_tag in enumerate(module.tags.download):
@@ -66,6 +90,9 @@
version = download_tag.version,
)
+ if (not download_tag.goos or download_tag.goos == host_detected_goos) and (not download_tag.goarch or download_tag.goarch == host_detected_goarch):
+ first_host_compatible_toolchain = first_host_compatible_toolchain or "@{}//:ROOT".format(name)
+
toolchains.append(struct(
goos = download_tag.goos,
goarch = download_tag.goarch,
@@ -99,7 +126,9 @@
sdk_type = "host",
sdk_version = host_tag.version,
))
+ first_host_compatible_toolchain = first_host_compatible_toolchain or "@{}//:ROOT".format(name)
+ host_compatible_toolchain(name = "go_host_compatible_sdk_label", toolchain = first_host_compatible_toolchain)
if len(toolchains) > _MAX_NUM_TOOLCHAINS:
fail("more than {} go_sdk tags are not supported".format(_MAX_NUM_TOOLCHAINS))
diff --git a/go/private/sdk.bzl b/go/private/sdk.bzl
index 5a3ef42..8a9bc64 100644
--- a/go/private/sdk.bzl
+++ b/go/private/sdk.bzl
@@ -59,7 +59,7 @@
def _go_download_sdk_impl(ctx):
if not ctx.attr.goos and not ctx.attr.goarch:
- goos, goarch = _detect_host_platform(ctx)
+ goos, goarch = detect_host_platform(ctx)
else:
if not ctx.attr.goos:
fail("goarch set but goos not set")
@@ -173,7 +173,7 @@
def go_toolchains_single_definition(ctx, *, prefix, goos, goarch, sdk_repo, sdk_type, sdk_version):
if not goos and not goarch:
- goos, goarch = _detect_host_platform(ctx)
+ goos, goarch = detect_host_platform(ctx)
else:
if not goos:
fail("goarch set but goos not set")
@@ -354,7 +354,7 @@
if ctx.attr.root_file:
root_file = ctx.attr.root_file
else:
- goos, goarch = _detect_host_platform(ctx)
+ goos, goarch = detect_host_platform(ctx)
platform = goos + "_" + goarch
if platform not in ctx.attr.root_files:
fail("unsupported platform {}".format(platform))
@@ -466,7 +466,7 @@
content = _define_version_constants(version),
)
-def _detect_host_platform(ctx):
+def detect_host_platform(ctx):
goos = ctx.os.name
if goos == "mac os x":
goos = "darwin"
diff --git a/tests/bcr/MODULE.bazel b/tests/bcr/MODULE.bazel
index 151f522..b774feb 100644
--- a/tests/bcr/MODULE.bazel
+++ b/tests/bcr/MODULE.bazel
@@ -30,6 +30,9 @@
# Bring the default SDK into scope to verify that it exists.
use_repo(go_sdk, "go_default_sdk")
+# Bring the selected host compatible SDK into scope to verify that it exists.
+use_repo(go_sdk, "go_host_compatible_sdk_label")
+
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.module(
path = "google.golang.org/grpc",