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

[インデックス 12556] ファイルの概要

このコミットは、Go言語のツールチェインの一部である cmd/api ディレクトリ内の goapi.go ファイルに対する変更です。cmd/api は、Goの標準ライブラリのAPIサーフェスを検査し、その変更を追跡するためのツールです。goapi.go は、このツールのビルドコンテキスト(異なるOSやアーキテクチャの組み合わせ)を定義しています。

コミット

commit 764880e2b2a025e7eb4dfdb226f50ff2586aa384
Author: David Symonds <dsymonds@golang.org>
Date:   Mon Mar 12 11:25:38 2012 +1100

    cmd/api: set compiler for all build contexts.
    
    The generated syscall files for Windows are still breaking "go tool api"
    (unknown function []byte); I'll look at fixing that separately.
    
    Fixes #3285.
    
    R=bradfitz
    CC=golang-dev
    https://golang.org/cl/5777062

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/764880e2b2a025e7eb4dfdb226f50ff2586aa384

元コミット内容

cmd/api ツールにおいて、すべてのビルドコンテキストに対してコンパイラを設定する変更です。 この変更は、Windows向けの生成されたsyscallファイルが「go tool api」を壊す問題(unknown function []byte)とは別に対応される予定です。 Go issue #3285 を修正します。

変更の背景

このコミットは、Go言語のIssue #3285「cmd/api: unknown compiler」を修正するために行われました。この問題は、go tool api コマンドを実行した際に、「unknown compiler」というエラーが発生するというものでした。

go tool api は、Goの標準ライブラリのAPI定義を生成・検証するために使用される内部ツールです。このツールは、異なるオペレーティングシステム(GOOS)とアーキテクチャ(GOARCH)の組み合わせ(ビルドコンテキスト)でGoのコードをコンパイルする際に、それぞれのコンテキストに適したコンパイラ情報が必要となります。

以前の cmd/api の実装では、これらのビルドコンテキストに対して明示的にコンパイラが設定されていませんでした。そのため、特定の環境やGoのバージョンにおいて、go tool api がどのコンパイラを使用すべきかを判断できず、「unknown compiler」エラーを引き起こしていました。

このコミットの目的は、各ビルドコンテキストにデフォルトのコンパイラを明示的に設定することで、このエラーを解消し、go tool api の安定性と信頼性を向上させることです。コミットメッセージには、Windows向けのsyscallファイルに関する別の問題が言及されていますが、これはこのコミットの範囲外であり、別途修正されることが示されています。

前提知識の解説

  • go tool api: Go言語の標準ライブラリのAPIサーフェスを検査し、その変更を追跡するための内部ツールです。Goの互換性ポリシーを維持するために使用されます。
  • ビルドコンテキスト (build.Context): Goのビルドシステムにおいて、特定のコンパイル環境(ターゲットOS、ターゲットアーキテクチャ、Cgoの有効/無効など)を定義する構造体です。go/build パッケージで定義されています。
  • GOOSGOARCH: Goの環境変数で、それぞれターゲットとなるオペレーティングシステム(例: linux, windows, darwin)とアーキテクチャ(例: amd64, 386, arm)を指定します。Goのクロスコンパイルにおいて重要な役割を果たします。
  • build.Default.Compiler: go/build パッケージで提供される、現在のGo環境におけるデフォルトのコンパイラ名(通常は "gc")を保持するフィールドです。
  • init() 関数: Go言語の特別な関数で、パッケージが初期化される際に自動的に実行されます。main() 関数が呼び出される前に実行され、パッケージレベルの変数の初期化や、一度だけ実行する必要があるセットアップ処理などに使用されます。

技術的詳細

Goのビルドシステムは、異なるプラットフォームやアーキテクチャ向けにコードをコンパイルする際に、build.Context 構造体を使用してその環境を抽象化します。cmd/api ツールは、Goの標準ライブラリのAPIを検証するために、複数の build.Context インスタンスを定義しています。これらは、GOOSGOARCH の様々な組み合わせ(例: linux-amd64, windows-386 など)を表します。

build.Context 構造体には、Compiler というフィールドがあります。このフィールドは、そのコンテキストで使用されるコンパイラの名前(例: "gc" for Go compiler, "gccgo" for GCC-based Go compiler)を指定します。go tool api がAPI定義を生成する際、内部的にGoのコンパイラツールチェーンの一部を利用します。このプロセスでは、各ビルドコンテキストに対して適切なコンパイラが設定されていることが期待されます。

Issue #3285 の問題は、cmd/api が定義する contexts スライス内の build.Context インスタンスの Compiler フィールドが未設定であったために発生しました。Goのビルドツールがこれらのコンテキストを処理しようとした際、コンパイラ情報が不足しているため、「unknown compiler」というエラーをスローしていました。

このコミットでは、Goの init() 関数を利用して、この問題を解決しています。init() 関数は、main() 関数が実行される前に、パッケージがロードされる際に自動的に実行されます。この init() 関数内で、contexts スライス内の各 build.Context インスタンスをループ処理し、それぞれの c.Compiler フィールドに build.Default.Compiler の値を代入しています。

これにより、cmd/api が起動し、API検証プロセスを開始する前に、すべてのビルドコンテキストに対してデフォルトのGoコンパイラ(通常は gc)が明示的に設定されるようになります。これにより、コンパイラ情報が不足していることによるエラーが解消され、go tool api が意図した通りに機能するようになります。

コアとなるコードの変更箇所

src/cmd/api/goapi.go ファイルに以下の変更が加えられました。

--- a/src/cmd/api/goapi.go
+++ b/src/cmd/api/goapi.go
@@ -52,6 +52,12 @@ var contexts = []*build.Context{\n 	{GOOS: "windows", GOARCH: "386"},\n }\n \n+func init() {\n+\tfor _, c := range contexts {\n+\t\tc.Compiler = build.Default.Compiler\n+\t}\n+}\n+\n func contextName(c *build.Context) string{\n 	s := c.GOOS + "-" + c.GOARCH\n 	if c.CgoEnabled {\n```

## コアとなるコードの解説

追加された `init()` 関数は、`goapi.go` パッケージが初期化される際に一度だけ実行されます。

```go
func init() {
	for _, c := range contexts {
		c.Compiler = build.Default.Compiler
	}
}

この init() 関数は以下の処理を行います。

  1. contexts スライスをループします。contexts は、cmd/api がサポートする様々な GOOSGOARCH の組み合わせを表す *build.Context のスライスです。
  2. ループの各イテレーションで、現在の build.Context インスタンス c を取得します。
  3. c.Compiler = build.Default.Compiler を実行します。これは、現在のビルドコンテキスト cCompiler フィールドに、Goのビルドシステムが提供するデフォルトのコンパイラ名(例: "gc")を設定します。

このシンプルな変更により、go tool api が内部的にGoのビルドツールを呼び出す際に、各ビルドコンテキストが適切なコンパイラ情報を持つことが保証され、「unknown compiler」エラーが解消されます。

関連リンク

参考にした情報源リンク