Skip to content

Commit 21e441c

Browse files
committed
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 <[email protected]> Trust: Bryan C. Mills <[email protected]> Run-TryBot: Michael Matloob <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Jay Conrod <[email protected]> Reviewed-by: Bryan C. Mills <[email protected]>
1 parent 748c0d8 commit 21e441c

File tree

5 files changed

+125
-21
lines changed

5 files changed

+125
-21
lines changed

src/cmd/go/internal/work/exec.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2214,6 +2214,8 @@ func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []s
22142214
// when -trimpath is enabled.
22152215
if b.gccSupportsFlag(compiler, "-fdebug-prefix-map=a=b") {
22162216
if cfg.BuildTrimpath {
2217+
// TODO(#39958): handle overlays
2218+
22172219
// Keep in sync with Action.trimpath.
22182220
// The trimmed paths are a little different, but we need to trim in the
22192221
// same situations.

src/cmd/go/internal/work/gc.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,6 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, s
152152
// so these paths can be handed directly to tools.
153153
// Deleted files won't show up in when scanning directories earlier,
154154
// so OverlayPath will never return "" (meaning a deleted file) here.
155-
// TODO(#39958): Handle -trimprefix and other cases where
156-
// tools depend on the names of the files that are passed in.
157155
// TODO(#39958): Handle cases where the package directory
158156
// doesn't exist on disk (this can happen when all the package's
159157
// 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
167165
args = append(args, f)
168166
}
169167

170-
output, err = b.runOut(a, p.Dir, nil, args...)
168+
output, err = b.runOut(a, base.Cwd, nil, args...)
171169
return ofile, output, err
172170
}
173171

@@ -256,17 +254,28 @@ func (a *Action) trimpath() string {
256254
}
257255
rewrite := objdir + "=>"
258256

259-
// For "go build -trimpath", rewrite package source directory
260-
// to a file system-independent path (just the import path).
257+
rewriteDir := a.Package.Dir
261258
if cfg.BuildTrimpath {
262259
if m := a.Package.Module; m != nil && m.Version != "" {
263-
rewrite += ";" + a.Package.Dir + "=>" + m.Path + "@" + m.Version + strings.TrimPrefix(a.Package.ImportPath, m.Path)
260+
rewriteDir = m.Path + "@" + m.Version + strings.TrimPrefix(a.Package.ImportPath, m.Path)
264261
} else {
265-
rewrite += ";" + a.Package.Dir + "=>" + a.Package.ImportPath
262+
rewriteDir = a.Package.ImportPath
266263
}
264+
rewrite += ";" + a.Package.Dir + "=>" + rewriteDir
267265
}
268266

269-
// TODO(#39958): Add rewrite rules for overlaid files.
267+
// Add rewrites for overlays. The 'from' and 'to' paths in overlays don't need to have
268+
// same basename, so go from the overlay contents file path (passed to the compiler)
269+
// to the path the disk path would be rewritten to.
270+
if fsys.OverlayFile != "" {
271+
for _, filename := range a.Package.AllFiles() {
272+
overlayPath, ok := fsys.OverlayPath(filepath.Join(a.Package.Dir, filename))
273+
if !ok {
274+
continue
275+
}
276+
rewrite += ";" + overlayPath + "=>" + filepath.Join(rewriteDir, filename)
277+
}
278+
}
270279

271280
return rewrite
272281
}

src/cmd/go/internal/work/gccgo.go

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
"cmd/go/internal/base"
1717
"cmd/go/internal/cfg"
18+
"cmd/go/internal/fsys"
1819
"cmd/go/internal/load"
1920
"cmd/go/internal/str"
2021
"cmd/internal/pkgpath"
@@ -93,13 +94,37 @@ func (tools gccgoToolchain) gc(b *Builder, a *Action, archive string, importcfg
9394
args = append(args, "-I", root)
9495
}
9596
}
96-
if cfg.BuildTrimpath && b.gccSupportsFlag(args[:1], "-ffile-prefix-map=a=b") {
97-
args = append(args, "-ffile-prefix-map="+base.Cwd+"=.")
98-
args = append(args, "-ffile-prefix-map="+b.WorkDir+"=/tmp/go-build")
97+
98+
if b.gccSupportsFlag(args[:1], "-ffile-prefix-map=a=b") {
99+
if cfg.BuildTrimpath {
100+
args = append(args, "-ffile-prefix-map="+base.Cwd+"=.")
101+
args = append(args, "-ffile-prefix-map="+b.WorkDir+"=/tmp/go-build")
102+
}
103+
if fsys.OverlayFile != "" {
104+
for _, name := range gofiles {
105+
absPath := mkAbs(p.Dir, name)
106+
overlayPath, ok := fsys.OverlayPath(absPath)
107+
if !ok {
108+
continue
109+
}
110+
toPath := absPath
111+
// gccgo only applies the last matching rule, so also handle the case where
112+
// BuildTrimpath is true and the path is relative to base.Cwd.
113+
if cfg.BuildTrimpath && str.HasFilePathPrefix(toPath, base.Cwd) {
114+
toPath = "." + toPath[len(base.Cwd):]
115+
}
116+
args = append(args, "-ffile-prefix-map="+overlayPath+"="+toPath)
117+
}
118+
}
99119
}
120+
100121
args = append(args, a.Package.Internal.Gccgoflags...)
101122
for _, f := range gofiles {
102-
args = append(args, mkAbs(p.Dir, f))
123+
f := mkAbs(p.Dir, f)
124+
// Overlay files if necessary.
125+
// See comment on gctoolchain.gc about overlay TODOs
126+
f, _ = fsys.OverlayPath(f)
127+
args = append(args, f)
103128
}
104129

105130
output, err = b.runOut(a, p.Dir, nil, args)

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

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,52 +9,94 @@
99
# file in an overlay and one file outside the overlay, which in turn imports m/dir,
1010
# which only has source files in the overlay.
1111

12+
cd m
13+
1214
! go build .
1315
go build -overlay overlay.json -o main$GOEXE .
1416
exec ./main$goexe
1517
stdout '^hello$'
1618

17-
-- go.mod --
19+
go build -overlay overlay.json -o print_abspath$GOEXE ./printpath
20+
exec ./print_abspath$GOEXE
21+
stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go
22+
23+
go build -overlay overlay.json -o print_trimpath$GOEXE -trimpath ./printpath
24+
exec ./print_trimpath$GOEXE
25+
stdout ^m[/\\]printpath[/\\]main.go
26+
27+
# Run same tests but with gccgo.
28+
env GO111MODULE=off
29+
[!exec:gccgo] stop
30+
31+
! go build -compiler=gccgo .
32+
go build -compiler=gccgo -overlay overlay.json -o main_gccgo$GOEXE .
33+
exec ./main_gccgo$goexe
34+
stdout '^hello$'
35+
36+
go build -compiler=gccgo -overlay overlay.json -o print_abspath_gccgo$GOEXE ./printpath
37+
exec ./print_abspath_gccgo$GOEXE
38+
stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go
39+
40+
go build -compiler=gccgo -overlay overlay.json -o print_trimpath_gccgo$GOEXE -trimpath ./printpath
41+
exec ./print_trimpath_gccgo$GOEXE
42+
stdout ^\.[/\\]printpath[/\\]main.go
43+
44+
-- m/go.mod --
1845
// TODO(matloob): how do overlays work with go.mod (especially if mod=readonly)
1946
module m
2047

2148
go 1.16
2249

23-
-- dir2/h.go --
50+
-- m/dir2/h.go --
2451
package dir2
2552

2653
func PrintMessage() {
2754
printMessage()
2855
}
29-
-- dir/foo.txt --
56+
-- m/dir/foo.txt --
3057
The build action code currently expects the package directory
3158
to exist, so it can run the compiler in that directory.
3259
TODO(matloob): Remove this requirement.
33-
-- overlay.json --
60+
-- m/printpath/about.txt --
61+
the actual code is in the overlay
62+
-- m/overlay.json --
3463
{
3564
"Replace": {
3665
"f.go": "overlay/f.go",
3766
"dir/g.go": "overlay/dir_g.go",
38-
"dir2/i.go": "overlay/dir2_i.go"
67+
"dir2/i.go": "overlay/dir2_i.go",
68+
"printpath/main.go": "overlay/printpath.go"
3969
}
4070
}
41-
-- overlay/f.go --
71+
-- m/overlay/f.go --
4272
package main
4373

4474
import "m/dir2"
4575

4676
func main() {
4777
dir2.PrintMessage()
4878
}
49-
-- overlay/dir_g.go --
79+
-- m/overlay/dir_g.go --
5080
package dir
5181

5282
import "fmt"
5383

5484
func PrintMessage() {
5585
fmt.Println("hello")
5686
}
57-
-- overlay/dir2_i.go --
87+
-- m/overlay/printpath.go --
88+
package main
89+
90+
import (
91+
"fmt"
92+
"runtime"
93+
)
94+
95+
func main() {
96+
_, file, _, _ := runtime.Caller(0)
97+
fmt.Println(file)
98+
}
99+
-- m/overlay/dir2_i.go --
58100
package dir2
59101

60102
import "m/dir"

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

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ env GO111MODULE=on
99
mkdir $WORK/a/src/paths $WORK/b/src/paths
1010
cp paths.go $WORK/a/src/paths
1111
cp paths.go $WORK/b/src/paths
12+
cp overlay.json $WORK/a/src/paths
13+
cp overlay.json $WORK/b/src/paths
1214
cp go.mod $WORK/a/src/paths/
1315
cp go.mod $WORK/b/src/paths/
1416

@@ -43,6 +45,29 @@ go build -trimpath -o $WORK/paths-b.exe
4345
cmp -q $WORK/paths-a.exe $WORK/paths-b.exe
4446

4547

48+
# Same sequence of tests but with overlays.
49+
# A binary built without -trimpath should contain the module root dir
50+
# and GOROOT for debugging and stack traces.
51+
cd $WORK/a/src/paths
52+
go build -overlay overlay.json -o $WORK/paths-dbg.exe ./overlaydir
53+
exec $WORK/paths-dbg.exe $WORK/paths-dbg.exe
54+
stdout 'binary contains module root: true'
55+
stdout 'binary contains GOROOT: true'
56+
57+
# A binary built with -trimpath should not contain the current workspace
58+
# or GOROOT.
59+
go build -overlay overlay.json -trimpath -o $WORK/paths-a.exe ./overlaydir
60+
exec $WORK/paths-a.exe $WORK/paths-a.exe
61+
stdout 'binary contains module root: false'
62+
stdout 'binary contains GOROOT: false'
63+
64+
# Two binaries built from identical packages in different directories
65+
# should be identical.
66+
cd $WORK/b/src/paths
67+
go build -overlay overlay.json -trimpath -o $WORK/paths-b.exe ./overlaydir
68+
cmp -q $WORK/paths-a.exe $WORK/paths-b.exe
69+
70+
4671
# Same sequence of tests but in GOPATH mode.
4772
# A binary built without -trimpath should contain GOPATH and GOROOT.
4873
env GO111MODULE=off
@@ -129,7 +154,8 @@ func check(data []byte, desc, dir string) {
129154
containsSlashDir := bytes.Contains(data, []byte(filepath.ToSlash(dir)))
130155
fmt.Printf("binary contains %s: %v\n", desc, containsDir || containsSlashDir)
131156
}
132-
157+
-- overlay.json --
158+
{ "Replace": { "overlaydir/paths.go": "paths.go" } }
133159
-- go.mod --
134160
module paths
135161

0 commit comments

Comments
 (0)