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

[インデックス 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=0go/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言語公式ドキュメント: go/buildパッケージ
  • Go言語公式ドキュメント: CGO
  • Go言語公式ドキュメント: go testコマンド
  • Go言語のクロスコンパイルとCGOに関する記事 (一般的な情報源)
  • GitHubのgolang/goリポジトリのIssueトラッカー
  • Go言語のソースコード (特にsrc/pkg/go/build/ディレクトリ)