cmd/go: add -buildversion build flag
要約
概要
go build/go install実行時に、ビルドプロセス側が把握しているバージョン文字列を明示的に指定できる新フラグ-buildversionを追加する提案です。これによりruntime/debug.BuildInfo.Main.Versionに反映されるバージョン情報を、VCS(バージョン管理システム)情報に頼らずに設定できるようになります。
ステータス変更
active → hold
2026-08-19の提案レビュー会議で「hold」(保留)と判定されました。直近の議論で、セマンティックバージョニング(semver)形式に厳密に制限すべきか、-buildversionが-buildvcsを完全に上書き(タイムスタンプやコミットハッシュを喪失)してよいか、パッケージャ以外のプロジェクトオーナーのユースケースをどう扱うかなど、複数の設計上の論点で合意形成が完了していないため、議論継続が必要と判断されました。
技術的背景
現状の問題点
Goバイナリのバージョン情報は現在、-buildvcsフラグによりGit等のVCS情報から自動的にスタンプされます。しかし、以下のようなケースでは正しいバージョンを埋め込めません。
- Linuxディストリビューションのパッケージマネージャが、GitHub自動生成のソースtarball(
.gitを含まない)からビルドする場合 - 独自のバージョン体系(例:
1.2.3-1のようなDebian形式)を持つパッケージング環境 - リビルド時のキャッシュ効率のため
.gitをあえて含めないdocker buildのようなワークフロー
これまでの回避策は-ldflags -X main.Version=...をMakefile等で組み合わせる手法であり、標準化されていませんでした。
提案された解決策
提案者Filippo Valsorda氏(@FiloSottile)による当初案は、go build -buildversion=v1.2.3のようにバージョン文字列を直接指定するシンプルなフラグでした。議論を経て、cmd/goワーキンググループは以下の設計に収斂しました。
- 値は
golang.org/x/mod/semverで妥当と判定されるsemver形式(マイナー・パッチ含む)である必要がある -buildversionが指定されると-buildvcsは強制的にoffになり、vcs.revisionやvcs.timeは空になる- パッケージングエコシステムを示す情報は、semverのビルドメタデータ(
+以降)にv1.2.3+debian.1.2.3-4のような慣習で埋め込むことを推奨 go version -mの出力に-buildversionフラグ自体が記録され、自動スタンプでないことが分かるようにする
一方、ファイル方式(go.infoをgo.mod横に配置し、GOPROXYの.info形式でバージョン・タイムスタンプ等を記述)という代替案も長く検討されましたが、コミット時の陳腐化リスクや複雑さへの懸念から、最終的にフラグ方式が優先されました。
これによって何ができるようになるか
パッケージマネージャやディストリビューションのビルドスクリプトが、自身の持つバージョン情報をGoバイナリに正確に埋め込めるようになります。これによりdebug.ReadBuildInfo()を使ったバージョン表示が、あらゆるビルド経路で一貫して機能することが期待されます。
コード例
// Before: ldflagsでバージョンを埋め込むワークアラウンド
// Makefile側:
// go build -ldflags "-X main.Version=$(VERSION)" ./cmd/foo
var Version = "dev"
// After: -buildversionフラグで指定し、debug.BuildInfoから標準的に取得
buildInfo, ok := debug.ReadBuildInfo()
if !ok {
panic("must be built with modules")
}
fmt.Println(buildInfo.Main.Version) // go build -buildversion=v1.2.3+debian.1 で埋め込まれた値
議論のハイライト
- 当初はVCS情報を持たないソースアーカイブ(シナリオ4)にも対応できる
go.infoファイル方式が有力視されたが、コミットされたファイルの陳腐化リスクや、GitHub自動生成tarballとの相性の悪さから、最終的にはフラグ方式に回帰した(AURやnixpkgsの実態調査で、パッケージの大半がVCS無しの自動生成tarballを使っていることが判明したことも影響)。 - cmd/goワーキンググループは、
vcs.timeやvcs.revision個別指定は誤情報のリスクがあるとして見送り、単一のsemverバージョン文字列+ビルドメタデータのみをサポートする方針を採用。 - semver形式への厳格な制限に対し、GraysonTinker氏らから「ディストリビューション固有のバージョン体系と相性が悪いのでは」との懸念が出た。
- mvdan氏や sudomateo氏から、プロジェクトオーナー自身がタイムスタンプ付き擬似バージョンを注入したいユースケース(
-buildvcs廃止による情報損失)への懸念が示され、議論が紛糾。コミュニティメンバーが「意見が正当に扱われていないと感じる」という運営面の摩擦も表面化した。 - 最終的に、設計の細部(semver制約の是非、
-buildvcsとの排他性、パッケージエコシステム表記の慣習)について合意が固まりきらず、holdとされた。