]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: distinguish packages built for different main packages in printing
authorCherry Mui <cherryyz@google.com>
Fri, 3 Mar 2023 00:16:34 +0000 (19:16 -0500)
committerCherry Mui <cherryyz@google.com>
Mon, 6 Mar 2023 19:27:53 +0000 (19:27 +0000)
In -pgo=auto mode, a package may be built multiple times. E.g. for

go build -pgo=auto cmd/a cmd/b

and both cmd/a and cmd/b imports package p, p may be built twice,
one using a's profile, one using b's. If we need to print p, e.g.
in "go list -deps" or when there is a build failure, p will be
printed twice, and currently we don't distinguish them.

We have a precedence for a similar case: for testing, there is the
original package, and the (internal) test version of the package
(which includes _test.go files). Packages that import the package
under testing may also have two versions (one imports the original,
one imports the testing version). In printing, the go command
distinguishes them by adding a "[p.test]" suffix for the latter,
as they are specifically built for the p.test binary.

We do the similar. When a package needs to be compiled multiple
times for different main packages, we attach the main package's
import path, like "p [cmd/a]" for package p built specifically
for cmd/a.

For #58099.

Change-Id: I4a040cf17e1dceb5ca1810c217f16e734c858ab6
Reviewed-on: https://go-review.googlesource.com/c/go/+/473275
Reviewed-by: Michael Pratt <mpratt@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
src/cmd/go/internal/list/list.go
src/cmd/go/internal/load/pkg.go
src/cmd/go/testdata/script/build_pgo_auto_multi.txt

index 259fa2c857faf72900dc7528451a402e0b329fd2..6d6deda884635c2abae1d16b9a5c48b1e503849b 100644 (file)
@@ -733,19 +733,20 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
                }
        }
 
-       if *listTest {
+       if *listTest || (cfg.BuildPGO == "auto" && len(cmdline) > 1) {
                all := pkgs
                if !*listDeps {
                        all = loadPackageList(pkgs)
                }
                // Update import paths to distinguish the real package p
-               // from p recompiled for q.test.
+               // from p recompiled for q.test, or to distinguish between
+               // p compiled with different PGO profiles.
                // This must happen only once the build code is done
                // looking at import paths, because it will get very confused
                // if it sees these.
                old := make(map[string]string)
                for _, p := range all {
-                       if p.ForTest != "" {
+                       if p.ForTest != "" || p.Internal.ForMain != "" {
                                new := p.Desc()
                                old[new] = p.ImportPath
                                p.ImportPath = new
@@ -756,7 +757,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
                m := make(map[string]string)
                for _, p := range all {
                        for _, p1 := range p.Internal.Imports {
-                               if p1.ForTest != "" {
+                               if p1.ForTest != "" || p1.Internal.ForMain != "" {
                                        m[old[p1.ImportPath]] = p1.ImportPath
                                }
                        }
index 628495522891c6f43d8635fdffc9ef569f818ef1..40278dda4d2c992d335a6720259e0b365cfc2937 100644 (file)
@@ -195,6 +195,9 @@ func (p *Package) Desc() string {
        if p.ForTest != "" {
                return p.ImportPath + " [" + p.ForTest + ".test]"
        }
+       if p.Internal.ForMain != "" {
+               return p.ImportPath + " [" + p.Internal.ForMain + "]"
+       }
        return p.ImportPath
 }
 
@@ -234,6 +237,7 @@ type PackageInternal struct {
        Embed             map[string][]string  // //go:embed comment mapping
        OrigImportPath    string               // original import path before adding '_test' suffix
        PGOProfile        string               // path to PGO profile
+       ForMain           string               // the main package if this package is built specifically for it
 
        Asmflags   []string // -asmflags for this package
        Gcflags    []string // -gcflags for this package
@@ -2944,6 +2948,7 @@ func setPGOProfilePath(pkgs []*Package) {
                                        p1.Internal.Imports = slices.Clone(p.Internal.Imports)
                                        copied[p] = p1
                                        p = p1
+                                       p.Internal.ForMain = pmain.ImportPath
                                }
                                p.Internal.PGOProfile = file
                                // Recurse to dependencies.
index 6905ad94f66524878e689f56fa884314806fc13f..19f022838d8f6dce6796f12917c5c0350ec9d816 100644 (file)
@@ -40,6 +40,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'
 
+# go list -deps prints packages built multiple times.
+go list -pgo=auto -deps ./a ./b ./nopgo
+stdout 'test/dep \[test/a\]'
+stdout 'test/dep \[test/b\]'
+stdout 'test/dep$'
+
 # Here we have 3 main packages, a, b, and nopgo, where a and b each has
 # its own default.pgo profile, and nopgo has none.
 # All 3 main packages import dep and dep2, both of which then import dep3