Golang開源:gbb-自動生成程序版本號
gbb
昨天跑得好好的程序突然出了問題,查看它的版本號,機器冷冰冰地告訴你 :point_down:
$ 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 就能幫到你,耐心往下 :eyes: 吧。
安裝
-
拉取源代碼
$ 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源代碼的。類似 :point_down:
$ 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</code></pre>
可以看到當前目錄下已經多了一個可執行的二進制文件。沒錯,這個 ./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 的版本信息 :point_down:
$ gbb version
gbb version v0.0.1
date: 2016-12-17T15:37:09+08:00
commit: db8b606cfc2b24a24e2e09acac24a52c47b68401
這個版本信息,除了常規的 v0.0.1 ,還有這個 gbb 二進制文件編譯生成的時間,以及項目所使用的源代碼管理工具 git 的最近一次 commit 號。這樣的版本信息是否比簡單的一個 v0.0.1 要更加友好呢?豐富的版本信息也為 debug 降低了難度,因為這個二進制能和倉庫中的源代碼唯一對應了。
step0
為了在版本信息中顯示 編譯時間 和 commit號 這兩個關鍵信息,需要先定義兩個變量(變量不需要賦初值)。
package build
var (
Date string
Commit string
)
然后,在代碼中打印版本號的位置上將這些信息格式化輸出,類似 :point_down:
package cmd
import (
"fmt"
"github.com/spf13/cobra"
"github.com/voidint/gbb/build"
)
var (
// Version 版本號
Version = "v0.0.1"
)
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)
}</code></pre>
step1
在項目目錄 合適的地方 執行 gbb init 生成 gbb.json 文件。
合適的地方指哪些地方?一般規律是這樣:
- 若使用的是 go build/install 工具編譯代碼( gbb init 執行過程中填寫的 tool 項對應的值),那么這個 合適的地方 就是 main 方法所在目錄。
- 若使用 gb 工具編譯代碼,那么這個 合適的地方 就是項目根目錄。
按照 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.
version: (0.0.1)
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.0.1",
"tool": "go install",
"package": "github.com/voidint/gbb/build",
"variables": [
{
"variable": "Date",
"value": "{{.date}}"
},
{
"variable": "Commit",
"value": "{{.gitCommit}}"
}
]
}
Is this ok?[y/n] y</code></pre>
關于 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 v0.0.1
date: 2016-12-17T22:18:32+08:00
commit: db8b606cfc2b24a24e2e09acac24a52c47b68401
:blush:
gbb.json
gbb.json 可以認為是 gbb 工具的配置文件,通過 gbb init 自動創建(感謝 npm init )。通常它的格式是這樣:
{
"version": "0.0.1",
"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}} 。內置變量表達式列表。
</li>
</ul>