[インデックス 16196] ファイルの概要
このコミットは、Go言語のダッシュボードビルダにおけるクロスコンパイル時のCgoの挙動に関する問題を修正するものです。具体的には、クロスコンパイル環境下でCgoが無効になることによって発生する問題を解決するため、ビルダが常にネイティブビルドを行うように変更されています。
コミット
commit de2fcae372bd4b06b684380ea6b55100683e433a
Author: Dave Cheney <dave@cheney.net>
Date: Thu Apr 18 16:42:56 2013 +1000
misc/dashboard/builder: always do a native build
https://golang.org/cl/8134043 disabled cgo when cross compiling, this means builders which compile for both amd64 and 386 will be compiling the latter with cgo disabled.
This proposal modifies the builder to mirror the dist tool by always doing a native build.
Tested on my darwin/amd64 builder and confirmed the result when building darwin/386 is a native 386 build with cgo enabled.
R=bradfitz, dsymonds, r, adg
CC=golang-dev
https://golang.org/cl/8842044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/de2fcae372bd4b06b684380ea6b55100683e433a
元コミット内容
このコミットの元々の目的は、misc/dashboard/builder
がクロスコンパイル時にCgoを無効にするという挙動を修正することでした。以前の変更(https://golang.org/cl/8134043
)により、クロスコンパイル時にCgoが無効化されていました。これは、例えばamd64
と386
の両方のためにコンパイルするビルダが、386
向けのビルドをCgo無効で行ってしまうという問題を引き起こしていました。
このコミットは、dist
ツールと同様に、ビルダが常にネイティブビルドを行うように修正することを提案しています。これにより、クロスコンパイル時でもCgoが有効な状態でビルドが行われるようになります。コミットメッセージには、darwin/amd64
環境でdarwin/386
をビルドした際に、Cgoが有効なネイティブ386
ビルドが生成されることを確認した旨が記載されています。
変更の背景
Go言語のビルドシステムでは、異なるアーキテクチャやOS向けにバイナリを生成する「クロスコンパイル」がサポートされています。しかし、Cgo(GoとC言語の相互運用機能)を使用するプログラムをクロスコンパイルする際には、いくつかの課題が存在します。
以前の変更(https://golang.org/cl/8134043
)により、Goのビルドシステムの一部であるmisc/dashboard/builder
が、クロスコンパイルを行う際にCgoを意図せず無効化してしまう問題が発生していました。これは、例えばamd64
アーキテクチャのホストマシンで386
アーキテクチャ向けのバイナリをビルドする際に、386
向けのバイナリではCgoが利用できなくなることを意味します。Cgoは、GoプログラムがCライブラリやシステムコールを直接呼び出すために不可欠であり、Cgoに依存するGoプログラムが正しく動作しない原因となります。
この問題は、特にGoの公式ダッシュボード(継続的インテグレーションシステム)でGoの様々なバージョンやプラットフォーム向けのビルドを生成する際に顕著でした。Cgoが有効な状態でビルドされるべきバイナリが、クロスコンパイルの過程でCgoが無効化されてしまうと、テストの失敗や機能の欠如につながる可能性があります。
このコミットは、このCgo無効化の問題を解決し、クロスコンパイル時でもCgoが適切に機能するように、ビルダの挙動を修正することを目的としています。
前提知識の解説
このコミットを理解するためには、以下のGo言語およびビルドシステムに関する知識が必要です。
- Cgo: Go言語とC言語の相互運用を可能にするGoの機能です。Goプログラム内でCの関数を呼び出したり、Cのデータ構造を利用したりするために使用されます。Cgoを使用するプログラムは、Goコンパイラだけでなく、Cコンパイラ(通常はGCCやClang)も必要とします。クロスコンパイル環境では、ターゲットアーキテクチャとOSに対応するCコンパイラ(クロスコンパイラ)が必要になります。
- クロスコンパイル (Cross-compilation): あるプラットフォーム(ホスト)上で、別のプラットフォーム(ターゲット)で実行可能なバイナリを生成するプロセスです。Go言語は、
GOOS
(ターゲットOS)とGOARCH
(ターゲットアーキテクチャ)環境変数を設定することで、簡単にクロスコンパイルを行うことができます。 GOOS
とGOARCH
: Goのビルド時に使用される環境変数です。GOOS
: ビルド対象のオペレーティングシステムを指定します(例:linux
,windows
,darwin
)。GOARCH
: ビルド対象のCPUアーキテクチャを指定します(例:amd64
,386
,arm
)。
GOHOSTOS
とGOHOSTARCH
: Goのビルド時に使用される環境変数で、ビルドを実行しているホスト環境のOSとアーキテクチャを示します。これらは通常、Goツールチェーンが自動的に設定しますが、明示的に設定することも可能です。このコミットでは、これらの変数を明示的に設定することで、ビルダの挙動を制御しています。misc/dashboard/builder
: Goプロジェクトのmisc
ディレクトリにある、Goの継続的インテグレーション(CI)ダッシュボードの一部として使用されるビルドツールです。Goの様々なコミットやブランチに対して、異なるプラットフォーム向けのバイナリを自動的にビルドし、テストを実行する役割を担っています。dist
ツール: Goのソースコードリポジトリに含まれる、Goツールチェーン自体をビルドするための内部ツールです。src/make.bash
(Unix系)やsrc/make.bat
(Windows)などのスクリプトから呼び出され、Goのコンパイラ、リンカ、標準ライブラリなどを構築します。このツールは、Goのビルドプロセスにおける「ネイティブビルド」の基準となる挙動を持っています。- ネイティブビルド (Native Build): ビルドを実行しているホスト環境と同じOSとアーキテクチャ向けのバイナリをビルドすることです。クロスコンパイルとは対照的です。このコミットの文脈では、「ネイティブビルド」の挙動を模倣することで、クロスコンパイル時でもCgoが有効になるようにしています。
技術的詳細
このコミットの核心は、GoのビルドシステムがCgoを扱う方法と、クロスコンパイル時の環境変数の設定にあります。
Goのビルドプロセスでは、GOOS
とGOARCH
がターゲット環境を決定するのに対し、GOHOSTOS
とGOHOSTARCH
はビルドを実行しているホスト環境を決定します。Cgoが有効なビルドを行うためには、GoコンパイラがCコンパイラを呼び出す際に、ターゲット環境とホスト環境の整合性が重要になります。
以前のhttps://golang.org/cl/8134043
の変更では、クロスコンパイル時にGOHOSTARCH
とGOHOSTOS
が適切に設定されず、Cgoが有効にならない状況が発生していました。これは、Goのビルドツールが、ホストとターゲットが異なる場合にCgoを無効にするロジックを持っていたためと考えられます。
このコミットでは、misc/dashboard/builder/main.go
内のextraEnv
変数からGOHOSTARCH
とGOHOSTOS
を削除し、代わりにenvv()
関数とenvvWindows()
関数内でこれらの変数を明示的にb.goos
とb.goarch
(つまりターゲットのOSとアーキテクチャ)に設定しています。
これにより、ビルダは、たとえクロスコンパイルを行っている場合でも、GOHOSTOS
とGOHOSTARCH
をターゲットのOSとアーキテクチャと同じ値に設定します。Goのビルドツールは、GOHOSTOS
とGOHOSTARCH
がGOOS
とGOARCH
と同じであると認識するため、Cgoを無効にする判断を行わなくなります。結果として、クロスコンパイル時でもCgoが有効な状態でビルドが実行されるようになります。
このアプローチは、Goツールチェーン自体をビルドする際に使用されるdist
ツールの挙動を模倣しています。dist
ツールも同様に、クロスコンパイル時でもCgoが有効なビルドを生成するために、内部的にホストとターゲットの環境変数を調整しています。このコミットは、ダッシュボードビルダの挙動をdist
ツールに合わせることで、一貫性のあるビルド結果を保証しています。
コアとなるコードの変更箇所
変更は misc/dashboard/builder/main.go
ファイルに集中しています。
--- a/misc/dashboard/builder/main.go
+++ b/misc/dashboard/builder/main.go
@@ -33,8 +33,6 @@ const (
var extraEnv = []string{
"CC",
"GOARM",
- "GOHOSTARCH",
- "GOHOSTOS",
"PATH",
"TMPDIR",
"USER",
@@ -409,7 +407,9 @@ func (b *Builder) envv() []string {
}\n\te := []string{\n \t\t\"GOOS=\" + b.goos,\n+\t\t\"GOHOSTOS=\" + b.goos,\n \t\t\"GOARCH=\" + b.goarch,\n+\t\t\"GOHOSTARCH=\" + b.goarch,\n \t\t\"GOROOT_FINAL=/usr/local/go\",\n \t}\n \tfor _, k := range extraEnv {\n@@ -424,7 +424,9 @@ func (b *Builder) envvWindows() []string {\n func (b *Builder) envvWindows() []string {\n \tstart := map[string]string{\n \t\t\"GOOS\": b.goos,\n+\t\t\"GOHOSTOS\": b.goos,\n \t\t\"GOARCH\": b.goarch,\n+\t\t\"GOHOSTARCH\": b.goarch,\n \t\t\"GOROOT_FINAL\": `c:\\go`,\n \t\t\"GOBUILDEXIT\": \"1\", // exit all.bat with completion status.\n \t}\n```
## コアとなるコードの解説
このコミットの主要な変更点は以下の2つです。
1. **`extraEnv` から `GOHOSTARCH` と `GOHOSTOS` の削除**:
`extraEnv` は、ビルドプロセスに渡される追加の環境変数のキーを定義するスライスです。以前はここに`"GOHOSTARCH"`と`"GOHOSTOS"`が含まれていましたが、このコミットで削除されました。これは、これらの変数を自動的に引き継ぐのではなく、ビルダが明示的に設定することを意図しています。
```go
var extraEnv = []string{
"CC",
"GOARM",
// - "GOHOSTARCH", // 削除
// - "GOHOSTOS", // 削除
"PATH",
"TMPDIR",
"USER",
}
```
2. **`envv()` および `envvWindows()` 関数での `GOHOSTOS` と `GOHOSTARCH` の明示的な設定**:
`envv()` 関数はUnix系システム向けの環境変数を、`envvWindows()` 関数はWindowsシステム向けの環境変数を構築します。これらの関数内で、`GOOS`と`GOARCH`を設定するのと同様に、`GOHOSTOS`と`GOHOSTARCH`もターゲットのOSとアーキテクチャ(`b.goos`と`b.goarch`)に設定されるようになりました。
**`envv()` 関数 (Unix系)**:
```go
func (b *Builder) envv() []string {
// ...
e := []string{
"GOOS=" + b.goos,
"GOHOSTOS=" + b.goos, // 追加
"GOARCH=" + b.goarch,
"GOHOSTARCH=" + b.goarch, // 追加
"GOROOT_FINAL=/usr/local/go",
}
// ...
}
```
**`envvWindows()` 関数 (Windows)**:
```go
func (b *Builder) envvWindows() []string {
start := map[string]string{
"GOOS": b.goos,
"GOHOSTOS": b.goos, // 追加
"GOARCH": b.goarch,
"GOHOSTARCH": b.goarch, // 追加
"GOROOT_FINAL": `c:\go`,
"GOBUILDEXIT": "1", // exit all.bat with completion status.
}
// ...
}
```
この変更により、`misc/dashboard/builder`は、クロスコンパイルを行う際でも、ビルド環境に対して「ホストOSとホストアーキテクチャがターゲットOSとターゲットアーキテクチャと同じである」と偽装する形になります。これにより、GoのビルドツールチェーンはCgoを無効にする判断を行わず、結果としてクロスコンパイル時でもCgoが有効な状態でビルドが進行するようになります。これは、Goの`dist`ツールが内部的に行っている「ネイティブビルド」の挙動を模倣するものです。
## 関連リンク
* Go言語公式ウェブサイト: [https://golang.org/](https://golang.org/)
* Go言語のCgoに関するドキュメント: [https://go.dev/blog/cgo](https://go.dev/blog/cgo) (GoブログのCgoに関する記事)
* Go言語のクロスコンパイルに関するドキュメント: [https://go.dev/doc/install/source#environment](https://go.dev/doc/install/source#environment) (Goの環境変数に関する公式ドキュメント)
## 参考にした情報源リンク
* 元の変更セット (Cgoを無効にした原因): [https://golang.org/cl/8134043](https://golang.org/cl/8134043)
* このコミットの変更セット: [https://golang.org/cl/8842044](https://golang.org/cl/8842044)
* Goの`dist`ツールに関する情報 (Goのソースコードリポジトリ内): `src/make.bash` や `src/make.bat` などのスクリプトを参照。
* Goの環境変数に関する一般的な情報源 (例: `GOOS`, `GOARCH`, `GOHOSTOS`, `GOHOSTARCH`): Goの公式ドキュメントやGoコミュニティの議論。
* Dave Cheney氏のブログやGoに関する記事 (コミット著者): [https://dave.cheney.net/](https://dave.cheney.net/) (一般的な情報源として)