[インデックス 11937] ファイルの概要
このコミットは、Go言語のコマンドラインツール go test
における cgo
パッケージの取り扱いに関するバグ修正です。具体的には、go test -i
コマンドが cgo
パッケージを正しく処理し、特に runtime/cgo
パッケージ自体が古い場合に適切に再ビルドされるようにするための変更が含まれています。
コミット
commit 9c1f54c9ed67b77385940c58fb15af18166d4840
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Wed Feb 15 13:26:22 2012 -0500
cmd/go: go test -i correctly handle cgo packages
Previous CL (5674043) omit the case where runtime/cgo itself is out-of-date.
Fixes #2936 (again).
R=rsc
CC=golang-dev
https://golang.org/cl/5674048
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/9c1f54c9ed67b77385940c58fb15af18166d4840
元コミット内容
cmd/go: go test -i correctly handle cgo packages
(cmd/go
: go test -i
が cgo
パッケージを正しく処理するようにする)
Previous CL (5674043) omit the case where runtime/cgo itself is out-of-date.
(以前の変更リスト (5674043) は、runtime/cgo
自体が古いケースを見落としていた。)
Fixes #2936 (again).
(Issue #2936 を(再び)修正。)
変更の背景
このコミットは、Go言語のビルドシステムにおける cgo
パッケージの依存関係解決に関する既存のバグを修正するために行われました。特に、go test -i
コマンド(テストに必要な依存関係をインストールするオプション)を使用する際に、cgo
を利用するパッケージのテストが正しく動作しない問題がありました。
以前の変更リスト (CL 5674043) では、この問題の一部が修正されましたが、runtime/cgo
パッケージ自体が古い(つまり、再ビルドが必要な)場合に、そのケースが考慮されていませんでした。これにより、cgo
を使用するテストが、runtime/cgo
の古いバージョンに依存してしまい、期待通りに動作しない、またはビルドエラーが発生する可能性がありました。
このコミットは、Go Issue #2936 に関連しており、この問題が以前にも報告され、修正が試みられたものの、完全に解決されていなかったことを示唆しています。今回の修正は、runtime/cgo
の更新が必要なシナリオを明示的に考慮に入れることで、より堅牢な cgo
パッケージの依存関係解決を実現し、go test -i
の信頼性を向上させることを目的としています。
前提知識の解説
Go言語のビルドシステムとパッケージ管理
Go言語は、go build
、go install
、go test
といったコマンドを通じて、ソースコードのコンパイル、パッケージのインストール、テストの実行を行います。これらのコマンドは、Goのワークスペース(GOPATH)やモジュールシステム(Go Modules)に基づいて、依存関係を自動的に解決し、必要なパッケージをビルドします。
go test -i
コマンド
go test
コマンドは、Goパッケージのテストを実行するために使用されます。-i
フラグは、テストを実行する前に、テスト対象のパッケージとその依存関係をインストール(ビルドしてGOPATH/pkgまたはモジュールキャッシュに配置)することを指示します。これにより、テストの実行が高速化されたり、特定のビルド環境での依存関係の問題を回避したりできます。
cgo
とは
cgo
は、GoプログラムからC言語のコードを呼び出すためのGoの機能です。これにより、既存のCライブラリをGoプロジェクトで再利用したり、Goでは実装が難しい低レベルの操作を行ったりすることが可能になります。cgo
を使用するGoパッケージは、通常のGoコードとは異なり、Cコンパイラ(通常はGCCやClang)とGoコンパイラの両方によって処理される必要があります。
cgo
を使用するパッケージは、import "C"
という特別なインポート宣言を含みます。この宣言は、Goのビルドツールに対して、そのパッケージがCコードを含んでおり、cgo
ツールによる特別な処理が必要であることを伝えます。
runtime/cgo
パッケージ
runtime/cgo
は、GoランタイムとCコード間の相互運用を管理する内部パッケージです。cgo
を使用するすべてのGoプログラムは、この runtime/cgo
パッケージに暗黙的に依存します。このパッケージは、C関数呼び出しのスタック管理、GoとCのメモリモデルの調整、スレッドの管理など、cgo
の低レベルなメカニズムを提供します。
依存関係グラフとビルド順序
Goのビルドシステムは、パッケージ間の依存関係を解決し、正しい順序でビルドを行います。あるパッケージが別のパッケージに依存している場合、依存先のパッケージが先にビルドされる必要があります。cgo
を使用するパッケージの場合、その依存関係グラフには runtime/cgo
が含まれます。
Go Issue #2936
Go Issue #2936 は、go test -i
コマンドが cgo
パッケージの依存関係を正しく処理しないというバグを追跡するために作成されたものです。この問題は、特に runtime/cgo
パッケージが再ビルドを必要とする場合に顕在化し、テストの失敗やビルドエラーを引き起こしていました。
技術的詳細
このコミットの技術的な核心は、go test -i
コマンドがパッケージの依存関係を解決する際に、cgo
を使用するパッケージの特別なケースを適切に処理することにあります。
Goのビルドシステムでは、パッケージの依存関係は内部的にマップ(deps
)として管理されます。このマップには、ビルド対象のパッケージが依存するすべてのパッケージが含まれます。cgo
を使用するパッケージは、Goのソースコード内で import "C"
と記述することで、C言語のコードとの連携を示します。しかし、この "C"
は実際のGoパッケージではなく、cgo
ツールに対する指示です。
以前の go test
の実装では、"C"
という擬似パッケージが依存関係リストに含まれていた場合、それを単に無視していました。これは、"C"
自体がビルドされるべきパッケージではないため、一見正しいように見えます。しかし、cgo
を使用するパッケージは、実際には runtime/cgo
パッケージに依存しており、さらに、クロスコンパイル環境でない限り、cmd/cgo
ツールにも依存します。
このコミットの修正前は、deps["C"]
が存在する場合に delete(deps, "C")
が行われていましたが、これは runtime/cgo
や cmd/cgo
への依存関係を明示的に追加する処理の前に実行されていました。その結果、runtime/cgo
が古い場合でも、その依存関係が正しく認識されず、再ビルドがトリガーされないという問題が発生していました。
今回の修正では、"C"
が依存関係リストに存在する場合、それを runtime/cgo
と cmd/cgo
(ホストOS/アーキテクチャとターゲットOS/アーキテクチャが一致する場合)に変換するように変更されました。これにより、cgo
を使用するパッケージのビルド時に、runtime/cgo
が最新の状態であることが保証され、必要に応じて再ビルドが実行されるようになります。
特に重要なのは、buildContext.GOOS == runtime.GOOS && buildContext.GOARCH == runtime.GOARCH
という条件です。これは、現在のビルドがホスト環境(つまり、クロスコンパイルではない)で行われている場合にのみ cmd/cgo
への依存関係を追加することを示しています。クロスコンパイルの場合、cmd/cgo
はホスト上で実行されるため、ターゲット環境の依存関係としては不要です。
コアとなるコードの変更箇所
変更は src/cmd/go/test.go
ファイルに集中しています。
--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -15,6 +15,7 @@ import (
"os/exec"
"path"
"path/filepath"
+ "runtime"
"sort"
"strings"
"text/template"
@@ -273,8 +274,15 @@ func runTest(cmd *Command, args []string) {
}
}
+ // translate C to runtime/cgo
+ if deps["C"] {
+ delete(deps, "C")
+ deps["runtime/cgo"] = true
+ if buildContext.GOOS == runtime.GOOS && buildContext.GOARCH == runtime.GOARCH {
+ deps["cmd/cgo"] = true
+ }
+ }
// Ignore pseudo-packages.
- delete(deps, "C")
delete(deps, "unsafe")
all := []string{}
コアとなるコードの解説
-
import "runtime"
の追加:runtime
パッケージが新しくインポートされています。これは、runtime.GOOS
とruntime.GOARCH
を使用して、現在の実行環境のOSとアーキテクチャを判定するために必要です。 -
// translate C to runtime/cgo
ブロックの追加: この新しいコードブロックが、既存のdelete(deps, "C")
の行の前に挿入されています。if deps["C"] { ... }
:deps
マップに"C"
というキーが存在するかどうかを確認します。これは、テスト対象のパッケージがcgo
を使用していることを意味します。delete(deps, "C")
: まず、擬似パッケージである"C"
を依存関係リストから削除します。これは以前の動作と同じですが、重要なのはこの削除がruntime/cgo
への依存関係を追加する前に行われることです。deps["runtime/cgo"] = true
:cgo
を使用するパッケージは必ずruntime/cgo
に依存するため、この依存関係を明示的に追加します。これにより、runtime/cgo
が必要に応じてビルドされるようになります。if buildContext.GOOS == runtime.GOOS && buildContext.GOARCH == runtime.GOARCH { deps["cmd/cgo"] = true }
: この条件は、現在のビルドがクロスコンパイルではない(つまり、ビルドターゲットのOSとアーキテクチャが現在の実行環境のOSとアーキテクチャと同じである)場合にのみ真となります。この場合、cmd/cgo
ツール自体もビルド依存関係として追加されます。cmd/cgo
はcgo
コードを処理するためのツールであり、ホスト環境で実行されるため、クロスコンパイル時にはターゲットの依存関係としては不要です。
-
既存の
delete(deps, "C")
の削除: 新しいブロックで"C"
の削除と変換が行われるため、以前のdelete(deps, "C")
の行は不要となり、削除されました。
この変更により、go test -i
は cgo
を使用するパッケージの依存関係をより正確に解決し、特に runtime/cgo
が古い場合に適切に再ビルドをトリガーできるようになりました。これにより、Go Issue #2936 で報告された問題が根本的に解決されます。
関連リンク
- Go Issue #2936: https://github.com/golang/go/issues/2936 (このコミットが修正した問題のトラッキング)
- Go Change List 5674048: https://golang.org/cl/5674048 (このコミットの元の変更リスト)
- Go Change List 5674043: https://golang.org/cl/5674043 (このコミットが言及している以前の変更リスト)
参考にした情報源リンク
- Go言語の公式ドキュメント (cgo): https://go.dev/blog/cgo
- Go言語の公式ドキュメント (go command): https://go.dev/cmd/go/
- Go言語のソースコード (src/cmd/go/test.go): https://github.com/golang/go/blob/master/src/cmd/go/test.go
- Go言語のソースコード (src/runtime/cgo): https://github.com/golang/go/tree/master/src/runtime/cgo
- Go言語のソースコード (src/cmd/cgo): https://github.com/golang/go/tree/master/src/cmd/cgo
[インデックス 11937] ファイルの概要
このコミットは、Go言語のコマンドラインツール go test
における cgo
パッケージの取り扱いに関するバグ修正です。具体的には、go test -i
コマンドが cgo
パッケージを正しく処理し、特に runtime/cgo
パッケージ自体が古い場合に適切に再ビルドされるようにするための変更が含まれています。
コミット
commit 9c1f54c9ed67b77385940c58fb15af18166d4840
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Wed Feb 15 13:26:22 2012 -0500
cmd/go: go test -i correctly handle cgo packages
Previous CL (5674043) omit the case where runtime/cgo itself is out-of-date.
Fixes #2936 (again).
R=rsc
CC=golang-dev
https://golang.org/cl/5674048
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/9c1f54c9ed67b77385940c58fb15af18166d4840
元コミット内容
cmd/go: go test -i correctly handle cgo packages
(cmd/go
: go test -i
が cgo
パッケージを正しく処理するようにする)
Previous CL (5674043) omit the case where runtime/cgo itself is out-of-date.
(以前の変更リスト (5674043) は、runtime/cgo
自体が古いケースを見落としていた。)
Fixes #2936 (again).
(Issue #2936 を(再び)修正。)
変更の背景
このコミットは、Go言語のビルドシステムにおける cgo
パッケージの依存関係解決に関する既存のバグを修正するために行われました。特に、go test -i
コマンド(テストに必要な依存関係をインストールするオプション)を使用する際に、cgo
を利用するパッケージのテストが正しく動作しない問題がありました。
以前の変更リスト (CL 5674043) では、この問題の一部が修正されましたが、runtime/cgo
パッケージ自体が古い(つまり、再ビルドが必要な)場合に、そのケースが考慮されていませんでした。これにより、cgo
を使用するテストが、runtime/cgo
の古いバージョンに依存してしまい、期待通りに動作しない、またはビルドエラーが発生する可能性がありました。
このコミットは、Go Issue #2936 に関連しており、この問題が以前にも報告され、修正が試みられたものの、完全に解決されていなかったことを示唆しています。今回の修正は、runtime/cgo
の更新が必要なシナリオを明示的に考慮に入れることで、より堅牢な cgo
パッケージの依存関係解決を実現し、go test -i
の信頼性を向上させることを目的としています。
前提知識の解説
Go言語のビルドシステムとパッケージ管理
Go言語は、go build
、go install
、go test
といったコマンドを通じて、ソースコードのコンパイル、パッケージのインストール、テストの実行を行います。これらのコマンドは、Goのワークスペース(GOPATH)やモジュールシステム(Go Modules)に基づいて、依存関係を自動的に解決し、必要なパッケージをビルドします。
go test -i
コマンド
go test
コマンドは、Goパッケージのテストを実行するために使用されます。-i
フラグは、テストを実行する前に、テスト対象のパッケージとその依存関係をインストール(ビルドしてGOPATH/pkgまたはモジュールキャッシュに配置)することを指示します。これにより、テストの実行が高速化されたり、特定のビルド環境での依存関係の問題を回避したりできます。
cgo
とは
cgo
は、GoプログラムからC言語のコードを呼び出すためのGoの機能です。これにより、既存のCライブラリをGoプロジェクトで再利用したり、Goでは実装が難しい低レベルの操作を行ったりすることが可能になります。cgo
を使用するGoパッケージは、通常のGoコードとは異なり、Cコンパイラ(通常はGCCやClang)とGoコンパイラの両方によって処理される必要があります。
cgo
を使用するパッケージは、import "C"
という特別なインポート宣言を含みます。この宣言は、Goのビルドツールに対して、そのパッケージがCコードを含んでおり、cgo
ツールによる特別な処理が必要であることを伝えます。
runtime/cgo
パッケージ
runtime/cgo
は、GoランタイムとCコード間の相互運用を管理する内部パッケージです。cgo
を使用するすべてのGoプログラムは、この runtime/cgo
パッケージに暗黙的に依存します。このパッケージは、C関数呼び出しのスタック管理、GoとCのメモリモデルの調整、スレッドの管理など、cgo
の低レベルなメカニズムを提供します。
依存関係グラフとビルド順序
Goのビルドシステムは、パッケージ間の依存関係を解決し、正しい順序でビルドを行います。あるパッケージが別のパッケージに依存している場合、依存先のパッケージが先にビルドされる必要があります。cgo
を使用するパッケージの場合、その依存関係グラフには runtime/cgo
が含まれます。
Go Issue #2936
Go Issue #2936 は、go test -i
コマンドが cgo
パッケージの依存関係を正しく処理しないというバグを追跡するために作成されたものです。この問題は、特に runtime/cgo
パッケージが再ビルドを必要とする場合に顕在化し、テストの失敗やビルドエラーを引き起こしていました。Web検索の結果によると、この問題は go test -i
が import 'C'
の行で失敗し、「can't load package: C: package could not be found locally」のようなエラーが発生するというものでした。
技術的詳細
このコミットの技術的な核心は、go test -i
コマンドがパッケージの依存関係を解決する際に、cgo
を使用するパッケージの特別なケースを適切に処理することにあります。
Goのビルドシステムでは、パッケージの依存関係は内部的にマップ(deps
)として管理されます。このマップには、ビルド対象のパッケージが依存するすべてのパッケージが含まれます。cgo
を使用するパッケージは、Goのソースコード内で import "C"
と記述することで、C言語のコードとの連携を示します。しかし、この "C"
は実際のGoパッケージではなく、cgo
ツールに対する指示です。
以前の go test
の実装では、"C"
という擬似パッケージが依存関係リストに含まれていた場合、それを単に無視していました。これは、"C"
自体がビルドされるべきパッケージではないため、一見正しいように見えます。しかし、cgo
を使用するパッケージは、実際には runtime/cgo
パッケージに依存しており、さらに、クロスコンパイル環境でない限り、cmd/cgo
ツールにも依存します。
このコミットの修正前は、deps["C"]
が存在する場合に delete(deps, "C")
が行われていましたが、これは runtime/cgo
や cmd/cgo
への依存関係を明示的に追加する処理の前に実行されていました。その結果、runtime/cgo
が古い場合でも、その依存関係が正しく認識されず、再ビルドがトリガーされないという問題が発生していました。
今回の修正では、"C"
が依存関係リストに存在する場合、それを runtime/cgo
と cmd/cgo
(ホストOS/アーキテクチャとターゲットOS/アーキテクチャが一致する場合)に変換するように変更されました。これにより、cgo
を使用するパッケージのビルド時に、runtime/cgo
が最新の状態であることが保証され、必要に応じて再ビルドが実行されるようになります。
特に重要なのは、buildContext.GOOS == runtime.GOOS && buildContext.GOARCH == runtime.GOARCH
という条件です。これは、現在のビルドがホスト環境(つまり、クロスコンパイルではない)で行われている場合にのみ cmd/cgo
への依存関係を追加することを示しています。クロスコンパイルの場合、cmd/cgo
はホスト上で実行されるため、ターゲット環境の依存関係としては不要です。
コアとなるコードの変更箇所
変更は src/cmd/go/test.go
ファイルに集中しています。
--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -15,6 +15,7 @@ import (
"os/exec"
"path"
"path/filepath"
+ "runtime"
"sort"
"strings"
"text/template"
@@ -273,8 +274,15 @@ func runTest(cmd *Command, args []string) {
}
}
+ // translate C to runtime/cgo
+ if deps["C"] {
+ delete(deps, "C")
+ deps["runtime/cgo"] = true
+ if buildContext.GOOS == runtime.GOOS && buildContext.GOARCH == runtime.GOARCH {
+ deps["cmd/cgo"] = true
+ }
+ }
// Ignore pseudo-packages.
- delete(deps, "C")
delete(deps, "unsafe")
all := []string{}
コアとなるコードの解説
-
import "runtime"
の追加:runtime
パッケージが新しくインポートされています。これは、runtime.GOOS
とruntime.GOARCH
を使用して、現在の実行環境のOSとアーキテクチャを判定するために必要です。 -
// translate C to runtime/cgo
ブロックの追加: この新しいコードブロックが、既存のdelete(deps, "C")
の行の前に挿入されています。if deps["C"] { ... }
:deps
マップに"C"
というキーが存在するかどうかを確認します。これは、テスト対象のパッケージがcgo
を使用していることを意味します。delete(deps, "C")
: まず、擬似パッケージである"C"
を依存関係リストから削除します。これは以前の動作と同じですが、重要なのはこの削除がruntime/cgo
への依存関係を追加する前に行われることです。deps["runtime/cgo"] = true
:cgo
を使用するパッケージは必ずruntime/cgo
に依存するため、この依存関係を明示的に追加します。これにより、runtime/cgo
が必要に応じてビルドされるようになります。if buildContext.GOOS == runtime.GOOS && buildContext.GOARCH == runtime.GOARCH { deps["cmd/cgo"] = true }
: この条件は、現在のビルドがクロスコンパイルではない(つまり、ビルドターゲットのOSとアーキテクチャが現在の実行環境のOSとアーキテクチャと同じである)場合にのみ真となります。この場合、cmd/cgo
ツール自体もビルド依存関係として追加されます。cmd/cgo
はcgo
コードを処理するためのツールであり、ホスト環境で実行されるため、クロスコンパイル時にはターゲットの依存関係としては不要です。
-
既存の
delete(deps, "C")
の削除: 新しいブロックで"C"
の削除と変換が行われるため、以前のdelete(deps, "C")
の行は不要となり、削除されました。
この変更により、go test -i
は cgo
を使用するパッケージの依存関係をより正確に解決し、特に runtime/cgo
が古い場合に適切に再ビルドをトリガーできるようになりました。これにより、Go Issue #2936 で報告された問題が根本的に解決されます。
関連リンク
- Go Issue #2936: https://github.com/golang/go/issues/2936 (このコミットが修正した問題のトラッキング)
- Go Change List 5674048: https://golang.org/cl/5674048 (このコミットの元の変更リスト)
- Go Change List 5674043: https://golang.org/cl/5674043 (このコミットが言及している以前の変更リスト)
参考にした情報源リンク
- Go言語の公式ドキュメント (cgo): https://go.dev/blog/cgo
- Go言語の公式ドキュメント (go command): https://go.dev/cmd/go/
- Go言語のソースコード (src/cmd/go/test.go): https://github.com/golang/go/blob/master/src/cmd/go/test.go
- Go言語のソースコード (src/runtime/cgo): https://github.com/golang/go/tree/master/src/runtime/cgo
- Go言語のソースコード (src/cmd/cgo): https://github.com/golang/go/tree/master/src/cmd/cgo
- Web検索結果: "Go issue 2936" (https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQEU-9GN3shDmwz7aCgQcvAQsMbct53kEv9eZrP8csrND078CRNjfvSfFhQj8srMoFV6CevLjhtponry_XPxMbZSJlcd71yt_bqYJzQGmSE2HTX7899OYf_s_2LceajSobDdIX0=)