Skip to content

Commit

Permalink
go_sdk extension: create go_host_compatible_sdk repository (#3543)
Browse files Browse the repository at this point in the history
See issue 1469 on https://github.com/bazelbuild/bazel-gazelle

Co-authored-by: Fabian Meumertzheim <fabian@meumertzhe.im>
  • Loading branch information
ylecornec and fmeum authored May 31, 2023
1 parent 896849a commit b8d560e
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 5 deletions.
31 changes: 30 additions & 1 deletion go/private/extensions.bzl
Original file line number Diff line number Diff line change
@@ -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(),
Expand Down Expand Up @@ -33,6 +52,11 @@ def _go_sdk_impl(ctx):
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):
Expand Down Expand Up @@ -66,6 +90,9 @@ def _go_sdk_impl(ctx):
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,
Expand Down Expand Up @@ -99,7 +126,9 @@ def _go_sdk_impl(ctx):
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))

Expand Down
8 changes: 4 additions & 4 deletions go/private/sdk.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def go_host_sdk(name, register_toolchains = True, **kwargs):

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")
Expand Down Expand Up @@ -173,7 +173,7 @@ def _to_constant_name(s):

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")
Expand Down Expand Up @@ -354,7 +354,7 @@ def _go_wrap_sdk_impl(ctx):
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))
Expand Down Expand Up @@ -466,7 +466,7 @@ def _sdk_build_file(ctx, platform, version, experiments):
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"
Expand Down
3 changes: 3 additions & 0 deletions tests/bcr/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ go_sdk.host(version = "3.0.0")
# 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",
Expand Down

0 comments on commit b8d560e

Please sign in to comment.