mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/pack: treat compiler's -linkobj output as "compiler object"
Treat the compiler's -linkobj output as "compiler object, which means "pack c" will "see through" the file and add individual entry to the new archive, instead of the object as a whole. This is somewhat peculiar. But Go 1.15's cmd/pack does this, although seemingly accidental. We just do the same. FWIW, it does make things more consistent with/without -linkobj flag. Fixes #43271. Change-Id: I6b2d99256db7ebf0fa430f85afa7464e334f6bcb Reviewed-on: https://go-review.googlesource.com/c/go/+/279483 Trust: Cherry Zhang <cherryyz@google.com> Run-TryBot: Cherry Zhang <cherryyz@google.com> Reviewed-by: Jeremy Faller <jeremy@golang.org> Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
bc7e4d9257
commit
9b6147120a
2 changed files with 84 additions and 13 deletions
|
|
@ -315,20 +315,25 @@ func (ar *Archive) extractContents1(e *archive.Entry, out io.Writer) {
|
|||
}
|
||||
|
||||
// isGoCompilerObjFile reports whether file is an object file created
|
||||
// by the Go compiler, which is an archive file with exactly two entries:
|
||||
// __.PKGDEF and _go_.o.
|
||||
// by the Go compiler, which is an archive file with exactly one entry
|
||||
// of __.PKGDEF, or _go_.o, or both entries.
|
||||
func isGoCompilerObjFile(a *archive.Archive) bool {
|
||||
if len(a.Entries) != 2 {
|
||||
switch len(a.Entries) {
|
||||
case 1:
|
||||
return (a.Entries[0].Type == archive.EntryGoObj && a.Entries[0].Name == "_go_.o") ||
|
||||
(a.Entries[0].Type == archive.EntryPkgDef && a.Entries[0].Name == "__.PKGDEF")
|
||||
case 2:
|
||||
var foundPkgDef, foundGo bool
|
||||
for _, e := range a.Entries {
|
||||
if e.Type == archive.EntryPkgDef && e.Name == "__.PKGDEF" {
|
||||
foundPkgDef = true
|
||||
}
|
||||
if e.Type == archive.EntryGoObj && e.Name == "_go_.o" {
|
||||
foundGo = true
|
||||
}
|
||||
}
|
||||
return foundPkgDef && foundGo
|
||||
default:
|
||||
return false
|
||||
}
|
||||
var foundPkgDef, foundGo bool
|
||||
for _, e := range a.Entries {
|
||||
if e.Type == archive.EntryPkgDef && e.Name == "__.PKGDEF" {
|
||||
foundPkgDef = true
|
||||
}
|
||||
if e.Type == archive.EntryGoObj && e.Name == "_go_.o" {
|
||||
foundGo = true
|
||||
}
|
||||
}
|
||||
return foundPkgDef && foundGo
|
||||
}
|
||||
|
|
|
|||
|
|
@ -302,6 +302,72 @@ func TestIssue21703(t *testing.T) {
|
|||
run(goBin, "tool", "compile", "-I", ".", "b.go")
|
||||
}
|
||||
|
||||
// Test the "c" command can "see through" the archive generated by the compiler.
|
||||
// This is peculiar. (See issue )
|
||||
func TestCreateWithCompilerObj(t *testing.T) {
|
||||
testenv.MustHaveGoBuild(t)
|
||||
|
||||
dir := tmpDir(t)
|
||||
defer os.RemoveAll(dir)
|
||||
src := filepath.Join(dir, "p.go")
|
||||
prog := "package p; var X = 42\n"
|
||||
err := os.WriteFile(src, []byte(prog), 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
run := func(args ...string) string {
|
||||
return doRun(t, dir, args...)
|
||||
}
|
||||
|
||||
goBin := testenv.GoToolPath(t)
|
||||
run(goBin, "build", "cmd/pack") // writes pack binary to dir
|
||||
run(goBin, "tool", "compile", "-pack", "-o", "p.a", "p.go")
|
||||
run("./pack", "c", "packed.a", "p.a")
|
||||
fi, err := os.Stat(filepath.Join(dir, "p.a"))
|
||||
if err != nil {
|
||||
t.Fatalf("stat p.a failed: %v", err)
|
||||
}
|
||||
fi2, err := os.Stat(filepath.Join(dir, "packed.a"))
|
||||
if err != nil {
|
||||
t.Fatalf("stat packed.a failed: %v", err)
|
||||
}
|
||||
// For compiler-generated object file, the "c" command is
|
||||
// expected to get (essentially) the same file back, instead
|
||||
// of packing it into a new archive with a single entry.
|
||||
if want, got := fi.Size(), fi2.Size(); want != got {
|
||||
t.Errorf("packed file with different size: want %d, got %d", want, got)
|
||||
}
|
||||
|
||||
// Test -linkobj flag as well.
|
||||
run(goBin, "tool", "compile", "-linkobj", "p2.a", "-o", "p.x", "p.go")
|
||||
run("./pack", "c", "packed2.a", "p2.a")
|
||||
fi, err = os.Stat(filepath.Join(dir, "p2.a"))
|
||||
if err != nil {
|
||||
t.Fatalf("stat p2.a failed: %v", err)
|
||||
}
|
||||
fi2, err = os.Stat(filepath.Join(dir, "packed2.a"))
|
||||
if err != nil {
|
||||
t.Fatalf("stat packed2.a failed: %v", err)
|
||||
}
|
||||
if want, got := fi.Size(), fi2.Size(); want != got {
|
||||
t.Errorf("packed file with different size: want %d, got %d", want, got)
|
||||
}
|
||||
|
||||
run("./pack", "c", "packed3.a", "p.x")
|
||||
fi, err = os.Stat(filepath.Join(dir, "p.x"))
|
||||
if err != nil {
|
||||
t.Fatalf("stat p.x failed: %v", err)
|
||||
}
|
||||
fi2, err = os.Stat(filepath.Join(dir, "packed3.a"))
|
||||
if err != nil {
|
||||
t.Fatalf("stat packed3.a failed: %v", err)
|
||||
}
|
||||
if want, got := fi.Size(), fi2.Size(); want != got {
|
||||
t.Errorf("packed file with different size: want %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// doRun runs a program in a directory and returns the output.
|
||||
func doRun(t *testing.T, dir string, args ...string) string {
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue