gbb
昨天跑得好好的程序突然出了问题,查看它的版本号,机器冷冰冰地告诉你👇
$ xxx --version
xxx version 1.0.12
如果没有详细的发布记录信息,我想此时的你一定是崩溃的。因为实在不知道这个1.0.12
到底是什么时候编译的,更加不知道是从哪份源代码编译而来,想要找出其中的bug,难度大了不少。
那么,同样的场景下,机器告诉你的信息是这样,那debug是否容易多了呢?!
$ xxx --version
xxx version 1.0.12
date: 2016-12-18T15:37:09+08:00
commit: db8b606cfc2b24a24e2e09acac24a52c47b68401
如果以上的场景你也似曾相识,那么也许gbb
就能帮到你,耐心往下👀吧。
安装
-
拉取源代码
$ go get -u github.com/voidint/gbb
-
编译(默认情况下go get
就会编译)
$ cd $GOPATH/src/github.com/voidint/gbb && go install
-
将可执行文件gbb
放置到环境变量PATH
-
执行which gbb
确认是否安装成功
-
若gbb
重名,那么建议设置别名,比如alias gbb=gbb2
。
基本使用
gbb
是自举的,换句话说,使用以上步骤安装的gbb
可执行二进制文件是可以编译gbb源代码的。类似👇
$ cd $GOPATH/src/github.com/voidint/gbb && gbb --debug
==> go build -ldflags '-X "github.com/voidint/gbb/build.Date=2016-12-17T17:00:04+08:00" -X "github.com/voidint/gbb/build.Commit=db8b606cfc2b24a24e2e09acac24a52c47b68401"'
$ ls -l ./gbb
-rwxr-xr-x 1 voidint staff 4277032 12 17 17:00 ./gbb
可以看到当前目录下已经多了一个可执行的二进制文件。没错,这个./gbb
就是使用已经安装的gbb
编译源代码后的产物。
如果是一个全新的项目,该怎么使用gbb
来代替go build/install
或者gb
来完成日常的代码编译工作呢?很简单,跟着下面的步骤尝试一下,立马就能学会了。
准备
既然需要演示使用方法,必然就需要有个go项目。我这里就以gbb
项目为例来展开。
为了从零开始我们的演示,请先把源代码目录下的gbb.json
文件删除。gbb.json
的作用以及文件内容的含义暂且不表,下文自然会提到。
$ rm -f gbb.json
首先,明确下gbb
工具要干什么事?我知道这个措辞很烂,在没有更好的措辞之前,先将就着看吧。
对go install/build、gb等golang编译工具进行包装,使编译得到的二进制文件的版本信息中包含编译时间戳、git commit等信息。
其次,看gbb
的版本信息👇
$ gbb version
gbb version 0.1.0
date: 2016-12-17T15:37:09+08:00
commit: db8b606cfc2b24a24e2e09acac24a52c47b68401
这个版本信息,除了常规的0.1.0
,还有这个gbb
二进制文件编译生成的时间,以及项目所使用的源代码管理工具git
的最近一次commit
号。这样的版本信息是否比简单的一个0.1.0
要更加友好呢?丰富的版本信息也为debug
降低了难度,因为这个二进制能和仓库中的源代码唯一对应了。
step0
为了在版本信息中显示编译时间
和commit号
这两个关键信息,需要先定义两个变量(变量不需要赋初值)。
package build
var (
Date string
Commit string
)
然后,在代码中打印版本号的位置上将这些信息格式化输出,类似👇
package cmd
import (
"fmt"
"github.com/spf13/cobra"
"github.com/voidint/gbb/build"
)
var (
// Version 版本号
Version = "0.1.0"
)
var versionCmd = &cobra.Command{
Use: "version",
Short: "Print version information",
Long: ``,
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("gbb version %s\n", Version)
if build.Date != "" {
fmt.Printf("date: %s\n", build.Date)
}
if build.Commit != "" {
fmt.Printf("commit: %s\n", build.Commit)
}
},
}
func init() {
RootCmd.AddCommand(versionCmd)
}
step1
在项目根目录执行gbb init
,按照gbb init
的提示,逐步填写完信息并最终生成gbb.json
文件。
$ gbb init
This utility will walk you through creating a gbb.json file.
It only covers the most common items, and tries to guess sensible defaults.
Press ^C at any time to quit.
tool: (go_install) go_build
package: (main) github.com/voidint/gbb/build
variable: Date
value: {{.date}}
Do you want to continue?[y/n] y
variable: Commit
value: {{.gitCommit}}
Do you want to continue?[y/n] n
About to write to /Users/voidint/cloud/workspace/go/projects/src/github.com/voidint/gbb/gbb.json:
{
"version": "0.1.0",
"tool": "go install",
"package": "github.com/voidint/gbb/build",
"variables": [
{
"variable": "Date",
"value": "{{.date}}"
},
{
"variable": "Commit",
"value": "{{.gitCommit}}"
}
]
}
Is this ok?[y/n] y
关于gbb.json
,请参见下文的详细说明。
step2
在gbb.json
文件所在目录编译(若目录下没有gbb.json
文件,gbb init
会被自动调用)。
$ gbb --debug
==> go build -ldflags '-X "github.com/voidint/gbb/build.Date=2016-12-17T22:18:32+08:00" -X "github.com/voidint/gbb/build.Commit=db8b606cfc2b24a24e2e09acac24a52c47b68401"'
编译完后在目录下多出一个编译后的二进制文件,接着打印版本信息,看看是否实现我们设定的目标了。
$ ./gbb version
gbb version 0.1.0
date: 2016-12-17T22:18:32+08:00
commit: db8b606cfc2b24a24e2e09acac24a52c47b68401
😊
gbb.json
gbb.json
可以认为是gbb
工具的配置文件,通过gbb init
自动创建(感谢npm init
)。通常它的格式是这样:
{
"version": "0.1.0",
"tool": "gb_build",
"package": "build",
"variables": [
{
"variable":"Date",
"value":"{{.date}}"
},
{
"variable":"Commit",
"value":"{{.gitCommit}}"
}
]
}
version
: 版本号。预留字段。
tool
: gbb实际调用的编译工具。已知的可选值包括:go_build
、go_install
、gb_build
。注意:这个值不能包含空格issue,因此暂时通过下划线_
连接。
pakcage
: 包名,也就是定义Date
、Commit
这类变量的包全路径,如github.com/voidint/gbb/build
。
variables
: 变量列表。列表中的每个元素都包含variable
和value
两个属性。
variable
属性表示变量名,比如Date
。
value
属性表示变量值表达式,比如{{.date}}
。内置变量表达式列表。