[インデックス 17786] ファイルの概要
このコミットは、Go言語のビルドシステム (go/build
パッケージ) におけるテストの修正に関するものです。具体的には、CGO_ENABLED=0
(CGOが無効) の環境でビルドされた場合に発生するテストの失敗を修正しています。
コミット
commit 96648e019567d9e50c147638f104f0bf4a381350
Author: Ian Lance Taylor <iant@golang.org>
Date: Fri Oct 11 15:55:50 2013 -0700
go/build: fix test if built with CGO_ENABLED=0
Fixes #6567.
R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/14502060
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/96648e019567d9e50c147638f104f0bf4a381350
元コミット内容
go/build: fix test if built with CGO_ENABLED=0
(go/build
: CGO_ENABLED=0
でビルドされた場合のテストを修正)
Fixes #6567.
(Issue #6567 を修正)
変更の背景
このコミットは、Go言語のビルドプロセスにおいて、CGO(C言語との相互運用機能)が無効化されている環境で特定のテストが失敗するという問題(Issue #6567)を解決するために行われました。
Go言語では、CGO_ENABLED
という環境変数を用いてCGOの有効/無効を切り替えることができます。CGO_ENABLED=1
(デフォルト)の場合、GoプログラムはC言語のコードを呼び出すことができ、C言語のライブラリとリンクすることも可能です。一方、CGO_ENABLED=0
の場合、CGOは無効化され、C言語のコードを呼び出す機能やCライブラリへのリンクは行われません。これは、クロスコンパイル時や、CGOに依存しない純粋なGoバイナリを生成したい場合などに利用されます。
問題の根本は、go/build
パッケージ内のテストスイートが、runtime/cgo
パッケージへの依存関係を適切に処理していなかったことにあります。runtime/cgo
パッケージはCGOが有効な場合にのみ利用されるパッケージであり、CGO_ENABLED=0
の環境ではビルドされません。しかし、テストコードがこの状況を考慮せずにruntime/cgo
パッケージの存在を期待していたため、テストが失敗していました。
この修正は、CGO_ENABLED=0
の環境でテストを実行する際に、runtime/cgo
パッケージに関連するテストケースをスキップすることで、テストの信頼性を向上させることを目的としています。
前提知識の解説
Go言語のビルドシステム (go/build
パッケージ)
go/build
パッケージは、Go言語のソースコードを解析し、パッケージの依存関係を解決するための機能を提供します。Goコマンド(go build
, go install
など)の内部で利用され、ソースファイルのGoバージョン、OS、アーキテクチャ、ビルドタグなどの情報を基に、どのファイルをビルドに含めるべきかを決定します。このパッケージは、Goのモジュールシステムやクロスコンパイルの基盤となる重要なコンポーネントです。
CGO
CGOは、GoプログラムからC言語の関数を呼び出したり、C言語のコードをGoプログラムに組み込んだりするためのGo言語の機能です。これにより、既存のCライブラリをGoから利用したり、パフォーマンスが重要な部分をC言語で記述したりすることが可能になります。CGOを使用するには、Goのソースコード内でimport "C"
という特殊なインポート文を使用し、C言語のコードをGoのコメントブロック内に記述します。
CGO_ENABLED
環境変数
CGO_ENABLED
は、Goのビルドプロセスを制御する環境変数の一つです。
CGO_ENABLED=1
(デフォルト): CGOが有効になります。GoコンパイラはCコンパイラ(通常はGCCやClang)と連携して、CGOを使用するGoプログラムをビルドします。CGO_ENABLED=0
: CGOが無効になります。GoコンパイラはCGOを使用するGoプログラムをビルドせず、純粋なGoコードのみで構成されたバイナリを生成します。これにより、Cコンパイラがインストールされていない環境でもビルドが可能になったり、生成されるバイナリが小さくなったり、クロスコンパイルが容易になったりする利点があります。
runtime/cgo
パッケージ
runtime/cgo
パッケージは、Goランタイムの一部であり、CGOが有効な場合にC言語との相互運用に必要な低レベルの機能を提供します。このパッケージは、CGOが有効なビルドでのみコンパイルされ、CGOが無効なビルドでは含まれません。
Goのテストフレームワーク
Go言語には、標準ライブラリにtesting
パッケージが用意されており、これを用いてユニットテストやベンチマークテストを記述できます。テストファイルは通常、テスト対象のファイルと同じディレクトリに_test.go
というサフィックスを付けて配置されます。go test
コマンドを実行することで、これらのテストが実行されます。
技術的詳細
このコミットは、src/pkg/go/build/deps_test.go
ファイル内のTestDependencies
関数に修正を加えています。TestDependencies
は、様々なOS、アーキテクチャ、CGOの有効/無効の組み合わせでパッケージの依存関係が正しく解決されるかをテストする関数です。
既存のテストロジックでは、ctxt.GOOS
(ターゲットOS)とpkg
(パッケージ名)の組み合わせで許可されるエラーをチェックしていました。しかし、CGO_ENABLED=0
の環境でruntime/cgo
パッケージの依存関係をチェックしようとすると、このパッケージがビルドに含まれないため、テストが失敗していました。
この修正では、以下の条件を追加することでこの問題を解決しています。
if !ctxt.CgoEnabled && pkg == "runtime/cgo" {
continue
}
このコードは、現在のビルドコンテキスト (ctxt
) でCGOが無効 (!ctxt.CgoEnabled
) であり、かつテスト対象のパッケージがruntime/cgo
である場合に、現在のテストイテレーションをスキップする (continue
) ように指示しています。これにより、CGO_ENABLED=0
の環境ではruntime/cgo
に関連するテストが実行されなくなり、テストの失敗が回避されます。
この変更は、Goのビルドシステムが異なるビルド環境(特にCGOの有効/無効)に対してより堅牢であることを保証し、テストの誤った失敗を防ぐ上で重要です。
コアとなるコードの変更箇所
変更はsrc/pkg/go/build/deps_test.go
ファイルにあります。
--- a/src/pkg/go/build/deps_test.go
+++ b/src/pkg/go/build/deps_test.go
@@ -392,6 +392,9 @@ func TestDependencies(t *testing.T) {
if allowedErrors[osPkg{ctxt.GOOS, pkg}] {
continue
}
+ if !ctxt.CgoEnabled && pkg == "runtime/cgo" {
+ continue
+ }
// Some of the combinations we try might not
// be reasonable (like arm,plan9,cgo), so ignore
// errors for the auto-generated combinations.
コアとなるコードの解説
追加された3行のコードは、TestDependencies
関数内のループ内で実行されます。このループは、様々なビルドコンテキスト(ctxt
)とパッケージ(pkg
)の組み合わせを試行し、依存関係の解決をテストします。
!ctxt.CgoEnabled
: これはブール式で、現在のビルドコンテキスト (ctxt
) においてCGOが有効でない(つまりCGO_ENABLED=0
である)場合にtrue
を返します。pkg == "runtime/cgo"
: これは、現在テストされているパッケージの名前が文字列"runtime/cgo"
と等しい場合にtrue
を返します。
これら二つの条件が&&
(論理AND)で結合されているため、両方の条件がtrue
である場合にのみ、continue
文が実行されます。continue
文は、現在のループのイテレーションを終了し、次のイテレーションに進むことを意味します。
したがって、このコードは「もしCGOが無効なビルド環境で、かつruntime/cgo
パッケージの依存関係をテストしようとしているならば、そのテストケースはスキップする」というロジックを実装しています。これにより、CGO_ENABLED=0
の環境でruntime/cgo
パッケージが存在しないことによるテストの失敗を防ぎ、テストスイート全体の安定性を向上させています。
関連リンク
- Go Issue #6567: https://github.com/golang/go/issues/6567
- Go CL 14502060: https://golang.org/cl/14502060
参考にした情報源リンク
- Go言語公式ドキュメント:
go/build
パッケージ - Go言語公式ドキュメント: CGO
- Go言語公式ドキュメント:
go test
コマンド - Go言語のクロスコンパイルとCGOに関する記事 (一般的な情報源)
- GitHubのgolang/goリポジトリのIssueトラッカー
- Go言語のソースコード (特に
src/pkg/go/build/
ディレクトリ)