1
0
mirror of https://github.com/golang/go synced 2024-11-27 01:11:20 -07:00

cmd/go: rewrite paths for overlaid files using -trimpath

Pass the trimpath flag to cmd/compile to use the correct file paths
for files that are overlaid: that is, the "destination" path in the
overlay's Replace mapping rather than the "source" path.

Also fix paths to go source files provided to the gccgo compiler.

For #39958

Change-Id: I3741aeb2272bd0d5aa32cb28133b61e58264fd39
Reviewed-on: https://go-review.googlesource.com/c/go/+/257198
Trust: Michael Matloob <matloob@golang.org>
Trust: Bryan C. Mills <bcmills@google.com>
Run-TryBot: Michael Matloob <matloob@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
Michael Matloob 2020-10-14 16:21:39 -04:00
parent 748c0d87e2
commit 21e441c461
5 changed files with 125 additions and 21 deletions

View File

@ -2214,6 +2214,8 @@ func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []s
// when -trimpath is enabled.
if b.gccSupportsFlag(compiler, "-fdebug-prefix-map=a=b") {
if cfg.BuildTrimpath {
// TODO(#39958): handle overlays
// Keep in sync with Action.trimpath.
// The trimmed paths are a little different, but we need to trim in the
// same situations.

View File

@ -152,8 +152,6 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, s
// so these paths can be handed directly to tools.
// Deleted files won't show up in when scanning directories earlier,
// so OverlayPath will never return "" (meaning a deleted file) here.
// TODO(#39958): Handle -trimprefix and other cases where
// tools depend on the names of the files that are passed in.
// TODO(#39958): Handle cases where the package directory
// doesn't exist on disk (this can happen when all the package's
// files are in an overlay): the code expects the package directory
@ -167,7 +165,7 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, s
args = append(args, f)
}
output, err = b.runOut(a, p.Dir, nil, args...)
output, err = b.runOut(a, base.Cwd, nil, args...)
return ofile, output, err
}
@ -256,17 +254,28 @@ func (a *Action) trimpath() string {
}
rewrite := objdir + "=>"
// For "go build -trimpath", rewrite package source directory
// to a file system-independent path (just the import path).
rewriteDir := a.Package.Dir
if cfg.BuildTrimpath {
if m := a.Package.Module; m != nil && m.Version != "" {
rewrite += ";" + a.Package.Dir + "=>" + m.Path + "@" + m.Version + strings.TrimPrefix(a.Package.ImportPath, m.Path)
rewriteDir = m.Path + "@" + m.Version + strings.TrimPrefix(a.Package.ImportPath, m.Path)
} else {
rewrite += ";" + a.Package.Dir + "=>" + a.Package.ImportPath
rewriteDir = a.Package.ImportPath
}
rewrite += ";" + a.Package.Dir + "=>" + rewriteDir
}
// TODO(#39958): Add rewrite rules for overlaid files.
// Add rewrites for overlays. The 'from' and 'to' paths in overlays don't need to have
// same basename, so go from the overlay contents file path (passed to the compiler)
// to the path the disk path would be rewritten to.
if fsys.OverlayFile != "" {
for _, filename := range a.Package.AllFiles() {
overlayPath, ok := fsys.OverlayPath(filepath.Join(a.Package.Dir, filename))
if !ok {
continue
}
rewrite += ";" + overlayPath + "=>" + filepath.Join(rewriteDir, filename)
}
}
return rewrite
}

View File

@ -15,6 +15,7 @@ import (
"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/fsys"
"cmd/go/internal/load"
"cmd/go/internal/str"
"cmd/internal/pkgpath"
@ -93,13 +94,37 @@ func (tools gccgoToolchain) gc(b *Builder, a *Action, archive string, importcfg
args = append(args, "-I", root)
}
}
if cfg.BuildTrimpath && b.gccSupportsFlag(args[:1], "-ffile-prefix-map=a=b") {
args = append(args, "-ffile-prefix-map="+base.Cwd+"=.")
args = append(args, "-ffile-prefix-map="+b.WorkDir+"=/tmp/go-build")
if b.gccSupportsFlag(args[:1], "-ffile-prefix-map=a=b") {
if cfg.BuildTrimpath {
args = append(args, "-ffile-prefix-map="+base.Cwd+"=.")
args = append(args, "-ffile-prefix-map="+b.WorkDir+"=/tmp/go-build")
}
if fsys.OverlayFile != "" {
for _, name := range gofiles {
absPath := mkAbs(p.Dir, name)
overlayPath, ok := fsys.OverlayPath(absPath)
if !ok {
continue
}
toPath := absPath
// gccgo only applies the last matching rule, so also handle the case where
// BuildTrimpath is true and the path is relative to base.Cwd.
if cfg.BuildTrimpath && str.HasFilePathPrefix(toPath, base.Cwd) {
toPath = "." + toPath[len(base.Cwd):]
}
args = append(args, "-ffile-prefix-map="+overlayPath+"="+toPath)
}
}
}
args = append(args, a.Package.Internal.Gccgoflags...)
for _, f := range gofiles {
args = append(args, mkAbs(p.Dir, f))
f := mkAbs(p.Dir, f)
// Overlay files if necessary.
// See comment on gctoolchain.gc about overlay TODOs
f, _ = fsys.OverlayPath(f)
args = append(args, f)
}
output, err = b.runOut(a, p.Dir, nil, args)

View File

@ -9,36 +9,66 @@
# file in an overlay and one file outside the overlay, which in turn imports m/dir,
# which only has source files in the overlay.
cd m
! go build .
go build -overlay overlay.json -o main$GOEXE .
exec ./main$goexe
stdout '^hello$'
-- go.mod --
go build -overlay overlay.json -o print_abspath$GOEXE ./printpath
exec ./print_abspath$GOEXE
stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go
go build -overlay overlay.json -o print_trimpath$GOEXE -trimpath ./printpath
exec ./print_trimpath$GOEXE
stdout ^m[/\\]printpath[/\\]main.go
# Run same tests but with gccgo.
env GO111MODULE=off
[!exec:gccgo] stop
! go build -compiler=gccgo .
go build -compiler=gccgo -overlay overlay.json -o main_gccgo$GOEXE .
exec ./main_gccgo$goexe
stdout '^hello$'
go build -compiler=gccgo -overlay overlay.json -o print_abspath_gccgo$GOEXE ./printpath
exec ./print_abspath_gccgo$GOEXE
stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go
go build -compiler=gccgo -overlay overlay.json -o print_trimpath_gccgo$GOEXE -trimpath ./printpath
exec ./print_trimpath_gccgo$GOEXE
stdout ^\.[/\\]printpath[/\\]main.go
-- m/go.mod --
// TODO(matloob): how do overlays work with go.mod (especially if mod=readonly)
module m
go 1.16
-- dir2/h.go --
-- m/dir2/h.go --
package dir2
func PrintMessage() {
printMessage()
}
-- dir/foo.txt --
-- m/dir/foo.txt --
The build action code currently expects the package directory
to exist, so it can run the compiler in that directory.
TODO(matloob): Remove this requirement.
-- overlay.json --
-- m/printpath/about.txt --
the actual code is in the overlay
-- m/overlay.json --
{
"Replace": {
"f.go": "overlay/f.go",
"dir/g.go": "overlay/dir_g.go",
"dir2/i.go": "overlay/dir2_i.go"
"dir2/i.go": "overlay/dir2_i.go",
"printpath/main.go": "overlay/printpath.go"
}
}
-- overlay/f.go --
-- m/overlay/f.go --
package main
import "m/dir2"
@ -46,7 +76,7 @@ import "m/dir2"
func main() {
dir2.PrintMessage()
}
-- overlay/dir_g.go --
-- m/overlay/dir_g.go --
package dir
import "fmt"
@ -54,7 +84,19 @@ import "fmt"
func PrintMessage() {
fmt.Println("hello")
}
-- overlay/dir2_i.go --
-- m/overlay/printpath.go --
package main
import (
"fmt"
"runtime"
)
func main() {
_, file, _, _ := runtime.Caller(0)
fmt.Println(file)
}
-- m/overlay/dir2_i.go --
package dir2
import "m/dir"

View File

@ -9,6 +9,8 @@ env GO111MODULE=on
mkdir $WORK/a/src/paths $WORK/b/src/paths
cp paths.go $WORK/a/src/paths
cp paths.go $WORK/b/src/paths
cp overlay.json $WORK/a/src/paths
cp overlay.json $WORK/b/src/paths
cp go.mod $WORK/a/src/paths/
cp go.mod $WORK/b/src/paths/
@ -43,6 +45,29 @@ go build -trimpath -o $WORK/paths-b.exe
cmp -q $WORK/paths-a.exe $WORK/paths-b.exe
# Same sequence of tests but with overlays.
# A binary built without -trimpath should contain the module root dir
# and GOROOT for debugging and stack traces.
cd $WORK/a/src/paths
go build -overlay overlay.json -o $WORK/paths-dbg.exe ./overlaydir
exec $WORK/paths-dbg.exe $WORK/paths-dbg.exe
stdout 'binary contains module root: true'
stdout 'binary contains GOROOT: true'
# A binary built with -trimpath should not contain the current workspace
# or GOROOT.
go build -overlay overlay.json -trimpath -o $WORK/paths-a.exe ./overlaydir
exec $WORK/paths-a.exe $WORK/paths-a.exe
stdout 'binary contains module root: false'
stdout 'binary contains GOROOT: false'
# Two binaries built from identical packages in different directories
# should be identical.
cd $WORK/b/src/paths
go build -overlay overlay.json -trimpath -o $WORK/paths-b.exe ./overlaydir
cmp -q $WORK/paths-a.exe $WORK/paths-b.exe
# Same sequence of tests but in GOPATH mode.
# A binary built without -trimpath should contain GOPATH and GOROOT.
env GO111MODULE=off
@ -129,7 +154,8 @@ func check(data []byte, desc, dir string) {
containsSlashDir := bytes.Contains(data, []byte(filepath.ToSlash(dir)))
fmt.Printf("binary contains %s: %v\n", desc, containsDir || containsSlashDir)
}
-- overlay.json --
{ "Replace": { "overlaydir/paths.go": "paths.go" } }
-- go.mod --
module paths