[インデックス 18581] ファイルの概要
このコミットは、Go言語のツールチェインの一部である cmd/pack のテストコード pack_test.go における変更です。具体的には、go build コマンドがWindows環境で実行可能ファイルに自動的に .exe サフィックスを追加する挙動に対応するため、テスト内でビルドされる実行可能ファイルの名前を明示的に指定するように修正しています。これにより、テストの安定性とクロスプラットフォーム互換性が向上しました。
コミット
commit 0d11cd1b6ecede754c3bf24c87a955d175568093
Author: Alex Brainman <alex.brainman@gmail.com>
Date: Thu Feb 20 11:29:37 2014 +1100
cmd/pack: provide executable name in TestHello
otherwise go build command adds .exe suffix
Fixes #7362
LGTM=bradfitz
R=golang-codereviews, bradfitz
CC=golang-codereviews
https://golang.org/cl/66250043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/0d11cd1b6ecede754c3bf24c87a955d175568093
元コミット内容
cmd/pack: provide executable name in TestHello
otherwise go build command adds .exe suffix
Fixes #7362
LGTM=bradfitz
R=golang-codereviews, bradfitz
CC=golang-codereviews
https://golang.org/cl/66250043
変更の背景
このコミットは、Go言語のビルドシステムにおける特定の挙動、特にWindows環境での実行可能ファイル名の自動的なサフィックス追加に対応するために行われました。
Go言語の go build コマンドは、デフォルトではビルド対象のパッケージ名に基づいて実行可能ファイル名を決定します。例えば、main パッケージを含む cmd/pack をビルドすると、通常は pack という名前の実行可能ファイルが生成されます。しかし、Windows環境では、実行可能ファイルには慣例的に .exe という拡張子が付与されます。go build はこの慣例に従い、Windows上でビルドを行うと自動的に pack.exe のようなファイル名を生成します。
TestHello というテスト関数では、cmd/pack をビルドした後、そのビルドされた pack バイナリを ./pack というパスで実行しようとしていました。しかし、Windows環境で pack.exe が生成されると、./pack という名前ではファイルが見つからず、テストが失敗するという問題が発生していました。
この問題は、Go issue #7362 として報告されており、このコミットはその問題を解決するために導入されました。テストの実行環境に依存しない形で、ビルドされた実行可能ファイルにアクセスできるようにすることが目的です。
前提知識の解説
Go言語のビルドシステム (go build)
go build はGo言語のソースコードをコンパイルして実行可能バイナリを生成するためのコマンドです。
- デフォルトの出力ファイル名:
go buildは、特に指定がない場合、ビルド対象のパッケージ名(mainパッケージの場合)またはディレクトリ名に基づいて出力ファイル名を決定します。例えば、go build ./cmd/packと実行すると、カレントディレクトリにpack(またはpack.exeon Windows) という名前のバイナリが生成されます。 -oフラグ:go buildコマンドには-oフラグがあり、これを使用することで出力される実行可能ファイルの名前とパスを明示的に指定できます。例:go build -o myapp ./cmd/myappはmyappという名前のバイナリを生成します。- クロスプラットフォームビルド: Goはクロスプラットフォーム開発を強力にサポートしており、
GOOS(オペレーティングシステム) やGOARCH(アーキテクチャ) といった環境変数を設定することで、異なるOSやアーキテクチャ向けのバイナリをビルドできます。この際、OS固有のファイル名規則(例: Windowsの.exe拡張子)が適用されることがあります。
cmd/pack
cmd/pack は、Go言語の初期のツールチェインの一部であり、Goのアーカイブファイル(.a 拡張子を持つファイル)を操作するためのコマンドでした。これは、C言語の ar コマンドに似た機能を提供し、オブジェクトファイルやライブラリをまとめるために使用されていました。現代のGoでは、go build や go install が内部的にこれらの処理を抽象化しているため、直接 pack コマンドを使用することは稀です。しかし、Goのビルドシステムやリンカの低レベルなテストでは、このようなツールが使われることがあります。
go tool
go tool は、Goツールチェインに含まれる低レベルなツール(アセンブラ go tool asm、リンカ go tool link、コンパイラ go tool compile など)を実行するためのコマンドです。これらのツールは通常、go build や go run のような高レベルなコマンドによって内部的に呼び出されますが、開発者やテストコードが特定のビルドステップを細かく制御したい場合に直接使用されることがあります。このコミットでは go tool char+g (コンパイラ) や go tool char+l (リンカ) が使われています。char は GOCHAR 環境変数から取得され、ターゲットアーキテクチャを示す文字(例: 8 for amd64)が入ります。
技術的詳細
このコミットの核心は、go build コマンドの呼び出し方にあります。
変更前:
run("go", "build", "cmd/pack") // writes pack binary to dir
このコマンドは、cmd/pack パッケージをビルドし、その結果生成される実行可能ファイルをカレントディレクトリに配置します。Windows環境では、この実行可能ファイルは pack.exe という名前になります。しかし、その後のテストコードでは、このバイナリを ./pack という固定の名前で参照しようとしていました。
変更後:
run("go", "build", "-o", "pack", "cmd/pack") // writes pack binary to dir
この変更では、go build コマンドに -o pack という引数を追加しています。
-oフラグは、出力ファイルの名前を明示的に指定します。packは、出力ファイルの名前として指定された文字列です。
これにより、go build は、オペレーティングシステムに関わらず、常に pack という名前の実行可能ファイルを生成するようになります。Windows環境であっても、pack.exe ではなく pack という名前でファイルが作成されるため、その後の ./pack という参照が正しく機能し、テストが安定して実行されるようになります。
この修正は、テストコードが特定のOSのファイル命名規則に依存しないようにすることで、テストのポータビリティと信頼性を向上させるものです。
コアとなるコードの変更箇所
--- a/src/cmd/pack/pack_test.go
+++ b/src/cmd/pack/pack_test.go
@@ -202,7 +202,7 @@ func TestHello(t *testing.T) {
t.Fatal("cannot find GOCHAR in 'go env' output:\n", out)
}
char := fields[1]
- run("go", "build", "cmd/pack") // writes pack binary to dir
+ run("go", "build", "-o", "pack", "cmd/pack") // writes pack binary to dir
run("go", "tool", char+"g", "hello.go")
run("go", "tool", char+"l", "-o", "a.out", "hello.a")
コアとなるコードの解説
変更された行は src/cmd/pack/pack_test.go ファイルの204行目です。
-
変更前:
run("go", "build", "cmd/pack")- これは
go build cmd/packというシェルコマンドを実行します。 - Windowsでは、このコマンドは
pack.exeという名前の実行可能ファイルを生成します。 - テストコードの次のステップでは、このバイナリを
./packとして実行しようとしますが、pack.exeが存在するためファイルが見つからずエラーになります。
- これは
-
変更後:
run("go", "build", "-o", "pack", "cmd/pack")- これは
go build -o pack cmd/packというシェルコマンドを実行します。 -o packオプションは、出力ファイルの名前を明示的にpackに指定します。- これにより、Windowsを含むすべてのOSで、
packという名前の実行可能ファイルが生成されます。 - 結果として、その後の
./packという実行コマンドが正しく機能し、テストが成功するようになります。
- これは
この修正は、Goのビルドコマンドの挙動をより細かく制御することで、テストの堅牢性を高める典型的な例です。
関連リンク
- Go issue #7362: https://github.com/golang/go/issues/7362
- Gerrit Code Review (Change-Id): https://golang.org/cl/66250043
参考にした情報源リンク
- Go Command Documentation (
go build): https://pkg.go.dev/cmd/go#hdr-Build_packages_and_dependencies - Go Command Documentation (
go tool): https://pkg.go.dev/cmd/go#hdr-Go_tool_commands - Go issue #7362 (詳細な議論): https://github.com/golang/go/issues/7362
cmd/packの歴史的背景に関する情報 (Goの古いツールチェイン): https://go.dev/doc/go1.1 (Go 1.1リリースノートなど、古いドキュメントで言及がある場合があります)- Windowsにおける実行可能ファイルの命名規則: 一般的なOSの知識