[インデックス 12318] ファイルの概要
このコミットは、Go言語のコマンドラインツール cmd/go における gc コマンド(Goコンパイラ)への -I フラグの渡し方に関するバグ修正です。具体的には、コンパイラがパッケージのインクルードパスを正しく解決できるように、ビルドディレクトリのパス生成ロジックが改善されています。
コミット
commit 04450d8a26406f46f2fc6659469b872ce0b85579
Author: Gustavo Niemeyer <gustavo@niemeyer.net>
Date: Thu Mar 1 20:13:04 2012 -0300
cmd/go: fix -I flag for gc command
R=rsc, remyoudompheng
CC=golang-dev
https://golang.org/cl/5711056
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/04450d8a26406f46f2fc6659469b872ce0b85579
元コミット内容
cmd/go: fix -I flag for gc command
変更の背景
Go言語のビルドシステムにおいて、go コマンドは内部的に gc (Goコンパイラ) や gccgo (GCCベースのGoコンパイラ) などのツールを呼び出してソースコードをコンパイルします。これらのコンパイラは、依存するパッケージのコンパイル済みアーカイブファイル(通常 .a 拡張子を持つ)を探すために、-I フラグを使用してインクルードディレクトリを指定します。
このコミット以前は、cmd/go が gc コマンドに渡す -I フラグのパス生成ロジックに問題がありました。特に gccgo ツールチェインを使用する場合、または標準の gc ツールチェインでクロスコンパイルを行う場合に、コンパイラが期待するパッケージアーカイブの場所と、cmd/go が生成するパスが一致しないことがありました。これにより、コンパイルエラーや予期せぬビルドの失敗が発生する可能性がありました。
この修正の目的は、cmd/go が gc や gccgo に渡す -I フラグのパスが、各ツールチェインの期待するディレクトリ構造と、現在のOS (goos) およびアーキテクチャ (goarch) に基づいて正しく解決されるようにすることです。
前提知識の解説
cmd/go: Go言語の公式コマンドラインツールであり、Goプログラムのビルド、テスト、実行、パッケージ管理など、多岐にわたる機能を提供します。ユーザーがgo buildやgo installなどのコマンドを実行すると、cmd/goが内部的にコンパイラやリンカなどのツールを呼び出します。gc: Go言語の公式コンパイラです。Goソースコードを機械語にコンパイルし、パッケージアーカイブ(.aファイル)を生成します。gccgo: GCC (GNU Compiler Collection) をバックエンドとして使用するGo言語の代替コンパイラです。gcとは異なるビルドパスや内部構造を持つことがあります。-Iフラグ: コンパイラにインクルードディレクトリ(またはライブラリ検索パス)を指定するための一般的なフラグです。Goコンパイラの場合、これはコンパイル済みパッケージアーカイブ(.aファイル)が置かれているディレクトリを指します。goosとgoarch: Go言語のビルド環境変数を指します。goos: ターゲットとするオペレーティングシステム(例:linux,windows,darwin)。goarch: ターゲットとするアーキテクチャ(例:amd64,arm,386)。 これらの変数は、クロスコンパイル(異なるOSやアーキテクチャ向けにビルドすること)を行う際に特に重要になります。コンパイル済みパッケージは、通常、$GOROOT/pkg/$GOOS_$GOARCHのようなパスに配置されます。
filepath.Join: Go言語のpath/filepathパッケージにある関数で、OS固有のパス区切り文字を使用して複数のパス要素を結合します。これにより、異なるOS上でも正しいパスが生成されます。PkgRoot: Goのパッケージがインストールされるルートディレクトリを指します。通常は$GOROOT/pkgまたは$GOPATH/pkgに対応します。
技術的詳細
このコミットは、src/cmd/go/build.go ファイル内の includeArgs 関数を変更しています。この関数は、go コマンドがコンパイラに渡す -I フラグの引数を生成する役割を担っています。
変更の核心は、コンパイル済みパッケージが格納されるディレクトリのパスを決定するロジックの改善です。
-
gccgoToolchainのパス解決の修正:- 変更前:
filepath.Join(filepath.Dir(dir), "gccgo", filepath.Base(dir))これは、dirの親ディレクトリにgccgoを追加し、さらにdirのベース名を結合するという、やや複雑なパス生成を行っていました。これは特定のgccgoのディレクトリ構造を想定している可能性がありますが、汎用性に欠けるか、あるいは誤ったパスを生成する可能性がありました。 - 変更後:
filepath.Join(dir, "gccgo")よりシンプルに、既存のdirに直接gccgoサブディレクトリを追加するように変更されました。これは、gccgoがパッケージをPkgRoot/gccgoのような構造で配置することを期待している場合に、より正確なパスとなります。
- 変更前:
-
標準
gcツールチェインのパス解決の追加:- 変更前:
gccgoToolchainの場合のみパスが特別に処理され、それ以外の場合は既存のdirがそのまま使用されるか、あるいは適切なパスが生成されない可能性がありました。 - 変更後:
else { dir = filepath.Join(dir, goos+"_"+goarch) }gccgoToolchainでない場合(つまり、標準のgcコンパイラを使用する場合)、dirにgoos_goarchという形式のサブディレクトリを追加するように変更されました。これは、gcコンパイラがコンパイル済みパッケージを$PkgRoot/$GOOS_$GOARCHのようなディレクトリ構造で管理するというGoの標準的な慣習に合致します。例えば、Linux AMD64向けにビルドされたパッケージはPkgRoot/linux_amd64に置かれます。
- 変更前:
この修正により、cmd/go は、使用されているツールチェイン(gc または gccgo)とターゲットのOS/アーキテクチャ (goos/goarch) に応じて、コンパイラがパッケージアーカイブを見つけるための正しいインクルードパスを生成できるようになりました。
コアとなるコードの変更箇所
src/cmd/go/build.go ファイルの includeArgs 関数内の以下の部分が変更されました。
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -791,7 +791,9 @@ func (b *builder) includeArgs(flag string, all []*action) []string {
for _, a1 := range all {
if dir := a1.pkgdir; dir == a1.p.build.PkgRoot && !incMap[dir] {
if _, ok := buildToolchain.(gccgoToolchain); ok {
- dir = filepath.Join(filepath.Dir(dir), "gccgo", filepath.Base(dir))
+ dir = filepath.Join(dir, "gccgo")
+ } else {
+ dir = filepath.Join(dir, goos+"_"+goarch)
}
incMap[dir] = true
inc = append(inc, flag, dir)
コアとなるコードの解説
変更されたコードブロックは、go コマンドがコンパイラに渡す -I フラグの引数を構築するループの一部です。
-
if dir := a1.pkgdir; dir == a1.p.build.PkgRoot && !incMap[dir]この条件は、現在のパッケージのビルドディレクトリ (a1.pkgdir) がルートパッケージディレクトリ (a1.p.build.PkgRoot) と一致し、かつそのディレクトリがまだインクルードマップ (incMap) に追加されていない場合に真となります。これは、ルートパッケージディレクトリ自体をインクルードパスとして追加する必要があることを示しています。 -
if _, ok := buildToolchain.(gccgoToolchain); ok { ... }この行は、現在使用されているビルドツールチェインがgccgoToolchainであるかどうかをチェックしています。- 変更前:
dir = filepath.Join(filepath.Dir(dir), "gccgo", filepath.Base(dir))gccgoのパッケージパスを生成していました。例えば、dirが/path/to/goroot/pkgの場合、これは/path/to/goroot/gccgo/pkgのようなパスを生成しようとしていた可能性があります。しかし、これはgccgoがパッケージを格納する実際のパスと一致しない場合がありました。 - 変更後:
dir = filepath.Join(dir, "gccgo")dir(例:/path/to/goroot/pkg) に直接gccgoを結合し、/path/to/goroot/pkg/gccgoのようなパスを生成します。これは、gccgoがコンパイル済みパッケージをPkgRoot/gccgoの下に置くという慣習に合致します。
- 変更前:
-
else { dir = filepath.Join(dir, goos+"_"+goarch) }このelseブロックは、ツールチェインがgccgoToolchainでない場合(つまり、標準のgcコンパイラを使用する場合)に実行されます。- 新規追加:
dir(例:/path/to/goroot/pkg) にgoos_goarch(例:linux_amd64) を結合し、/path/to/goroot/pkg/linux_amd64のようなパスを生成します。これは、gcコンパイラがコンパイル済みパッケージを$GOROOT/pkg/$GOOS_$GOARCHの下に格納するというGoの標準的なディレクトリ構造に完全に一致します。
- 新規追加:
この修正により、cmd/go は、Goのビルドシステムが期待するパッケージアーカイブの場所を正確にコンパイラに伝えることができるようになり、異なるツールチェインやクロスコンパイル環境でのビルドの信頼性が向上しました。
関連リンク
- Go Gerrit Change-Id: https://golang.org/cl/5711056
参考にした情報源リンク
- コミットメッセージと差分情報
- Go言語のビルドシステムに関する一般的な知識
goosおよびgoarch環境変数に関するGoのドキュメントpath/filepathパッケージのドキュメント- Goコンパイラ (
gc) およびgccgoの動作に関する一般的な情報 (Web検索)go build -I flaggo gc compiler include pathgolang gccgo package pathgolang goos goarch pkg directory# [インデックス 12318] ファイルの概要
このコミットは、Go言語のコマンドラインツール cmd/go における gc コマンド(Goコンパイラ)への -I フラグの渡し方に関するバグ修正です。具体的には、コンパイラがパッケージのインクルードパスを正しく解決できるように、ビルドディレクトリのパス生成ロジックが改善されています。
コミット
commit 04450d8a26406f46f2fc6659469b872ce0b85579
Author: Gustavo Niemeyer <gustavo@niemeyer.net>
Date: Thu Mar 1 20:13:04 2012 -0300
cmd/go: fix -I flag for gc command
R=rsc, remyoudompheng
CC=golang-dev
https://golang.org/cl/5711056
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/04450d8a26406f46f2fc6659469b872ce0b85579
元コミット内容
cmd/go: fix -I flag for gc command
変更の背景
Go言語のビルドシステムにおいて、go コマンドは内部的に gc (Goコンパイラ) や gccgo (GCCベースのGoコンパイラ) などのツールを呼び出してソースコードをコンパイルします。これらのコンパイラは、依存するパッケージのコンパイル済みアーカイブファイル(通常 .a 拡張子を持つ)を探すために、-I フラグを使用してインクルードディレクトリを指定します。
このコミット以前は、cmd/go が gc コマンドに渡す -I フラグのパス生成ロジックに問題がありました。特に gccgo ツールチェインを使用する場合、または標準の gc ツールチェインでクロスコンパイルを行う場合に、コンパイラが期待するパッケージアーカイブの場所と、cmd/go が生成するパスが一致しないことがありました。これにより、コンパイルエラーや予期せぬビルドの失敗が発生する可能性がありました。
この修正の目的は、cmd/go が gc や gccgo に渡す -I フラグのパスが、各ツールチェインの期待するディレクトリ構造と、現在のOS (goos) およびアーキテクチャ (goarch) に基づいて正しく解決されるようにすることです。
前提知識の解説
cmd/go: Go言語の公式コマンドラインツールであり、Goプログラムのビルド、テスト、実行、パッケージ管理など、多岐にわたる機能を提供します。ユーザーがgo buildやgo installなどのコマンドを実行すると、cmd/goが内部的にコンパイラやリンカなどのツールを呼び出します。gc: Go言語の公式コンパイラです。Goソースコードを機械語にコンパイルし、パッケージアーカイブ(.aファイル)を生成します。gccgo: GCC (GNU Compiler Collection) をバックエンドとして使用するGo言語の代替コンパイラです。gcとは異なるビルドパスや内部構造を持つことがあります。-Iフラグ: コンパイラにインクルードディレクトリ(またはライブラリ検索パス)を指定するための一般的なフラグです。Goコンパイラの場合、これはコンパイル済みパッケージアーカイブ(.aファイル)が置かれているディレクトリを指します。goosとgoarch: Go言語のビルド環境変数を指します。goos: ターゲットとするオペレーティングシステム(例:linux,windows,darwin)。goarch: ターゲットとするアーキテクチャ(例:amd64,arm,386)。 これらの変数は、クロスコンパイル(異なるOSやアーキテクチャ向けにビルドすること)を行う際に特に重要になります。コンパイル済みパッケージは、通常、$GOROOT/pkg/$GOOS_$GOARCHのようなパスに配置されます。
filepath.Join: Go言語のpath/filepathパッケージにある関数で、OS固有のパス区切り文字を使用して複数のパス要素を結合します。これにより、異なるOS上でも正しいパスが生成されます。PkgRoot: Goのパッケージがインストールされるルートディレクトリを指します。通常は$GOROOT/pkgまたは$GOPATH/pkgに対応します。
技術的詳細
このコミットは、src/cmd/go/build.go ファイル内の includeArgs 関数を変更しています。この関数は、go コマンドがコンパイラに渡す -I フラグの引数を生成する役割を担っています。
変更の核心は、コンパイル済みパッケージが格納されるディレクトリのパスを決定するロジックの改善です。
-
gccgoToolchainのパス解決の修正:- 変更前:
filepath.Join(filepath.Dir(dir), "gccgo", filepath.Base(dir))これは、dirの親ディレクトリにgccgoを追加し、さらにdirのベース名を結合するという、やや複雑なパス生成を行っていました。これは特定のgccgoのディレクトリ構造を想定している可能性がありますが、汎用性に欠けるか、あるいは誤ったパスを生成する可能性がありました。 - 変更後:
filepath.Join(dir, "gccgo")よりシンプルに、既存のdirに直接gccgoサブディレクトリを追加するように変更されました。これは、gccgoがパッケージをPkgRoot/gccgoのような構造で配置することを期待している場合に、より正確なパスとなります。
- 変更前:
-
標準
gcツールチェインのパス解決の追加:- 変更前:
gccgoToolchainの場合のみパスが特別に処理され、それ以外の場合は既存のdirがそのまま使用されるか、あるいは適切なパスが生成されない可能性がありました。 - 変更後:
else { dir = filepath.Join(dir, goos+"_"+goarch) }gccgoToolchainでない場合(つまり、標準のgcコンパイラを使用する場合)、dirにgoos_goarchという形式のサブディレクトリを追加するように変更されました。これは、gcコンパイラがコンパイル済みパッケージを$PkgRoot/$GOOS_$GOARCHのようなディレクトリ構造で管理するというGoの標準的な慣習に合致します。例えば、Linux AMD64向けにビルドされたパッケージはPkgRoot/linux_amd64に置かれます。
- 変更前:
この修正により、cmd/go は、使用されているツールチェイン(gc または gccgo)とターゲットのOS/アーキテクチャ (goos/goarch) に応じて、コンパイラがパッケージアーカイブを見つけるための正しいインクルードパスを生成できるようになりました。
コアとなるコードの変更箇所
src/cmd/go/build.go ファイルの includeArgs 関数内の以下の部分が変更されました。
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -791,7 +791,9 @@ func (b *builder) includeArgs(flag string, all []*action) []string {
for _, a1 := range all {
if dir := a1.pkgdir; dir == a1.p.build.PkgRoot && !incMap[dir] {
if _, ok := buildToolchain.(gccgoToolchain); ok {
- dir = filepath.Join(filepath.Dir(dir), "gccgo", filepath.Base(dir))
+ dir = filepath.Join(dir, "gccgo")
+ } else {
+ dir = filepath.Join(dir, goos+"_"+goarch)
}
incMap[dir] = true
inc = append(inc, flag, dir)
コアとなるコードの解説
変更されたコードブロックは、go コマンドがコンパイラに渡す -I フラグの引数を構築するループの一部です。
-
if dir := a1.pkgdir; dir == a1.p.build.PkgRoot && !incMap[dir]この条件は、現在のパッケージのビルドディレクトリ (a1.pkgdir) がルートパッケージディレクトリ (a1.p.build.PkgRoot) と一致し、かつそのディレクトリがまだインクルードマップ (incMap) に追加されていない場合に真となります。これは、ルートパッケージディレクトリ自体をインクルードパスとして追加する必要があることを示しています。 -
if _, ok := buildToolchain.(gccgoToolchain); ok { ... }この行は、現在使用されているビルドツールチェインがgccgoToolchainであるかどうかをチェックしています。- 変更前:
dir = filepath.Join(filepath.Dir(dir), "gccgo", filepath.Base(dir))gccgoのパッケージパスを生成していました。例えば、dirが/path/to/goroot/pkgの場合、これは/path/to/goroot/gccgo/pkgのようなパスを生成しようとしていた可能性があります。しかし、これはgccgoがパッケージを格納する実際のパスと一致しない場合がありました。 - 変更後:
dir = filepath.Join(dir, "gccgo")dir(例:/path/to/goroot/pkg) に直接gccgoを結合し、/path/to/goroot/pkg/gccgoのようなパスを生成します。これは、gccgoがコンパイル済みパッケージをPkgRoot/gccgoの下に置くという慣習に合致します。
- 変更前:
-
else { dir = filepath.Join(dir, goos+"_"+goarch) }このelseブロックは、ツールチェインがgccgoToolchainでない場合(つまり、標準のgcコンパイラを使用する場合)に実行されます。- 新規追加:
dir(例:/path/to/goroot/pkg) にgoos_goarch(例:linux_amd64) を結合し、/path/to/goroot/pkg/linux_amd64のようなパスを生成します。これは、gcコンパイラがコンパイル済みパッケージを$GOROOT/pkg/$GOOS_$GOARCHの下に格納するというGoの標準的なディレクトリ構造に完全に一致します。
- 新規追加:
この修正により、cmd/go は、Goのビルドシステムが期待するパッケージアーカイブの場所を正確にコンパイラに伝えることができるようになり、異なるツールチェインやクロスコンパイル環境でのビルドの信頼性が向上しました。
関連リンク
- Go Gerrit Change-Id: https://golang.org/cl/5711056
参考にした情報源リンク
- コミットメッセージと差分情報
- Go言語のビルドシステムに関する一般的な知識
goosおよびgoarch環境変数に関するGoのドキュメントpath/filepathパッケージのドキュメント- Goコンパイラ (
gc) およびgccgoの動作に関する一般的な情報 (Web検索)go build -I flaggo gc compiler include pathgolang gccgo package pathgolang goos goarch pkg directory