[インデックス 19725] ファイルの概要
コミット
- コミットハッシュ: 8b836fa87234c5809891eceaeb87f63223217999
- 作者: Peter Collingbourne pcc@google.com
- 日付: Mon Jul 14 09:51:20 2014 -0400
- コミットメッセージ: cmd/go: introduce support for $GCCGO env var This variable allows users to select the compiler when using the gccgo toolchain. LGTM=rsc R=rsc, iant, minux, aram CC=axwalk, golang-codereviews https://golang.org/cl/106700044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/8b836fa87234c5809891eceaeb87f63223217999
元コミット内容
commit 8b836fa87234c5809891eceaeb87f63223217999
Author: Peter Collingbourne <pcc@google.com>
Date: Mon Jul 14 09:51:20 2014 -0400
cmd/go: introduce support for $GCCGO env var
This variable allows users to select the compiler when using the
gccgo toolchain.
LGTM=rsc
R=rsc, iant, minux, aram
CC=axwalk, golang-codereviews
https://golang.org/cl/106700044
---
src/cmd/go/build.go | 16 ++++++++++++----\n 1 file changed, 12 insertions(+), 4 deletions(-)\n
変更の背景
このコミットは、Go言語のビルドツールであるcmd/go
に、GCCGO
という新しい環境変数を導入するものです。この環境変数は、gccgo
ツールチェーンを使用してGoプログラムをビルドする際に、ユーザーが使用するgccgo
コンパイラの実行ファイルを明示的に指定できるようにすることを目的としています。
Go言語のビルドシステムは、通常、go build
コマンドを通じてgc
(Goコンパイラ)を使用します。しかし、Go言語にはGCC(GNU Compiler Collection)のフロントエンドとして実装された代替コンパイラであるgccgo
も存在します。gccgo
は、GCCの強力な最適化機能や、より広範なプロセッサアーキテクチャへの対応といった利点を提供します。
このコミット以前は、cmd/go
がgccgo
ツールチェーンを選択した場合、システムパスからgccgo
という名前の実行ファイルを自動的に検索して使用していました。しかし、このアプローチにはいくつかの課題がありました。
- 複数バージョンの
gccgo
の共存: 開発者のシステムに複数のバージョンのgccgo
がインストールされている場合、cmd/go
が意図しないバージョンのgccgo
を選択してしまう可能性がありました。 - 特定の
gccgo
バイナリの使用: ユーザーがカスタムビルドしたgccgo
や、特定のパスに配置されたgccgo
バイナリを使用したい場合、そのための直接的なメカニズムがありませんでした。 - 柔軟性の欠如: ビルド環境の多様化に対応するためには、コンパイラの選択に対するより高い柔軟性が求められていました。
これらの課題を解決するため、GCCGO
環境変数が導入されました。これにより、ユーザーはGCCGO
にgccgo
実行ファイルのパスまたは名前を設定することで、cmd/go
が使用するgccgo
コンパイラを柔軟に制御できるようになり、より堅牢でカスタマイズ可能なビルドプロセスが実現されます。
前提知識の解説
このコミットの変更内容を深く理解するためには、以下のGo言語および関連技術に関する前提知識が必要です。
Go言語のツールチェーン
Go言語は、ソースコードをコンパイルして実行可能なバイナリを生成するための複数の「ツールチェーン」をサポートしています。ツールチェーンとは、コンパイラ、アセンブラ、リンカなどの一連のツール群を指します。
-
gc
(Go Compiler):- Go言語の公式かつデフォルトのコンパイラです。Goチームによって開発・メンテナンスされており、Go言語の最新の仕様と機能に最も早く対応します。
- コンパイル速度が非常に高速であることで知られており、Go開発の大部分で利用されます。
- 生成されるバイナリは通常、静的にリンクされ、外部依存性が少ないのが特徴です。
-
gccgo
:- GCC (GNU Compiler Collection) のフロントエンドとして実装されたGo言語のコンパイラです。GCCの一部として開発されており、GCCの強力な最適化バックエンドを利用できます。
gc
コンパイラと比較して、コンパイル時間は長くなる傾向がありますが、生成されるコードの最適化レベルが高い場合があります。- GCCがサポートする幅広いCPUアーキテクチャに対応しているため、
gc
がサポートしないニッチなアーキテクチャでのGo開発に利用されることがあります。 libgo
というGo言語のランタイムライブラリに動的にリンクするバイナリを生成するオプションがあり、これにより実行ファイルのサイズを小さくできる可能性があります(ただし、実行環境にlibgo
が必要になります)。
cmd/go
cmd/go
は、Go言語のソースコードのビルド、テスト、パッケージ管理、ドキュメント生成など、Go開発における中心的なコマンドラインツールです。go build
、go run
、go test
、go get
などのよく知られたコマンドは、すべてcmd/go
によって提供されます。
cmd/go
は、ユーザーが指定したコマンドや設定に基づいて、適切なツールチェーン(gc
またはgccgo
)を選択し、そのツールチェーンのコンパイラやリンカなどのツールを内部的に呼び出して、実際の処理を実行します。
環境変数
環境変数とは、オペレーティングシステムが提供する、システム全体または特定のユーザーセッションで利用可能な動的な名前付きの値の集合です。プログラムはこれらの環境変数を読み取ることで、実行時の動作をカスタマイズしたり、設定情報を取得したりすることができます。
例えば、PATH
環境変数は、コマンドを実行する際にシステムが実行可能ファイルを検索するディレクトリのリストを定義します。cmd/go
もまた、GOPATH
やGOOS
、GOARCH
など、多くの環境変数を利用してその動作を制御しています。
技術的詳細
このコミットの技術的な実装は、cmd/go
がgccgo
コンパイラを特定し、実行するロジックに柔軟性をもたらすことに焦点を当てています。具体的には、src/cmd/go/build.go
ファイル内のgccgoToolchain
構造体に関連するコードが変更されました。
変更の核心は、gccgo
実行ファイルのパスを決定する際に、まずGCCGO
という新しい環境変数の値を優先的に使用し、それが設定されていない場合にのみ従来のデフォルトのgccgo
という名前の実行ファイルをシステムパスから検索するというロロジックです。
-
gccgoName
とgccgoBin
変数の導入:- 以前は、
gccgoBin
という変数が直接exec.LookPath("gccgo")
の結果で初期化されていました。これは、常にgccgo
という名前の実行ファイルを検索することを意味します。 - このコミットでは、
gccgoName
とgccgoBin
という2つの変数が導入されました。gccgoName
は使用するgccgo
コンパイラの名前(またはパス)を保持し、gccgoBin
はその名前からexec.LookPath
で解決された実際のバイナリパスを保持します。
- 以前は、
-
init()
関数による初期化ロジックの変更:- Go言語の
init()
関数は、パッケージがインポートされた際に自動的に実行される特別な関数です。このコミットでは、gccgoName
とgccgoBin
の初期化ロジックがinit()
関数内に移動されました。 init()
関数内で、まずos.Getenv("GCCGO")
を呼び出してGCCGO
環境変数の値を取得します。- 取得した値が空文字列(つまり、
GCCGO
環境変数が設定されていないか、空に設定されている)の場合、gccgoName
はデフォルトの"gccgo"
に設定されます。 GCCGO
環境変数が設定されている場合、その値がgccgoName
として使用されます。- 最後に、
exec.LookPath(gccgoName)
を呼び出して、決定されたgccgoName
に基づいて実際の実行ファイルのパスを検索し、gccgoBin
に格納します。
- Go言語の
-
gccgoName
の動的な使用:gccgoToolchain
構造体のメソッド(gc
、asm
、ld
など、コンパイル、アセンブル、リンクの各段階でgccgo
を呼び出す部分)では、これまでハードコードされていた"gccgo"
という文字列が、新しく導入されたgccgoName
変数に置き換えられました。- これにより、
cmd/go
がgccgo
ツールチェーンの各段階で外部コマンドを呼び出す際に、GCCGO
環境変数の設定が動的に反映されるようになります。
この一連の変更により、ユーザーはGCCGO
環境変数を設定するだけで、cmd/go
が使用するgccgo
コンパイラを簡単に切り替えることができるようになり、ビルドプロセスの柔軟性と制御性が大幅に向上しました。
コアとなるコードの変更箇所
変更はsrc/cmd/go/build.go
ファイルに集中しています。
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -1775,7 +1775,15 @@ func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error
// The Gccgo toolchain.
type gccgoToolchain struct{}
-var gccgoBin, _ = exec.LookPath("gccgo")
+var gccgoName, gccgoBin string
+
+func init() {
+ gccgoName = os.Getenv("GCCGO")
+ if gccgoName == "" {
+ gccgoName = "gccgo"
+ }
+ gccgoBin, _ = exec.LookPath(gccgoName)
+}
func (gccgoToolchain) compiler() string {
return gccgoBin
@@ -1796,7 +1804,7 @@ func (gccgoToolchain) gc(b *builder, p *Package, archive, obj string, importArgs
if p.localPrefix != "" {
gcargs = append(gcargs, "-fgo-relative-import-path="+p.localPrefix)
}
- args := stringList("gccgo", importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags)
+ args := stringList(gccgoName, importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags)
for _, f := range gofiles {
args = append(args, mkAbs(p.Dir, f))
}
@@ -1812,7 +1820,7 @@ func (gccgoToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) erro
defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`)
}\n\tdefs = append(defs, b.gccArchArgs()...)\n-\treturn b.run(p.Dir, p.ImportPath, nil, "gccgo", "-I", obj, "-o", ofile, defs, sfile)\n+\treturn b.run(p.Dir, p.ImportPath, nil, gccgoName, "-I", obj, "-o", ofile, defs, sfile)\n }\n \n func (gccgoToolchain) pkgpath(basedir string, p *Package) string {\n@@ -1889,7 +1897,7 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []
if objc {\n ldflags = append(ldflags, "-lobjc")\n }\n-\treturn b.run(\".\", p.ImportPath, nil, "gccgo", "-o", out, ofiles, "-Wl,-(\", ldflags, "-Wl,-)\", buildGccgoflags)\n+\treturn b.run(\".\", p.ImportPath, nil, gccgoName, "-o", out, ofiles, "-Wl,-(\", ldflags, "-Wl,-)\", buildGccgoflags)\n }\n \n func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {\n```
## コアとなるコードの解説
このコミットにおける最も重要なコード変更は、`src/cmd/go/build.go`ファイル内の`gccgoToolchain`構造体に関連する`gccgo`バイナリの特定と使用方法のロジックです。
1. **`gccgoBin`と`gccgoName`変数の宣言と`init()`関数による初期化**:
* 変更前は、`var gccgoBin, _ = exec.LookPath("gccgo")`という行で、`gccgoBin`変数がパッケージの初期化時に一度だけ、`gccgo`という名前の実行ファイルをシステムパスから検索して初期化されていました。これは、常に`gccgo`という固定の名前を使用することを意味します。
* 変更後は、`gccgoName`と`gccgoBin`という2つの新しいパッケージレベル変数が導入されました。
* そして、`func init() { ... }`ブロックが追加されました。Go言語の`init()`関数は、パッケージがインポートされ、そのパッケージ内のすべてのグローバル変数が初期化された後に自動的に実行されます。
* この`init()`関数内で、まず`os.Getenv("GCCGO")`を呼び出して`GCCGO`環境変数の値を取得し、`gccgoName`に格納します。
* `if gccgoName == "" { gccgoName = "gccgo" }`という条件文により、もし`GCCGO`環境変数が設定されていない(または空文字列)であれば、`gccgoName`は従来のデフォルト値である`"gccgo"`に設定されます。
* 最後に、`gccgoBin, _ = exec.LookPath(gccgoName)`を呼び出すことで、`gccgoName`(環境変数から取得した値、またはデフォルトの`"gccgo"`)で指定された実行ファイルをシステムパスから検索し、そのフルパスを`gccgoBin`に格納します。これにより、`GCCGO`環境変数が設定されていればその値が、設定されていなければデフォルトの`gccgo`が使用されるようになります。
2. **`gccgoName`の使用箇所への変更**:
* `gccgoToolchain`構造体の主要なメソッドである`gc`(Goソースコードのコンパイル)、`asm`(アセンブリコードのアセンブル)、`ld`(オブジェクトファイルのリンク)において、外部コマンド(`gccgo`)を呼び出す際の実行ファイル名を指定する箇所が変更されました。
* 具体的には、`stringList("gccgo", ...)`や`b.run(..., "gccgo", ...)`のようにハードコードされていた`"gccgo"`という文字列が、新しく導入された`gccgoName`変数に置き換えられました。
* これにより、`cmd/go`が`gccgo`ツールチェーンの各段階で`gccgo`コンパイラを呼び出す際に、`GCCGO`環境変数の設定が動的に反映されるようになります。例えば、`GCCGO=/usr/local/bin/gccgo-4.9`と設定されていれば、`cmd/go`は`gccgo-4.9`を呼び出すようになります。
これらの変更により、`cmd/go`は`gccgo`コンパイラの選択においてより柔軟になり、ユーザーは環境変数を通じて特定の`gccgo`バイナリを簡単に指定できるようになりました。これは、異なる`gccgo`バージョンを切り替えたり、カスタムビルドされた`gccgo`を使用したりする際に非常に有用です。
## 関連リンク
* Go CL 106700044 (このコミットの元の変更リスト): [https://golang.org/cl/106700044](https://golang.org/cl/106700044)
## 参考にした情報源リンク
* Go言語の公式ドキュメント (gccgoに関する情報): [https://go.dev/doc/install/gccgo](https://go.dev/doc/install/gccgo)
* GCCGoに関するStack Overflowの議論 (一般的な情報収集): [https://stackoverflow.com/questions/tagged/gccgo](https://stackoverflow.com/questions/tagged/gccgo)
* Go言語のツールチェーンに関する一般的な情報 (Go公式ブログやドキュメントを参照)