Skip to content

Commit

Permalink
Basic bzlmod setup (#3047)
Browse files Browse the repository at this point in the history
* Replace Label(...).workspace_name with explicit repo name

With the repository mappings used by bzlmod, the
Label(...).workspace_name construct always returns the canonical,
post-repo mapping repo name, which can't be used to construct a valid
label. Until bazelbuild/bazel#15593 has been
fixed, we have to hardcode the non-canonical repo name here.

* Remove remaining repo-absolute labels in load statements

* Refactor repository macros for bzlmod

The existing repository macros can be reused for the module setup
with only very few fully backwards compatible changes:

* The macros wrapping the Go SDK repository rules should make toolchain
  registration optional. With bzlmod, toolchains are registered with the
  toolchains_to_register attribute of the module function instead.
* The repository macro should not use _maybe with bzlmod. Instead, repos
  loaded by module extensions are given globally unique internal names
  automatically.

* Add basic bzlmod setup

This commit adds a MODULE.bazel that makes rules_go usable as a bzlmod
module for basic use cases.

The new module definition is verified by a test module that will be used
in the presubmit tests of the Bazel Central Registry (BCR).

The following features require more thought and/or work and are not yet
supported:
* SDK rules other than go_host_sdk and go_download_sdk.
* non-no-op nogo
* go_proto_library
  • Loading branch information
fmeum committed Jul 1, 2022
1 parent e01cf17 commit e80bb2c
Show file tree
Hide file tree
Showing 17 changed files with 198 additions and 28 deletions.
14 changes: 14 additions & 0 deletions .bazelci/presubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ tasks:
- "//..."
test_targets:
- "//..."
ubuntu2004_bcr_tests:
name: BCR test module
platform: ubuntu2004
bazel: 6.0.0-pre.20220526.1
working_directory: tests/bcr
build_flags:
- "--experimental_enable_bzlmod"
test_flags:
- "--experimental_enable_bzlmod"
build_targets:
- "//..."
- "@go_sdk//..."
test_targets:
- "//..."
macos:
shell_commands:
- tests/core/cgo/generate_imported_dylib.sh
Expand Down
1 change: 1 addition & 0 deletions .bazelignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tests/bcr
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/bazel-*
/tests/core/cgo/libimported.*
/tests/core/cgo/libversioned.*
/tests/bcr/bazel-*
12 changes: 6 additions & 6 deletions BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
load(
"@io_bazel_rules_go//go/private/tools:lines_sorted_test.bzl",
"//go/private/tools:lines_sorted_test.bzl",
"lines_sorted_test",
)
load(
"@io_bazel_rules_go//go/private/rules:nogo.bzl",
"//go/private/rules:nogo.bzl",
"nogo",
)
load(
"@io_bazel_rules_go//go/private/rules:info.bzl",
"//go/private/rules:info.bzl",
"go_info",
)
load(
"@io_bazel_rules_go//go:def.bzl",
"//go:def.bzl",
"TOOLS_NOGO",
)
load(
"@io_bazel_rules_go//go/private:context.bzl",
"//go/private:context.bzl",
"cgo_context_data",
"cgo_context_data_proxy",
"go_config",
"go_context_data",
)
load(
"@io_bazel_rules_go//go/private/rules:stdlib.bzl",
"//go/private/rules:stdlib.bzl",
"stdlib",
)

Expand Down
23 changes: 23 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module(
name = "io_bazel_rules_go",
version = "0.33.0",
compatibility_level = 0,
toolchains_to_register = [
"@go_default_sdk//:all",
],
)

print("WARNING: The rules_go Bazel module is still highly experimental and subject to change at any time. Only use it to try out bzlmod for now.")

bazel_dep(name = "bazel_skylib", version = "1.2.0")
bazel_dep(name = "platforms", version = "0.0.4")

non_module_dependencies = use_extension("@io_bazel_rules_go//go/private:extensions.bzl", "non_module_dependencies")
use_repo(
non_module_dependencies,
"io_bazel_rules_nogo",
)

go_sdk = use_extension("@io_bazel_rules_go//go:extensions.bzl", "go_sdk")
go_sdk.download(name = "go_default_sdk", version = "1.18.3")
use_repo(go_sdk, "go_default_sdk")
3 changes: 3 additions & 0 deletions go/extensions.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
load("//go/private:extensions.bzl", _go_sdk = "go_sdk")

go_sdk = _go_sdk
53 changes: 53 additions & 0 deletions go/private/extensions.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
load("//go/private:sdk.bzl", "go_download_sdk", "go_host_sdk")
load("//go/private:repositories.bzl", "go_rules_dependencies")

_download_tag = tag_class(
attrs = {
"name": attr.string(mandatory = True),
"goos": attr.string(),
"goarch": attr.string(),
"sdks": attr.string_list_dict(),
"urls": attr.string_list(default = ["https://dl.google.com/go/{}"]),
"version": attr.string(),
"strip_prefix": attr.string(default = "go"),
},
)

_host_tag = tag_class(
attrs = {
"name": attr.string(mandatory = True),
},
)

def _go_sdk_impl(ctx):
for mod in ctx.modules:
for download_tag in mod.tags.download:
go_download_sdk(
name = download_tag.name,
goos = download_tag.goos,
goarch = download_tag.goarch,
sdks = download_tag.sdks,
urls = download_tag.urls,
version = download_tag.version,
register_toolchains = False,
)
for host_tag in mod.tags.host:
go_host_sdk(
name = host_tag.name,
register_toolchains = False,
)

go_sdk = module_extension(
implementation = _go_sdk_impl,
tag_classes = {
"download": _download_tag,
"host": _host_tag,
},
)

def _non_module_dependencies_impl(ctx):
go_rules_dependencies(force = True)

non_module_dependencies = module_extension(
implementation = _non_module_dependencies_impl,
)
34 changes: 21 additions & 13 deletions go/private/repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ load("//go/private:nogo.bzl", "DEFAULT_NOGO", "go_register_nogo")
load("//proto:gogo.bzl", "gogo_special_proto")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

def go_rules_dependencies():
def go_rules_dependencies(force = False):
"""Declares workspaces the Go rules depend on. Workspaces that use
rules_go should call this.
Expand All @@ -38,11 +38,16 @@ def go_rules_dependencies():
if getattr(native, "bazel_version", None):
versions.check(MINIMUM_BAZEL_VERSION, bazel_version = native.bazel_version)

if force:
wrapper = _always
else:
wrapper = _maybe

# Needed by rules_go implementation and tests.
# We can't call bazel_skylib_workspace from here. At the moment, it's only
# used to register unittest toolchains, which rules_go does not need.
# releaser:upgrade-dep bazelbuild bazel-skylib
_maybe(
wrapper(
http_archive,
name = "bazel_skylib",
# 1.2.1, latest as of 2022-06-05
Expand All @@ -56,7 +61,7 @@ def go_rules_dependencies():

# Needed for nogo vet checks and go/packages.
# releaser:upgrade-dep golang tools
_maybe(
wrapper(
http_archive,
name = "org_golang_x_tools",
# v0.1.9, latest as of 2022-03-14
Expand All @@ -78,7 +83,7 @@ def go_rules_dependencies():
)

# releaser:upgrade-dep golang sys
_maybe(
wrapper(
http_archive,
name = "org_golang_x_sys",
# master, as of 2022-06-05
Expand All @@ -97,7 +102,7 @@ def go_rules_dependencies():

# Needed by golang.org/x/tools/go/packages
# releaser:upgrade-dep golang xerrors
_maybe(
wrapper(
http_archive,
name = "org_golang_x_xerrors",
# master, as of 2022-06-05
Expand Down Expand Up @@ -132,7 +137,7 @@ def go_rules_dependencies():

# Go protobuf runtime library and utilities.
# releaser:upgrade-dep protocolbuffers protobuf-go
_maybe(
wrapper(
http_archive,
name = "org_golang_google_protobuf",
sha256 = "dc4339bd2011a230d81d5ec445361efeb78366f1d30a7757e8fbea3e7221080e",
Expand All @@ -155,7 +160,7 @@ def go_rules_dependencies():
# We need to apply a patch to enable both go_proto_library and
# go_library with pre-generated sources.
# releaser:upgrade-dep golang protobuf
_maybe(
wrapper(
http_archive,
name = "com_github_golang_protobuf",
# v1.5.2, latest as of 2022-06-05
Expand All @@ -175,7 +180,7 @@ def go_rules_dependencies():
# Extra protoc plugins and libraries.
# Doesn't belong here, but low maintenance.
# releaser:upgrade-dep mwitkow go-proto-validators
_maybe(
wrapper(
http_archive,
name = "com_github_mwitkow_go_proto_validators",
# v0.3.2, latest as of 2022-06-05
Expand All @@ -189,7 +194,7 @@ def go_rules_dependencies():
)

# releaser:upgrade-dep gogo protobuf
_maybe(
wrapper(
http_archive,
name = "com_github_gogo_protobuf",
# v1.3.2, latest as of 2022-06-05
Expand All @@ -206,7 +211,7 @@ def go_rules_dependencies():
patch_args = ["-p1"],
)

_maybe(
wrapper(
gogo_special_proto,
name = "gogo_special_proto",
)
Expand All @@ -216,7 +221,7 @@ def go_rules_dependencies():
# Doesn't belong here, but it would be an annoying source of errors if
# this weren't generated with -proto disable_global.
# releaser:upgrade-dep googleapis go-genproto
_maybe(
wrapper(
http_archive,
name = "org_golang_google_genproto",
# main, as of 2022-06-05
Expand All @@ -239,7 +244,7 @@ def go_rules_dependencies():
# here. Gazelle should resolve dependencies to com_google_googleapis
# instead, and we should remove this.
# releaser:upgrade-dep googleapis googleapis
_maybe(
wrapper(
http_archive,
name = "go_googleapis",
# master, as of 2022-06-05
Expand Down Expand Up @@ -281,7 +286,7 @@ def go_rules_dependencies():
# This may be overridden by go_register_toolchains, but it's not mandatory
# for users to call that function (they may declare their own @go_sdk and
# register their own toolchains).
_maybe(
wrapper(
go_register_nogo,
name = "io_bazel_rules_nogo",
nogo = DEFAULT_NOGO,
Expand All @@ -290,3 +295,6 @@ def go_rules_dependencies():
def _maybe(repo_rule, name, **kwargs):
if name not in native.existing_rules():
repo_rule(name = name, **kwargs)

def _always(repo_rule, name, **kwargs):
repo_rule(name = name, **kwargs)
22 changes: 13 additions & 9 deletions go/private/sdk.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ _go_host_sdk = repository_rule(
environ = ["GOROOT"],
)

def go_host_sdk(name, **kwargs):
def go_host_sdk(name, register_toolchains = True, **kwargs):
_go_host_sdk(name = name, **kwargs)
_register_toolchains(name)
if register_toolchains:
_register_toolchains(name)

def _go_download_sdk_impl(ctx):
if not ctx.attr.goos and not ctx.attr.goarch:
Expand Down Expand Up @@ -125,9 +126,10 @@ _go_download_sdk = repository_rule(
},
)

def go_download_sdk(name, **kwargs):
def go_download_sdk(name, register_toolchains = True, **kwargs):
_go_download_sdk(name = name, **kwargs)
_register_toolchains(name)
if register_toolchains:
_register_toolchains(name)

def _go_local_sdk_impl(ctx):
goroot = ctx.attr.path
Expand All @@ -142,9 +144,10 @@ _go_local_sdk = repository_rule(
},
)

def go_local_sdk(name, **kwargs):
def go_local_sdk(name, register_toolchains = True, **kwargs):
_go_local_sdk(name = name, **kwargs)
_register_toolchains(name)
if register_toolchains:
_register_toolchains(name)

def _go_wrap_sdk_impl(ctx):
if not ctx.attr.root_file and not ctx.attr.root_files:
Expand Down Expand Up @@ -178,9 +181,10 @@ _go_wrap_sdk = repository_rule(
},
)

def go_wrap_sdk(name, **kwargs):
def go_wrap_sdk(name, register_toolchains = True, **kwargs):
_go_wrap_sdk(name = name, **kwargs)
_register_toolchains(name)
if register_toolchains:
_register_toolchains(name)

def _register_toolchains(repo):
labels = [
Expand Down Expand Up @@ -233,7 +237,7 @@ def _sdk_build_file(ctx, platform):
"{goos}": goos,
"{goarch}": goarch,
"{exe}": ".exe" if goos == "windows" else "",
"{rules_go_repo_name}": Label("//go/private:BUILD.sdk.bazel").workspace_name,
"{rules_go_repo_name}": "io_bazel_rules_go",
},
)

Expand Down
1 change: 1 addition & 0 deletions tests/bcr/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build --experimental_enable_bzlmod
1 change: 1 addition & 0 deletions tests/bcr/.bazelversion
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6.0.0-pre.20220526.1
19 changes: 19 additions & 0 deletions tests/bcr/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
load("@my_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")

go_library(
name = "lib",
srcs = ["lib.go"],
importpath = "example.com/lib",
)

go_binary(
name = "main",
srcs = ["main.go"],
deps = [":lib"],
)

go_test(
name = "test",
srcs = ["test.go"],
embed = [":lib"],
)
15 changes: 15 additions & 0 deletions tests/bcr/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module(
name = "rules_go_bcr_tests",
# Test that the default SDK is registered by not registering one from the test module.
)

bazel_dep(name = "io_bazel_rules_go", version = "", repo_name = "my_rules_go")
local_path_override(
module_name = "io_bazel_rules_go",
path = "../..",
)

# Test that this correctly downloads the SDK by requesting it from the commandline (see presubmit.yml).
go_sdk = use_extension("@my_rules_go//go:extensions.bzl", "go_sdk")
go_sdk.download(name = "go_sdk", version = "1.17.5")
use_repo(go_sdk, "go_sdk")
Empty file added tests/bcr/WORKSPACE
Empty file.
5 changes: 5 additions & 0 deletions tests/bcr/lib.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package lib

func Name() string {
return "bzlmod"
}
11 changes: 11 additions & 0 deletions tests/bcr/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package main

import (
"fmt"

"example.com/lib"
)

func main() {
fmt.Printf("Hello %s!", lib.Name())
}
Loading

0 comments on commit e80bb2c

Please sign in to comment.