[インデックス 12460] ファイルの概要
このコミットは、Go言語のコマンドラインツール cmd/go
における、Windows環境での実行ファイル名に関する挙動の修正です。具体的には、go build
コマンドで生成される実行ファイルに、Windowsでは常に .exe
サフィックスが付与されるように変更されました。
コミット
commit 6a426169f531971dd69b2ad17c848dbb8fae125a
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Wed Mar 7 14:25:24 2012 +0800
cmd/go: always provide .exe suffix on windows
Fixes #3190.
R=rsc, tjyang2001, rsc
CC=golang-dev
https://golang.org/cl/5759056
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/6a426169f531971dd69b2ad17c848dbb8fae125a
元コミット内容
cmd/go: always provide .exe suffix on windows
Fixes #3190.
R=rsc, tjyang2001, rsc
CC=golang-dev
https://golang.org/cl/5759056
変更の背景
この変更は、Go言語のIssue #3190を修正するために行われました。Issue #3190は、Windows環境で go build
コマンドを使用して実行ファイルをビルドする際に、特定の条件下で .exe
拡張子が自動的に付与されないという問題点を指摘していました。
通常、Windowsの実行ファイルは .exe
拡張子を持つことが期待されます。しかし、go build
が常にこの拡張子を付与するわけではなかったため、ユーザーがビルドした実行ファイルを直接実行しようとした際に、OSがそれを実行可能ファイルとして認識できず、不便が生じていました。このコミットは、この一貫性のない挙動を修正し、Windows上でのGoプログラムのビルド体験を向上させることを目的としています。
前提知識の解説
Go言語のビルドシステム (cmd/go
)
cmd/go
は、Go言語の公式ツールチェーンの一部であり、ソースコードのコンパイル、パッケージの管理、テストの実行など、Go開発における様々なタスクを処理します。その中でも go build
コマンドは、Goのソースコードを実行可能なバイナリにコンパイルするために使用されます。
実行ファイルの拡張子とOSの挙動
オペレーティングシステム(OS)は、ファイルの種類を識別するためにファイル拡張子を利用します。
- Windows: Windowsでは、実行可能ファイルは通常
.exe
拡張子を持ちます。OSは、この拡張子を持つファイルを直接実行可能なプログラムとして認識します。拡張子がない場合や、異なる拡張子の場合、ユーザーは手動で実行方法を指定する必要があるか、OSがそのファイルをプログラムとして認識しない可能性があります。 - Unix系OS (Linux, macOSなど): Unix系のOSでは、ファイル拡張子はファイルの種類を示すための慣習的なものであり、実行可能性を決定する主要な要素ではありません。ファイルの実行可能性は、ファイルパーミッション(実行ビット)によって制御されます。
go build
の出力ファイル名決定ロジック(変更前)
このコミット以前の go build
の挙動では、出力ファイル名の決定ロジックが複雑でした。
go build -o <output_name>
のように-o
フラグで出力ファイル名が明示的に指定された場合、その名前がそのまま使用されます。-o
フラグが指定されず、ビルド対象が単一のmain
パッケージである場合、デフォルトの出力ファイル名が決定されます。- Unix系OSでは、通常、パッケージのインポートパスの最後の要素(例:
github.com/user/project
ならproject
)がファイル名となります。 - Windowsでは、このデフォルト名に
.exe
が付与される場合とされない場合がありました。特に、go build main.go
のように単一のGoファイルを指定してビルドした場合、.exe
が付与されないことが問題となっていました。
- Unix系OSでは、通常、パッケージのインポートパスの最後の要素(例:
技術的詳細
このコミットの技術的な核心は、GoのビルドツールがWindows上で実行ファイルを生成する際に、常に .exe
拡張子を付与するように、ファイル名決定ロジックを簡素化し、統一することにあります。
変更は src/cmd/go/build.go
ファイルに対して行われました。このファイルは、go build
コマンドの主要なロジックを含んでいます。
具体的な変更点は以下の通りです。
-
exeSuffix
変数の導入: Goのビルドシステムは、クロスコンパイルをサポートしています。つまり、Linux上でWindows用のバイナリをビルドすることも可能です。このため、OS固有の実行ファイル拡張子をハードコードするのではなく、exeSuffix
という変数(または定数)を導入し、その値がターゲットOSに応じて適切に設定されるようにします。Windowsの場合、このexeSuffix
は.exe
となります。 -
出力ファイル名決定ロジックの統一: 以前は、Windowsの場合にのみ
.exe
を追加する条件分岐がコード内に散在していました。この変更により、*buildO += exeSuffix
という形式で、常にexeSuffix
を出力ファイル名に追加するように統一されました。これにより、コードの可読性と保守性が向上し、将来的に他のOSが追加された場合でも、同様のロジックで対応できるようになります。特に、以下の2つのケースで変更が適用されました。
go build
コマンドで-o
フラグが指定されず、かつビルド対象が単一のmain
パッケージである場合。go build <file.go>
のように単一のGoファイルを指定してビルドし、-o
フラグが指定されない場合。
この修正により、Windows環境で go build
を実行すると、どのような状況でも生成される実行ファイルには必ず .exe
拡張子が付与されるようになり、ユーザーは期待通りのファイル名で実行ファイルを受け取れるようになりました。
コアとなるコードの変更箇所
変更は src/cmd/go/build.go
ファイルに集中しています。
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -168,9 +168,7 @@ func runBuild(cmd *Command, args []string) {
if len(pkgs) == 1 && pkgs[0].Name == "main" && *buildO == "" {
_, *buildO = path.Split(pkgs[0].ImportPath)
- if goos == "windows" {
- *buildO += ".exe"
- }
+ *buildO += exeSuffix
}
if *buildO != "" {
@@ -392,7 +390,7 @@ func goFilesPackage(gofiles []string) *Package {
if *buildO == "" {
if pkg.Name == "main" {
_, elem := filepath.Split(gofiles[0])
- *buildO = elem[:len(elem)-len(".go")]
+ *buildO = elem[:len(elem)-len(".go")] + exeSuffix
} else {
*buildO = pkg.Name + ".a"
}
コアとなるコードの解説
上記の差分は、src/cmd/go/build.go
内の2つの異なる場所で、出力ファイル名の決定ロジックが変更されたことを示しています。
-
最初の変更箇所 (L168-171):
// 変更前 if goos == "windows" { *buildO += ".exe" } // 変更後 *buildO += exeSuffix
この部分は、
go build
コマンドが単一のmain
パッケージをビルドし、かつ-o
フラグで出力ファイル名が指定されていない場合のデフォルトのファイル名決定ロジックです。 変更前は、明示的にgoos == "windows"
という条件で.exe
を追加していました。 変更後は、exeSuffix
という変数(または定数)を無条件に追加するように修正されています。これにより、exeSuffix
がWindows環境では.exe
に解決されるため、より汎用的で簡潔な記述になっています。 -
二番目の変更箇所 (L392-394):
// 変更前 *buildO = elem[:len(elem)-len(".go")] // 変更後 *buildO = elem[:len(elem)-len(".go")] + exeSuffix
この部分は、
go build <file.go>
のように単一のGoファイルを指定してビルドし、-o
フラグが指定されていない場合のデフォルトのファイル名決定ロジックです。 変更前は、.go
拡張子を取り除いたファイル名がそのまま出力ファイル名となっていました。 変更後は、.go
拡張子を取り除いたファイル名にexeSuffix
を追加するように修正されています。これにより、go build main.go
のようなコマンドでも、Windowsではmain.exe
が生成されるようになります。
これらの変更により、Windows環境における go build
の出力ファイル名が、常に .exe
拡張子を持つように統一され、ユーザーエクスペリエンスが向上しました。
関連リンク
- Go Issue #3190: https://github.com/golang/go/issues/3190
- Go CL 5759056: https://golang.org/cl/5759056
参考にした情報源リンク
- Go Issue Tracker (GitHub): https://github.com/golang/go/issues
- Go Code Review (Gerrit): https://go-review.googlesource.com/
- Go Documentation: https://go.dev/doc/
- Windowsファイル拡張子に関する一般的な情報 (Microsoft Learnなど)
- Unix系OSの実行ファイルパーミッションに関する一般的な情報 (Linux man pagesなど)
go build
コマンドの公式ドキュメント
[インデックス 12460] ファイルの概要
このコミットは、Go言語のコマンドラインツール cmd/go
における、Windows環境での実行ファイル名に関する挙動の修正です。具体的には、go build
コマンドで生成される実行ファイルに、Windowsでは常に .exe
サフィックスが付与されるように変更されました。
コミット
commit 6a426169f531971dd69b2ad17c848dbb8fae125a
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Wed Mar 7 14:25:24 2012 +0800
cmd/go: always provide .exe suffix on windows
Fixes #3190.
R=rsc, tjyang2001, rsc
CC=golang-dev
https://golang.org/cl/5759056
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/6a426169f531971dd69b2ad17c848dbb8fae125a
元コミット内容
cmd/go: always provide .exe suffix on windows
Fixes #3190.
R=rsc, tjyang2001, rsc
CC=golang-dev
https://golang.org/cl/5759056
変更の背景
この変更は、Go言語のIssue #3190を修正するために行われました。Issue #3190は、Windows環境で go build
コマンドを使用して実行ファイルをビルドする際に、特定の条件下で .exe
拡張子が自動的に付与されないという問題点を指摘していました。
通常、Windowsの実行ファイルは .exe
拡張子を持つことが期待されます。しかし、go build
が常にこの拡張子を付与するわけではなかったため、ユーザーがビルドした実行ファイルを直接実行しようとした際に、OSがそれを実行可能ファイルとして認識できず、不便が生じていました。このコミットは、この一貫性のない挙動を修正し、Windows上でのGoプログラムのビルド体験を向上させることを目的としています。
前提知識の解説
Go言語のビルドシステム (cmd/go
)
cmd/go
は、Go言語の公式ツールチェーンの一部であり、ソースコードのコンパイル、パッケージの管理、テストの実行など、Go開発における様々なタスクを処理します。その中でも go build
コマンドは、Goのソースコードを実行可能なバイナリにコンパイルするために使用されます。
実行ファイルの拡張子とOSの挙動
オペレーティングシステム(OS)は、ファイルの種類を識別するためにファイル拡張子を利用します。
- Windows: Windowsでは、実行可能ファイルは通常
.exe
拡張子を持ちます。OSは、この拡張子を持つファイルを直接実行可能なプログラムとして認識します。拡張子がない場合や、異なる拡張子の場合、ユーザーは手動で実行方法を指定する必要があるか、OSがそのファイルをプログラムとして認識しない可能性があります。 - Unix系OS (Linux, macOSなど): Unix系のOSでは、ファイル拡張子はファイルの種類を示すための慣習的なものであり、実行可能性を決定する主要な要素ではありません。ファイルの実行可能性は、ファイルパーミッション(実行ビット)によって制御されます。
go build
の出力ファイル名決定ロジック(変更前)
このコミット以前の go build
の挙動では、出力ファイル名の決定ロジックが複雑でした。
go build -o <output_name>
のように-o
フラグで出力ファイル名が明示的に指定された場合、その名前がそのまま使用されます。-o
フラグが指定されず、ビルド対象が単一のmain
パッケージである場合、デフォルトの出力ファイル名が決定されます。- Unix系OSでは、通常、パッケージのインポートパスの最後の要素(例:
github.com/user/project
ならproject
)がファイル名となります。 - Windowsでは、このデフォルト名に
.exe
が付与される場合とされない場合がありました。特に、go build main.go
のように単一のGoファイルを指定してビルドした場合、.exe
が付与されないことが問題となっていました。
- Unix系OSでは、通常、パッケージのインポートパスの最後の要素(例:
技術的詳細
このコミットの技術的な核心は、GoのビルドツールがWindows上で実行ファイルを生成する際に、常に .exe
拡張子を付与するように、ファイル名決定ロジックを簡素化し、統一することにあります。
変更は src/cmd/go/build.go
ファイルに対して行われました。このファイルは、go build
コマンドの主要なロジックを含んでいます。
具体的な変更点は以下の通りです。
-
exeSuffix
変数の導入: Goのビルドシステムは、クロスコンパイルをサポートしています。つまり、Linux上でWindows用のバイナリをビルドすることも可能です。このため、OS固有の実行ファイル拡張子をハードコードするのではなく、exeSuffix
という変数(または定数)を導入し、その値がターゲットOSに応じて適切に設定されるようにします。Windowsの場合、このexeSuffix
は.exe
となります。 -
出力ファイル名決定ロジックの統一: 以前は、Windowsの場合にのみ
.exe
を追加する条件分岐がコード内に散在していました。この変更により、*buildO += exeSuffix
という形式で、常にexeSuffix
を出力ファイル名に追加するように統一されました。これにより、コードの可読性と保守性が向上し、将来的に他のOSが追加された場合でも、同様のロジックで対応できるようになります。特に、以下の2つのケースで変更が適用されました。
go build
コマンドで-o
フラグが指定されず、かつビルド対象が単一のmain
パッケージである場合。go build <file.go>
のように単一のGoファイルを指定してビルドし、-o
フラグが指定されない場合。
この修正により、Windows環境で go build
を実行すると、どのような状況でも生成される実行ファイルには必ず .exe
拡張子が付与されるようになり、ユーザーは期待通りのファイル名で実行ファイルを受け取れるようになりました。
コアとなるコードの変更箇所
変更は src/cmd/go/build.go
ファイルに集中しています。
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -168,9 +168,7 @@ func runBuild(cmd *Command, args []string) {
if len(pkgs) == 1 && pkgs[0].Name == "main" && *buildO == "" {
_, *buildO = path.Split(pkgs[0].ImportPath)
- if goos == "windows" {
- *buildO += ".exe"
- }
+ *buildO += exeSuffix
}
if *buildO != "" {
@@ -392,7 +390,7 @@ func goFilesPackage(gofiles []string) *Package {
if *buildO == "" {
if pkg.Name == "main" {
_, elem := filepath.Split(gofiles[0])
- *buildO = elem[:len(elem)-len(".go")]
+ *buildO = elem[:len(elem)-len(".go")] + exeSuffix
} else {
*buildO = pkg.Name + ".a"
}
コアとなるコードの解説
上記の差分は、src/cmd/go/build.go
内の2つの異なる場所で、出力ファイル名の決定ロジックが変更されたことを示しています。
-
最初の変更箇所 (L168-171):
// 変更前 if goos == "windows" { *buildO += ".exe" } // 変更後 *buildO += exeSuffix
この部分は、
go build
コマンドが単一のmain
パッケージをビルドし、かつ-o
フラグで出力ファイル名が指定されていない場合のデフォルトのファイル名決定ロジックです。 変更前は、明示的にgoos == "windows"
という条件で.exe
を追加していました。 変更後は、exeSuffix
という変数(または定数)を無条件に追加するように修正されています。これにより、exeSuffix
がWindows環境では.exe
に解決されるため、より汎用的で簡潔な記述になっています。 -
二番目の変更箇所 (L392-394):
// 変更前 *buildO = elem[:len(elem)-len(".go")] // 変更後 *buildO = elem[:len(elem)-len(".go")] + exeSuffix
この部分は、
go build <file.go>
のように単一のGoファイルを指定してビルドし、-o
フラグが指定されていない場合のデフォルトのファイル名決定ロジックです。 変更前は、.go
拡張子を取り除いたファイル名がそのまま出力ファイル名となっていました。 変更後は、.go
拡張子を取り除いたファイル名にexeSuffix
を追加するように修正されています。これにより、go build main.go
のようなコマンドでも、Windowsではmain.exe
が生成されるようになります。
これらの変更により、Windows環境における go build
の出力ファイル名が、常に .exe
拡張子を持つように統一され、ユーザーエクスペリエンスが向上しました。
関連リンク
- Go Issue #3190: https://github.com/golang/go/issues/3190
- Go CL 5759056: https://golang.org/cl/5759056
参考にした情報源リンク
- Go Issue Tracker (GitHub): https://github.com/golang/go/issues
- Go Code Review (Gerrit): https://go-review.googlesource.com/
- Go Documentation: https://go.dev/doc/
- Windowsファイル拡張子に関する一般的な情報 (Microsoft Learnなど)
- Unix系OSの実行ファイルパーミッションに関する一般的な情報 (Linux man pagesなど)
go build
コマンドの公式ドキュメント