繁体   English   中英

使用git从git获得动态版本

[英]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 getgo 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.ReadBuildInforuntime/debug.ReadBuildInfo的输出当前将该模块报告为具有版本(devel)

如果源树是来自版本控制系统的原始签出-或在(只读)模块缓存中-我们可以查询版本控制系统以找到要嵌入的相应版本或伪版本。

但是,有一些警告:

  1. 这将要求我们在用户的源代码树中运行VCS命令。 从历史上看,运行VCS命令一直是导致go命令漏洞太多的根源,因此我们真的想避免发出VCS命令,除非绝对必要。
  2. 给定一个提交,我们可以为该提交生成一个伪版本,但是我们无法确定该提交是否已发布到原始位置。
    最好保留在调试信息中仅公告已发布版本的不变性,但这可能会导致额外的网络获取。
  3. 在一个模块中,我们应用了该模块的替换和排除,并且用户的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM