)
// The 'path' used for GOROOT_FINAL when -trimpath is specified
-const trimPathGoRootFinal = "go"
+const trimPathGoRootFinal string = "$GOROOT"
var runtimePackages = map[string]struct{}{
"internal/abi": struct{}{},
--- /dev/null
+# Regression test for https://go.dev/issue/51461 and https://go.dev/issue/51483.
+#
+# When built with -trimpath, runtime.GOROOT() returned the bogus string "go"
+# if GOROOT was not set explicitly in the environment.
+# It should instead return the empty string, since we know that we don't
+# have a valid path to return.
+#
+# TODO(#51483): when runtime.GOROOT() returns the empty string,
+# go/build should default to 'go env GOROOT' instead.
+
+[short] skip
+
+env GOROOT=
+env GOROOT_FINAL=
+
+go run .
+stdout '^GOROOT '$TESTGO_GOROOT'$'
+stdout '^runtime '$TESTGO_GOROOT${/}src${/}runtime'$'
+
+go test -v .
+stdout '^GOROOT '$TESTGO_GOROOT'$'
+stdout '^runtime '$TESTGO_GOROOT${/}src${/}runtime'$'
+
+! go run -trimpath .
+stdout '^GOROOT $'
+stderr '^package runtime is not in GOROOT \(src'${/}'runtime\)$'
+
+! go test -trimpath -v .
+stdout '^GOROOT $'
+stdout '^package runtime is not in GOROOT \(src'${/}'runtime\)$'
+
+-- go.mod --
+module example
+
+go 1.19
+-- main.go --
+package main
+
+import (
+ "fmt"
+ "go/build"
+ "os"
+ "runtime"
+)
+
+func main() {
+ fmt.Println("GOROOT", runtime.GOROOT())
+
+ p, err := build.Default.Import("runtime", "", build.FindOnly)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ fmt.Println("runtime", p.Dir)
+}
+-- main_test.go --
+package main
+
+import "testing"
+
+func TestMain(*testing.M) {
+ main()
+}
}
}
- final := gorootFinal()
- addstrdata1(ctxt, "runtime.defaultGOROOT="+final)
+ if final := gorootFinal(); final == "$GOROOT" {
+ // cmd/go sets GOROOT_FINAL to the dummy value "$GOROOT" when -trimpath is set,
+ // but runtime.GOROOT() should return the empty string, not a bogus value.
+ // (See https://go.dev/issue/51461.)
+ } else {
+ addstrdata1(ctxt, "runtime.defaultGOROOT="+final)
+ }
buildVersion := buildcfg.Version
if goexperiment := buildcfg.Experiment.String(); goexperiment != "" {
func expandGoroot(s string) string {
const n = len("$GOROOT")
if len(s) >= n+1 && s[:n] == "$GOROOT" && (s[n] == '/' || s[n] == '\\') {
- return filepath.ToSlash(filepath.Join(gorootFinal(), s[n:]))
+ if final := gorootFinal(); final != "" {
+ return filepath.ToSlash(filepath.Join(final, s[n:]))
+ }
}
return s
}