From 7c31b8108135d2f7c9cc9926a24578d7d0177f13 Mon Sep 17 00:00:00 2001 From: Yves-Stan Le Cornec Date: Wed, 31 May 2023 13:27:09 +0200 Subject: [PATCH] go_sdk extension: create `go_host_compatible_sdk` repository See issue 1469 on https://github.com/bazelbuild/bazel-gazelle Co-authored-by: Fabian Meumertzheim --- go/private/extensions.bzl | 31 ++++++++++++++++++++++++++++++- go/private/sdk.bzl | 8 ++++---- tests/bcr/MODULE.bazel | 3 +++ 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/go/private/extensions.bzl b/go/private/extensions.bzl index dd1166ec3b..249ec10a0e 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 @@ 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): @@ -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, @@ -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)) diff --git a/go/private/sdk.bzl b/go/private/sdk.bzl index 5a3ef4228c..8a9bc642d6 100644 --- a/go/private/sdk.bzl +++ b/go/private/sdk.bzl @@ -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") @@ -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") @@ -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)) @@ -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" diff --git a/tests/bcr/MODULE.bazel b/tests/bcr/MODULE.bazel index 151f522e63..b774feb49b 100644 --- a/tests/bcr/MODULE.bazel +++ b/tests/bcr/MODULE.bazel @@ -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",