Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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/gogc コマンドに渡す -I フラグのパス生成ロジックに問題がありました。特に gccgo ツールチェインを使用する場合、または標準の gc ツールチェインでクロスコンパイルを行う場合に、コンパイラが期待するパッケージアーカイブの場所と、cmd/go が生成するパスが一致しないことがありました。これにより、コンパイルエラーや予期せぬビルドの失敗が発生する可能性がありました。

この修正の目的は、cmd/gogcgccgo に渡す -I フラグのパスが、各ツールチェインの期待するディレクトリ構造と、現在のOS (goos) およびアーキテクチャ (goarch) に基づいて正しく解決されるようにすることです。

前提知識の解説

  • cmd/go: Go言語の公式コマンドラインツールであり、Goプログラムのビルド、テスト、実行、パッケージ管理など、多岐にわたる機能を提供します。ユーザーが go buildgo install などのコマンドを実行すると、cmd/go が内部的にコンパイラやリンカなどのツールを呼び出します。
  • gc: Go言語の公式コンパイラです。Goソースコードを機械語にコンパイルし、パッケージアーカイブ(.a ファイル)を生成します。
  • gccgo: GCC (GNU Compiler Collection) をバックエンドとして使用するGo言語の代替コンパイラです。gc とは異なるビルドパスや内部構造を持つことがあります。
  • -I フラグ: コンパイラにインクルードディレクトリ(またはライブラリ検索パス)を指定するための一般的なフラグです。Goコンパイラの場合、これはコンパイル済みパッケージアーカイブ(.a ファイル)が置かれているディレクトリを指します。
  • goosgoarch: 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 フラグの引数を生成する役割を担っています。

変更の核心は、コンパイル済みパッケージが格納されるディレクトリのパスを決定するロジックの改善です。

  1. gccgoToolchain のパス解決の修正:

    • 変更前: filepath.Join(filepath.Dir(dir), "gccgo", filepath.Base(dir)) これは、dir の親ディレクトリに gccgo を追加し、さらに dir のベース名を結合するという、やや複雑なパス生成を行っていました。これは特定の gccgo のディレクトリ構造を想定している可能性がありますが、汎用性に欠けるか、あるいは誤ったパスを生成する可能性がありました。
    • 変更後: filepath.Join(dir, "gccgo") よりシンプルに、既存の dir に直接 gccgo サブディレクトリを追加するように変更されました。これは、gccgo がパッケージを PkgRoot/gccgo のような構造で配置することを期待している場合に、より正確なパスとなります。
  2. 標準 gc ツールチェインのパス解決の追加:

    • 変更前: gccgoToolchain の場合のみパスが特別に処理され、それ以外の場合は既存の dir がそのまま使用されるか、あるいは適切なパスが生成されない可能性がありました。
    • 変更後: else { dir = filepath.Join(dir, goos+"_"+goarch) } gccgoToolchain でない場合(つまり、標準の gc コンパイラを使用する場合)、dirgoos_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言語のビルドシステムに関する一般的な知識
  • 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/gogc コマンドに渡す -I フラグのパス生成ロジックに問題がありました。特に gccgo ツールチェインを使用する場合、または標準の gc ツールチェインでクロスコンパイルを行う場合に、コンパイラが期待するパッケージアーカイブの場所と、cmd/go が生成するパスが一致しないことがありました。これにより、コンパイルエラーや予期せぬビルドの失敗が発生する可能性がありました。

この修正の目的は、cmd/gogcgccgo に渡す -I フラグのパスが、各ツールチェインの期待するディレクトリ構造と、現在のOS (goos) およびアーキテクチャ (goarch) に基づいて正しく解決されるようにすることです。

前提知識の解説

  • cmd/go: Go言語の公式コマンドラインツールであり、Goプログラムのビルド、テスト、実行、パッケージ管理など、多岐にわたる機能を提供します。ユーザーが go buildgo install などのコマンドを実行すると、cmd/go が内部的にコンパイラやリンカなどのツールを呼び出します。
  • gc: Go言語の公式コンパイラです。Goソースコードを機械語にコンパイルし、パッケージアーカイブ(.a ファイル)を生成します。
  • gccgo: GCC (GNU Compiler Collection) をバックエンドとして使用するGo言語の代替コンパイラです。gc とは異なるビルドパスや内部構造を持つことがあります。
  • -I フラグ: コンパイラにインクルードディレクトリ(またはライブラリ検索パス)を指定するための一般的なフラグです。Goコンパイラの場合、これはコンパイル済みパッケージアーカイブ(.a ファイル)が置かれているディレクトリを指します。
  • goosgoarch: 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 フラグの引数を生成する役割を担っています。

変更の核心は、コンパイル済みパッケージが格納されるディレクトリのパスを決定するロジックの改善です。

  1. gccgoToolchain のパス解決の修正:

    • 変更前: filepath.Join(filepath.Dir(dir), "gccgo", filepath.Base(dir)) これは、dir の親ディレクトリに gccgo を追加し、さらに dir のベース名を結合するという、やや複雑なパス生成を行っていました。これは特定の gccgo のディレクトリ構造を想定している可能性がありますが、汎用性に欠けるか、あるいは誤ったパスを生成する可能性がありました。
    • 変更後: filepath.Join(dir, "gccgo") よりシンプルに、既存の dir に直接 gccgo サブディレクトリを追加するように変更されました。これは、gccgo がパッケージを PkgRoot/gccgo のような構造で配置することを期待している場合に、より正確なパスとなります。
  2. 標準 gc ツールチェインのパス解決の追加:

    • 変更前: gccgoToolchain の場合のみパスが特別に処理され、それ以外の場合は既存の dir がそのまま使用されるか、あるいは適切なパスが生成されない可能性がありました。
    • 変更後: else { dir = filepath.Join(dir, goos+"_"+goarch) } gccgoToolchain でない場合(つまり、標準の gc コンパイラを使用する場合)、dirgoos_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言語のビルドシステムに関する一般的な知識
  • 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