如何从 Go 1.18 二进制文件中读取调试 VCS 版本信息?

Tra*_*itz 8 go

我正在尝试从 Go 二进制文件中读取版本控制信息,但构建信息似乎不包含任何 VCS 信息。

来自 Go 1.18发行说明

go 命令现在将版本控制信息嵌入到二进制文件中。它包括当前签出的修订版本、提交时间以及指示是否存在已编辑或未跟踪文件的标志。如果在 Git、Mercurial、Fossil 或 Bazaar 存储库内的目录中调用 go 命令,并且主包及其包含的主模块位于同一存储库中,则会嵌入版本控制信息。使用标志 -buildvcs=false 可以省略此信息。

示例程序:

package main

import (
    "fmt"
    "runtime/debug"
)

func main() {
    if bi, ok := debug.ReadBuildInfo(); ok {
        fmt.Printf("%+v\n", bi)
    }
}
Run Code Online (Sandbox Code Playgroud)

使用此代码,这是我的输出:

走走1.18
路径[已编辑]
mod [已编辑](开发)
dep [已编辑] v1.2.3  
构建-编译器=gc
构建 CGO_ENABLED=1
构建 CGO_CFLAGS=
构建 CGO_CPPFLAGS=
构建 CGO_CXXFLAGS=
构建 CGO_LDFLAGS=
构建 GOARCH=amd64
构建 GOOS=windows
构建 GOAMD64=v1

我希望看到这一点,但没有:

构建 vcs=git
构建 vcs.revision=[sha]
构建 vcs.time=2022-03-28T03:11:12Z
构建 vcs.modified=true

我正在go从 git 存储库的根目录运行该命令,并且该存储库已提交。我正在构建的程序位于存储库的子目录中。

我尝试了许多不同的变体来构建二进制文件,但没有一个起作用:

go      go1.18
path    [redacted]
mod     [redacted]     (devel)
dep     [redacted]        v1.2.3  
build   -compiler=gc
build   CGO_ENABLED=1
build   CGO_CFLAGS=
build   CGO_CPPFLAGS=
build   CGO_CXXFLAGS=
build   CGO_LDFLAGS=
build   GOARCH=amd64
build   GOOS=windows
build   GOAMD64=v1

需要明确的是,该程序会构建并执行,但不包含嵌入的 VCS 信息。

我还尝试使用它go version -m client.exe来查看是否可以读取二进制文件本身无法读取的内容,但结果是相同的。

我正在使用 Go 1.18 的第一个版本,因此据我所知-buildvcs仍应默认为。true我在问题跟踪器上看到,未来的次要版本可能会将默认值更改为-buildvcs=auto.

据我所知,从go项目根目录构建时,发行说明中列出的两个条件(在 git 存储库内的目录中调用,并且主包位于同一存储库中)都应该得到满足。我可能做错了什么?

Tra*_*itz 6

我相信我的问题是由于go rungo build命令的错误使用造成的。我正在针对文件模式运行和构建,因为我最初是go build client从项目根尝试的,并收到“包不在 GOROOT 中”的错误,所以我在构建文件模式而不理解其中的差异(因为它编译并成功运行)。

我发现,如果我将目录更改为我想要构建的程序的子目录(而不是从项目根目录构建),构建命令将按预期嵌入版本信息。

例如:

cd client/ && go build
Run Code Online (Sandbox Code Playgroud)

正如 @JimB 在评论中指出的那样,该go命令旨在对包进行操作。

从项目根目录构建时,这是我应该使用的命令,它将正确地将 VCS 版本信息嵌入到二进制文件中:

go build ./client
Run Code Online (Sandbox Code Playgroud)

这种围绕相对路径名的行为对我来说仍然是令人困惑的行为,因为我期望go build clientgo build ./client是等效的(它们显然不是)。相对路径周围的行为似乎记录在此处:https ://pkg.go.dev/cmd/go@go1.18#hdr-Relative_import_paths