From af0609b080dd6d9101d8c6aa31ef6378ac70d60a Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 18 Jul 2023 16:23:27 -0400 Subject: [PATCH] cmd/go: attach PGO profile for test dependencies When running "go test" including a main package which has a PGO profile, we currently build the package being tested and its dependencies with PGO, but we failed to attach the profile to test-only dependencies. If a package is (transitively) imported by both the package being tested and the test, the PGO version and the non-PGO version of the package are both linked into the binary, causing link-time error. This CL fixes this by attaching the PGO profile to dependencies of the test. Fixes #61376. Change-Id: I2559db9843c4cdab596b31e2025d8475ffbf58ec Reviewed-on: https://go-review.googlesource.com/c/go/+/510835 Run-TryBot: Cherry Mui Reviewed-by: Bryan Mills TryBot-Result: Gopher Robot --- src/cmd/go/internal/load/test.go | 6 ++++++ src/cmd/go/testdata/script/build_pgo_auto_multi.txt | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/cmd/go/internal/load/test.go b/src/cmd/go/internal/load/test.go index ceedb99e2f1..e9ed0d332bc 100644 --- a/src/cmd/go/internal/load/test.go +++ b/src/cmd/go/internal/load/test.go @@ -473,6 +473,7 @@ func recompileForTest(pmain, preal, ptest, pxtest *Package) *PackageError { p.Target = "" p.Internal.BuildInfo = nil p.Internal.ForceLibrary = true + p.Internal.PGOProfile = preal.Internal.PGOProfile } // Update p.Internal.Imports to use test copies. @@ -496,6 +497,11 @@ func recompileForTest(pmain, preal, ptest, pxtest *Package) *PackageError { if p.Name == "main" && p != pmain && p != ptest { split() } + // Split and attach PGO information to test dependencies if preal + // is built with PGO. + if preal.Internal.PGOProfile != "" && p.Internal.PGOProfile == "" { + split() + } } // Do search to find cycle. diff --git a/src/cmd/go/testdata/script/build_pgo_auto_multi.txt b/src/cmd/go/testdata/script/build_pgo_auto_multi.txt index 9ac57ce0c16..991b72ce850 100644 --- a/src/cmd/go/testdata/script/build_pgo_auto_multi.txt +++ b/src/cmd/go/testdata/script/build_pgo_auto_multi.txt @@ -45,6 +45,12 @@ stderr 'compile.*-pgoprofile=.*b(/|\\\\)default\.pgo.*b(/|\\\\)b_test\.go' stderr 'compile.*-pgoprofile=.*b(/|\\\\)default\.pgo.*dep(/|\\\\)dep\.go' ! stderr 'compile.*-pgoprofile=.*nopgo(/|\\\\)nopgo_test\.go' +# test-only dependencies also have profiles attached +stderr 'compile.*-pgoprofile=.*a(/|\\\\)default\.pgo.*testdep(/|\\\\)testdep\.go' +stderr 'compile.*-pgoprofile=.*b(/|\\\\)default\.pgo.*testdep(/|\\\\)testdep\.go' +stderr 'compile.*-pgoprofile=.*a(/|\\\\)default\.pgo.*testdep2(/|\\\\)testdep2\.go' +stderr 'compile.*-pgoprofile=.*b(/|\\\\)default\.pgo.*testdep2(/|\\\\)testdep2\.go' + # go list -deps prints packages built multiple times. go list -pgo=auto -deps ./a ./b ./nopgo stdout 'test/dep \[test/a\]' @@ -66,6 +72,7 @@ func main() {} -- a/a_test.go -- package main import "testing" +import _ "test/testdep" func TestA(*testing.T) {} -- a/default.pgo -- -- b/b.go -- @@ -76,6 +83,7 @@ func main() {} -- b/b_test.go -- package main import "testing" +import _ "test/testdep" func TestB(*testing.T) {} -- b/default.pgo -- -- nopgo/nopgo.go -- @@ -94,3 +102,8 @@ import _ "test/dep3" package dep2 -- dep3/dep3.go -- package dep3 +-- testdep/testdep.go -- +package testdep +import _ "test/testdep2" +-- testdep2/testdep2.go -- +package testdep2