[インデックス 11518] ファイルの概要
このコミットは、Go言語のコマンドラインツール cmd/go
における gccgo
標準ライブラリの取り扱いに関するバグ修正です。具体的には、go
ツールが gccgo
を使用して標準ライブラリをビルドしようとするのを防ぐためのロジックが導入されています。
コミット
commit d7172084d09b845a5decdbe97ee39f02cfe1cd03
Author: Rémy Oudompheng <oudomphe@phare.normalesup.org>
Date: Tue Jan 31 19:41:38 2012 +0100
cmd/go: fix handling of gccgo standard library.
The previous logic was mainly non-working. It only needs to
ensure that the go tool doesn't try to build the standard
library with gccgo.
R=golang-dev, rsc
CC=golang-dev, remy
https://golang.org/cl/5580051
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/d7172084d09b845a5decdbe97ee39f02cfe1cd03
元コミット内容
cmd/go: fix handling of gccgo standard library.
The previous logic was mainly non-working. It only needs to ensure that the go tool doesn't try to build the standard library with gccgo.
変更の背景
Go言語には、公式のGoコンパイラ(gc
)と、GCC(GNU Compiler Collection)をベースにしたgccgo
という2つの主要なコンパイラ実装が存在します。go
コマンド(cmd/go
)は、Goプロジェクトのビルド、テスト、インストールなどを管理するための主要なツールです。
このコミットが行われた2012年当時、go
ツールはgccgo
ツールチェインを使用している場合に、標準ライブラリのビルドを不適切に扱っていました。gccgo
は通常、独自の標準ライブラリのバージョンを管理しており、go
ツールがそれを再ビルドしようとすると、不要な処理やエラーが発生する可能性がありました。
コミットメッセージによると、「以前のロジックはほとんど機能していなかった」とあり、go
ツールがgccgo
で標準ライブラリをビルドしようとしないようにすることが唯一の要件であったことが示唆されています。これは、gccgo
が既にコンパイル済みの標準ライブラリを提供しているため、go
ツールがその部分に介入する必要がないという設計思想に基づいています。
前提知識の解説
- Goツールチェイン: Go言語のプログラムを開発・実行するために必要な一連のツール群を指します。これには、コンパイラ(
gc
またはgccgo
)、アセンブラ、リンカ、デバッガ、そしてgo
コマンド自体が含まれます。 cmd/go
: Go言語のビルドシステムの中核をなすコマンドラインツールです。ソースコードのコンパイル、パッケージの管理、テストの実行、依存関係の解決など、Go開発における多くのタスクを自動化します。gc
(Go Compiler): Go言語の公式かつ主要なコンパイラです。Go言語のソースコードをネイティブバイナリにコンパイルします。gccgo
: GCCのフロントエンドとして実装されたGo言語のコンパイラです。gc
とは異なるコンパイラバックエンドを使用するため、生成されるバイナリの特性や最適化が異なる場合があります。gccgo
はGCCの既存の最適化インフラストラクチャを活用できるという利点があります。- 標準ライブラリ: Go言語に標準で付属する豊富なパッケージ群です。ファイルI/O、ネットワーク通信、暗号化、データ構造など、様々な機能を提供します。これらのライブラリは通常、Goツールチェインのインストール時に事前にコンパイルされた形式で提供されます。
buildMode
:cmd/go
内部で使用される概念で、ビルドのモード(例: 通常のビルド、テストビルドなど)を定義します。Package
: Goのソースコードの単位であり、関連するGoファイルとリソースの集合です。action
:cmd/go
が実行するビルドアクションを表す内部構造体です。buildToolchain
: 現在使用されているGoツールチェイン(gc
またはgccgo
)を表すインターフェースまたは構造体です。gccgoToolchain
:buildToolchain
インターフェースを実装するgccgo
固有のツールチェインを表す型です。p.Standard
:Package
構造体のフィールドで、そのパッケージがGoの標準ライブラリの一部であるかどうかを示すブール値です。p.target
: ビルドされたパッケージの出力パス(ターゲットファイル名)です。
技術的詳細
このコミットは、cmd/go
がgccgo
ツールチェインを使用している場合に、標準ライブラリのビルドプロセスをスキップするように変更します。
以前のロジックでは、pkg.go
内で標準ライブラリ(p.Standard
がtrue
)かつgccgoToolchain
が使用されている場合に、p.target
をgoToolchain{}.pkgpath(dir, p)
に設定し直していました。これは、gccgo
が標準ライブラリを「通常の」Goツールチェインが配置する場所と同じ場所にインストールするという前提に基づいていたようです。しかし、このロジックは「ほとんど機能していなかった」とされており、go
ツールがgccgo
の標準ライブラリをビルドしようとするのを防ぐという本来の目的を達成できていませんでした。
新しいロジックでは、build.go
のaction
関数内で、パッケージが標準ライブラリ(p.Standard
がtrue
)であり、かつgccgoToolchain
が使用されている場合に、ビルドアクションを早期に終了させるように変更されています。具体的には、action
構造体のtarget
フィールドにp.target
を設定し、そのままaction
を返します。これにより、go
ツールはgccgo
の標準ライブラリに対して実際のビルド操作を行わず、「フェイクパッケージ」(ビルド不要なパッケージ)として扱います。cgo
(C言語との連携)を使用する場合にはターゲット名が必要となるため、a.target = p.target
という行が追加されています。
この変更により、go
ツールはgccgo
の標準ライブラリに対して不必要なビルド試行を行わなくなり、ビルドプロセスの効率化と安定化が図られます。
コアとなるコードの変更箇所
このコミットでは、以下の2つのファイルが変更されています。
-
src/cmd/go/build.go
:func (b *builder) action(...)
メソッド内に新しいロジックが追加されました。- 標準ライブラリかつ
gccgoToolchain
の場合に、ビルドをスキップする条件が追加されています。
-
src/cmd/go/pkg.go
:func scanPackage(...)
メソッドから、gccgo
の標準ライブラリに関する古いロジックが削除されました。
src/cmd/go/build.go
の変更点
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -349,6 +349,12 @@ func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action
// Fake packages - nothing to build.
return a
}
+ // gccgo standard library is "fake" too.
+ if _, ok := buildToolchain.(gccgoToolchain); ok {
+ // the target name is needed for cgo.
+ a.target = p.target
+ return a
+ }
}
if !p.Stale && !buildA && p.target != "" {
src/cmd/go/pkg.go
の変更点
--- a/src/cmd/go/pkg.go
+++ b/src/cmd/go/pkg.go
@@ -295,14 +295,6 @@ func scanPackage(ctxt *build.Context, t *build.Tree, arg, importPath, dir string
dir = filepath.Join(filepath.Dir(dir), "gccgo", filepath.Base(dir))
}
p.target = buildToolchain.pkgpath(dir, p)
-
- // NB. Currently we have gccgo install the standard libraries
- // in the "usual" location, where the Go toolchain puts them.
- if p.Standard {
- if _, ok := buildToolchain.(gccgoToolchain); ok {
- p.target = goToolchain{}.pkgpath(dir, p)
- }
- }
}
var built time.Time
コアとなるコードの解説
src/cmd/go/build.go
の変更
action
関数は、特定のパッケージに対して実行すべきビルドアクションを決定します。
追加されたコードブロックは以下の通りです。
// gccgo standard library is "fake" too.
if _, ok := buildToolchain.(gccgoToolchain); ok {
// the target name is needed for cgo.
a.target = p.target
return a
}
if _, ok := buildToolchain.(gccgoToolchain); ok
: これは型アサーションと型スイッチの組み合わせです。現在使用されているbuildToolchain
がgccgoToolchain
型であるかどうかをチェックしています。ok
がtrue
であれば、gccgo
が使用されていることを意味します。- この
if
ブロックは、外側のif p.Standard
ブロック(変更前のコードのコンテキストから推測)の内側に存在するため、このロジックは「標準ライブラリ」かつ「gccgo
ツールチェイン」の場合にのみ適用されます。 a.target = p.target
:action
構造体のtarget
フィールドに、現在のパッケージのターゲットパスを設定します。これは、cgo
を使用する場合に必要となる情報です。return a
: この行が重要です。この行により、gccgo
の標準ライブラリに対するビルド処理がここで早期に終了し、それ以降の実際のビルドステップがスキップされます。これにより、go
ツールはgccgo
の標準ライブラリを「ビルド不要なもの」として扱います。
src/cmd/go/pkg.go
の変更
scanPackage
関数は、パッケージの情報をスキャンし、そのターゲットパスなどを決定します。
削除されたコードブロックは以下の通りです。
// NB. Currently we have gccgo install the standard libraries
// in the "usual" location, where the Go toolchain puts them.
if p.Standard {
if _, ok := buildToolchain.(gccgoToolchain); ok {
p.target = goToolchain{}.pkgpath(dir, p)
}
}
- このコードは、
gccgo
が標準ライブラリをgc
ツールチェインと同じ場所にインストールするという前提に基づいて、gccgo
使用時に標準ライブラリのターゲットパスをgoToolchain
のパスに上書きしていました。 - コミットメッセージにある「The previous logic was mainly non-working.」という記述から、このロジックが意図した通りに機能していなかったか、あるいは
go
ツールがgccgo
の標準ライブラリをビルドしようとするのを防ぐという目的には不適切であったことが示唆されます。 - このコードを削除することで、
go
ツールはgccgo
の標準ライブラリのターゲットパスを特別に操作する必要がなくなり、build.go
で導入された新しい早期終了ロジックに一貫性がもたらされます。
これらの変更により、go
ツールはgccgo
ツールチェインを使用している場合に、標準ライブラリのビルドを適切にスキップし、gccgo
が提供する既存の標準ライブラリを使用するようになります。
関連リンク
- Go言語の公式ドキュメント: https://go.dev/doc/
- GCCGoプロジェクトページ: https://gcc.gnu.org/onlinedocs/gccgo/
- Goのビルドシステムに関する議論(古いものも含む)は、GoのメーリングリストやIssueトラッカーで確認できます。
参考にした情報源リンク
- Go言語のソースコード(特に
src/cmd/go
ディレクトリ) - Go言語のコミット履歴
- Go言語のメーリングリスト(golang-dev)のアーカイブ
- GCCGoのドキュメント