-
-
Notifications
You must be signed in to change notification settings - Fork 661
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix gopackagesdriver for Go 1.18 by replicating stdlib #3083
Conversation
The stdliblist operation that the gopackagesdriver relies on fails on Go 1.18rc1 with the following error: ``` external/go_sdk/src/crypto/elliptic/p256_asm.go:24:12: pattern p256_asm_table.bin: cannot embed irregular file p256_asm_table.bin ``` We see this failure because Bazel builds a symlink tree of the GOROOT run `go list` with. However, since [CL 380475][1], the Go standard library uses `go:embed` to embed a file in `crypto/elliptic`, but `go:embed` does not support symlinks. [1]: https://go.dev/cl/380475 Fix this by having stdliblist copy the relevant portions of the GOROOT to run `go list` with. This matches [what the stdlib action does][2]. [2]: https://github.com/bazelbuild/rules_go/blob/e9a7054ff11a520e3b8aceb76a3ba44bb8da4c94/go/tools/builders/stdlib.go#L54-L57 Resolves #3080
Add a dependency on `GoStdLib._list_json` to the stdlib test. This ensures that we can successfully build the JSON data needed by the gopackagesdriver.
This isn't quite right. Specifically, the output paths are not right: Before:
Now:
These are missing the "external/go_sdk". Switching to WIP while I investigate. |
The prior version of this fix was incomplete because it generated incorrect relative paths. For example, before a path would be: __BAZEL_OUTPUT_BASE__/external/go_sdk/src/archive/tar/common.go But with the prior version of this change. __BAZEL_OUTPUT_BASE__/src/archive/tar/common.go It would drop the external/go_sdk from the path because the flattening logic in stdliblist makes these relative to the execRoot. We cannot overwrite external/go_sdk in execRoot because that's a path controlled by Bazel. Instead, create a parallel external/go_sdk under a new directory "root", and flatten paths relative to that.
Fixed. The solution is a bit janky: we have to create a copy of external/go_sdk under a |
// cloneRoot returns the new root directory and the new GOROOT we should run | ||
// under. | ||
func cloneRoot(execRoot, goroot string) (newRoot string, newGoroot string, err error) { | ||
relativeGoroot, err := filepath.Rel(abs(execRoot), abs(goroot)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you add args.add("-sdk", go.sdk.root_file.dirname)
to here: https://github.com/bazelbuild/rules_go/blob/d606ba2c123826f153bbd037cf46e80b5eb8dc3e/go/private/actions/stdlib.bzl#L56-L57
Then you can get a relative path of goroot from execRoot with goenv.sdk
.
@@ -158,19 +195,22 @@ func stdliblist(args []string) error { | |||
return err | |||
} | |||
|
|||
execRoot, goroot, err := cloneRoot(".", os.Getenv("GOROOT")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"execRoot" is a special name in Bazel. It means the "The working directory for all actions" (https://bazel.build/docs/output_directories). Because you copied the symlink tree to to a different place, it's no longer the actual execRoot. Please rename it to something like "newBase" or "cloneBase". There are several variables/arguments in this file called "execRoot". After this pull request, they are no longer the actual execroot. Please also renaming all of them.
return "", "", err | ||
} | ||
|
||
if err := replicate(goroot, newGoroot, replicatePaths("src", "pkg/tool", "pkg/include")); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need to replicate pkg/tool
?
return "", "", fmt.Errorf("GOROOT %q is not relative to execution root %q: %v", goroot, execRoot) | ||
} | ||
|
||
newRoot = filepath.Join(execRoot, "root") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am a bit nervous about writing things to execRoot. It's supposed to contain a symlink tree intended to be read-only. This may have unexpected result if there happen to be a root
directory under execRoot
. Can you copy it to ioutil.TempDir
?
I am also thinking about how to write tests to cover |
Superseded by #3157 |
What type of PR is this?
Bug fix
What does this PR do? Why is it needed?
The gopackagesdriver relies on the "stdliblist" action provided by rules_go.
The stdliblist action fails on Go 1.18 with the following error:
We see this failure because Bazel builds a symlink tree of the GOROOT to run
go list
with. However, since CL 380475, the Go standard library usesgo:embed
to embed a file incrypto/elliptic
, butgo:embed
does notsupport symlinks.
Fix this by having stdliblist copy the relevant portions of the GOROOT to
run
go list
with. This matches what the stdlib action does.Which issues(s) does this PR fix?
Fixes #3080
Other notes for review
I've updated the existing stdlib test to also depend on the output of
stdliblist, and verified that that fails with Go 1.18rc1 without this change.