Goアプリがコンパイルされるたびにマイナーバージョン番号を自動的にインクリメントすることは可能ですか?
自動インクリメントセクションを使用して、プログラム内にバージョン番号を設定したいと思います。
$ myapp -version
MyApp version 0.5.132
私が設定したバージョン番号は0.5で、バイナリがコンパイルされるたびに自動的に増加する値です。
これはGoで可能ですか?
Goアプリがコンパイルされるたびにマイナーバージョン番号を自動的にインクリメントすることは可能ですか?
自動インクリメントセクションを使用して、プログラム内にバージョン番号を設定したいと思います。
$ myapp -version
MyApp version 0.5.132
私が設定したバージョン番号は0.5で、バイナリがコンパイルされるたびに自動的に増加する値です。
これはGoで可能ですか?
Goリンカ(go tool link)には、初期化されていない文字列変数の値を設定するオプションがあります。
-X importpath.name=value Set the value of the string variable in importpath named name to
価値。Go 1.5より前では、このオプションは2つの別々の引数をとっていたことに注意してください。これで、最初の=記号で1つの引数が分割されます。
ビルドプロセスの一部として、これを使用してバージョン文字列変数を設定できます。go
を使用して、これをツールに渡すことができます-ldflags
。たとえば、次のソースファイルがあるとします。
package main
import "fmt"
var xyz string
func main() {
fmt.Println(xyz)
}
それで:
$ go run -ldflags "-X main.xyz=abc" main.go
abc
main.minversion
ビルド時にビルド日時を設定するには:
go build -ldflags "-X main.minversion=`date -u +.%Y%m%d.%H%M%S`" service.go
この方法で初期化せずにコンパイルするmain.minversion
と、空の文字列が含まれます。
さらに、gitとmakefileの使用方法の簡単な例を投稿したいと思います。
--- Makefile ----
# This how we want to name the binary output
BINARY=gomake
# These are the values we want to pass for VERSION and BUILD
# git tag 1.0.1
# git commit -am "One more change after the tags"
VERSION=`git describe --tags`
BUILD=`date +%FT%T%z`
# Setup the -ldflags option for go build here, interpolate the variable values
LDFLAGS_f1=-ldflags "-w -s -X main.Version=${VERSION} -X main.Build=${BUILD} -X main.Entry=f1"
LDFLAGS_f2=-ldflags "-w -s -X main.Version=${VERSION} -X main.Build=${BUILD} -X main.Entry=f2"
# Builds the project
build:
go build ${LDFLAGS_f1} -o ${BINARY}_f1
go build ${LDFLAGS_f2} -o ${BINARY}_f2
# Installs our project: copies binaries
install:
go install ${LDFLAGS_f1}
# Cleans our project: deletes binaries
clean:
if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi
.PHONY: clean install
makeファイルは2つの実行可能ファイルを作成します。1つは関数1を実行し、もう1つは関数2をメインエントリとして使用します。
package main
import (
"fmt"
)
var (
Version string
Build string
Entry string
funcs = map[string]func() {
"f1":functionOne,"f2":functionTwo,
}
)
func functionOne() {
fmt.Println("This is function one")
}
func functionTwo() {
fmt.Println("This is function two")
}
func main() {
fmt.Println("Version: ", Version)
fmt.Println("Build Time: ", Build)
funcs[Entry]()
}
次に、実行します。
make
あなたが得るでしょう:
mab@h2470988:~/projects/go/gomake/3/gomake$ ls -al
total 2020
drwxrwxr-x 3 mab mab 4096 Sep 7 22:41 .
drwxrwxr-x 3 mab mab 4096 Aug 16 10:00 ..
drwxrwxr-x 8 mab mab 4096 Aug 17 16:40 .git
-rwxrwxr-x 1 mab mab 1023488 Sep 7 22:41 gomake_f1
-rwxrwxr-x 1 mab mab 1023488 Sep 7 22:41 gomake_f2
-rw-rw-r-- 1 mab mab 399 Aug 16 10:21 main.go
-rw-rw-r-- 1 mab mab 810 Sep 7 22:41 Makefile
mab@h2470988:~/projects/go/gomake/3/gomake$ ./gomake_f1
Version: 1.0.1-1-gfb51187
Build Time: 2016-09-07T22:41:38+0200
This is function one
mab@h2470988:~/projects/go/gomake/3/gomake$ ./gomake_f2
Version: 1.0.1-1-gfb51187
Build Time: 2016-09-07T22:41:39+0200
This is function two
ldflags
に変数を設定するために使用します。main
ファイル付きmain.go
:
package main
import "fmt"
var (
version string
build string
)
func main() {
fmt.Println("version=", version)
fmt.Println("build=", build)
}
次に、以下を実行します。
go run \
-ldflags "-X main.version=1.0.0 -X main.build=12082019" \
main.go
建てる:
go build -o mybinary \
-ldflags "-X main.version=1.0.0 -X 'main.build=$(date)'" \
main.go
ldflags
に変数を設定するために使用します。non-main
ファイル付きconfig.go
:
package config
import "fmt"
var (
Version string
)
func LogVersion() {
fmt.Println("version=", Version)
}
また、ファイルが必要になりますmain.go
:
package main
import (
"fmt"
"github.com/user/repo/config"
}
func main() {
config.LogVersion()
}
最初にバイナリを作成します。
go build -o mybinary main.go
設定する変数名のフルパスを見つけます。
go tool nm <path_to_binary> | grep Version
バイナリを再度実行してビルドしますが、ldflags
:を使用します
go run \
-ldflags "-X github.com/user/repo/config.Version=1.0.0" \
main.go --version
go build -o mybinary \
-ldflags "-X github.com/user/repo/config.Version=1.0.0" \
main.go
https://github.com/golang/go/wiki/GcToolchainTricks#include-build-information-in-the-executableに触発されました
また、使用している場合は、このhttps://goreleaser.com/environment/#using-the-mainversiongoreleaser
をお読みください。
デフォルトの賢明なGoReleaserは、3つのldflagを設定します。
main.version:現在のGitタグ
main.commit:現在のgit commit SHA
main.date:RFC3339に準拠した日付
これを実際に確認したい場合:https ://github.com/hoto/fuzzy-repo-finder/blob/master/pkg/config/config.go
コマンドラインアプリとライブラリの混合プロジェクトをビルドするときにパラメーターを使用するのに問題があった-ldflags
ため、Makefileターゲットを使用して、アプリのバージョンとビルド日を含むGoソースファイルを生成することになりました。
BUILD_DATE := `date +%Y-%m-%d\ %H:%M`
VERSIONFILE := cmd/myapp/version.go
gensrc:
rm -f $(VERSIONFILE)
@echo "package main" > $(VERSIONFILE)
@echo "const (" >> $(VERSIONFILE)
@echo " VERSION = \"1.0\"" >> $(VERSIONFILE)
@echo " BUILD_DATE = \"$(BUILD_DATE)\"" >> $(VERSIONFILE)
@echo ")" >> $(VERSIONFILE)
私のinit()
方法では、これを行います:
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "%s version %s\n", os.Args[0], VERSION)
fmt.Fprintf(os.Stderr, "built %s\n", BUILD_DATE)
fmt.Fprintln(os.Stderr, "usage:")
flag.PrintDefaults()
}
ただし、ビルド日付ではなくアトミックに増加するビルド番号が必要な場合は、最後のビルド番号を含むローカルファイルを作成する必要があります。Makefileはファイルの内容を変数に読み込み、それをインクリメントし、version.go
日付の代わりにファイルに挿入し、新しいビルド番号をファイルに書き戻します。
マルチを使用するには-ldflags
:
$ go build -ldflags "-X name1=value1 -X name2=value2" -o path/to/output
Windows OSの場合、以下のプログラムを指定します
package main
import "fmt"
var (
version string
date string
)
func main() {
fmt.Printf("version=%s, date=%s", version, date)
}
を使用して構築できます
go build -ldflags "-X main.version=0.0.1 -X main.date=%date:~10,4%-%date:~4,2%-%date:~7,2%T%time:~0,2%:%time:~3,2%:%time:~6,2%"
echo %date%
日付形式は、ご使用の環境が現在Fri 07/22/2016
およびecho %time%
であると想定しています16:21:52.88
次に、出力は次のようになります。version=0.0.1, date=2016-07-22T16:21:52
他の回答に基づいて、最近のgoバージョンでは、ビルドIDをELFセクションに書き込むこともできますが、プログラム内からはそれほど簡単に読み取ることはできません。
次のようなものを使用して、両方に同じ値を書き込みます。
BuildInfo:= "BUILD #x, branch @ rev built yymmdd hh:mm:ss"
// note the nested quotes "''" required to get a string with
// spaces passed correctly to the underlying tool
ldFl := fmt.Sprintf("-X 'main.buildId=%s' -s -w '-buildid=%s'", BuildInfo, BuildInfo)
args := []string{
"build",
"-ldflags", ldFl,
"-trimpath",
"-gcflags", "-dwarf=false",
}
buildpath:="path/to/my/cmd"
args=append(args,buildpath)
buildCmd:=exec.Command("go", args...)
これはmage
、goで記述されたビルドツールで使用します。上記の追加のフラグは必要ありませんが、リリースバイナリからできるだけ多くの情報を取り除くためにフラグを選択しました。
(オフトピック:Mageは、Makeのようなものよりも少し前もって作業する必要がありますが、makeベースのビルドシステムよりも拡張/保守がはるかに簡単です。さらに、goと他の構文の間でメンタルギアを切り替える必要はありません。)