[英]Dynamic version from git with go get
我正在使用git标签在go程序中注入版本,例如在Makefile
:
VERSION = $(shell git describe --always --dirty)
github_pki: main.go
CGO_ENABLED=0 GOOS=linux \
go build -a \
-ldflags="-X main.version=$(VERSION)" \
-installsuffix cgo -o $@ $<
在main.go
version
定义为:
var version = "undefined"
使用make
可以很好地工作,但使用go get
或go build
时效果不好。 有没有一种方法可以使此ldflags
在不使用外部构建系统的情况下工作(即,使用go build
/ go get
)?
从发行问题22147 cmd/go
:可以更轻松地将已编译的git SHA嵌入二进制文件中 ,(对于Go 1.12 +,Q1 2019,2年后),现在有了依赖项的替代方案(尚未对主程序使用)。
因此,您仍然需要-ldflags
来记录源的版本。
而不是记录依赖项的版本:现在可用。
从Go 1.12开始,您可以使用
runtime/debug.BuildInfo
获得编译成二进制文件(在模块模式下)的所有模块的版本。如果使用的版本是伪版本,则它还将包含VCS提交ID的前十二个字符。
// BuildInfo represents the build information read from the running binary.
type BuildInfo struct {
Path string // The main package path
Main Module // The main module information
Deps []*Module // Module dependencies
}
// ReadBuildInfo returns the build information embedded in the running binary.
The information is available only in binaries built with module support.
func ReadBuildInfo() (info *BuildInfo, ok bool)
这来自于commit 45e9c55 :
运行时/调试:添加API以读取二进制文件中的模块信息
启用模块后,go工具会将与模块相关的构建信息嵌入到二进制文件中,包括依赖项和替换信息(请参阅
src/cmd/go/internal/modload#PackageBuildInfo()
,来自commit f7248f0 )。新引入的
ReadBuildInfo
读取信息并以编程方式使其可访问。
您可以看到它在问题26404中使用:“ cmd / go:以编程方式导出二进制文件的模块信息”
package main
import (
"log"
"runtime/debug"
"github.com/kr/pretty"
)
func main() {
bi, ok := debug.ReadBuildInfo()
if !ok {
log.Fatal("!ok")
}
pretty.Println(bi)
}
你得到:
&debug.BuildInfo{
Path: "foo.to/v",
Main: debug.Module{
Path: "foo.to/v",
Version: "(devel)",
Sum: "",
Replace: (*debug.Module)(nil),
},
Deps: {
&debug.Module{
Path: "github.com/kr/pretty",
Version: "v0.1.0",
Sum: "h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=",
Replace: (*debug.Module)(nil),
},
&debug.Module{
Path: "github.com/kr/text",
Version: "v0.1.0",
Sum: "h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=",
Replace: (*debug.Module)(nil),
},
},
}
如果使用1.12( #24250 )从模块外部以模块模式构建二进制文件,则将获取其所有版本信息。
但是此二进制文件的报告版本目前始终
(devel)
。 即使已提交并标记
因此,主要问题仍然存在: issues / 29814“ cmd/go
:使用版本控制来发现主模块的版本吗?” 。
当从模块的源树中构建二进制文件
runtime/debug.ReadBuildInfo
,runtime/debug.ReadBuildInfo
的输出当前将该模块报告为具有版本(devel)
。如果源树是来自版本控制系统的原始签出-或在(只读)模块缓存中-我们可以查询版本控制系统以找到要嵌入的相应版本或伪版本。
但是,有一些警告:
- 这将要求我们在用户的源代码树中运行VCS命令。 从历史上看,运行VCS命令一直是导致go命令漏洞太多的根源,因此我们真的想避免发出VCS命令,除非绝对必要。
- 给定一个提交,我们可以为该提交生成一个伪版本,但是我们无法确定该提交是否已发布到原始位置。
最好保留在调试信息中仅公告已发布版本的不变性,但这可能会导致额外的网络获取。- 在一个模块中,我们应用了该模块的替换和排除,并且用户的VCS结帐可能还应用了一些转换。
(devel)
目前提供线索说明那些特定于模块的更改正在生效:如果我们要指示显式版本,则需要提供某种方式来指示已应用替换和排除。
Go 1.13 (2019年第三季度)包括:
现在,
go version
命令接受命名可执行文件和目录的参数。
- 在可执行文件上调用时,
go version
打印用于构建可执行文件的Go版本。- 如果使用
-m
标志,则go version
打印可执行文件的嵌入式模块版本信息(如果有)。 (runtime/debug#BuildInfo
)- 在目录上调用
go version
,它go version
打印有关目录及其子目录中包含的可执行文件的信息。
以下是您想要的吗?
VERSION=`git describe --always --dirty`; \
CGO_ENABLED=0 GOOS=linux \
go build -a \
-ldflags="-X main.version=$(VERSION)" \
-installsuffix cgo -o github_pki main.go
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.