1
0
mirror of https://github.com/golang/go synced 2024-11-17 18:34:44 -07:00

cmd/go: do not pass a local prefix to the compiler in module mode

In GOPATH mode, source files may import other packages using relative
(“local”) paths. In module mode, relative imports are never allowed:
import paths must always be fully specified.

When local imports are allowed, we pass a local-import prefix to the
compiler using the '-D' flag. That could theoretically change the
compiler's output, so it must be included in the cache key even when
-trimpath is set. (TODO: when -trimpath is set, the local-import
prefix ought to be trimmed anyway, so it still shouldn't matter.)

However, when local imports are disallowed, we should not pass the
local-import prefix and it should not affect cmd/go's cache key or the
final build ID of any artifact.

For #48557

Change-Id: I2d627d67d13e5da2cac6d411cd4e2d87e510876c
Reviewed-on: https://go-review.googlesource.com/c/go/+/352810
Trust: Bryan C. Mills <bcmills@google.com>
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
This commit is contained in:
Bryan C. Mills 2021-09-28 11:52:45 -04:00
parent 7109323af5
commit 316057142c
3 changed files with 61 additions and 5 deletions

View File

@ -1678,9 +1678,10 @@ func (p *Package) DefaultExecName() string {
func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk *ImportStack, importPos []token.Position, bp *build.Package, err error) {
p.copyBuild(opts, bp)
// The localPrefix is the path we interpret ./ imports relative to.
// The localPrefix is the path we interpret ./ imports relative to,
// if we support them at all (not in module mode!).
// Synthesized main packages sometimes override this.
if p.Internal.Local {
if p.Internal.Local && !cfg.ModulesEnabled {
p.Internal.LocalPrefix = dirToImportPath(p.Dir)
}
@ -2703,7 +2704,9 @@ func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Pa
pkg.Internal.Local = true
pkg.Internal.CmdlineFiles = true
pkg.load(ctx, opts, "command-line-arguments", &stk, nil, bp, err)
pkg.Internal.LocalPrefix = dirToImportPath(dir)
if !cfg.ModulesEnabled {
pkg.Internal.LocalPrefix = dirToImportPath(dir)
}
pkg.ImportPath = "command-line-arguments"
pkg.Target = ""
pkg.Match = gofiles

View File

@ -165,8 +165,9 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg
}
args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", a.trimpath(), defaultGcFlags, gcflags}
if p.Internal.LocalPrefix != "" {
// Workaround #43883.
if p.Internal.LocalPrefix == "" {
args = append(args, "-nolocalimports")
} else {
args = append(args, "-D", p.Internal.LocalPrefix)
}
if importcfg != nil {

View File

@ -0,0 +1,52 @@
# Regression test for issue #48557.
# Since builds in module mode do not support relative imports at all, the build
# ID for (and other contents of) a binary built with -trimpath in module mode
# should not depend on its working directory, even if the binary is specified as
# a list of relative source files.
[short] skip # links and runs binaries
env GOFLAGS=-trimpath
env GOCACHE=$WORK/gocache
# When we build a binary in module mode with -trimpath, the -D flag (for the
# "local import prefix") should not be passed to it.
cd $WORK/tmp/foo
go build -x -o a.exe main.go
stderr ${/}compile$GOEXE.*' -nolocalimports'
! stderr ${/}compile$GOEXE.*' -D[ =]'
go tool buildid a.exe
cp stdout ../foo-buildid.txt
go version a.exe
cp stdout ../foo-version.txt
cd ..
# On the second build — in a different directory but with -trimpath — the
# compiler should not be invoked, since the cache key should be identical.
# Only the linker and buildid tool should be needed.
mkdir bar
cp foo/main.go bar/main.go
cd bar
go build -x -o a.exe main.go
! stderr ${/}compile$GOEXE
go tool buildid a.exe
cp stdout ../bar-buildid.txt
go version a.exe
cp stdout ../bar-version.txt
cd ..
cmp bar-buildid.txt foo-buildid.txt
cmp bar-version.txt foo-version.txt
cmp bar/a.exe foo/a.exe
-- $WORK/tmp/foo/main.go --
package main
func main() {}