]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: move module build info formatting into runtime/debug
authorJay Conrod <jayconrod@google.com>
Thu, 30 Sep 2021 21:37:30 +0000 (14:37 -0700)
committerJay Conrod <jayconrod@google.com>
Thu, 14 Oct 2021 18:43:59 +0000 (18:43 +0000)
Previously, modload.PackageBuildInfo returned a string containing
information about modules used to build an executable. This string is
embedded in the binary and can be read with debug.ReadBuildInfo or
'go version -m'.

With this change, debug.BuildInfo now has a MarshalText method that
returns a string in the same format as modload.PackageBuildInfo.

Package.load now calls Package.setBuildInfo, which constructs a
debug.BuildInfo, formats it with MarshalText, then sets
Package.Internal.BuildInfo. This is equivalent to what
modload.PackageBuildInfo did.

modload.PackageBuildInfo is deleted, since it's no longer used.

For #37475

Change-Id: I5875a98cb64737637fec2a450ab2ffa7f1805707
Reviewed-on: https://go-review.googlesource.com/c/go/+/353886
Trust: Jay Conrod <jayconrod@google.com>
Run-TryBot: Jay Conrod <jayconrod@google.com>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
api/next.txt
src/cmd/go/internal/load/pkg.go
src/cmd/go/internal/modload/build.go
src/runtime/debug/mod.go

index 1192fc9069614a9d9ef84b9327e550d85fc01b2c..cb729ea72f92e5e7450d9a3ea0b2c63d9e755d8f 100644 (file)
@@ -1,3 +1,4 @@
+pkg runtime/debug, method (*BuildInfo) MarshalText() ([]byte, error)
 pkg syscall (darwin-amd64), func RecvfromInet4(int, []uint8, int, *SockaddrInet4) (int, error)
 pkg syscall (darwin-amd64), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
 pkg syscall (darwin-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
index a3a8de81c92621d4d69262750857dd50e5b467c1..a7428ed42011224fa2732e5ba6352a44b9ea8fc7 100644 (file)
@@ -21,6 +21,7 @@ import (
        pathpkg "path"
        "path/filepath"
        "runtime"
+       "runtime/debug"
        "sort"
        "strconv"
        "strings"
@@ -1921,9 +1922,8 @@ func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk *
        }
        p.Internal.Imports = imports
        p.collectDeps()
-
-       if cfg.ModulesEnabled && p.Error == nil && p.Name == "main" && len(p.DepsErrors) == 0 {
-               p.Internal.BuildInfo = modload.PackageBuildInfo(pkgPath, p.Deps)
+       if p.Error == nil && p.Name == "main" && len(p.DepsErrors) == 0 {
+               p.setBuildInfo()
        }
 
        // unsafe is a fake package.
@@ -2195,6 +2195,83 @@ func (p *Package) collectDeps() {
        }
 }
 
+// setBuildInfo gathers build information, formats it as a string to be
+// embedded in the binary, then sets p.Internal.BuildInfo to that string.
+// setBuildInfo should only be called on a main package with no errors.
+//
+// This information can be retrieved using debug.ReadBuildInfo.
+func (p *Package) setBuildInfo() {
+       setPkgErrorf := func(format string, args ...interface{}) {
+               if p.Error == nil {
+                       p.Error = &PackageError{Err: fmt.Errorf(format, args...)}
+               }
+       }
+
+       var debugModFromModinfo func(*modinfo.ModulePublic) *debug.Module
+       debugModFromModinfo = func(mi *modinfo.ModulePublic) *debug.Module {
+               dm := &debug.Module{
+                       Path:    mi.Path,
+                       Version: mi.Version,
+               }
+               if mi.Replace != nil {
+                       dm.Replace = debugModFromModinfo(mi.Replace)
+               } else {
+                       dm.Sum = modfetch.Sum(module.Version{Path: mi.Path, Version: mi.Version})
+               }
+               return dm
+       }
+
+       var main debug.Module
+       if p.Module != nil {
+               main = *debugModFromModinfo(p.Module)
+       }
+
+       visited := make(map[*Package]bool)
+       mdeps := make(map[module.Version]*debug.Module)
+       var q []*Package
+       q = append(q, p.Internal.Imports...)
+       for len(q) > 0 {
+               p1 := q[0]
+               q = q[1:]
+               if visited[p1] {
+                       continue
+               }
+               visited[p1] = true
+               if p1.Module != nil {
+                       m := module.Version{Path: p1.Module.Path, Version: p1.Module.Version}
+                       if p1.Module.Path != main.Path && mdeps[m] == nil {
+                               mdeps[m] = debugModFromModinfo(p1.Module)
+                       }
+               }
+               q = append(q, p1.Internal.Imports...)
+       }
+       sortedMods := make([]module.Version, 0, len(mdeps))
+       for mod := range mdeps {
+               sortedMods = append(sortedMods, mod)
+       }
+       module.Sort(sortedMods)
+       deps := make([]*debug.Module, len(sortedMods))
+       for i, mod := range sortedMods {
+               deps[i] = mdeps[mod]
+       }
+
+       pkgPath := p.ImportPath
+       if p.Internal.CmdlineFiles {
+               pkgPath = "command-line-arguments"
+       }
+       info := &debug.BuildInfo{
+               Path: pkgPath,
+               Main: main,
+               Deps: deps,
+       }
+       text, err := info.MarshalText()
+       if err != nil {
+               setPkgErrorf("error formatting build info: %v", err)
+               return
+       }
+       p.Internal.BuildInfo = string(text)
+}
+
 // SafeArg reports whether arg is a "safe" command-line argument,
 // meaning that when it appears in a command-line, it probably
 // doesn't have some special meaning other than its own name.
index 8a9792089b94a54c858ed121fca1aa6d1edab1bb..da5074313890e2001a9a2bc0163016599f9184c9 100644 (file)
@@ -5,7 +5,6 @@
 package modload
 
 import (
-       "bytes"
        "context"
        "encoding/hex"
        "errors"
@@ -336,53 +335,6 @@ func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, mode Li
        return info
 }
 
-// PackageBuildInfo returns a string containing module version information
-// for modules providing packages named by path and deps. path and deps must
-// name packages that were resolved successfully with LoadPackages.
-func PackageBuildInfo(path string, deps []string) string {
-       if !Enabled() {
-               return ""
-       }
-       target, _ := findModule(loaded, path)
-       mdeps := make(map[module.Version]bool)
-       for _, dep := range deps {
-               if m, ok := findModule(loaded, dep); ok {
-                       mdeps[m] = true
-               }
-       }
-       var mods []module.Version
-       delete(mdeps, target)
-       for mod := range mdeps {
-               mods = append(mods, mod)
-       }
-       module.Sort(mods)
-
-       var buf bytes.Buffer
-       fmt.Fprintf(&buf, "path\t%s\n", path)
-
-       writeEntry := func(token string, m module.Version) {
-               mv := m.Version
-               if mv == "" {
-                       mv = "(devel)"
-               }
-               fmt.Fprintf(&buf, "%s\t%s\t%s", token, m.Path, mv)
-               if r, _ := Replacement(m); r.Path == "" {
-                       fmt.Fprintf(&buf, "\t%s\n", modfetch.Sum(m))
-               } else {
-                       fmt.Fprintf(&buf, "\n=>\t%s\t%s\t%s\n", r.Path, r.Version, modfetch.Sum(r))
-               }
-       }
-
-       if target.Path != "" {
-               writeEntry("mod", target)
-       }
-       for _, mod := range mods {
-               writeEntry("dep", mod)
-       }
-
-       return buf.String()
-}
-
 // findModule searches for the module that contains the package at path.
 // If the package was loaded, its containing module and true are returned.
 // Otherwise, module.Version{} and false are returned.
index 05cad61155cf0859ba4cac235bbf7874c211386b..11f995ba758f2888d0cbf7b7cc2c9c2bdd4a93d9 100644 (file)
@@ -5,6 +5,8 @@
 package debug
 
 import (
+       "bytes"
+       "fmt"
        "strings"
 )
 
@@ -34,6 +36,41 @@ type Module struct {
        Replace *Module // replaced by this module
 }
 
+func (bi *BuildInfo) MarshalText() ([]byte, error) {
+       buf := &bytes.Buffer{}
+       if bi.Path != "" {
+               fmt.Fprintf(buf, "path\t%s\n", bi.Path)
+       }
+       var formatMod func(string, Module)
+       formatMod = func(word string, m Module) {
+               buf.WriteString(word)
+               buf.WriteByte('\t')
+               buf.WriteString(m.Path)
+               mv := m.Version
+               if mv == "" {
+                       mv = "(devel)"
+               }
+               buf.WriteByte('\t')
+               buf.WriteString(mv)
+               if m.Replace == nil {
+                       buf.WriteByte('\t')
+                       buf.WriteString(m.Sum)
+               } else {
+                       buf.WriteByte('\n')
+                       formatMod("=>", *m.Replace)
+               }
+               buf.WriteByte('\n')
+       }
+       if bi.Main.Path != "" {
+               formatMod("mod", bi.Main)
+       }
+       for _, dep := range bi.Deps {
+               formatMod("dep", *dep)
+       }
+
+       return buf.Bytes(), nil
+}
+
 func readBuildInfo(data string) (*BuildInfo, bool) {
        if len(data) < 32 {
                return nil, false