Skip to content

Commit 65ffee6

Browse files
author
Bryan C. Mills
committed
cmd/go: insert goroot to the hash of build cache when the packages include C files
This reverts CL 351851, which itself reverted CL 348991. The problem with the original CL, as far as I can tell, was due to a bug in the Go project's builder infrastructure (#33598) and not the change itself. Once the build infrastructure is fixed, this change can be resubmitted. Fixes #48319 Updates #33598 Change-Id: I0fdbcc241eb2bdeb350944aad58bf58774fb591e Reviewed-on: https://go-review.googlesource.com/c/go/+/353352 Trust: Bryan C. Mills <[email protected]> Run-TryBot: Bryan C. Mills <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Jay Conrod <[email protected]>
1 parent 52078fa commit 65ffee6

File tree

2 files changed

+177
-10
lines changed

2 files changed

+177
-10
lines changed

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

+24-10
Original file line numberDiff line numberDiff line change
@@ -223,18 +223,32 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
223223
// same compiler settings and can reuse each other's results.
224224
// If not, the reason is already recorded in buildGcflags.
225225
fmt.Fprintf(h, "compile\n")
226-
// Only include the package directory if it may affect the output.
227-
// We trim workspace paths for all packages when -trimpath is set.
228-
// The compiler hides the exact value of $GOROOT
229-
// when building things in GOROOT.
230-
// Assume b.WorkDir is being trimmed properly.
231-
// When -trimpath is used with a package built from the module cache,
232-
// use the module path and version instead of the directory.
233-
if !p.Goroot && !cfg.BuildTrimpath && !strings.HasPrefix(p.Dir, b.WorkDir) {
226+
227+
// Include information about the origin of the package that
228+
// may be embedded in the debug info for the object file.
229+
if cfg.BuildTrimpath {
230+
// When -trimpath is used with a package built from the module cache,
231+
// its debug information refers to the module path and version
232+
// instead of the directory.
233+
if p.Module != nil {
234+
fmt.Fprintf(h, "module %s@%s\n", p.Module.Path, p.Module.Version)
235+
}
236+
} else if p.Goroot {
237+
// The Go compiler always hides the exact value of $GOROOT
238+
// when building things in GOROOT, but the C compiler
239+
// merely rewrites GOROOT to GOROOT_FINAL.
240+
if len(p.CFiles) > 0 {
241+
fmt.Fprintf(h, "goroot %s\n", cfg.GOROOT_FINAL)
242+
}
243+
// b.WorkDir is always either trimmed or rewritten to
244+
// the literal string "/tmp/go-build".
245+
} else if !strings.HasPrefix(p.Dir, b.WorkDir) {
246+
// -trimpath is not set and no other rewrite rules apply,
247+
// so the object file may refer to the absolute directory
248+
// containing the package.
234249
fmt.Fprintf(h, "dir %s\n", p.Dir)
235-
} else if cfg.BuildTrimpath && p.Module != nil {
236-
fmt.Fprintf(h, "module %s@%s\n", p.Module.Path, p.Module.Version)
237250
}
251+
238252
if p.Module != nil {
239253
fmt.Fprintf(h, "go %s\n", p.Module.GoVersion)
240254
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
[short] skip
2+
[!cgo] skip
3+
4+
# Set up fresh GOCACHE
5+
env GOCACHE=$WORK/gocache
6+
mkdir $GOCACHE
7+
8+
# 1. unset GOROOT_FINAL, Build a simple binary with cgo by origin go.
9+
# The DW_AT_comp_dir of runtime/cgo should have a prefix with origin goroot.
10+
env GOROOT_FINAL=
11+
# If using "go run", it is no debuginfo in binary. So use "go build".
12+
# And we can check the stderr to judge if the cache of "runtime/cgo"
13+
# was used or not.
14+
go build -o binary.exe
15+
exec ./binary.exe $TESTGO_GOROOT
16+
stdout 'cgo DW_AT_comp_dir is right in binary'
17+
18+
19+
# 2. GOROOT_FINAL will be changed, the runtime/cgo will be rebuild.
20+
env GOROOT_FINAL=$WORK/gorootfinal
21+
go build -x -o binary.exe
22+
stderr '(clang|gcc)( |\.exe).*gcc_.*\.c'
23+
exec ./binary.exe $GOROOT_FINAL
24+
stdout 'cgo DW_AT_comp_dir is right in binary'
25+
26+
27+
[!symlink] skip
28+
29+
# Symlink the compiler to another path
30+
env GOROOT=$WORK/goroot
31+
symlink $GOROOT -> $TESTGO_GOROOT
32+
33+
# 3. GOROOT_FINAL is same with 2, build with the other go
34+
# the runtime/cgo will not be rebuild.
35+
go build -x -o binary.exe
36+
! stderr '(clang|gcc)( |\.exe).*gcc_.*\.c'
37+
exec ./binary.exe $GOROOT_FINAL
38+
stdout 'cgo DW_AT_comp_dir is right in binary'
39+
40+
41+
# 4. unset GOROOT_FINAL, build with the other go
42+
# the runtime/cgo will be rebuild.
43+
env GOROOT_FINAL=
44+
go build -x -o binary.exe
45+
stderr '(clang|gcc)( |\.exe).*gcc_.*\.c'
46+
exec ./binary.exe $GOROOT
47+
stdout 'cgo DW_AT_comp_dir is right in binary'
48+
49+
-- go.mod --
50+
module main
51+
52+
go 1.18
53+
-- main.go --
54+
package main
55+
56+
import "C"
57+
import (
58+
"debug/dwarf"
59+
"fmt"
60+
"log"
61+
"os"
62+
"path/filepath"
63+
"strings"
64+
)
65+
66+
var _ C.int
67+
68+
func main() {
69+
dwarfData, err := readDWARF(os.Args[0])
70+
if err != nil {
71+
log.Fatal(err)
72+
}
73+
goroot := filepath.Join(os.Args[1], "src")
74+
dwarfReader := dwarfData.Reader()
75+
cgopackage := filepath.Join("runtime", "cgo")
76+
var hascgo bool
77+
for {
78+
e, err := dwarfReader.Next()
79+
if err != nil {
80+
log.Fatal(err)
81+
}
82+
if e == nil {
83+
break
84+
}
85+
field := e.AttrField(dwarf.AttrCompDir)
86+
if field == nil {
87+
continue
88+
}
89+
compdir := field.Val.(string)
90+
if strings.HasSuffix(compdir, cgopackage) {
91+
hascgo = true
92+
if !strings.HasPrefix(compdir, goroot) {
93+
fmt.Printf("cgo DW_AT_comp_dir %s contains incorrect path in binary.\n", compdir)
94+
return
95+
}
96+
}
97+
}
98+
if hascgo {
99+
fmt.Println("cgo DW_AT_comp_dir is right in binary")
100+
} else {
101+
fmt.Println("binary does not contain cgo")
102+
}
103+
}
104+
-- read_darwin.go --
105+
package main
106+
107+
import (
108+
"debug/dwarf"
109+
"debug/macho"
110+
)
111+
112+
func readDWARF(exePath string) (*dwarf.Data, error) {
113+
machoFile, err := macho.Open(exePath)
114+
if err != nil {
115+
return nil, err
116+
}
117+
defer machoFile.Close()
118+
return machoFile.DWARF()
119+
}
120+
-- read_elf.go --
121+
// +build android dragonfly freebsd illumos linux netbsd openbsd solaris
122+
123+
package main
124+
125+
import (
126+
"debug/dwarf"
127+
"debug/elf"
128+
)
129+
130+
func readDWARF(exePath string) (*dwarf.Data, error) {
131+
elfFile, err := elf.Open(exePath)
132+
if err != nil {
133+
return nil, err
134+
}
135+
defer elfFile.Close()
136+
return elfFile.DWARF()
137+
}
138+
-- read_windows.go --
139+
package main
140+
141+
import (
142+
"debug/dwarf"
143+
"debug/pe"
144+
)
145+
146+
func readDWARF(exePath string) (*dwarf.Data, error) {
147+
peFile, err := pe.Open(exePath)
148+
if err != nil {
149+
return nil, err
150+
}
151+
defer peFile.Close()
152+
return peFile.DWARF()
153+
}

0 commit comments

Comments
 (0)