[インデックス 11706] ファイルの概要
このコミットは、Go言語のツールチェインの一部である cmd/dist
ディレクトリ内の build.c
ファイルに対する変更です。cmd/dist
は、Goのソースコードからブートストラップツールや標準ライブラリをビルドするためのユーティリティ群を含むディレクトリです。build.c
は、そのビルドプロセスにおいてC言語で書かれたコンポーネント(例えば、Goのランタイムの一部やツール)をコンパイルおよびリンクするロジックを担っています。具体的には、gcc
などのCコンパイラを呼び出す際の引数管理を行っています。
コミット
commit 136f12f51fde69d5b0c89ec7a9cd9436c7b7535d
Author: Russ Cox <rsc@golang.org>
Date: Wed Feb 8 11:12:14 2012 -0500
cmd/dist: pass -m32 or -m64 to link too, not just compile
R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/5646053
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/136f12f51fde69d5b0c89ec7a9cd9436c7b7535d
元コミット内容
cmd/dist
: コンパイル時だけでなく、リンク時にも -m32
または -m64
フラグを渡すように変更。
変更の背景
このコミットの背景には、Go言語のビルドシステムがC言語で書かれたコンポーネント(特にブートストラップツールやランタイムの一部)をコンパイルおよびリンクする際の、アーキテクチャ指定フラグの扱いに問題があったことが挙げられます。
Goのビルドプロセスでは、異なるターゲットアーキテクチャ(例: 32ビットまたは64ビット)向けにバイナリを生成する必要があります。これには、Cコンパイラ(通常はGCC)に対して適切なフラグ(-m32
または -m64
)を渡すことが不可欠です。
以前の実装では、これらのアーキテクチャ指定フラグがコンパイルステップ(.o
ファイルを生成する段階)には渡されていましたが、リンクステップ(実行可能ファイルを生成する段階)には適切に渡されていませんでした。これにより、特定の環境やクロスコンパイルのシナリオにおいて、コンパイルされたオブジェクトファイルとリンカが期待するアーキテクチャが一致せず、リンクエラーが発生する可能性がありました。
この変更は、コンパイルとリンクの両方で一貫してアーキテクチャ指定フラグが適用されるようにすることで、ビルドの堅牢性と正確性を向上させることを目的としています。
前提知識の解説
cmd/dist
cmd/dist
は、Go言語のソースコードからGoツールチェイン自体をビルドするためのブートストラップツールです。GoはGo自身で書かれていますが、最初のコンパイラをビルドするためには既存のCコンパイラ(GCCなど)が必要です。cmd/dist
はこの初期ビルドプロセスを管理し、Goのコンパイラ、リンカ、標準ライブラリなどを構築します。
GCC (GNU Compiler Collection)
GCCは、C、C++、Goなど様々なプログラミング言語に対応したコンパイラ群です。Goのビルドプロセスでは、特に初期のブートストラップ段階や、C言語で書かれたGoランタイムの一部をコンパイル・リンクするためにGCCが利用されます。
-m32
および -m64
フラグ
これらはGCCのコンパイラおよびリンカオプションで、生成するバイナリのターゲットアーキテクチャを指定します。
-m32
: 32ビットアーキテクチャ(例: x86)向けのコードを生成するよう指示します。-m64
: 64ビットアーキテクチャ(例: x86-64/amd64)向けのコードを生成するよう指示します。 これらのフラグは、コンパイル時(ソースコードをオブジェクトファイルに変換する際)とリンク時(オブジェクトファイルを結合して実行可能ファイルを生成する際)の両方で、一貫して適用される必要があります。
コンパイルとリンク
ソフトウェアのビルドプロセスは、大きく分けて「コンパイル」と「リンク」の2つのフェーズに分かれます。
- コンパイル: ソースコード(例:
.c
ファイル)を機械語のオブジェクトファイル(例:.o
ファイル)に変換するプロセスです。この段階で、ソースコードの文法チェックや最適化が行われます。 - リンク: 複数のオブジェクトファイルやライブラリを結合し、最終的な実行可能ファイルや共有ライブラリを生成するプロセスです。この段階で、関数呼び出しのアドレス解決などが行われます。
go_bootstrap
Goのブートストラッププロセスで生成される初期のGoコンパイラやツールを指します。これは、最終的なGoツールチェインをビルドするために使用されます。
技術的詳細
src/cmd/dist/build.c
は、GoのビルドシステムがC言語で書かれたコンポーネントを処理する際の中心的なロジックを含んでいます。このファイル内の install
関数は、特定のターゲット(C言語のツールやライブラリ)をビルドする責任を負っています。
ビルドプロセスでは、gcc
コマンドが複数回呼び出されます。
- コンパイル時: Cソースファイルをオブジェクトファイル(
.o
)にコンパイルするためにgcc -c ...
が実行されます。 - リンク時: 生成されたオブジェクトファイルを結合し、最終的な実行可能ファイル(例:
go_bootstrap
やその他のC言語ツール)を生成するためにgcc -o ...
が実行されます。
問題は、gccargs
という変数に格納されているコンパイラオプションが、コンパイル時には適切に適用されていたものの、リンク時には一部が欠落していた点にありました。特に、アーキテクチャ指定フラグである -m32
や -m64
は、コンパイル時には compile
ベクタに追加されていましたが、リンク時には link
ベクタに明示的に追加されていませんでした。
このコミットは、リンク時にも gohostarch
(ホストアーキテクチャ)に基づいて適切な -m32
または -m64
フラグを link
ベクタに追加することで、この不整合を解消しています。また、gccargs
から -c
フラグを削除し、コンパイル時にのみ明示的に追加するように変更することで、gccargs
がコンパイルとリンクの両方に共通して適用されるべきオプションのみを含むように整理しています。
コアとなるコードの変更箇所
src/cmd/dist/build.c
ファイルにおいて、以下の変更が行われました。
-
proto_gccargs
配列から-c
フラグが削除されました。--- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -348,7 +348,6 @@ static char *proto_gccargs[] = { "-fno-common", "-ggdb", "-O2", - "-c", };
-
install
関数内のCコマンドのリンク処理において、gccargs
の内容をコピーし、さらにgohostarch
に基づいて-m32
または-m64
フラグが追加されるようになりました。--- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -561,9 +560,16 @@ install(char *dir)\ vadd(&link, bpathf(&b, "%s/bin/tool/go_bootstrap%s", goroot, exe));\ } else {\ // C command.\ - vadd(&link, "gcc");\ + // Use gccargs, but ensure that link.p[2] is output file,\ + // as noted above.\ + vadd(&link, gccargs.p[0]);\ vadd(&link, "-o");\ vadd(&link, bpathf(&b, "%s/bin/tool/%s%s", goroot, name, exe));\ + vcopy(&link, gccargs.p+1, gccargs.len-1);\ + if(streq(gohostarch, "amd64"))\ + vadd(&link, "-m64");\ + else if(streq(gohostarch, "386"))\ + vadd(&link, "-m32");\ }\ tttarg = mtime(link.p[2]);\
-
install
関数内のCライブラリまたはツールのコンパイル処理において、compile
ベクタにgccargs
をコピーした後、明示的に-c
フラグが追加されるようになりました。--- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -750,6 +756,7 @@ install(char *dir)\ if(!isgo) {\ // C library or tool.\ vcopy(&compile, gccargs.p, gccargs.len);\ + vadd(&compile, "-c");\ if(streq(gohostarch, "amd64"))\ vadd(&compile, "-m64");\ else if(streq(gohostarch, "386"))\
コアとなるコードの解説
proto_gccargs
から -c
の削除
proto_gccargs
は、GCCに渡されるデフォルトの引数を定義しています。以前はここに -c
(コンパイルのみを行うフラグ) が含まれていました。しかし、-c
はコンパイル時にのみ必要なフラグであり、リンク時には不要です。この変更により、gccargs
(最終的に proto_gccargs
から初期化される) は、コンパイルとリンクの両方に共通して適用されるべきオプションのみを含むように整理されました。これにより、gccargs
をリンクコマンドにコピーする際に、不要な -c
フラグが渡されるのを防ぎます。
Cコマンドのリンク処理の変更
} else {
// C command.
// Use gccargs, but ensure that link.p[2] is output file,
// as noted above.
vadd(&link, gccargs.p[0]); // gccコマンド自体を追加
vadd(&link, "-o"); // 出力ファイル指定フラグ
vadd(&link, bpathf(&b, "%s/bin/tool/%s%s", goroot, name, exe)); // 出力ファイルパス
vcopy(&link, gccargs.p+1, gccargs.len-1); // gccargsの残りのオプションをコピー
if(streq(gohostarch, "amd64"))
vadd(&link, "-m64"); // amd64の場合、-m64を追加
else if(streq(gohostarch, "386"))
vadd(&link, "-m32"); // 386の場合、-m32を追加
}
このブロックは、C言語で書かれたツール(例: go_bootstrap
以外のCコマンド)をリンクする際のロジックです。
- 以前は単に
vadd(&link, "gcc");
となっていましたが、gccargs.p[0]
を使用することで、gccargs
に設定されたコンパイラパス(例えば、特定のバージョンのGCCへのパス)を確実に使用するように変更されました。 vcopy(&link, gccargs.p+1, gccargs.len-1);
は、gccargs
に含まれる-fno-common
,-ggdb
,-O2
などの共通オプションをリンクコマンドにコピーします。これにより、コンパイル時とリンク時で一貫した最適化レベルやデバッグ情報が適用されるようになります。- 最も重要な変更は、
gohostarch
(ビルドを実行しているホストのアーキテクチャ)に基づいて、-m64
または-m32
フラグが明示的にlink
ベクタに追加されるようになった点です。これにより、リンクされるオブジェクトファイルとリンカが期待するアーキテクチャが確実に一致し、クロスコンパイルや特定の環境でのビルドエラーが解消されます。
Cライブラリまたはツールのコンパイル処理の変更
if(!isgo) {
// C library or tool.
vcopy(&compile, gccargs.p, gccargs.len); // gccargsの全オプションをコピー
vadd(&compile, "-c"); // コンパイル時のみ-cを追加
if(streq(gohostarch, "amd64"))
vadd(&compile, "-m64");
else if(streq(gohostarch, "386"))
vadd(&compile, "-m32");
}
このブロックは、C言語で書かれたライブラリやツールをコンパイルする際のロジックです。
vcopy(&compile, gccargs.p, gccargs.len);
は、gccargs
に含まれる共通オプションをコンパイルコマンドにコピーします。vadd(&compile, "-c");
は、proto_gccargs
から削除された-c
フラグを、コンパイル時(オブジェクトファイルを生成する際)にのみ明示的に追加するように変更されました。これにより、-c
フラグが適切なフェーズでのみ適用されることが保証されます。- コンパイル時にも
gohostarch
に基づいて-m64
または-m32
フラグが追加されるロジックは以前から存在していましたが、このコミットで-c
フラグの追加位置が調整されたことで、より論理的なコードフローになりました。
これらの変更により、GoのブートストラップビルドプロセスにおけるC言語コンポーネントのコンパイルとリンクが、ターゲットアーキテクチャに対してより堅牢かつ正確に行われるようになりました。
関連リンク
- Go CL (Change List): https://golang.org/cl/5646053
参考にした情報源リンク
- Go言語のソースコード (特に
src/cmd/dist/build.c
の変更前後の比較) - GCCのドキュメント (
-m32
,-m64
,-c
フラグに関する情報) - コンパイルとリンクの一般的な概念に関する知識
- Go言語のブートストラッププロセスに関する一般的な知識
- Gitのコミットと差分表示の理解