[インデックス 16185] ファイルの概要
このコミットは、Go言語のビルドプロセスにおいて、macOS (Darwin) 上でGCCコンパイラを使用する際に、-mmacosx-version-min=10.6
フラグを渡すように変更を加えるものです。これにより、macOSの古いバージョンとの互換性を確保し、特定の環境で発生していた「Illegal Instruction」エラーを修正します。
コミット
- コミットハッシュ:
a5fe79ef787ab6b9048368648736ca66f3622f5b
- 作者: Shenghou Ma minux.ma@gmail.com
- コミット日時: 2013年4月16日 火曜日 13:30:52 -0700
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/a5fe79ef787ab6b9048368648736ca66f3622f5b
元コミット内容
cmd/dist, make.bash: pass -mmacosx-version-min=10.6 to gcc on Darwin
Fixes #5261.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/8798044
変更の背景
この変更は、GoプログラムがmacOS上で「Illegal Instruction」エラーを発生させる問題(Issue #5261)を解決するために行われました。このエラーは、特に古いバージョンのmacOS(例: OS X 10.6 Snow Leopard)でGoのバイナリを実行しようとした際に顕著でした。
「Illegal Instruction」エラーは、プログラムがCPUが理解できない、または現在のCPUの命令セットではサポートされていない命令を実行しようとしたときに発生します。これは通常、新しいバージョンのコンパイラが、ターゲットとするOSの最小バージョンを考慮せずに、より新しいCPU命令(例えば、SSE4.2やAVXなどの拡張命令セット)を使用するバイナリを生成してしまう場合に起こります。
Goのビルドシステムは、クロスコンパイルやブートストラップの過程でGCC(またはClang)を使用します。この際、macOS環境では、コンパイラがデフォルトでターゲットとするmacOSのバージョンが、実際に実行される環境よりも新しい命令セットを要求する可能性がありました。その結果、古いmacOS環境で実行すると、サポートされていない命令に遭遇し、「Illegal Instruction」エラーでクラッシュするという問題が発生していました。
前提知識の解説
gcc
on Darwin (macOS): macOSでは、Apple ClangがデフォルトのC/C++/Objective-Cコンパイラとして提供されていますが、GCCも利用可能です。Goのビルドプロセスでは、Cgoやランタイムの一部をコンパイルするためにCコンパイラ(通常はGCC互換のコンパイラ)を使用します。-mmacosx-version-min
フラグ: これはGCCやClangなどのコンパイラに渡されるオプションで、生成されるバイナリが動作するmacOSの最小バージョンを指定します。このフラグを使用することで、コンパイラは指定された最小バージョンで利用可能な命令セットのみを使用するように制限され、それより新しい命令セットに依存するコードの生成を避けます。例えば、-mmacosx-version-min=10.6
は、生成されるバイナリがmacOS 10.6 (Snow Leopard) 以降で動作することを保証します。これにより、古いmacOS環境での互換性が向上します。- Goのビルドプロセス (
cmd/dist
,make.bash
):make.bash
: GoのソースコードからGoツールチェイン全体をビルドするための主要なシェルスクリプトです。Goのブートストラッププロセス(Go自身をGoでビルドする)の最初のステップとして、C言語で書かれたcmd/dist
ツールをコンパイルするために使用されます。cmd/dist
: Goのディストリビューションを構築するためのコマンドラインツールです。Goの標準ライブラリやツールをコンパイルする際に、内部的にCコンパイラ(GCCなど)を呼び出します。
Illegal Instruction
エラー: CPUが認識できない、または現在のCPUのモードや権限では実行できない命令に遭遇したときに発生する実行時エラーです。ソフトウェアが、実行環境のCPUがサポートしていない命令セット(例: 特定のSIMD命令)を使用しようとした場合に頻繁に見られます。dlsym
: Unix系システムにおける動的リンキングライブラリ(dlfcn.h
)の一部で、実行時に共有ライブラリからシンボル(関数や変数)のアドレスを取得するために使用される関数です。Issue #5261の報告では、dlsym
が期待されるシンボルを見つけられないという記述があり、これはコンパイルされたバイナリが特定の環境で動的にロードされるライブラリとの互換性問題を示唆している可能性があります。
技術的詳細
このコミットは、GoのビルドシステムがmacOS上でCコンパイラ(GCCまたはClang)を呼び出す際に、明示的に -mmacosx-version-min=10.6
フラグを追加することで、この問題を解決します。
具体的には、以下の2つのファイルが変更されています。
-
src/cmd/dist/build.c
:cmd/dist
はGoのビルドプロセスの中核をなすツールであり、Goの標準ライブラリやツール群をコンパイルする際にCコンパイラを呼び出します。このファイルにフラグを追加することで、dist
がGoのコンポーネントをビルドする際に使用するCコンパイラが、macOS 10.6以降との互換性を持つバイナリを生成するようになります。これにより、GoのランタイムやCgoでリンクされる部分が、古いmacOS環境でも正しく動作するようになります。 -
src/make.bash
:make.bash
はGoのブートストラップビルドの最初の段階で、cmd/dist
自体をコンパイルするために使用されます。このスクリプトにも同じフラグを追加することで、cmd/dist
ツール自体がmacOS 10.6以降との互換性を持ってコンパイルされるようになります。これは、dist
ツールが正しく動作するための基盤を確保する上で重要です。
この変更により、Goのバイナリは、macOS 10.6で利用可能な命令セットのみを使用するようにコンパイルされるため、それより古いmacOSバージョンで実行された場合に発生する「Illegal Instruction」エラーが回避されます。これは、Goがより広範なmacOS環境で安定して動作するための重要な互換性修正です。
コアとなるコードの変更箇所
src/cmd/dist/build.c
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -622,6 +622,10 @@ install(char *dir)
// clang is too smart about unused command-line arguments
vadd(&gccargs, "-Qunused-arguments");
}
+ if(streq(gohostos, "darwin")) {
+ // golang.org/issue/5261
+ vadd(&gccargs, "-mmacosx-version-min=10.6");
+ }
}
islib = hasprefix(dir, "lib") || streq(dir, "cmd/cc") || streq(dir, "cmd/gc");
src/make.bash
--- a/src/make.bash
+++ b/src/make.bash
@@ -111,6 +111,10 @@ case "$GOHOSTARCH" in
386) mflag=-m32;;
amd64) mflag=-m64;;
esac
+if [ "$(uname)" == "Darwin" ]; then
+ # golang.org/issue/5261
+ mflag="$mflag -mmacosx-version-min=10.6"
+fi
${CC:-gcc} $mflag -O2 -Wall -Werror -o cmd/dist/dist -Icmd/dist "$DEFGOROOT" cmd/dist/*.c
eval $(./cmd/dist/dist env -p)
コアとなるコードの解説
src/cmd/dist/build.c
の変更
install
関数内で、gohostos
が "darwin" (macOS) である場合に、gccargs
(GCCに渡す引数のリスト) に "-mmacosx-version-min=10.6"
を追加しています。
これは、Goのビルドプロセス中にcmd/dist
がCコンパイラを呼び出す際に、生成されるバイナリがmacOS 10.6以降で動作するように、コンパイラに明示的に指示するためのものです。これにより、GoのランタイムやCgoで利用されるCコードが、古いmacOS環境でも互換性のある命令セットでコンパイルされることが保証されます。
src/make.bash
の変更
make.bash
スクリプト内で、uname
コマンドの出力が "Darwin" (macOS) であることを確認し、mflag
変数に "-mmacosx-version-min=10.6"
を追加しています。
mflag
は、make.bash
が cmd/dist/dist
ツール自体をコンパイルするために gcc
を呼び出す際に使用されるフラグです。この変更により、Goのブートストラッププロセスで最初にコンパイルされるdist
ツール自体が、macOS 10.6以降との互換性を持ってビルドされるようになります。これは、Goのビルドシステム全体の安定性と互換性を確保するために重要です。
両方の変更箇所で、コメントとして // golang.org/issue/5261
または # golang.org/issue/5261
が追加されており、この変更が特定のGitHub Issueに対応するものであることを示しています。
関連リンク
- GitHub Issue #5261: https://github.com/golang/go/issues/5261
- Go CL (Change List) 8798044: https://golang.org/cl/8798044