[インデックス 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.exe
on 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の知識