[インデックス 12150] ファイルの概要
このコミットは、Go言語のビルドシステムにおけるクロスコンパイル時の不具合を修正するものです。具体的には、cmd/dist
ツールが非ARMシステム上でcmd/5g
をインストールする際の挙動を修正し、誤ったビルドスキップを防ぎます。
コミット
commit 37decab5a31f6418ae52d4548d06b2022d99c72f
Author: Russ Cox <rsc@golang.org>
Date: Wed Feb 22 16:29:05 2012 -0500
cmd/dist: fix install cmd/5g on non-arm system
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5689072
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/37decab5a31f6418ae52d4548d06b2022d99c72f
元コミット内容
cmd/dist: fix install cmd/5g on non-arm system
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5689072
変更の背景
このコミットは、Go言語のビルドシステムであるcmd/dist
が、特定の条件下でクロスコンパイルされたバイナリ(特にcmd/5g
)のインストールを誤ってスキップしてしまうバグを修正するために行われました。
Go言語は、異なるオペレーティングシステム(OS)やアーキテクチャ(CPU)向けにバイナリを生成する「クロスコンパイル」機能を強力にサポートしています。この機能は、例えばLinux上でWindows向けの実行ファイルをビルドする際などに非常に便利です。
cmd/dist
はGoのソースコードからツールチェイン全体をビルド・インストールする役割を担っています。このツールは、ビルド対象のOS (goos
) とアーキテクチャ (goarch
) が、ホスト環境のOS (gohostos
) とアーキテクチャ (gohostarch
) と異なる場合に、クロスコンパイルと判断します。
問題は、cmd/5g
のような特定のコンパイラ(5g
はARMアーキテクチャ向けのGoコンパイラを指します)を非ARMシステム上でビルド・インストールしようとした際に発生しました。以前のコードでは、goos != gohostos
または goarch != gohostarch
の条件が真であれば、無条件にビルドをスキップしていました。しかし、cmd/5g
自体はGoで書かれたツールではなく、C言語で書かれたコンパイラであるため、Goのクロスコンパイルのロジックが適用されるべきではありませんでした。
この誤ったスキップにより、非ARMシステム上でGoのツールチェインをビルドする際に、cmd/5g
が正しくインストールされないという不具合が生じていました。このコミットは、このビルドスキップの条件に&& isgo
(ビルド対象がGo言語で書かれたものであるか)という条件を追加することで、この問題を解決しています。
前提知識の解説
Go言語のビルドシステム (cmd/dist
)
cmd/dist
は、Go言語のソースコードからGoのコンパイラ、リンカ、標準ライブラリ、その他のツールチェイン全体をビルドし、インストールするための内部ツールです。Goのソースコードをダウンロードしてall.bash
(Unix系)やall.bat
(Windows)を実行すると、このcmd/dist
が起動され、Go環境の構築が行われます。
クロスコンパイル
クロスコンパイルとは、あるプラットフォーム(ホスト環境)上で、それとは異なるプラットフォーム(ターゲット環境)向けの実行ファイルを生成することです。Go言語は、環境変数GOOS
とGOARCH
を設定することで、簡単にクロスコンパイルを行うことができます。
GOOS
: ビルド対象のオペレーティングシステム(例:linux
,windows
,darwin
)GOARCH
: ビルド対象のCPUアーキテクチャ(例:amd64
,arm
,arm64
)gohostos
/gohostarch
:cmd/dist
内部で使われる変数で、ビルドを実行しているホスト環境のOSとアーキテクチャを指します。
cmd/5g
Go言語の初期のコンパイラは、ターゲットアーキテクチャごとに異なる名前を持っていました。
8g
: x86 (32-bit)6g
: x86-64 (64-bit)5g
: ARM9g
: PowerPC
これらのコンパイラは、Go言語自体がまだ成熟していなかった初期の段階で、C言語で書かれていました。現在では、Go言語のコンパイラはGo言語自体で書かれており、go build
コマンドが内部的に適切なコンパイラを呼び出すため、これらの名前を直接意識することは少なくなりました。しかし、このコミットが作成された2012年当時は、これらのコンパイラがGoのビルドシステムにおいて重要な役割を担っていました。
isgo
変数
このコミットで追加されたisgo
変数は、ビルド対象のモジュールがGo言語で書かれているかどうかを示すフラグです。cmd/dist
は、Go言語で書かれたモジュールとC言語で書かれたモジュール(例えば、初期のコンパイラやランタイムの一部)を異なる方法で扱います。
技術的詳細
このコミットの核心は、src/cmd/dist/build.c
ファイル内のinstall
関数の条件分岐の変更です。
変更前のコードは以下のようになっていました。
if(!streq(goos, gohostos) || !streq(goarch, gohostarch)) {
// We've generated the right files; the go command can do the build.
if(vflag > 1)
xprintf("skip build for cross-compile %s\\n", dir);
}
この条件は、「ターゲットOSがホストOSと異なる」または「ターゲットアーキテクチャがホストアーキテクチャと異なる」場合に真となり、その後のビルド処理をスキップしていました。これは、Go言語で書かれたプログラムのクロスコンパイルにおいては正しい挙動です。なぜなら、Go言語のクロスコンパイルでは、ソースコードから直接ターゲット環境向けのバイナリが生成されるため、ホスト環境でビルドを「実行」する必要がないからです。
しかし、cmd/5g
のようなC言語で書かれたコンパイラの場合、このロジックは問題を引き起こしました。例えば、amd64
のLinux上でarm
向けのcmd/5g
をビルドしようとすると、goarch
(arm
) とgohostarch
(amd64
) が異なるため、上記の条件が真となり、cmd/5g
のビルドがスキップされてしまっていました。しかし、cmd/5g
はC言語で書かれているため、Goのクロスコンパイルのロジックとは独立して、Cコンパイラによってビルドされる必要があります。
この問題を解決するため、コミットでは条件に&& isgo
が追加されました。
if((!streq(goos, gohostos) || !streq(goarch, gohostarch)) && isgo) {
// We've generated the right files; the go command can do the build.
if(vflag > 1)
xprintf("skip build for cross-compile %s\\n", dir);
}
これにより、ビルドスキップの条件は「ターゲットOS/アーキテクチャがホストOS/アーキテクチャと異なり、かつビルド対象がGo言語で書かれている場合」に限定されるようになりました。cmd/5g
はGo言語で書かれていないため、isgo
が偽となり、この条件全体が偽となるため、ビルドがスキップされずに正しく実行されるようになります。
コアとなるコードの変更箇所
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -808,7 +808,7 @@ install(char *dir)
vuniq(&files);
}
- if(!streq(goos, gohostos) || !streq(goarch, gohostarch)) {
+ if((!streq(goos, gohostos) || !streq(goarch, gohostarch)) && isgo) {
// We've generated the right files; the go command can do the build.
if(vflag > 1)
xprintf("skip build for cross-compile %s\\n", dir);
コアとなるコードの解説
変更された行は、src/cmd/dist/build.c
ファイルのinstall
関数内のif
文です。
-
変更前:
if(!streq(goos, gohostos) || !streq(goarch, gohostarch)) {
この条件は、ターゲットOSまたはターゲットアーキテクチャがホストOSまたはホストアーキテクチャと異なる場合に真となります。これは、クロスコンパイルの一般的な検出ロジックです。
-
変更後:
if((!streq(goos, gohostos) || !streq(goarch, gohostarch)) && isgo) {
変更点として、既存の条件全体が括弧で囲まれ、その後に
&& isgo
が追加されています。isgo
は、現在処理しているモジュールがGo言語で書かれている場合に真となるフラグです。- この変更により、ビルドスキップの条件は「クロスコンパイルである」かつ「ビルド対象がGo言語で書かれている」という両方の条件が満たされた場合にのみ適用されるようになりました。
この修正によって、cmd/5g
のようなC言語で書かれたツールは、たとえクロスコンパイル環境下であっても、isgo
が偽であるためビルドスキップの対象から外れ、正しくビルドおよびインストールされるようになります。これにより、Goツールチェインのビルドプロセスがより堅牢になりました。
関連リンク
- Go Code Review:
https://golang.org/cl/5689072
参考にした情報源リンク
- Go言語のクロスコンパイルに関する一般的な情報
- Go言語の初期のコンパイラ(5g, 6g, 8gなど)に関する情報
cmd/dist
の役割に関する情報streq
関数はC言語の文字列比較関数strcmp
に相当するもので、!streq(a, b)
はstrcmp(a, b) != 0
と同じ意味です。
[インデックス 12150] ファイルの概要
このコミットは、Go言語のビルドシステムにおけるクロスコンパイル時の不具合を修正するものです。具体的には、cmd/dist
ツールが非ARMシステム上でcmd/5g
をインストールする際の挙動を修正し、誤ったビルドスキップを防ぎます。
コミット
commit 37decab5a31f6418ae52d4548d06b2022d99c72f
Author: Russ Cox <rsc@golang.org>
Date: Wed Feb 22 16:29:05 2012 -0500
cmd/dist: fix install cmd/5g on non-arm system
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5689072
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/37decab5a31f6418ae52d4548d06b2022d99c72f
元コミット内容
cmd/dist: fix install cmd/5g on non-arm system
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5689072
変更の背景
このコミットは、Go言語のビルドシステムであるcmd/dist
が、特定の条件下でクロスコンパイルされたバイナリ(特にcmd/5g
)のインストールを誤ってスキップしてしまうバグを修正するために行われました。
Go言語は、異なるオペレーティングシステム(OS)やアーキテクチャ(CPU)向けにバイナリを生成する「クロスコンパイル」機能を強力にサポートしています。この機能は、例えばLinux上でWindows向けの実行ファイルをビルドする際などに非常に便利です。
cmd/dist
はGoのソースコードからツールチェイン全体をビルド・インストールする役割を担っています。このツールは、ビルド対象のOS (goos
) とアーキテクチャ (goarch
) が、ホスト環境のOS (gohostos
) とアーキテクチャ (gohostarch
) と異なる場合に、クロスコンパイルと判断します。
問題は、cmd/5g
のような特定のコンパイラ(5g
はARMアーキテクチャ向けのGoコンパイラを指します)を非ARMシステム上でビルド・インストールしようとした際に発生しました。以前のコードでは、goos != gohostos
または goarch != gohostarch
の条件が真であれば、無条件にビルドをスキップしていました。しかし、cmd/5g
自体はGoで書かれたツールではなく、C言語で書かれたコンパイラであるため、Goのクロスコンパイルのロジックが適用されるべきではありませんでした。
この誤ったスキップにより、非ARMシステム上でGoのツールチェインをビルドする際に、cmd/5g
が正しくインストールされないという不具合が生じていました。このコミットは、このビルドスキップの条件に&& isgo
(ビルド対象がGo言語で書かれたものであるか)という条件を追加することで、この問題を解決しています。
前提知識の解説
Go言語のビルドシステム (cmd/dist
)
cmd/dist
は、Go言語のソースコードからGoのコンパイラ、リンカ、標準ライブラリ、その他のツールチェイン全体をビルドし、インストールするための内部ツールです。Goのソースコードをダウンロードしてall.bash
(Unix系)やall.bat
(Windows)を実行すると、このcmd/dist
が起動され、Go環境の構築が行われます。
クロスコンパイル
クロスコンパイルとは、あるプラットフォーム(ホスト環境)上で、それとは異なるプラットフォーム(ターゲット環境)向けの実行ファイルを生成することです。Go言語は、環境変数GOOS
とGOARCH
を設定することで、簡単にクロスコンパイルを行うことができます。
GOOS
: ビルド対象のオペレーティングシステム(例:linux
,windows
,darwin
)GOARCH
: ビルド対象のCPUアーキテクチャ(例:amd64
,arm
,arm64
)gohostos
/gohostarch
:cmd/dist
内部で使われる変数で、ビルドを実行しているホスト環境のOSとアーキテクチャを指します。
cmd/5g
Go言語の初期のコンパイラは、ターゲットアーキテクチャごとに異なる名前を持っていました。
8g
: x86 (32-bit)6g
: x86-64 (64-bit)5g
: ARM9g
: PowerPC
これらのコンパイラは、Go言語自体がまだ成熟していなかった初期の段階で、C言語で書かれていました。現在では、Go言語のコンパイラはGo言語自体で書かれており、go build
コマンドが内部的に適切なコンパイラを呼び出すため、これらの名前を直接意識することは少なくなりました。しかし、このコミットが作成された2012年当時は、これらのコンパイラがGoのビルドシステムにおいて重要な役割を担っていました。
isgo
変数
このコミットで追加されたisgo
変数は、ビルド対象のモジュールがGo言語で書かれているかどうかを示すフラグです。cmd/dist
は、Go言語で書かれたモジュールとC言語で書かれたモジュール(例えば、初期のコンパイラやランタイムの一部)を異なる方法で扱います。
技術的詳細
このコミットの核心は、src/cmd/dist/build.c
ファイル内のinstall
関数の条件分岐の変更です。
変更前のコードは以下のようになっていました。
if(!streq(goos, gohostos) || !streq(goarch, gohostarch)) {
// We've generated the right files; the go command can do the build.
if(vflag > 1)
xprintf("skip build for cross-compile %s\\n", dir);
}
この条件は、「ターゲットOSがホストOSと異なる」または「ターゲットアーキテクチャがホストアーキテクチャと異なる」場合に真となり、その後のビルド処理をスキップしていました。これは、Go言語で書かれたプログラムのクロスコンパイルにおいては正しい挙動です。なぜなら、Go言語のクロスコンパイルでは、ソースコードから直接ターゲット環境向けのバイナリが生成されるため、ホスト環境でビルドを「実行」する必要がないからです。
しかし、cmd/5g
のようなC言語で書かれたコンパイラの場合、このロジックは問題を引き起こしました。例えば、amd64
のLinux上でarm
向けのcmd/5g
をビルドしようとすると、goarch
(arm
) とgohostarch
(amd64
) が異なるため、上記の条件が真となり、cmd/5g
のビルドがスキップされてしまっていました。しかし、cmd/5g
はC言語で書かれているため、Goのクロスコンパイルのロジックとは独立して、Cコンパイラによってビルドされる必要があります。
この問題を解決するため、コミットでは条件に&& isgo
が追加されました。
if((!streq(goos, gohostos) || !streq(goarch, gohostarch)) && isgo) {
// We've generated the right files; the go command can do the build.
if(vflag > 1)
xprintf("skip build for cross-compile %s\\n", dir);
}
これにより、ビルドスキップの条件は「ターゲットOS/アーキテクチャがホストOS/アーキテクチャと異なり、かつビルド対象がGo言語で書かれている場合」に限定されるようになりました。cmd/5g
はGo言語で書かれていないため、isgo
が偽となり、この条件全体が偽となるため、ビルドがスキップされずに正しく実行されるようになります。
コアとなるコードの変更箇所
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -808,7 +808,7 @@ install(char *dir)
vuniq(&files);
}
- if(!streq(goos, gohostos) || !streq(goarch, gohostarch)) {
+ if((!streq(goos, gohostos) || !streq(goarch, gohostarch)) && isgo) {
// We've generated the right files; the go command can do the build.
if(vflag > 1)
xprintf("skip build for cross-compile %s\\n", dir);
コアとなるコードの解説
変更された行は、src/cmd/dist/build.c
ファイルのinstall
関数内のif
文です。
-
変更前:
if(!streq(goos, gohostos) || !streq(goarch, gohostarch)) {
この条件は、ターゲットOSまたはターゲットアーキテクチャがホストOSまたはホストアーキテクチャと異なる場合に真となります。これは、クロスコンパイルの一般的な検出ロジックです。
-
変更後:
if((!streq(goos, gohostos) || !streq(goarch, gohostarch)) && isgo) {
変更点として、既存の条件全体が括弧で囲まれ、その後に
&& isgo
が追加されています。isgo
は、現在処理しているモジュールがGo言語で書かれている場合に真となるフラグです。- この変更により、ビルドスキップの条件は「クロスコンパイルである」かつ「ビルド対象がGo言語で書かれている」という両方の条件が満たされた場合にのみ適用されるようになりました。
この修正によって、cmd/5g
のようなC言語で書かれたツールは、たとえクロスコンパイル環境下であっても、isgo
が偽であるためビルドスキップの対象から外れ、正しくビルドおよびインストールされるようになります。これにより、Goツールチェインのビルドプロセスがより堅牢になりました。
関連リンク
- Go Code Review:
https://golang.org/cl/5689072
参考にした情報源リンク
- Go言語のクロスコンパイルに関する一般的な情報
- Go言語の初期のコンパイラ(5g, 6g, 8gなど)に関する情報
cmd/dist
の役割に関する情報streq
関数はC言語の文字列比較関数strcmp
に相当するもので、!streq(a, b)
はstrcmp(a, b) != 0
と同じ意味です。