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

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

このコミットは、Go言語のcgoテストスイートにおけるビルドエラーを修正するものです。具体的には、cgoを使用するパッケージ内でC言語のソースファイル(.cファイル)がgccではなくGoの内部コンパイラ(当時の6c)でコンパイルされるべきケースに対応するため、runtime.cファイルをbackdoorという新しいパッケージに移動し、そのパッケージがcgoを使用しないように設定することで問題を解決しています。これにより、Goランタイムの特定のCコードがGoのビルドシステムによって正しく処理されるようになります。

コミット

commit fc98f28204899df74d0857fd569ba41447b9918c
Author: Russ Cox <rsc@golang.org>
Date:   Tue Mar 6 23:38:54 2012 -0500

    misc/cgo/test: fix build
    
    The last CL forgot the all-important 'backdoor' package.
    Cgo-using packages compile .c files with gcc, but we want
    to compile this one with 6c, so put it in a non-cgo package.
    
    TBR=golang-dev
    CC=golang-dev
    https://golang.org/cl/5758063
---
 misc/cgo/test/backdoor/backdoor.go     | 7 +++++++
 misc/cgo/test/{ => backdoor}/runtime.c | 4 +++-\n 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/misc/cgo/test/backdoor/backdoor.go b/misc/cgo/test/backdoor/backdoor.go
new file mode 100644
index 0000000000..3428e9e43f
--- /dev/null
+++ b/misc/cgo/test/backdoor/backdoor.go
@@ -0,0 +1,7 @@
+// Copyright 2012 The Go Authors.  All rights reserved.\n+// Use of this source code is governed by a BSD-style\n+// license that can be found in the LICENSE file.\n+\n+package backdoor\n+\n+func LockedOSThread() bool  // in runtime.c
diff --git a/misc/cgo/test/runtime.c b/misc/cgo/test/backdoor/runtime.c
similarity index 73%
rename from misc/cgo/test/runtime.c
rename to misc/cgo/test/backdoor/runtime.c
index e087c76220..54e6a1ef8b 100644
--- a/misc/cgo/test/runtime.c
+++ b/misc/cgo/test/backdoor/runtime.c
@@ -3,6 +3,8 @@
 // license that can be found in the LICENSE file.\n \n // Expose some runtime functions for testing.\n+// Must be in a non-cgo-using package so that\n+// the go command compiles this file with 6c, not gcc.\n \n typedef char bool;\n \n@@ -14,7 +16,7 @@ FLUSH(void*)\n }\n \n void\n-·lockedOSThread(bool b)\n+·LockedOSThread(bool b)\n {\n \tb = runtime·lockedOSThread();\n \tFLUSH(&b);\n```

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

[https://github.com/golang/go/commit/fc98f28204899df74d0857fd569ba41447b9918c](https://github.com/golang/go/commit/fc98f28204899df74d0857fd569ba41447b9918c)

## 元コミット内容

このコミットは、`misc/cgo/test`ディレクトリ内のビルド問題を修正することを目的としています。コミットメッセージによると、直前の変更("last CL")で「非常に重要な`backdoor`パッケージ」が忘れられていたことが原因で問題が発生していました。

通常、`cgo`を使用するGoパッケージは、関連するC言語のソースファイル(`.c`ファイルなど)を`gcc`のような外部のCコンパイラでコンパイルします。しかし、この特定のケースでは、`runtime.c`というファイルが`gcc`ではなく、Goの内部コンパイラである`6c`(当時のGoの標準コンパイラツールチェーン`gc`の一部で、64ビットシステム向けのGoコンパイラ)でコンパイルされる必要がありました。この要件を満たすため、`runtime.c`を`cgo`を使用しないパッケージに配置するという解決策が取られました。

## 変更の背景

Go言語のビルドシステムは、GoコードとCコードの連携において特定のルールを持っています。特に`cgo`を使用する場合、Goのソースファイル内に`import "C"`という記述があると、GoツールチェーンはGoコードとCコードの間のブリッジを生成し、Cコード部分をシステムのCコンパイラ(通常は`gcc`または`clang`)に渡してコンパイルさせます。

しかし、Goのランタイム(`runtime`パッケージ)には、Go言語自体が動作するために必要な低レベルのCコードやアセンブリコードが含まれています。これらのコードは、Goのガベージコレクション、スケジューラ、システムコールなど、Goのコア機能と密接に連携しており、Goのビルドツールチェーンによって特別に扱われる必要があります。具体的には、これらのCコードは`gcc`のような汎用Cコンパイラではなく、Goのツールチェーンが提供する専用のCコンパイラ(当時の`6c`など)でコンパイルされることが期待されます。これは、GoランタイムのCコードがGoの内部構造やABI(Application Binary Interface)に深く依存しているためです。

このコミットが行われる前の状態では、`misc/cgo/test`ディレクトリ内の`runtime.c`ファイルが、`cgo`の通常のルールに従って`gcc`でコンパイルされてしまい、Goランタイムの期待するコンパイル方法と合致せず、ビルドエラーや予期せぬ動作を引き起こしていたと考えられます。コミットメッセージにある「The last CL forgot the all-important 'backdoor' package.」という記述は、以前の変更でこの`runtime.c`をGoの内部コンパイラでコンパイルするための特別な仕組み(`backdoor`パッケージ)が考慮されていなかったことを示唆しています。

したがって、この変更の背景には、`cgo`の一般的な動作と、GoランタイムのCコードに対する特別なビルド要件との間のミスマッチを解消し、Goのテストスイートが正しくビルドされるようにするという目的がありました。

## 前提知識の解説

### Goのビルドプロセスとコンパイラ

Go言語のプログラムは、`go build`コマンドによってコンパイルされます。Goの標準コンパイラツールチェーンは`gc`と呼ばれ、Goのソースコードを直接機械語に変換します。Go 1.xの時代には、特定のアーキテクチャ向けに`6c`(amd64向け)、`8c`(386向け)、`5c`(arm向け)といったCコンパイラがGoツールチェーンの一部として存在し、GoランタイムのCコードをコンパイルするために使用されていました。これらはGoのビルドシステムと密接に統合されており、Goのランタイムコードの特殊な要件を満たすように設計されていました。

### cgoとは

`cgo`は、GoプログラムからC言語のコードを呼び出したり、C言語のライブラリを利用したりするためのGoツールです。Goのソースファイル内で`import "C"`と記述し、その直前のコメントブロックにC言語のコードを記述することで、GoとCの相互運用が可能になります。

`cgo`のビルドプロセスは以下のようになります:
1.  `go build`コマンドが実行されると、まず`cgo`ツールがGoソースファイルを解析します。
2.  `import "C"`を含むGoファイルと、それに付随するCコード(コメントブロック内や、同じパッケージ内の`.c`, `.h`などのファイル)を処理します。
3.  `cgo`は、GoとCの間で関数呼び出しを仲介するための「スタブ」コード(Go側とC側の両方)を生成します。
4.  生成されたCコードは、システムのCコンパイラ(通常は`gcc`または`clang`)によってコンパイルされます。
5.  GoコードはGoコンパイラによってコンパイルされます。
6.  最終的に、GoのオブジェクトファイルとCのオブジェクトファイルがGoリンカによってリンクされ、実行可能ファイルが生成されます。

### `6c`と`gcc`の役割の違い

*   **`gcc`**: GNU Compiler Collectionの一部であり、C、C++、Objective-C、Fortranなど様々な言語をコンパイルできる汎用的なコンパイラです。`cgo`を使用するGoプログラムが外部のCライブラリやCコードをリンクする場合、Goツールチェーンは通常`gcc`を呼び出してCコードをコンパイルします。
*   **`6c`**: Go 1.x時代のGoツールチェーン`gc`の一部であった、GoランタイムのCコードをコンパイルするためのGo独自のCコンパイラです。これはGoの内部構造と密接に連携しており、Goランタイムの特殊な要件(例:Goのガベージコレクタが認識できるようなスタックフレームの生成など)を満たすように設計されていました。Goのランタイムコードは、Goのビルドシステムによって`6c`のようなGo独自のコンパイラでコンパイルされることが前提となっていました。

このコミットの核心は、`cgo`がデフォルトでCファイルを`gcc`でコンパイルするのに対し、GoランタイムのCファイルは`6c`でコンパイルされる必要があるという、このコンパイラの選択に関する問題でした。

## 技術的詳細

このコミットが修正している問題は、GoのビルドシステムにおけるC言語ソースファイルのコンパイル方法の選択に関するものです。

1.  **`cgo`のデフォルト動作**: `cgo`が有効なGoパッケージ(`import "C"`を含むパッケージ)内に`.c`ファイルが存在する場合、Goツールチェーンはこれらの`.c`ファイルを自動的に検出し、システムのCコンパイラ(`gcc`)を使用してコンパイルします。これは、Goと外部Cライブラリを連携させるための標準的なメカニズムです。

2.  **Goランタイムの特殊性**: Goのランタイム(`runtime`パッケージ)は、Go言語の実行環境を支える非常に低レベルなコードを含んでいます。この中には、C言語で書かれた部分も多く存在します。これらのCコードは、Goのガベージコレクタ、スケジューラ、スタック管理など、Goのコア機能と密接に連携しており、Goのビルドツールチェーン(当時の`6c`などのGo独自のCコンパイラ)によってコンパイルされることが前提となっています。`gcc`のような汎用Cコンパイラでコンパイルすると、Goランタイムが期待する特定のABIや最適化、あるいはGoの内部構造との整合性が損なわれる可能性があります。

3.  **問題の発生**: `misc/cgo/test`ディレクトリは`cgo`のテストに関連するものであり、その中に`runtime.c`というファイルが存在していました。この`runtime.c`は、Goランタイムのテストのために、GoランタイムのCコードの一部を公開する目的で存在していたと考えられます。しかし、このファイルが`cgo`を使用するパッケージのコンテキストに置かれていたため、Goツールチェーンはこれを`cgo`のルールに従って`gcc`でコンパイルしようとしました。これが、`runtime.c`が`6c`でコンパイルされるべきというGoランタイムの要件と衝突し、ビルドエラーを引き起こしていました。

4.  **解決策としての「非cgoパッケージ」**: この問題を解決するために、`runtime.c`を「非`cgo`パッケージ」に移動するというアプローチが取られました。Goツールチェーンは、`import "C"`を含まないパッケージ内の`.c`ファイルに対しては、`cgo`のルールを適用せず、Go独自のCコンパイラ(`6c`)を使用してコンパイルします。これにより、`runtime.c`はGoランタイムが期待するコンパイラで処理されるようになり、ビルドエラーが解消されました。

5.  **`backdoor`パッケージの役割**: `backdoor`という名前のパッケージが作成されたのは、この`runtime.c`をGoの内部コンパイラでコンパイルさせるための「裏口」または「特別な経路」として機能させるためです。このパッケージ自体は`import "C"`を含まないため、その中の`.c`ファイルは`gcc`ではなく`6c`でコンパイルされます。`backdoor.go`ファイルは、`runtime.c`で定義されているC関数(`LockedOSThread`)をGo側から呼び出せるようにするためのGoの宣言を提供しています。

このコミットは、GoのビルドシステムにおけるCコードのコンパイルパスの複雑さと、Goランタイムの特殊な要件を理解していることを示しています。

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

このコミットでは、主に以下の2つのファイルが変更されています。

1.  **`misc/cgo/test/backdoor/backdoor.go` (新規作成)**
    *   新しいGoパッケージ`backdoor`が定義されています。
    *   `func LockedOSThread() bool`という関数宣言が含まれています。この宣言は、`runtime.c`で定義されているC関数`LockedOSThread`をGo側から呼び出すためのGoのシグネチャを提供します。コメント`// in runtime.c`がそのことを示しています。

2.  **`misc/cgo/test/{ => backdoor}/runtime.c` (ファイル移動と内容変更)**
    *   `misc/cgo/test/runtime.c`から`misc/cgo/test/backdoor/runtime.c`へとファイルが移動(リネーム)されました。
    *   ファイルの内容に以下のコメントが追加されました。
        ```c
        // Must be in a non-cgo-using package so that
        // the go command compiles this file with 6c, not gcc.
        ```
        このコメントは、このファイルが`cgo`を使用しないパッケージに配置される必要がある理由を明確に説明しています。
    *   関数名が`·lockedOSThread`から`·LockedOSThread`に変更されています。これはGoのリンカがC関数をGo関数として認識するための命名規則(Go 1.0以前の内部的な命名規則)に合わせたものと考えられます。Goの内部では、エクスポートされたC関数はGoの関数として扱われる際に、先頭に`·`(ドット)が付くことがありました。

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

### `misc/cgo/test/backdoor/backdoor.go`

このファイルは、`backdoor`という新しいGoパッケージを定義しています。このパッケージの主な目的は、`runtime.c`をGoのビルドシステムが`6c`(Goの内部Cコンパイラ)でコンパイルするように誘導することです。

```go
// Copyright 2012 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package backdoor

func LockedOSThread() bool  // in runtime.c
  • package backdoor: このファイルがbackdoorパッケージに属することを示します。
  • func LockedOSThread() bool // in runtime.c: これはGoの関数宣言ですが、実装はGoコードではなく、同じパッケージ内のruntime.cファイルにあるC関数LockedOSThreadによって提供されることを示しています。Goのビルドシステムは、Goの関数宣言に対応するC関数が同じパッケージ内のCソースファイルに存在する場合、それらをリンクします。この宣言自体はimport "C"を含んでいないため、このbackdoorパッケージはcgoを使用しないパッケージとして扱われます。

misc/cgo/test/backdoor/runtime.c

このファイルは、Goランタイムのテストのために、特定のランタイム関数を公開するC言語のソースファイルです。

// Copyright 2012 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Expose some runtime functions for testing.
// Must be in a non-cgo-using package so that
// the go command compiles this file with 6c, not gcc.

typedef char bool;

// ... (省略) ...

void
·LockedOSThread(bool b)
{
    b = runtime·lockedOSThread();
    FLUSH(&b);
}
  • ファイル移動の重要性: このファイルがmisc/cgo/test/backdoor/ディレクトリに移動されたことが最も重要です。これにより、このファイルはbackdoorパッケージの一部となり、このパッケージがimport "C"を含まないため、Goツールチェーンはcgoのルール(gccでコンパイル)を適用せず、Go独自のCコンパイラ(6c)でこのファイルをコンパイルするようになります。
  • 追加されたコメント:
    // Must be in a non-cgo-using package so that
    // the go command compiles this file with 6c, not gcc.
    
    このコメントは、ファイル移動の理由と、GoのビルドシステムにおけるCファイルのコンパイル方法の選択に関する重要な制約を明確に示しています。
  • 関数名の変更: ·lockedOSThreadから·LockedOSThreadへの変更は、Goの内部的な命名規則に合わせたものです。Goのリンカは、Goの関数とCの関数をリンクする際に、特定の命名規則を使用します。この変更により、backdoor.goで宣言されたLockedOSThread関数と、このCファイルで定義された·LockedOSThread関数が正しく関連付けられるようになります。

この変更により、runtime.cはGoランタイムのCコードとして正しくGoのビルドシステムによってコンパイルされ、cgoテストスイートのビルド問題が解決されました。

関連リンク

参考にした情報源リンク