From 10deaa03f8e5289a1461e5cb5b92cd6b75cbae9f Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Tue, 17 Sep 2024 11:31:08 +0200 Subject: [PATCH 1/3] Update Go SDK to 1.23.1 The default Go SDK with Bzlmod is kept at 1.22.7. Requires an update to golang.org/x/tools to avoid nogo silently failing to generate facts files with the new SDK. Also requires an update to golang.org/x/net to fix https://github.com/bettercap/bettercap/issues/1106. --- MODULE.bazel | 3 ++- README.rst | 6 +++--- WORKSPACE | 2 +- docs/go/core/bzlmod.md | 4 ++-- go.mod | 10 +++++----- go.sum | 28 ++++++++++++++-------------- go/nogo.rst | 2 +- go/toolchains.rst | 2 +- tests/bcr/MODULE.bazel | 2 +- tests/bcr/test_go_sdk.patch | 4 ++-- 10 files changed, 32 insertions(+), 31 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index bc7eb86bdd..05f8125fa8 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -16,7 +16,7 @@ bazel_dep(name = "protobuf", version = "3.19.2", repo_name = "com_google_protobu go_sdk = use_extension("//go:extensions.bzl", "go_sdk") go_sdk.download( name = "go_default_sdk", - version = "1.21.8", + version = "1.22.7", ) use_repo( go_sdk, @@ -24,6 +24,7 @@ use_repo( # This name is ugly on purpose to avoid a conflict with a user-named SDK. "io_bazel_rules_nogo", ) + register_toolchains("@go_toolchains//:all") bazel_dep(name = "gazelle", version = "0.36.0") diff --git a/README.rst b/README.rst index 100e1d9a6b..3337cb7b21 100644 --- a/README.rst +++ b/README.rst @@ -333,7 +333,7 @@ Go toolchain and register it for use. go_rules_dependencies() - go_register_toolchains(version = "1.22.4") + go_register_toolchains(version = "1.23.1") You can use rules_go at ``master`` by using `git_repository`_ instead of `http_archive`_ and pointing to a recent commit. @@ -390,7 +390,7 @@ Add the ``bazel_gazelle`` repository and its dependencies to your go_rules_dependencies() - go_register_toolchains(version = "1.22.4") + go_register_toolchains(version = "1.23.1") gazelle_dependencies() @@ -527,7 +527,7 @@ automatically from a go.mod or Gopkg.lock file. # Declare indirect dependencies and register toolchains. go_rules_dependencies() - go_register_toolchains(version = "1.22.4") + go_register_toolchains(version = "1.23.1") gazelle_dependencies() diff --git a/WORKSPACE b/WORKSPACE index 850484526f..44d2785088 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -27,7 +27,7 @@ bazel_features_deps() go_rules_dependencies() -go_register_toolchains(version = "1.21.8") +go_register_toolchains(version = "1.23.1") http_archive( name = "rules_proto", diff --git a/docs/go/core/bzlmod.md b/docs/go/core/bzlmod.md index 3e2cba0833..adc6c4e042 100644 --- a/docs/go/core/bzlmod.md +++ b/docs/go/core/bzlmod.md @@ -31,11 +31,11 @@ To register a particular version of the Go SDK, use the `go_sdk` module extensio go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk") # Download an SDK for the host OS & architecture as well as common remote execution platforms. -go_sdk.download(version = "1.20.3") +go_sdk.download(version = "1.23.1") # Alternately, download an SDK for a fixed OS/architecture. go_sdk.download( - version = "1.20.3", + version = "1.23.1", goarch = "amd64", goos = "linux", ) diff --git a/go.mod b/go.mod index 776305bc18..4a29f87973 100644 --- a/go.mod +++ b/go.mod @@ -6,8 +6,8 @@ require ( github.com/gogo/protobuf v1.3.2 github.com/golang/mock v1.7.0-rc.1 github.com/golang/protobuf v1.5.3 - golang.org/x/net v0.18.0 - golang.org/x/tools v0.15.0 + golang.org/x/net v0.26.0 + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 google.golang.org/grpc v1.40.1 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 @@ -15,7 +15,7 @@ require ( ) require ( - golang.org/x/mod v0.14.0 // indirect - golang.org/x/sys v0.15.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect ) diff --git a/go.sum b/go.sum index 629573b4ee..46841e9c80 100644 --- a/go.sum +++ b/go.sum @@ -42,8 +42,9 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -68,8 +69,8 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -81,8 +82,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= -golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -92,8 +93,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -102,15 +103,15 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -120,12 +121,11 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= -golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= diff --git a/go/nogo.rst b/go/nogo.rst index c1a815ecd8..e27eca87f8 100644 --- a/go/nogo.rst +++ b/go/nogo.rst @@ -75,7 +75,7 @@ instead. load("@io_bazel_rules_go//go:deps.bzl", "go_rules_dependencies", "go_register_nogo") go_rules_dependencies() - go_register_toolchains(version = "1.20.7") + go_register_toolchains(version = "1.23.1") go_register_nogo( nogo = "@//:my_nogo" # my_nogo is in the top-level BUILD file of this workspace includes = ["@//:__subpackages__"], # Labels to lint. By default only lints code in workspace. diff --git a/go/toolchains.rst b/go/toolchains.rst index 6bb2c15fb2..71aeef1752 100644 --- a/go/toolchains.rst +++ b/go/toolchains.rst @@ -129,7 +129,7 @@ platform. go_rules_dependencies() - go_register_toolchains(version = "1.22.4") + go_register_toolchains(version = "1.23.1") Using the installed Go SDK diff --git a/tests/bcr/MODULE.bazel b/tests/bcr/MODULE.bazel index 0944cc6425..eee6234a25 100644 --- a/tests/bcr/MODULE.bazel +++ b/tests/bcr/MODULE.bazel @@ -31,7 +31,7 @@ go_sdk.download( patches = [ "//:test_go_sdk.patch", ], - version = "1.21.1", + version = "1.23.1", ) # Request an invalid SDK to verify that it isn't fetched since the first tag takes precedence. diff --git a/tests/bcr/test_go_sdk.patch b/tests/bcr/test_go_sdk.patch index 83beb83b5f..520ea2a7b3 100644 --- a/tests/bcr/test_go_sdk.patch +++ b/tests/bcr/test_go_sdk.patch @@ -9,5 +9,5 @@ index 5306bcb..d110a19 100644 +const SayHello = "Hello" + // Readdir reads the contents of the directory associated with file and - // returns a slice of up to n FileInfo values, as would be returned - // by Lstat, in directory order. Subsequent calls on the same file will yield + // returns a slice of up to n [FileInfo] values, as would be returned + // by [Lstat], in directory order. Subsequent calls on the same file will yield From b2e8c8d631d8be887265b987f234e3e750bbe37a Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Tue, 17 Sep 2024 10:58:13 +0200 Subject: [PATCH 2/3] Add `language_version` attribute to Go SDK rules and extension --- go/private/BUILD.sdk.bazel | 1 + go/private/actions/compilepkg.bzl | 6 ++- go/private/extensions.bzl | 31 ++++++------ go/private/providers.bzl | 1 + go/private/rules/sdk.bzl | 4 ++ go/private/sdk.bzl | 75 +++++++++++++++--------------- go/tools/builders/nogo_main.go | 2 + tests/bcr/BUILD.bazel | 5 ++ tests/bcr/MODULE.bazel | 1 + tests/bcr/language_version_test.go | 17 +++++++ 10 files changed, 91 insertions(+), 52 deletions(-) create mode 100644 tests/bcr/language_version_test.go diff --git a/go/private/BUILD.sdk.bazel b/go/private/BUILD.sdk.bazel index deb22fb265..5bd5d90d47 100644 --- a/go/private/BUILD.sdk.bazel +++ b/go/private/BUILD.sdk.bazel @@ -71,6 +71,7 @@ go_sdk( root_file = "ROOT", tools = [":tools"], version = "{version}", + language_version = "{language_version}", ) go_tool_binary( diff --git a/go/private/actions/compilepkg.bzl b/go/private/actions/compilepkg.bzl index d7f2cd1830..9e6a720920 100644 --- a/go/private/actions/compilepkg.bzl +++ b/go/private/actions/compilepkg.bzl @@ -146,7 +146,11 @@ def emit_compilepkg( link_mode_flag = link_mode_arg(go.mode) - gc_flags = gc_goopts + go.mode.gc_goopts + gc_flags = [] + if sdk.language_version: + gc_flags.append("-lang=go" + sdk.language_version) + gc_flags += gc_goopts + gc_flags += go.mode.gc_goopts if go.mode.race: gc_flags.append("-race") if go.mode.msan: diff --git a/go/private/extensions.bzl b/go/private/extensions.bzl index 5d2412982e..54f4cc5a84 100644 --- a/go/private/extensions.bzl +++ b/go/private/extensions.bzl @@ -35,17 +35,25 @@ host_compatible_toolchain = repository_rule( doc = "An external repository to expose the first host compatible toolchain", ) +_COMMON_ATTRS = { + "name": attr.string(), + "version": attr.string( + doc = "The version of the Go SDK (e.g. \"1.22.3\")", + ), + "language_version": attr.string( + doc = "The version of the Go language to use (e.g. \"1.22.3\"). If not set, this defaults to the SDK version.", + ), + "experiments": attr.string_list( + doc = "Go experiments to enable via GOEXPERIMENT", + ), +} + _download_tag = tag_class( - attrs = { - "name": attr.string(), + attrs = _COMMON_ATTRS | { "goos": attr.string(), "goarch": attr.string(), "sdks": attr.string_list_dict(), - "experiments": attr.string_list( - doc = "Go experiments to enable via GOEXPERIMENT", - ), "urls": attr.string_list(default = ["https://dl.google.com/go/{}"]), - "version": attr.string(), "patches": attr.label_list( doc = "A list of patches to apply to the SDK after downloading it", ), @@ -58,13 +66,7 @@ _download_tag = tag_class( ) _host_tag = tag_class( - attrs = { - "name": attr.string(), - "version": attr.string(), - "experiments": attr.string_list( - doc = "Go experiments to enable via GOEXPERIMENT", - ), - }, + attrs = _COMMON_ATTRS, ) _nogo_tag = tag_class( @@ -189,6 +191,7 @@ def _go_sdk_impl(ctx): patch_strip = download_tag.patch_strip, urls = download_tag.urls, version = download_tag.version, + language_version = download_tag.language_version, strip_prefix = download_tag.strip_prefix, ) @@ -229,6 +232,7 @@ def _go_sdk_impl(ctx): sdks = download_tag.sdks, urls = download_tag.urls, version = download_tag.version, + language_version = download_tag.language_version, ) toolchains.append(struct( @@ -255,6 +259,7 @@ def _go_sdk_impl(ctx): go_host_sdk_rule( name = name, version = host_tag.version, + language_version = host_tag.language_version, experiments = host_tag.experiments, ) diff --git a/go/private/providers.bzl b/go/private/providers.bzl index e3becb68f0..d182ed2e2d 100644 --- a/go/private/providers.bzl +++ b/go/private/providers.bzl @@ -56,6 +56,7 @@ GoSDK = provider( "the execution platform, excluding the go binary file"), "go": "The go binary file", "version": "The Go SDK version", + "language_version": "The Go language version", }, ) diff --git a/go/private/rules/sdk.bzl b/go/private/rules/sdk.bzl index b73a7e84f1..8a10e59d42 100644 --- a/go/private/rules/sdk.bzl +++ b/go/private/rules/sdk.bzl @@ -34,6 +34,7 @@ def _go_sdk_impl(ctx): tools = depset(ctx.files.tools), go = ctx.executable.go, version = ctx.attr.version, + language_version = ctx.attr.language_version, )] go_sdk = rule( @@ -94,6 +95,9 @@ go_sdk = rule( "version": attr.string( doc = "The version of the Go SDK.", ), + "language_version": attr.string( + doc = "The version of the Go language to use.", + ), }, doc = ("Collects information about a Go SDK. The SDK must have a normal " + "GOROOT directory structure."), diff --git a/go/private/sdk.bzl b/go/private/sdk.bzl index 486919d7f0..08bf37c197 100644 --- a/go/private/sdk.bzl +++ b/go/private/sdk.bzl @@ -20,25 +20,38 @@ load("//go/private/skylib/lib:versions.bzl", "versions") MIN_SUPPORTED_VERSION = (1, 14, 0) +_COMMON_ATTRS = { + "version": attr.string( + doc = "The version of the Go SDK (e.g. \"1.22.3\")", + ), + "language_version": attr.string( + doc = "The version of the Go language to use (e.g. \"1.22.3\"). If not set, this defaults to the SDK version.", + ), + "experiments": attr.string_list( + doc = "Go experiments to enable via GOEXPERIMENT", + ), + "_sdk_build_file": attr.label( + default = Label("//go/private:BUILD.sdk.bazel"), + ), +} + def _go_host_sdk_impl(ctx): goroot = _detect_host_sdk(ctx) platform = _detect_sdk_platform(ctx, goroot) version = _detect_sdk_version(ctx, goroot) - _sdk_build_file(ctx, platform, version, experiments = ctx.attr.experiments) + _sdk_build_file( + ctx, + platform, + version, + experiments = ctx.attr.experiments, + language_version = ctx.attr.language_version, + ) _local_sdk(ctx, goroot) go_host_sdk_rule = repository_rule( implementation = _go_host_sdk_impl, environ = ["GOROOT"], - attrs = { - "version": attr.string(), - "experiments": attr.string_list( - doc = "Go experiments to enable via GOEXPERIMENT", - ), - "_sdk_build_file": attr.label( - default = Label("//go/private:BUILD.sdk.bazel"), - ), - }, + attrs = _COMMON_ATTRS, ) def go_host_sdk(name, register_toolchains = True, **kwargs): @@ -118,7 +131,13 @@ def _go_download_sdk_impl(ctx): patch(ctx, patch_args = _get_patch_args(ctx.attr.patch_strip)) detected_version = _detect_sdk_version(ctx, ".") - _sdk_build_file(ctx, platform, detected_version, experiments = ctx.attr.experiments) + _sdk_build_file( + ctx, + platform, + detected_version, + experiments = ctx.attr.experiments, + language_version = ctx.attr.language_version, + ) if not ctx.attr.sdks and not ctx.attr.version: # Returning this makes Bazel print a message that 'version' must be @@ -136,15 +155,11 @@ def _go_download_sdk_impl(ctx): go_download_sdk_rule = repository_rule( implementation = _go_download_sdk_impl, - attrs = { + attrs = _COMMON_ATTRS | { "goos": attr.string(), "goarch": attr.string(), "sdks": attr.string_list_dict(), - "experiments": attr.string_list( - doc = "Go experiments to enable via GOEXPERIMENT", - ), "urls": attr.string_list(default = ["https://dl.google.com/go/{}"]), - "version": attr.string(), "strip_prefix": attr.string(default = "go"), "patches": attr.label_list( doc = "A list of patches to apply to the SDK after downloading it", @@ -153,9 +168,6 @@ go_download_sdk_rule = repository_rule( default = 0, doc = "The number of leading path segments to be stripped from the file name in the patches.", ), - "_sdk_build_file": attr.label( - default = Label("//go/private:BUILD.sdk.bazel"), - ), }, ) @@ -332,20 +344,13 @@ def _go_local_sdk_impl(ctx): goroot = ctx.attr.path platform = _detect_sdk_platform(ctx, goroot) version = _detect_sdk_version(ctx, goroot) - _sdk_build_file(ctx, platform, version, ctx.attr.experiments) + _sdk_build_file(ctx, platform, version, ctx.attr.experiments, ctx.attr.language_version) _local_sdk(ctx, goroot) _go_local_sdk = repository_rule( implementation = _go_local_sdk_impl, - attrs = { + attrs = _COMMON_ATTRS | { "path": attr.string(), - "version": attr.string(), - "experiments": attr.string_list( - doc = "Go experiments to enable via GOEXPERIMENT", - ), - "_sdk_build_file": attr.label( - default = Label("//go/private:BUILD.sdk.bazel"), - ), }, ) @@ -378,12 +383,12 @@ def _go_wrap_sdk_impl(ctx): goroot = str(ctx.path(root_file).dirname) platform = _detect_sdk_platform(ctx, goroot) version = _detect_sdk_version(ctx, goroot) - _sdk_build_file(ctx, platform, version, ctx.attr.experiments) + _sdk_build_file(ctx, platform, version, ctx.attr.experiments, ctx.attr.language_version) _local_sdk(ctx, goroot) _go_wrap_sdk = repository_rule( implementation = _go_wrap_sdk_impl, - attrs = { + attrs = _COMMON_ATTRS | { "root_file": attr.label( mandatory = False, doc = "A file in the SDK root direcotry. Used to determine GOROOT.", @@ -392,13 +397,6 @@ _go_wrap_sdk = repository_rule( mandatory = False, doc = "A set of mappings from the host platform to a file in the SDK's root directory", ), - "version": attr.string(), - "experiments": attr.string_list( - doc = "Go experiments to enable via GOEXPERIMENT", - ), - "_sdk_build_file": attr.label( - default = Label("//go/private:BUILD.sdk.bazel"), - ), }, ) @@ -495,7 +493,7 @@ def _local_sdk(ctx, path): continue ctx.symlink(entry, entry.basename) -def _sdk_build_file(ctx, platform, version, experiments): +def _sdk_build_file(ctx, platform, version, experiments, language_version): ctx.file("ROOT") goos, _, goarch = platform.partition("_") @@ -516,6 +514,7 @@ def _sdk_build_file(ctx, platform, version, experiments): "{goarch}": goarch, "{exe}": ".exe" if goos == "windows" else "", "{version}": version, + "{language_version}": language_version, "{experiments}": repr(",".join(experiments)), "{exec_compatible_with}": repr([ GOARCH_CONSTRAINTS[goarch], diff --git a/go/tools/builders/nogo_main.go b/go/tools/builders/nogo_main.go index 8a3871d3f7..4d69f66c5c 100644 --- a/go/tools/builders/nogo_main.go +++ b/go/tools/builders/nogo_main.go @@ -354,6 +354,8 @@ func (act *action) execOnce() { factFilter[reflect.TypeOf(f)] = true } pass := &analysis.Pass{ + // TODO: Set Module and in particular Module.GoVersion to use the + // correct Go language version for the package being analyzed. Analyzer: act.a, Fset: act.pkg.fset, Files: act.pkg.syntax, diff --git a/tests/bcr/BUILD.bazel b/tests/bcr/BUILD.bazel index 3426c21810..a7a0c14454 100644 --- a/tests/bcr/BUILD.bazel +++ b/tests/bcr/BUILD.bazel @@ -37,6 +37,11 @@ go_test( srcs = ["sdk_patch_test.go"], ) +go_test( + name = "language_version_test", + srcs = ["language_version_test.go"], +) + go_library( name = "mockable", srcs = ["mockable.go"], diff --git a/tests/bcr/MODULE.bazel b/tests/bcr/MODULE.bazel index eee6234a25..3e79a79453 100644 --- a/tests/bcr/MODULE.bazel +++ b/tests/bcr/MODULE.bazel @@ -27,6 +27,7 @@ bazel_dep(name = "toolchains_protoc", version = "0.2.1") go_sdk = use_extension("@my_rules_go//go:extensions.bzl", "go_sdk") go_sdk.download( + language_version = "1.21", patch_strip = 1, patches = [ "//:test_go_sdk.patch", diff --git a/tests/bcr/language_version_test.go b/tests/bcr/language_version_test.go new file mode 100644 index 0000000000..31193d7bb4 --- /dev/null +++ b/tests/bcr/language_version_test.go @@ -0,0 +1,17 @@ +package language_version_test + +import "testing" + +func TestLanguageVersion(t *testing.T) { + // Verify that the language version is set to 1.21 by checking that for + // loop variable semantics have *not* been changed. + // https://github.com/golang/go/discussions/56010 + strings := []string{"foo", "bar"} + var stringRefs []*string + for _, s := range strings { + stringRefs = append(stringRefs, &s) + } + if *stringRefs[0] != "bar" { + t.Errorf("Expected bar, got %s", *stringRefs[0]) + } +} From 80023b4d9630b4c3394890bf50c60398f068afbc Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Tue, 17 Sep 2024 12:09:55 +0200 Subject: [PATCH 3/3] Add from_file tag --- go/private/extensions.bzl | 58 +++++++++---- go/private/extensions/BUILD.bazel | 0 go/private/extensions/go_mod.bzl | 135 ++++++++++++++++++++++++++++++ tests/bcr/BUILD.bazel | 18 +++- tests/bcr/MODULE.bazel | 5 +- 5 files changed, 199 insertions(+), 17 deletions(-) create mode 100644 go/private/extensions/BUILD.bazel create mode 100644 go/private/extensions/go_mod.bzl diff --git a/go/private/extensions.bzl b/go/private/extensions.bzl index 54f4cc5a84..24b85478ba 100644 --- a/go/private/extensions.bzl +++ b/go/private/extensions.bzl @@ -15,6 +15,7 @@ load("@io_bazel_rules_go_bazel_features//:features.bzl", "bazel_features") load("//go/private:nogo.bzl", "DEFAULT_NOGO", "NOGO_DEFAULT_EXCLUDES", "NOGO_DEFAULT_INCLUDES", "go_register_nogo") load("//go/private:sdk.bzl", "detect_host_platform", "go_download_sdk_rule", "go_host_sdk_rule", "go_multiple_toolchains") +load("//go/private/extensions:go_mod.bzl", "sdk_from_go_mod") def host_compatible_toolchain_impl(ctx): ctx.file("BUILD.bazel") @@ -48,23 +49,34 @@ _COMMON_ATTRS = { ), } -_download_tag = tag_class( - attrs = _COMMON_ATTRS | { - "goos": attr.string(), - "goarch": attr.string(), - "sdks": attr.string_list_dict(), - "urls": attr.string_list(default = ["https://dl.google.com/go/{}"]), - "patches": attr.label_list( - doc = "A list of patches to apply to the SDK after downloading it", - ), - "patch_strip": attr.int( - default = 0, - doc = "The number of leading path segments to be stripped from the file name in the patches.", +_from_file_tag = tag_class( + attrs = { + "go_mod": attr.label( + mandatory = True, + doc = "The go.mod file to read Go SDK information from", ), - "strip_prefix": attr.string(default = "go"), }, ) +_DOWNLOAD_ATTRS = _COMMON_ATTRS | { + "goos": attr.string(), + "goarch": attr.string(), + "sdks": attr.string_list_dict(), + "urls": attr.string_list(default = ["https://dl.google.com/go/{}"]), + "patches": attr.label_list( + doc = "A list of patches to apply to the SDK after downloading it", + ), + "patch_strip": attr.int( + default = 0, + doc = "The number of leading path segments to be stripped from the file name in the patches.", + ), + "strip_prefix": attr.string(default = "go"), +} + +_download_tag = tag_class( + attrs = _DOWNLOAD_ATTRS, +) + _host_tag = tag_class( attrs = _COMMON_ATTRS, ) @@ -160,7 +172,7 @@ def _go_sdk_impl(ctx): 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): + for index, download_tag in enumerate(_get_download_tags(ctx, module.tags)): # SDKs without an explicit version are fetched even when not selected by toolchain # resolution. This is acceptable if brought in by the root module, but transitive # dependencies should not slow down the build in this way. @@ -299,6 +311,23 @@ def _go_sdk_impl(ctx): else: return None +def _get_download_tags(ctx, tags): + download_tags = tags.download + if tags.from_file: + if len(tags.from_file) > 1: + fail("go_sdk: only one tag can be specified per module, got:\n", *[t for p in zip(tags.from_file, len(tags.from_file) * ["\n"]) for t in p]) + from_file_tag = tags.from_file[0] + versions = sdk_from_go_mod(ctx, from_file_tag.go_mod) + download_tag_attrs = {k: None for k in _DOWNLOAD_ATTRS.keys()} + download_tag_attrs["version"] = versions.toolchain.removeprefix("go") if versions.toolchain else versions.go + download_tag_attrs["language_version"] = versions.go + + # Required by go_multiple_toolchains. + download_tag_attrs["goos"] = "" + download_tag_attrs["goarch"] = "" + download_tags = [struct(**download_tag_attrs)] + download_tags + return download_tags + def _default_go_sdk_name(*, module, multi_version, tag_type, index, suffix = ""): # Keep the version out of the repository name if possible to prevent unnecessary rebuilds when # it changes. @@ -335,6 +364,7 @@ go_sdk_extra_kwargs = { go_sdk = module_extension( implementation = _go_sdk_impl, tag_classes = { + "from_file": _from_file_tag, "download": _download_tag, "host": _host_tag, "nogo": _nogo_tag, diff --git a/go/private/extensions/BUILD.bazel b/go/private/extensions/BUILD.bazel new file mode 100644 index 0000000000..e69de29bb2 diff --git a/go/private/extensions/go_mod.bzl b/go/private/extensions/go_mod.bzl new file mode 100644 index 0000000000..8d7f1e35be --- /dev/null +++ b/go/private/extensions/go_mod.bzl @@ -0,0 +1,135 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +visibility(["//go/private"]) + +def sdk_from_go_mod(module_ctx, go_mod_label): + """Loads the Go SDK information from go.mod. + + Args: + module_ctx: a https://bazel.build/rules/lib/module_ctx object passed + from the MODULE.bazel call. + go_mod_label: a Label for a `go.mod` file. + + Returns: + a struct with the following fields: + go: a string containing the effective go directive value (never None) + toolchain: a string containing the raw toolchain directive value (can be None) + """ + if go_mod_label.name != "go.mod": + fail("go_deps.from_file requires a 'go.mod' file, not '{}'".format(go_mod_label.name)) + + go_mod_path = module_ctx.path(go_mod_label) + go_mod_content = module_ctx.read(go_mod_path) + return _parse_go_mod(go_mod_content, go_mod_path) + +def _parse_go_mod(content, path): + # See https://go.dev/ref/mod#go-mod-file. + + # Valid directive values understood by this parser never contain tabs or + # carriage returns, so we can simplify the parsing below by canonicalizing + # whitespace upfront. + content = content.replace("\t", " ").replace("\r", " ") + + state = { + "go": None, + "toolchain": None, + } + + # Since we only care about simple directives, we parse the file in a lax way + # and just skip over anything that looks like a block. + in_block = None + for line_no, line in enumerate(content.splitlines(), 1): + tokens, comment = _tokenize_line(line, path, line_no) + if not tokens: + continue + tok = tokens[0] + if not in_block: + if tok in ("go", "toolchain"): + if len(tokens) == 1: + fail("{}:{}: expected another token after '{}'".format(path, line_no, tok)) + if state[tok] != None: + fail("{}:{}: unexpected second '{}' directive".format(path, line_no, tok)) + if len(tokens) > 2: + fail("{}:{}: unexpected token '{}' after '{}'".format(path, line_no, tokens[2], tokens[1])) + state[tok] = tokens[1] + continue + if len(tokens) >= 2 and tokens[1] == "(": + in_block = True + if len(tokens) > 2: + fail("{}:{}: unexpected token '{}' after '('".format(path, line_no, tokens[2])) + elif tok == ")": + in_block = False + if len(tokens) > 1: + fail("{}:{}: unexpected token '{}' after ')'".format(path, line_no, tokens[1])) + + return struct( + # "As of the Go 1.17 release, if the go directive is missing, go 1.16 is assumed." + go = state["go"] or "1.16", + toolchain = state["toolchain"], + ) + +def _tokenize_line(line, path, line_no): + tokens = [] + r = line + for _ in range(len(line)): + r = r.strip() + if not r: + break + + if r[0] == "`": + end = r.find("`", 1) + if end == -1: + fail("{}:{}: unterminated raw string".format(path, line_no)) + + tokens.append(r[1:end]) + r = r[end + 1:] + + elif r[0] == "\"": + value = "" + escaped = False + found_end = False + for pos in range(1, len(r)): + c = r[pos] + + if escaped: + value += c + escaped = False + continue + + if c == "\\": + escaped = True + continue + + if c == "\"": + found_end = True + break + + value += c + + if not found_end: + fail("{}:{}: unterminated interpreted string".format(path, line_no)) + + tokens.append(value) + r = r[pos + 1:] + + elif r.startswith("//"): + # A comment always ends the current line + return tokens, r[len("//"):].strip() + + else: + token, _, r = r.partition(" ") + tokens.append(token) + + return tokens, None diff --git a/tests/bcr/BUILD.bazel b/tests/bcr/BUILD.bazel index a7a0c14454..10e241be3b 100644 --- a/tests/bcr/BUILD.bazel +++ b/tests/bcr/BUILD.bazel @@ -1,8 +1,10 @@ +load("@bazel_skylib//rules:native_binary.bzl", "native_test") load("@my_rules_go//extras:gomock.bzl", "gomock") load( "@my_rules_go//go:def.bzl", "TOOLS_NOGO", "go_binary", + "go_cross_binary", "go_library", "go_test", "nogo", @@ -32,9 +34,23 @@ go_test( embed = [":lib"], ) -go_test( +native_test( name = "sdk_patch_test", + src = ":sdk_patch_test_bin", +) + +go_cross_binary( + name = "sdk_patch_test_bin", + testonly = True, + # Select the patched SDK. + sdk_version = "1.23.0", + target = ":sdk_patch_test_orig", +) + +go_test( + name = "sdk_patch_test_orig", srcs = ["sdk_patch_test.go"], + tags = ["manual"], ) go_test( diff --git a/tests/bcr/MODULE.bazel b/tests/bcr/MODULE.bazel index 3e79a79453..5cedbb8cf7 100644 --- a/tests/bcr/MODULE.bazel +++ b/tests/bcr/MODULE.bazel @@ -18,6 +18,7 @@ local_path_override( path = "../..", ) +bazel_dep(name = "bazel_skylib", version = "1.6.1") bazel_dep(name = "gazelle", version = "0.33.0") bazel_dep(name = "protobuf", version = "3.19.6") @@ -26,13 +27,13 @@ bazel_dep(name = "protobuf", version = "3.19.6") bazel_dep(name = "toolchains_protoc", version = "0.2.1") go_sdk = use_extension("@my_rules_go//go:extensions.bzl", "go_sdk") +go_sdk.from_file(go_mod = "//:go.mod") go_sdk.download( - language_version = "1.21", patch_strip = 1, patches = [ "//:test_go_sdk.patch", ], - version = "1.23.1", + version = "1.23.0", ) # Request an invalid SDK to verify that it isn't fetched since the first tag takes precedence.