[インデックス 13320] ファイルの概要
このコミットは、Go言語のツールチェインにおけるクロスコンパイルの問題を修正するものです。具体的には、src/cmd/5c/list.c
、src/cmd/5g/list.c
、src/cmd/5l/list.c
の3つのC言語ソースファイルが変更されています。これらのファイルは、Goのコンパイラ(5c
)、アセンブラ(5g
)、リンカ(5l
)のバックエンドの一部であり、特にPlan 9アーキテクチャ(5シリーズプロセッサ)をターゲットとしたツールに関連しています。
コミット
cmd/5c, cmd/5g, cmd/5l: fix cross compilation failure on darwin
Fixes #3708.
The fix to allow 5{c,g,l} to compile under clang 3.1 broke cross
compilation on darwin using the Apple default compiler on 10.7.3.
This failure was introduced in 9b455eb64690.
This has been tested by cross compiling on darwin/amd64 to linux/arm using
* gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.1.00)
* clang version 3.1 (branches/release_31)
As well as on linux/arm using
* gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
* Ubuntu clang version 3.0-6ubuntu3 (tags/RELEASE_30/final) (based on LLVM 3.0)
* Debian clang version 3.1-4 (branches/release_31) (based on LLVM 3.1)
R=consalus, rsc
CC=golang-dev
https://golang.org/cl/6307058
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/072e36d5ef1d51f70b446e6f5b141595e1108ebd
元コミット内容
このコミットは、Go言語のツールチェインの一部であるcmd/5c
(コンパイラ)、cmd/5g
(アセンブラ)、cmd/5l
(リンカ)が、Darwin(macOS)環境でのクロスコンパイル時に失敗する問題を修正するものです。この問題は、以前のコミット 9b455eb64690
で導入された、Clang 3.1でのコンパイルを可能にするための変更が原因で発生しました。特に、macOS 10.7.3に搭載されているAppleのデフォルトコンパイラ(おそらくGCCのApple版または古いClang)を使用した場合に問題が顕在化しました。
この修正は、darwin/amd64
からlinux/arm
へのクロスコンパイルで、様々なGCCおよびClangのバージョン(Apple Inc. build 5658のGCC 4.2.1、Clang 3.1、Ubuntu/LinaroのGCC 4.6.3、Ubuntu Clang 3.0、Debian Clang 3.1)を用いてテストされ、問題が解決されたことが確認されています。
変更の背景
この変更の背景には、Go言語のクロスコンパイル環境におけるコンパイラの互換性の問題があります。Goは設計上、異なるアーキテクチャやOS向けにバイナリを生成するクロスコンパイルを強力にサポートしています。しかし、そのツールチェイン自体はC言語で書かれた部分も多く、それらをコンパイルする際にホスト環境のCコンパイラ(GCCやClangなど)に依存します。
以前のコミット 9b455eb64690
では、Clang 3.1という比較的新しいCコンパイラでのGoツールチェインのビルドをサポートするための修正が行われました。しかし、この修正が、macOS 10.7.3に搭載されているAppleのデフォルトコンパイラ(これは古いGCCベースであるか、あるいは特定のClangのバージョンである可能性が高い)との間で互換性の問題を引き起こしました。具体的には、ポインタの型修飾子(const
)に関する厳密さの違いが原因で、クロスコンパイル時にコンパイルエラーが発生するようになりました。
このコミットは、その回帰バグ(regression bug)を修正し、Goツールチェインがより広範なCコンパイラ環境で安定して動作するようにすることを目的としています。
前提知識の解説
-
cmd/5c
,cmd/5g
,cmd/5l
: これらはGo言語の初期のツールチェインの一部で、それぞれコンパイラ(c
)、アセンブラ(g
)、リンカ(l
)を指します。5
というプレフィックスは、Plan 9アーキテクチャにおける5シリーズプロセッサ(ARMなど)をターゲットとしていたことに由来します。現代のGoでは、これらのツールはより汎用的なcmd/compile
、cmd/asm
、cmd/link
などに統合されていますが、このコミットが作成された2012年当時はまだこれらの名称が使われていました。これらのツールは、Goのソースコードを機械語に変換し、実行可能なバイナリを生成する上で不可欠な役割を担っています。 -
クロスコンパイル (Cross-compilation): あるコンピュータシステム(ホスト)上で、別のコンピュータシステム(ターゲット)で実行可能なコードを生成するプロセスです。例えば、macOS上でLinux ARMプロセッサ向けのGoバイナリをビルドするようなケースがこれに当たります。Go言語は、その設計思想としてクロスコンパイルを非常に重視しており、
GOOS
やGOARCH
といった環境変数を設定するだけで簡単にクロスコンパイルが可能です。 -
Darwin (macOS): AppleのオペレーティングシステムであるmacOSの基盤となるUNIX系OSです。Goのツールチェインは、macOS上でも動作し、macOS向けのバイナリを生成したり、他のOS向けのクロスコンパイルのホスト環境として利用されたりします。
-
Apple default compiler (on 10.7.3): macOS 10.7.3 (Lion) 時代のAppleのデフォルトC/C++/Objective-Cコンパイラは、Xcodeにバンドルされていました。この時期は、AppleがGCCからClang/LLVMへの移行を進めていた過渡期にあたります。そのため、システムによってはGCCベースのコンパイラが使われていたり、特定のバージョンや設定のClangが使われていたりする可能性があり、コンパイラの挙動に微妙な違いが生じることがありました。
-
Clang / LLVM: ClangはC、C++、Objective-C、Objective-C++言語のコンパイラフロントエンドであり、LLVMプロジェクトの一部です。LLVMは、コンパイラのバックエンドや最適化技術を提供するフレームワークです。ClangはGCCに比べて、より厳密なコードチェックを行う傾向があり、特にポインタの型安全性や
const
修飾子の使用に関して、GCCでは警告で済まされるようなケースでもエラーとなることがあります。 -
const
キーワード (C言語): C言語におけるconst
キーワードは、変数が定数であることを宣言し、その値が変更されないことをコンパイラに伝えます。ポインタの場合、const
の位置によって「ポインタが指す値が定数である」(const char *op;
) のか、「ポインタ自体が定数である」(char *const op;
) のか、あるいはその両方なのかが変わります。このコミットでは、char *op;
をconst char *op;
に変更しており、これは「op
が指す文字データが定数である」ことを意味します。これにより、コンパイラはop
が指すデータを変更しようとするコードに対して警告またはエラーを出すようになります。
技術的詳細
このコミットの技術的な核心は、C言語におけるポインタのconst
修飾子の扱いに関するコンパイラの厳密性の違いにあります。
元のコードでは、char *op;
と宣言されていました。これは、op
がchar
型へのポインタであり、そのポインタが指すchar
型の値は変更可能であることを意味します。しかし、実際の使用箇所では、op
が指す文字列は変更されない(読み取り専用として扱われる)にもかかわらず、const
修飾子が付与されていませんでした。
Clangのようなより新しい、またはより厳密なCコンパイラは、このような「const
ではないポインタが、実際にはconst
なデータ(例えば文字列リテラルなど)を指す可能性がある」という状況を、型安全性の観点から問題視することがあります。特に、関数呼び出しの引数として渡される際に、期待される型と実際の型がconst
の有無で異なる場合、コンパイラは型ミスマッチとしてエラーを出すことがあります。
このコミットでchar *op;
をconst char *op;
に変更したことにより、op
が指すデータが変更されないことを明示的にコンパイラに伝えました。これにより、Appleのデフォルトコンパイラ(おそらく古いGCCまたは特定のClangバージョン)が、以前のコミットで導入された変更(Clang 3.1でのコンパイルを可能にするための変更)と組み合わさった際に発生していた型ミスマッチのエラーが解消されました。
これは、C言語のコードベースを複数の異なるコンパイラ(特にバージョンやベンダーが異なるもの)でビルドする際に頻繁に遭遇する問題です。コンパイラはC標準に準拠していますが、警告レベルや特定のケースでのエラーの厳密さには差異があります。この修正は、GoツールチェインのC言語部分が、より広範なコンパイラ環境で堅牢に動作するための「const
安全性」を向上させるものです。
コアとなるコードの変更箇所
変更は、以下の3つのファイルの同じ行にわたって行われています。
diff --git a/src/cmd/5c/list.c b/src/cmd/5c/list.c
index 86a31ae7a9..30b88400fe 100644
--- a/src/cmd/5c/list.c
+++ b/src/cmd/5c/list.c
@@ -140,7 +140,7 @@ Dconv(Fmt *fp)
{
char str[STRINGSZ];
Adr *a;
- char *op;
+ const char *op;
int v;
a = va_arg(fp->args, Adr*);
diff --git a/src/cmd/5g/list.c b/src/cmd/5g/list.c
index 13e187145c..2596936956 100644
--- a/src/cmd/5g/list.c
+++ b/src/cmd/5g/list.c
@@ -83,7 +83,7 @@ int
Dconv(Fmt *fp)
{
char str[STRINGSZ];
- char *op;
+ const char *op;
Addr *a;
int i;
int32 v;
diff --git a/src/cmd/5l/list.c b/src/cmd/5l/list.c
index 2fd69edeb8..d05ec3b95d 100644
--- a/src/cmd/5l/list.c
+++ b/src/cmd/5l/list.c
@@ -161,7 +161,7 @@ int
Dconv(Fmt *fp)
{
char str[STRINGSZ];
- char *op;
+ const char *op;
Adr *a;
int32 v;
各ファイルで、char *op;
という変数の宣言が const char *op;
に変更されています。
コアとなるコードの解説
この変更は非常にシンプルですが、C言語の型システムとコンパイラの挙動において重要な意味を持ちます。
-
変更前:
char *op;
- これは「
op
はchar
へのポインタであり、op
が指すchar
型の値は変更可能である」と宣言しています。 - もし
op
が文字列リテラル(例:"hello"
)のような読み取り専用のメモリ領域を指していた場合、その文字列を変更しようとすると未定義動作を引き起こす可能性があります。また、厳密なコンパイラは、const char *
を期待する関数にchar *
を渡す際に警告やエラーを出すことがあります。
- これは「
-
変更後:
const char *op;
- これは「
op
はchar
へのポインタであり、op
が指すchar
型の値は変更不可能である(定数である)」と宣言しています。 - これにより、コンパイラは
op
が指すメモリ領域が読み取り専用であることを認識し、その領域を変更しようとするコードに対してコンパイルエラーを発生させることができます。 - この修正は、
op
が実際に指すデータが変更されないというコードの意図を明確にし、コンパイラがより正確な型チェックを行えるようにします。特に、Appleのデフォルトコンパイラが、以前のClang 3.1対応の変更によって厳密になった型チェックに引っかかっていた問題を解決しました。
- これは「
この修正は、コードの意図を明確にし、異なるコンパイラ間での互換性を高めるための「const
安全性」のベストプラクティスに従ったものです。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/072e36d5ef1d51f70b446e6f5b141595e1108ebd
- Go Issue #3708: https://golang.org/issue/3708 (このコミットが修正した問題)
- Go CL 6307058: https://golang.org/cl/6307058 (この変更のコードレビューリンク)
- 以前のコミット 9b455eb64690: https://github.com/golang/go/commit/9b455eb64690 (問題を引き起こしたコミット)
参考にした情報源リンク
- Go Issue Tracker (golang.org/issue)
- Go Code Review (golang.org/cl)
- C言語の
const
キーワードに関する一般的なドキュメント (例: C言語の教科書、オンラインリファレンス) - ClangとGCCのコンパイラの挙動に関する情報 (例: 各コンパイラのドキュメント、Stack Overflowなどの開発者コミュニティ)
- macOSのXcodeおよびコンパイラ環境の歴史に関する情報