Skip to content

Commit 6378c0e

Browse files
author
Bryan C. Mills
committed
go/build: avoid setting Default.GOROOT when runtime.GOROOT() is empty
Previously, we called path.Clean on the value of runtime.GOROOT() even if it was empty, which would set it explicitly to ".". That would cause (*Context).importGo to assume that errors resolving paths in GOROOT are fatal and return early: https://cs.opensource.google/go/go/+/master:src/go/build/build.go;l=1121-1127;drc=38174b3a3514629b84dcd76878b2f536b189dd7b If we instead leave it empty (and are in module mode), then importGo will fall back to letting the 'go' command resolve the path, which may succeed if the 'go' command can infer the correct GOROOT (from its own stamped-in default GOROOT or executable path). Fixes #51483 Change-Id: I44dce7cec6c3d1c86670e629ddfbca8be461130c Reviewed-on: https://go-review.googlesource.com/c/go/+/391805 Trust: Bryan Mills <[email protected]> Run-TryBot: Bryan Mills <[email protected]> Reviewed-by: Russ Cox <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 58631ba commit 6378c0e

File tree

3 files changed

+27
-24
lines changed

3 files changed

+27
-24
lines changed

src/cmd/go/testdata/script/build_trimpath_goroot.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ stdout '^runtime '$TESTGO_GOROOT${/}src${/}runtime'$'
2323

2424
! go run -trimpath .
2525
stdout '^GOROOT $'
26-
stderr '^package runtime is not in GOROOT \(src'${/}'runtime\)$'
26+
stderr 'cannot find package "runtime" in any of:\n\t\(\$GOROOT not set\)\n\t'$WORK${/}gopath${/}src${/}runtime' \(from \$GOPATH\)\nexit status 1\n\z'
2727

2828
! go test -trimpath -v .
2929
stdout '^GOROOT $'
30-
stdout '^package runtime is not in GOROOT \(src'${/}'runtime\)$'
30+
stdout 'cannot find package "runtime" in any of:\n\t\(\$GOROOT not set\)\n\t'$WORK${/}gopath${/}src${/}runtime' \(from \$GOPATH\)$'
3131

3232
-- go.mod --
3333
module example

src/go/build/build.go

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ type Context struct {
3535
GOARCH string // target architecture
3636
GOOS string // target operating system
3737
GOROOT string // Go root
38-
GOPATH string // Go path
38+
GOPATH string // Go paths
3939

4040
// Dir is the caller's working directory, or the empty string to use
4141
// the current directory of the running process. In module mode, this is used
@@ -302,7 +302,9 @@ func defaultContext() Context {
302302

303303
c.GOARCH = buildcfg.GOARCH
304304
c.GOOS = buildcfg.GOOS
305-
c.GOROOT = pathpkg.Clean(runtime.GOROOT())
305+
if goroot := runtime.GOROOT(); goroot != "" {
306+
c.GOROOT = filepath.Clean(goroot)
307+
}
306308
c.GOPATH = envOr("GOPATH", defaultGOPATH())
307309
c.Compiler = runtime.Compiler
308310

@@ -672,7 +674,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
672674
}
673675
return false
674676
}
675-
if ctxt.Compiler != "gccgo" && searchVendor(ctxt.GOROOT, true) {
677+
if ctxt.Compiler != "gccgo" && ctxt.GOROOT != "" && searchVendor(ctxt.GOROOT, true) {
676678
goto Found
677679
}
678680
for _, root := range gopath {
@@ -706,12 +708,12 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
706708
}
707709
tried.goroot = dir
708710
}
709-
}
710-
if ctxt.Compiler == "gccgo" && goroot.IsStandardPackage(ctxt.GOROOT, ctxt.Compiler, path) {
711-
p.Dir = ctxt.joinPath(ctxt.GOROOT, "src", path)
712-
p.Goroot = true
713-
p.Root = ctxt.GOROOT
714-
goto Found
711+
if ctxt.Compiler == "gccgo" && goroot.IsStandardPackage(ctxt.GOROOT, ctxt.Compiler, path) {
712+
p.Dir = ctxt.joinPath(ctxt.GOROOT, "src", path)
713+
p.Goroot = true
714+
p.Root = ctxt.GOROOT
715+
goto Found
716+
}
715717
}
716718
for _, root := range gopath {
717719
dir := ctxt.joinPath(root, "src", path)
@@ -1082,6 +1084,13 @@ func (ctxt *Context) importGo(p *Package, path, srcDir string, mode ImportMode)
10821084
return errNoModules
10831085
}
10841086

1087+
// If ctxt.GOROOT is not set, we don't know which go command to invoke,
1088+
// and even if we did we might return packages in GOROOT that we wouldn't otherwise find
1089+
// (because we don't know to search in 'go env GOROOT' otherwise).
1090+
if ctxt.GOROOT == "" {
1091+
return errNoModules
1092+
}
1093+
10851094
// Predict whether module aware mode is enabled by checking the value of
10861095
// GO111MODULE and looking for a go.mod file in the source directory or
10871096
// one of its parents. Running 'go env GOMOD' in the source directory would
@@ -1119,11 +1128,8 @@ func (ctxt *Context) importGo(p *Package, path, srcDir string, mode ImportMode)
11191128
}
11201129

11211130
// For efficiency, if path is a standard library package, let the usual lookup code handle it.
1122-
if ctxt.GOROOT != "" {
1123-
dir := ctxt.joinPath(ctxt.GOROOT, "src", path)
1124-
if ctxt.isDir(dir) {
1125-
return errNoModules
1126-
}
1131+
if dir := ctxt.joinPath(ctxt.GOROOT, "src", path); ctxt.isDir(dir) {
1132+
return errNoModules
11271133
}
11281134

11291135
// If GO111MODULE=auto, look to see if there is a go.mod.
@@ -1165,7 +1171,8 @@ func (ctxt *Context) importGo(p *Package, path, srcDir string, mode ImportMode)
11651171
}
11661172
}
11671173

1168-
cmd := exec.Command("go", "list", "-e", "-compiler="+ctxt.Compiler, "-tags="+strings.Join(ctxt.BuildTags, ","), "-installsuffix="+ctxt.InstallSuffix, "-f={{.Dir}}\n{{.ImportPath}}\n{{.Root}}\n{{.Goroot}}\n{{if .Error}}{{.Error}}{{end}}\n", "--", path)
1174+
goCmd := filepath.Join(ctxt.GOROOT, "bin", "go")
1175+
cmd := exec.Command(goCmd, "list", "-e", "-compiler="+ctxt.Compiler, "-tags="+strings.Join(ctxt.BuildTags, ","), "-installsuffix="+ctxt.InstallSuffix, "-f={{.Dir}}\n{{.ImportPath}}\n{{.Root}}\n{{.Goroot}}\n{{if .Error}}{{.Error}}{{end}}\n", "--", path)
11691176

11701177
if ctxt.Dir != "" {
11711178
cmd.Dir = ctxt.Dir

src/go/build/build_test.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
package build
66

77
import (
8-
"flag"
98
"internal/testenv"
109
"io"
1110
"os"
@@ -17,10 +16,7 @@ import (
1716
)
1817

1918
func TestMain(m *testing.M) {
20-
flag.Parse()
21-
if goTool, err := testenv.GoTool(); err == nil {
22-
os.Setenv("PATH", filepath.Dir(goTool)+string(os.PathListSeparator)+os.Getenv("PATH"))
23-
}
19+
Default.GOROOT = testenv.GOROOT(nil)
2420
os.Exit(m.Run())
2521
}
2622

@@ -84,7 +80,7 @@ func TestDotSlashImport(t *testing.T) {
8480
}
8581

8682
func TestEmptyImport(t *testing.T) {
87-
p, err := Import("", Default.GOROOT, FindOnly)
83+
p, err := Import("", testenv.GOROOT(t), FindOnly)
8884
if err == nil {
8985
t.Fatal(`Import("") returned nil error.`)
9086
}
@@ -658,7 +654,7 @@ func TestImportDirTarget(t *testing.T) {
658654
testenv.MustHaveGoBuild(t) // really must just have source
659655
ctxt := Default
660656
ctxt.GOPATH = ""
661-
p, err := ctxt.ImportDir(filepath.Join(ctxt.GOROOT, "src/path"), 0)
657+
p, err := ctxt.ImportDir(filepath.Join(testenv.GOROOT(t), "src/path"), 0)
662658
if err != nil {
663659
t.Fatal(err)
664660
}

0 commit comments

Comments
 (0)