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

Go Proposal Weekly Digest

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

#77020active

cmd/go: add -buildversion build flag

新規提案

要約

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

概要

go build でバイナリをビルドする際に、バージョン情報を debug.BuildInfo.Main.Version に埋め込むための -buildversion フラグを cmd/go に追加するプロポーザルです。パッケージマネージャーなど、バージョンを知っているビルドプロセスが、VCS情報なしでバイナリにバージョンを注入できるようにします。

ステータス変更

(新規)active
2026年4月16日、@aclements(Goコアチーム)がこのプロポーザルをアクティブカラムに追加し、週次プロポーザルレビューミーティングの審議対象となりました。@mvdan が Go 1.27 のフリーズまで約7週間というタイミングでレビューを強く促したことが直接的な契機となっています。

技術的背景

現状の問題点

Go バイナリには debug.BuildInfo を通じてバージョン情報が埋め込まれますが、そのソースは限られています。

  1. go install example.com/cli@v1.2.3 — モジュールバージョンが埋め込まれる(動作する)
  2. git clone してから go build — Go 1.24 で解決済み(#50603)、VCS タグからバージョンを埋め込めるようになった
  3. パッケージマネージャーによるビルド — 未解決。Nix や Debian などのパッケージマネージャーはソースアーカイブ(.tar.gz)からビルドするため .git ディレクトリが存在せず、バージョン情報が埋め込めない
  4. ソースアーカイブからの go build未解決
    ケース3において、パッケージマネージャーはビルドするバージョンを知っているにもかかわらず、それを cmd/go に伝える手段がありません。現在の回避策は -ldflags='-X main.version=v1.2.3' のような方法ですが、これはアプリケーション固有の変数を対象とするものであり、標準の debug.BuildInfo.Main.Version には反映されません。

提案された解決策

-buildversion フラグの追加:

-buildversion version
    The version of the main module being built. This overrides the version
    derived from -buildvcs information. It is an error to use this flag with
    "go install" with a version suffix. version must be a valid semver string
    with a "v" prefix.

このフラグを使用することで debug.BuildInfo.Main.Version が指定したバージョンに設定されます。

これによって何ができるようになるか

標準的な方法でバイナリ自身がバージョンを取得できるようになります。ビルドプロセスがバージョンを知っている場面(パッケージマネージャー、CI/CD パイプライン、Docker ビルドなど)で -buildvcs=false になる環境でもバージョンが埋め込まれます。

コード例

// Before: -ldflags を使った従来のワークアラウンド(ビルド側)
// go build -ldflags="-X main.version=v1.2.3" ./cmd/myapp
// アプリ固有の変数にしか反映されず、debug.BuildInfo.Main.Version は "(devel)" のまま
var version = "(devel)" // アプリ側でも変数を用意する必要がある
func printVersion() {
    fmt.Println(version) // ldflags で注入された値
}
// After: -buildversion を使った新しい方法(ビルド側)
// go build -buildversion=v1.2.3 ./cmd/myapp
// debug.BuildInfo.Main.Version に v1.2.3 が反映される
func printVersion() {
    info, ok := debug.ReadBuildInfo()
    if !ok {
        panic("build info unavailable")
    }
    fmt.Println(info.Main.Version) // v1.2.3
}

議論のハイライト

  • @ianlancetaylor はドキュメントに Buildinfo.Main.Version を設定するという効果を明記すべきと指摘。また、main パッケージ以外でのビルド時にエラーにすべきか質問した。提案者 @FiloSottile はメインモジュールのバージョンは main パッケージに限らない概念なので不要と返答。
  • @seankhliao は単一のバージョン文字列だけでなく、モジュールプロキシが使う .info ファイル(JSON形式でコミットハッシュやタイムスタンプを含む)をパスとして渡せるよう -buildvcs を拡張することを提案。Dockerビルドで .git.dockerignore に入れるケースで有用と指摘。
  • @mvdan.info ファイルアプローチに同意しつつ、govcs.info のような決まったファイル名が存在すれば自動的に読み込まれる仕組みが望ましいと主張。フラグを指定しなくても動作するため、ソースアーカイブに含めるだけでバージョン情報が保持できると説明。この考えに基づく実装CL(go.dev/cl/762920: cmd/go: read vcs info from a .info file)も投稿されている。
  • @stapelberg は Nix パッケージマネージャーにおいて VCS スタンピングのために git の挙動を模倣する複雑な回避策(.git/HEAD の合成と偽の git コマンドのインジェクション)を実装していることを紹介し、標準的な解決策の必要性を訴えた。
  • 議論は単純な -buildversion フラグから .info ファイルを使うより豊富なメタデータの受け渡しへと発展しており、最終的な API 設計はまだ確定していない。

関連リンク