概要
golangではbuild時にldflags
というオプションをつけると、変数に値を埋め込んだ状態でバイナリを生成することができます。
よく使われるのはビルド時のgitのcommitのハッシュを埋め込んで、そのバイナリがどのcommitで作成されたのかを明らかにして「想定したバージョンでビルドができているか」や「複数のサーバ間で同じバージョンを使用できているか」などをチェックしたりします。
今回はそのldflagsを使う上でハマったことを書きます。
環境
- go 1.7.4
ハマったこと
go 1.5から書き方が変わった
以前はスペースで区切って
go build -ldflags "-X パッケージ名.変数 値"
でしたが、今は=を使って
go build -ldflags "-X パッケージ名.変数=値"
となります。
複数埋め込みたい場合は
go build -ldflags "-X パッケージ名.変数=値 -X パッケージ名.変数=値"
でOKです。
main packageじゃない変数に埋め込みたい
よくネットの情報で見るのはmain packageの変数に埋め込むやり方で
package main import "fmt" var version string func main() { fmt.Println(version) }
というファイルで
$ go build -ldflags "-X main.version=1.0.0"
で埋め込みます。これはこれで正しいのですが、では別パッケージになった場合
github.com/jun06t/sample/api/alive.go
package api import "fmt" var version string func alive() { fmt.Println(version) }
に対して
$ go build -ldflags "-X api.version=1.0.0"
はできるかというと、できません。
正しくは$GOPATH/src
からのpathである必要があります。
$ go build -ldflags "-X github.com/jun06t/sample/api.version=1.0.0"
最後のapi.version
のapi
の部分はpackage名ではなくフォルダ名を指定する必要があるので注意してください。
usage: link [options] main.oが出る
$ COMMIT=$(git rev-parse --verify HEAD) \ > BUILDDATE=$(date '+%Y/%m/%d %H:%M:%S %Z') \ > go build -ldflags "-X github.com/jun06t/sample/api.commit=${COMMIT} -X github.com/jun06t/sample/api.builddate=${BUILDDATE}"
として実行しようとしたところなぜか
# command-line-arguments usage: link [options] main.o -B note add an ELF NT_GNU_BUILD_ID note when using ELF -C check Go calls to C code -D address set data segment address (default -1) -E entry set entry symbol name -H type set header type -I linker use linker as ELF dynamic linker
というように使い方を表示されました。
原因はBUILDDATE
の中身が2016/12/08 04:23:44 JST
のような形になっているのですが、これに半角スペースが含まれていることでGo1.5以前の記述とみなされて「使い方が間違ってるよ」と怒られてました。
正しくは
go build -ldflags "-X github.com/jun06t/sample/api.commit=${COMMIT} -X \"github.com/jun06t/sample/api.builddate=${BUILDDATE}\""
のように、空白を含む場合は-Xの引数全体を""
で囲う必要があります。
git describe –tagsでエラー
これもよく載っていますが、埋め込む際に
$ git describe --tags
を使っているのを見ます。僕のリポジトリで実行したところ
$ git describe --tags fatal: No names found, cannot describe anything.
というエラーになりました。理由はそのリポジトリにtagがなかったからです。
その場合コミットのハッシュ値にしたいと思うので
$ git rev-parse --verify HEAD
を使います。
[その他]バイナリに埋め込んだ方が良い情報
項目 | コマンド |
---|---|
commit hash | git rev-parse --verify HEAD |
ビルド日時 | date '+%Y/%m/%d %H:%M:%S %Z' |
Goバージョン | go version |
などがあれば十分だと思います。