From cdca20a93fa83dcca26f0883fd7bc15730f3ef89 Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Fri, 8 Nov 2024 10:56:14 +0100 Subject: [PATCH] Fix `go_tool_binary` non-hermeticity and Go 1.19 incompatibility `go_tool_binary` used to non-hermetically pick up rules_go's `go.mod` file when run unsandboxed, which resulted in it downloading a different toolchain and messing up version checks. Also make `nogo_main.go` compatible with Go 1.19. --- WORKSPACE | 11 ++++++++++- go/private/rules/binary.bzl | 18 +++++++++++++++++- go/tools/builders/nogo_main.go | 2 +- tests/core/compatibility/BUILD.bazel | 12 ++++++++++++ tests/core/compatibility/README.md | 5 +++++ tests/core/compatibility/hello.go | 7 +++++++ 6 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 tests/core/compatibility/BUILD.bazel create mode 100644 tests/core/compatibility/README.md create mode 100644 tests/core/compatibility/hello.go diff --git a/WORKSPACE b/WORKSPACE index df8d17d299..ce525319f4 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -1,7 +1,7 @@ workspace(name = "io_bazel_rules_go") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") -load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") +load("@io_bazel_rules_go//go:deps.bzl", "go_download_sdk", "go_register_nogo", "go_register_toolchains", "go_rules_dependencies") # Required by toolchains_protoc. http_archive( @@ -29,6 +29,15 @@ go_rules_dependencies() go_register_toolchains(version = "1.23.1") +go_download_sdk( + name = "rules_go_internal_compatibility_sdk", + version = "1.19.13", +) + +go_register_nogo( + nogo = "@//:tools_nogo", +) + http_archive( name = "rules_proto", sha256 = "303e86e722a520f6f326a50b41cfc16b98fe6d1955ce46642a5b7a67c11c0f5d", diff --git a/go/private/rules/binary.bzl b/go/private/rules/binary.bzl index 686d4f4eae..7c4d431084 100644 --- a/go/private/rules/binary.bzl +++ b/go/private/rules/binary.bzl @@ -464,6 +464,11 @@ go_non_executable_binary = rule(executable = False, **_go_binary_kwargs( )) def _go_tool_binary_impl(ctx): + # Keep in mind that the actions registered by this rule may not be + # sandboxed, so care must be taken to make them hermetic, for example by + # preventing `go build` from searching for go.mod or downloading a + # different toolchain version. + sdk = ctx.attr.sdk[GoSDK] name = ctx.label.name if sdk.goos == "windows": @@ -478,6 +483,8 @@ def _go_tool_binary_impl(ctx): set GOMAXPROCS=1 set GOCACHE=%cd%\\{gotmp}\\gocache set GOPATH=%cd%"\\{gotmp}\\gopath +set GOTOOLCHAIN=local +set GO111MODULE=off {go} build -o {out} -trimpath -ldflags \"{ldflags}\" {srcs} set GO_EXIT_CODE=%ERRORLEVEL% RMDIR /S /Q "{gotmp}" @@ -506,7 +513,16 @@ exit /b %GO_EXIT_CODE% ) else: # Note: GOPATH is needed for Go 1.16. - cmd = """GOTMP=$(mktemp -d);trap "rm -rf \"$GOTMP\"" EXIT;GOMAXPROCS=1 GOCACHE="$GOTMP"/gocache GOPATH="$GOTMP"/gopath {go} build -o {out} -trimpath -ldflags '{ldflags}' {srcs}""".format( + cmd = """ +GOTMP=$(mktemp -d) +trap "rm -rf \"$GOTMP\"" EXIT +GOMAXPROCS=1 \ +GOCACHE="$GOTMP"/gocache \ +GOPATH="$GOTMP"/gopath \ +GOTOOLCHAIN=local \ +GO111MODULE=off \ +{go} build -o {out} -trimpath -ldflags '{ldflags}' {srcs} +""".format( go = sdk.go.path, out = out.path, srcs = " ".join([f.path for f in ctx.files.srcs]), diff --git a/go/tools/builders/nogo_main.go b/go/tools/builders/nogo_main.go index 8a3871d3f7..23b063e616 100644 --- a/go/tools/builders/nogo_main.go +++ b/go/tools/builders/nogo_main.go @@ -223,7 +223,7 @@ func checkPackage(analyzers []*analysis.Analyzer, packagePath string, packageFil if _, ok := ignoreFilesSet[pkg.fset.Position(f.Pos()).Filename]; ok { for _, act := range actions { act.nolint = append(act.nolint, &Range{ - from: pkg.fset.Position(f.FileStart), + from: pkg.fset.Position(f.Pos()), to: pkg.fset.Position(f.End()).Line, }) } diff --git a/tests/core/compatibility/BUILD.bazel b/tests/core/compatibility/BUILD.bazel new file mode 100644 index 0000000000..bf5fcf4c3b --- /dev/null +++ b/tests/core/compatibility/BUILD.bazel @@ -0,0 +1,12 @@ +load("//go:def.bzl", "go_binary", "go_cross_binary") + +go_binary( + name = "hello", + srcs = ["hello.go"], +) + +go_cross_binary( + name = "hello_old", + sdk_version = "1.19", + target = ":hello", +) diff --git a/tests/core/compatibility/README.md b/tests/core/compatibility/README.md new file mode 100644 index 0000000000..6ee8e2989d --- /dev/null +++ b/tests/core/compatibility/README.md @@ -0,0 +1,5 @@ +# Compatibility + +## compatibility_test + +Verifies that a simple Go project builds with an older version of Go. diff --git a/tests/core/compatibility/hello.go b/tests/core/compatibility/hello.go new file mode 100644 index 0000000000..d8fa929218 --- /dev/null +++ b/tests/core/compatibility/hello.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + +func main() { + fmt.Println("hello") +}