[インデックス 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 flag
go gc compiler include path
golang gccgo package path
golang 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 flag
go gc compiler include path
golang gccgo package path
golang goos goarch pkg directory