cmd/link: skip zero values in fingerprint check

Normally, packages are loaded in dependency order, and if a
Library object is not nil, it is already loaded with the actual
fingerprint. In shared build mode, however, packages may be added
not in dependency order (e.g. go install -buildmode=shared std
adds all std packages before loading them), and it is possible
that a Library's fingerprint is not yet loaded. Skip the check
in this case (when the fingerprint is the zero value).

Fixes #39777.

Change-Id: I66208e92bf687c8778963ba8e33e9bd948f82f3a
Reviewed-on: https://go-review.googlesource.com/c/go/+/239517
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
Cherry Zhang 2020-06-23 12:02:54 -04:00
parent 18bcc7c285
commit 9f33108dfa
4 changed files with 28 additions and 1 deletions

View File

@ -1028,3 +1028,9 @@ func TestGeneratedHash(t *testing.T) {
goCmd(nil, "install", "-buildmode=shared", "-linkshared", "./issue30768/issue30768lib")
goCmd(nil, "test", "-linkshared", "./issue30768")
}
// Test that packages can be added not in dependency order (here a depends on b, and a adds
// before b). This could happen with e.g. go build -buildmode=shared std. See issue 39777.
func TestPackageOrder(t *testing.T) {
goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue39777/a", "./issue39777/b")
}

View File

@ -0,0 +1,9 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package a
import "testshared/issue39777/b"
func F() { b.F() }

View File

@ -0,0 +1,7 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package b
func F() {}

View File

@ -160,7 +160,12 @@ func addlib(ctxt *Link, src, obj, lib string, fingerprint goobj2.FingerprintType
pkg := pkgname(ctxt, lib)
// already loaded?
if l := ctxt.LibraryByPkg[pkg]; l != nil {
if l := ctxt.LibraryByPkg[pkg]; l != nil && !l.Fingerprint.IsZero() {
// Normally, packages are loaded in dependency order, and if l != nil
// l is already loaded with the actual fingerprint. In shared build mode,
// however, packages may be added not in dependency order, and it is
// possible that l's fingerprint is not yet loaded -- exclude it in
// checking.
checkFingerprint(l, l.Fingerprint, src, fingerprint)
return l
}