メインコンテンツへスキップ

Go Proposal Weekly Digest

Go言語のproposal更新を毎週お届け

cmd/go: add -buildversion build flag

ステータス変更: active hold

要約

AIによる要約であり、誤りを含む場合があります。

概要

go build/go install実行時に、ビルドプロセス側が把握しているバージョン文字列を明示的に指定できる新フラグ-buildversionを追加する提案です。これによりruntime/debug.BuildInfo.Main.Versionに反映されるバージョン情報を、VCS(バージョン管理システム)情報に頼らずに設定できるようになります。

ステータス変更

activehold
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.revisionvcs.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.timevcs.revision個別指定は誤情報のリスクがあるとして見送り、単一のsemverバージョン文字列+ビルドメタデータのみをサポートする方針を採用。
  • semver形式への厳格な制限に対し、GraysonTinker氏らから「ディストリビューション固有のバージョン体系と相性が悪いのでは」との懸念が出た。
  • mvdan氏や sudomateo氏から、プロジェクトオーナー自身がタイムスタンプ付き擬似バージョンを注入したいユースケース(-buildvcs廃止による情報損失)への懸念が示され、議論が紛糾。コミュニティメンバーが「意見が正当に扱われていないと感じる」という運営面の摩擦も表面化した。
  • 最終的に、設計の細部(semver制約の是非、-buildvcsとの排他性、パッケージエコシステム表記の慣習)について合意が固まりきらず、holdとされた。

関連リンク