pkg debug/buildinfo, type BuildInfo = debug.BuildInfo
pkg runtime/debug, method (*BuildInfo) MarshalText() ([]byte, error)
pkg runtime/debug, method (*BuildInfo) UnmarshalText() ([]byte, error)
+pkg runtime/debug, type BuildInfo struct, GoVersion string
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
// setBuildInfo should only be called on a main package with no errors.
//
// This information can be retrieved using debug.ReadBuildInfo.
+//
+// Note that the GoVersion field is not set here to avoid encoding it twice.
+// It is stored separately in the binary, mostly for historical reasons.
func (p *Package) setBuildInfo() {
setPkgErrorf := func(format string, args ...interface{}) {
if p.Error == nil {
// accessed through the given ReaderAt. Most information is only available for
// binaries built with module support.
func Read(r io.ReaderAt) (*BuildInfo, error) {
- _, mod, err := readRawBuildInfo(r)
+ vers, mod, err := readRawBuildInfo(r)
if err != nil {
return nil, err
}
if err := bi.UnmarshalText([]byte(mod)); err != nil {
return nil, err
}
+ bi.GoVersion = vers
return bi, nil
}
{
name: "valid_modules",
build: buildWithModules,
- want: "path\texample.com/m\n" +
+ want: "go\t$GOVERSION\n" +
+ "path\texample.com/m\n" +
"mod\texample.com/m\t(devel)\t\n",
},
{
{
name: "valid_gopath",
build: buildWithGOPATH,
- want: "",
+ want: "go\t$GOVERSION\n",
},
{
name: "invalid_gopath",
} else if got, err := info.MarshalText(); err != nil {
t.Fatalf("unexpected error marshaling BuildInfo: %v", err)
} else {
- got := string(got)
+ got := strings.ReplaceAll(string(got), runtime.Version(), "$GOVERSION")
if got != tc.want {
t.Fatalf("got:\n%s\nwant:\n%s", got, tc.want)
}
import (
"bytes"
"fmt"
+ "runtime"
)
// exported from runtime
if err := bi.UnmarshalText([]byte(data)); err != nil {
return nil, false
}
+
+ // The go version is stored separately from other build info, mostly for
+ // historical reasons. It is not part of the modinfo() string, and
+ // ParseBuildInfo does not recognize it. We inject it here to hide this
+ // awkwardness from the user.
+ bi.GoVersion = runtime.Version()
+
return bi, true
}
// BuildInfo represents the build information read from a Go binary.
type BuildInfo struct {
- Path string // The main package path
- Main Module // The module containing the main package
- Deps []*Module // Module dependencies
+ GoVersion string // Version of Go that produced this binary.
+ Path string // The main package path
+ Main Module // The module containing the main package
+ Deps []*Module // Module dependencies
}
// Module represents a module.
func (bi *BuildInfo) MarshalText() ([]byte, error) {
buf := &bytes.Buffer{}
+ if bi.GoVersion != "" {
+ fmt.Fprintf(buf, "go\t%s\n", bi.GoVersion)
+ }
if bi.Path != "" {
fmt.Fprintf(buf, "path\t%s\n", bi.Path)
}
line []byte
ok bool
)
- // Reverse of BuildInfo.String()
+ // Reverse of BuildInfo.String(), except for go version.
for len(data) > 0 {
line, data, ok = bytes.Cut(data, newline)
if !ok {