Skip to content

Commit

Permalink
cmd/go: insert goroot to the hash of build cache when the packages in…
Browse files Browse the repository at this point in the history
…clude 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 <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>
  • Loading branch information
Bryan C. Mills committed Oct 11, 2021
1 parent 52078fa commit 65ffee6
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 10 deletions.
34 changes: 24 additions & 10 deletions src/cmd/go/internal/work/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,18 +223,32 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
// same compiler settings and can reuse each other's results.
// If not, the reason is already recorded in buildGcflags.
fmt.Fprintf(h, "compile\n")
// Only include the package directory if it may affect the output.
// We trim workspace paths for all packages when -trimpath is set.
// The compiler hides the exact value of $GOROOT
// when building things in GOROOT.
// Assume b.WorkDir is being trimmed properly.
// When -trimpath is used with a package built from the module cache,
// use the module path and version instead of the directory.
if !p.Goroot && !cfg.BuildTrimpath && !strings.HasPrefix(p.Dir, b.WorkDir) {

// Include information about the origin of the package that
// may be embedded in the debug info for the object file.
if cfg.BuildTrimpath {
// When -trimpath is used with a package built from the module cache,
// its debug information refers to the module path and version
// instead of the directory.
if p.Module != nil {
fmt.Fprintf(h, "module %s@%s\n", p.Module.Path, p.Module.Version)
}
} else if p.Goroot {
// The Go compiler always hides the exact value of $GOROOT
// when building things in GOROOT, but the C compiler
// merely rewrites GOROOT to GOROOT_FINAL.
if len(p.CFiles) > 0 {
fmt.Fprintf(h, "goroot %s\n", cfg.GOROOT_FINAL)
}
// b.WorkDir is always either trimmed or rewritten to
// the literal string "/tmp/go-build".
} else if !strings.HasPrefix(p.Dir, b.WorkDir) {
// -trimpath is not set and no other rewrite rules apply,
// so the object file may refer to the absolute directory
// containing the package.
fmt.Fprintf(h, "dir %s\n", p.Dir)
} else if cfg.BuildTrimpath && p.Module != nil {
fmt.Fprintf(h, "module %s@%s\n", p.Module.Path, p.Module.Version)
}

if p.Module != nil {
fmt.Fprintf(h, "go %s\n", p.Module.GoVersion)
}
Expand Down
153 changes: 153 additions & 0 deletions src/cmd/go/testdata/script/build_issue48319.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
[short] skip
[!cgo] skip

# Set up fresh GOCACHE
env GOCACHE=$WORK/gocache
mkdir $GOCACHE

# 1. unset GOROOT_FINAL, Build a simple binary with cgo by origin go.
# The DW_AT_comp_dir of runtime/cgo should have a prefix with origin goroot.
env GOROOT_FINAL=
# If using "go run", it is no debuginfo in binary. So use "go build".
# And we can check the stderr to judge if the cache of "runtime/cgo"
# was used or not.
go build -o binary.exe
exec ./binary.exe $TESTGO_GOROOT
stdout 'cgo DW_AT_comp_dir is right in binary'


# 2. GOROOT_FINAL will be changed, the runtime/cgo will be rebuild.
env GOROOT_FINAL=$WORK/gorootfinal
go build -x -o binary.exe
stderr '(clang|gcc)( |\.exe).*gcc_.*\.c'
exec ./binary.exe $GOROOT_FINAL
stdout 'cgo DW_AT_comp_dir is right in binary'


[!symlink] skip

# Symlink the compiler to another path
env GOROOT=$WORK/goroot
symlink $GOROOT -> $TESTGO_GOROOT

# 3. GOROOT_FINAL is same with 2, build with the other go
# the runtime/cgo will not be rebuild.
go build -x -o binary.exe
! stderr '(clang|gcc)( |\.exe).*gcc_.*\.c'
exec ./binary.exe $GOROOT_FINAL
stdout 'cgo DW_AT_comp_dir is right in binary'


# 4. unset GOROOT_FINAL, build with the other go
# the runtime/cgo will be rebuild.
env GOROOT_FINAL=
go build -x -o binary.exe
stderr '(clang|gcc)( |\.exe).*gcc_.*\.c'
exec ./binary.exe $GOROOT
stdout 'cgo DW_AT_comp_dir is right in binary'

-- go.mod --
module main

go 1.18
-- main.go --
package main

import "C"
import (
"debug/dwarf"
"fmt"
"log"
"os"
"path/filepath"
"strings"
)

var _ C.int

func main() {
dwarfData, err := readDWARF(os.Args[0])
if err != nil {
log.Fatal(err)
}
goroot := filepath.Join(os.Args[1], "src")
dwarfReader := dwarfData.Reader()
cgopackage := filepath.Join("runtime", "cgo")
var hascgo bool
for {
e, err := dwarfReader.Next()
if err != nil {
log.Fatal(err)
}
if e == nil {
break
}
field := e.AttrField(dwarf.AttrCompDir)
if field == nil {
continue
}
compdir := field.Val.(string)
if strings.HasSuffix(compdir, cgopackage) {
hascgo = true
if !strings.HasPrefix(compdir, goroot) {
fmt.Printf("cgo DW_AT_comp_dir %s contains incorrect path in binary.\n", compdir)
return
}
}
}
if hascgo {
fmt.Println("cgo DW_AT_comp_dir is right in binary")
} else {
fmt.Println("binary does not contain cgo")
}
}
-- read_darwin.go --
package main

import (
"debug/dwarf"
"debug/macho"
)

func readDWARF(exePath string) (*dwarf.Data, error) {
machoFile, err := macho.Open(exePath)
if err != nil {
return nil, err
}
defer machoFile.Close()
return machoFile.DWARF()
}
-- read_elf.go --
// +build android dragonfly freebsd illumos linux netbsd openbsd solaris

package main

import (
"debug/dwarf"
"debug/elf"
)

func readDWARF(exePath string) (*dwarf.Data, error) {
elfFile, err := elf.Open(exePath)
if err != nil {
return nil, err
}
defer elfFile.Close()
return elfFile.DWARF()
}
-- read_windows.go --
package main

import (
"debug/dwarf"
"debug/pe"
)

func readDWARF(exePath string) (*dwarf.Data, error) {
peFile, err := pe.Open(exePath)
if err != nil {
return nil, err
}
defer peFile.Close()
return peFile.DWARF()
}

0 comments on commit 65ffee6

Please sign in to comment.