[インデックス 15285] ファイルの概要
このコミットは、Go言語のビルドシステムにおいて、Cコンパイラとしてclang
のサポートを導入し、既存のgcc
との互換性を維持しながら、ビルドプロセスをより柔軟にすることを目指しています。特に、cgo
(GoとCの相互運用機能)のビルドにおいてclang
が適切に動作するように、様々な調整が行われています。
コミット
commit 6d888f1e1b81bd2545e5da710d37a5a0ddce71d5
Author: Russ Cox <rsc@golang.org>
Date: Fri Feb 15 13:37:43 2013 -0800
build: clang support
This works with at least one version of clang
that existed at one moment in time.
No guarantees about clangs past or future.
To try:
CC=clang all.bash
It does not work with the Xcode clang,
because that clang fails at printing a useful answer
to:
clang -print-libgcc-file-name
The clang that works prints a full path name for
that command, not just "libgcc.a".
Fixes #4713.
R=iant, minux.ma
CC=golang-dev
https://golang.org/cl/7323068
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/6d888f1e1b81bd2545e5da710d37a5a0ddce71d5
元コミット内容
Goのビルドシステムにclang
コンパイラのサポートを追加します。この変更は、特定のバージョンのclang
で動作することが確認されていますが、将来のバージョンや過去のバージョンでの動作は保証されません。
clang
を試すには、CC=clang all.bash
を実行します。
Xcodeに付属するclang
では動作しません。これは、Xcodeのclang
がclang -print-libgcc-file-name
コマンドに対して有用な回答(完全なパス名)を返さず、単に"libgcc.a"とだけ返すためです。動作するclang
は、このコマンドに対して完全なパス名を返します。
このコミットは、Issue #4713を修正します。
変更の背景
このコミットの主な背景は、Goのビルドプロセス、特にcgo
を使用する際に、gcc
だけでなくclang
もCコンパイラとして利用できるようにすることです。これにより、ユーザーはより多様な開発環境でGoをビルドできるようになります。
コミットメッセージに記載されているように、特定のclang
バージョンでの動作が確認されており、Xcodeのclang
との互換性の問題も指摘されています。これは、clang
のバージョンや配布元によって挙動が異なる場合があるため、Goのビルドシステムがそれらの差異に対応する必要があったことを示唆しています。
また、Issue #4713の修正とあることから、既存のビルドシステムがclang
で問題を起こしていたか、あるいはclang
サポートが求められていたことが伺えます。
前提知識の解説
- Go言語のビルドシステム: Go言語は、独自のビルドツール(
go build
など)を持っており、ソースコードをコンパイルして実行可能ファイルを生成します。C言語のコードと連携するcgo
を使用する場合、Goのビルドツールは外部のCコンパイラ(通常はgcc
)を呼び出します。 cgo
: Go言語とC言語のコードを相互に呼び出すためのメカニズムです。cgo
を使用すると、Goプログラム内でCのライブラリを利用したり、CのコードからGoの関数を呼び出したりできます。cgo
は、Goのソースコード内の特別なコメント(import "C"
)を解析し、Cコンパイラを呼び出してCコードをコンパイルし、Goのコードとリンクします。gcc
(GNU Compiler Collection): 広く使われているオープンソースのコンパイラコレクションで、C、C++、Objective-C、Fortran、Ada、Goなどの多くのプログラミング言語をサポートしています。Linux環境ではデファクトスタンダードのCコンパイラです。clang
: LLVMプロジェクトの一部として開発されているC、C++、Objective-C、Objective-C++コンパイラです。gcc
に比べてコンパイル速度が速い、エラーメッセージが分かりやすいなどの特徴があり、macOSのXcodeなど、多くの環境で採用されています。- 環境変数
CC
: 多くのUnix系システムやビルドシステムで、Cコンパイラを指定するために使用される環境変数です。例えば、CC=clang
と設定すると、ビルドプロセスはデフォルトのgcc
ではなくclang
を使用しようとします。 all.bash
/make.bash
/run.bash
: Goのソースコードリポジトリに含まれるシェルスクリプトで、Goのツールチェイン全体をビルドしたり、テストを実行したりするために使用されます。これらはGoのビルドシステムの低レベルな部分を制御します。gccgo
: GCCのフロントエンドとして実装されたGoコンパイラです。Goの標準コンパイラ(gc
)とは異なる実装であり、GCCの最適化やバックエンドを利用できます。このコミットでは、gccgcToolchain
という内部的な名称がgccgoToolchain
に統一されています。- リンカフラグ (
-Wl,-(
と-Wl,-)
):gcc
やclang
などのコンパイラがリンカに渡すオプションの一部です。これらのフラグは、リンカに対して特定のライブラリグループを囲むように指示し、循環参照を持つライブラリが正しくリンクされるようにするために使用されます。
技術的詳細
このコミットは、Goのビルドシステムがclang
をCコンパイラとして認識し、適切に利用できるようにするための複数の変更を含んでいます。
-
Cコンパイラの選択の柔軟性向上:
src/cmd/cgo/gcc.go
内のgccName()
関数が変更され、環境変数CC
が優先的にCコンパイラとして使用されるようになりました。これにより、ユーザーはCC=clang
のように設定することで、ビルド時にclang
を選択できるようになります。misc/cgo/testso/test.bash
やsrc/make.bash
などのシェルスクリプトも、ハードコードされたgcc
の代わりに$(go env CC)
や${CC:-gcc}
を使用するように変更され、CC
環境変数の利用がビルドシステム全体にわたって適用されるようになりました。
-
clang
固有のコンパイラフラグとエラーハンドリング:src/cmd/cgo/gcc.go
では、clang
が使用されている場合に-ferror-limit=0
(エラー数の制限なし)と-Wno-unneeded-internal-declaration
(不要な内部宣言に関する警告を抑制)というフラグが追加されるようになりました。これは、clang
がgcc
とは異なる警告やエラーを出す可能性があり、それらに対応するためのものです。cgo
がCコードをスニッフィング(型推論)する際のエラーメッセージの解析ロジックが拡張され、clang
が生成する可能性のある異なるエラーメッセージ(例:declaration does not declare anything
,unexpected type name
)にも対応できるようになりました。
-
デバッグ情報の生成方法の調整:
src/cmd/dist/build.c
では、デバッグ情報の生成フラグがコンパイラによって条件付けされるようになりました。clang
の場合は-g
が、それ以外(主にgcc
)の場合は-ggdb
が使用されます。これは、両コンパイラがデバッグ情報を生成する際の推奨フラグが異なるためです。
-
gccgoToolchain
への名称統一:src/cmd/go/build.go
内で、GoのGCCフロントエンドを扱う内部的な型名がgccgcToolchain
からgccgoToolchain
に一貫して変更されました。これは機能的な変更ではなく、コードの可読性と命名規則の統一を目的としたリファクタリングです。
-
リンカオプションの調整:
src/cmd/go/build.go
のgccgoToolchain
のld
関数において、リンカフラグが-Wl,-(
と-Wl,-)
で囲まれるようになりました。これは、特に循環参照を持つライブラリをリンクする際に、リンカが正しく依存関係を解決できるようにするための標準的な手法です。
-
レース検出器テストの条件付け:
src/run.bash
では、レース検出器のテストがCC
環境変数に*gcc*
が含まれる場合にのみ実行されるように変更されました。これは、当時のclang
がレース検出器の機能と完全に互換性がなかったか、あるいは問題があったため、gcc
を使用している場合にのみテストを実行するように制限したものです。
これらの変更により、Goのビルドシステムはclang
をより適切にサポートし、異なるCコンパイラ環境でのビルドの信頼性を向上させています。
コアとなるコードの変更箇所
include/libc.h
:ARGBEGIN
マクロの内部で、未使用の式結果に関する警告を抑制するために(void)
キャストが追加されました。misc/cgo/testso/test.bash
:gcc
の代わりに$(go env CC)
を使用するように変更され、Cコンパイラが環境変数CC
で指定可能になりました。src/cmd/cgo/gcc.go
:#line
ディレクティブの開始行が0
から1
に変更されました。guessKinds
関数で、clang
が生成する可能性のある追加のエラーメッセージパターンに対応するようになりました。gccName()
関数がCC
環境変数を優先的に使用するように変更されました。clang
が使用されている場合に、-ferror-limit=0
と-Wno-unneeded-internal-declaration
フラグが追加されるようになりました。
src/cmd/dist/build.c
:proto_gccargs
から-ggdb
が削除されました。- コンパイラが
clang
であるかどうかに応じて、-g
または-ggdb
を条件付きで追加するロジックが導入されました。
src/cmd/go/build.go
:gccgcToolchain
という型名がgccgoToolchain
に一貫してリネームされました。gccgoToolchain
のld
関数で、リンカフラグが-Wl,-(
と-Wl,-)
で囲まれるようになりました。
src/cmd/go/env.go
:CC
環境変数がGoのビルド環境にエクスポートされるようになりました。src/make.bash
:cmd/dist/dist
のビルドに${CC:-gcc}
を使用するように変更され、CC
環境変数が尊重されるようになりました。src/run.bash
: レース検出器のテストが、CC
環境変数に*gcc*
が含まれる場合にのみ実行されるように条件が追加されました。
コアとなるコードの解説
このコミットの最も重要な変更は、GoのビルドシステムがCコンパイラとしてclang
をサポートするための基盤を確立した点です。
src/cmd/cgo/gcc.go
のgccName()
関数は、cgo
がCコンパイラを決定する際の中心的なロジックです。この関数がos.Getenv("CC")
を優先するように変更されたことで、Goのビルドプロセス全体でCC
環境変数がCコンパイラの選択に影響を与えるようになりました。これは、misc/cgo/testso/test.bash
やsrc/make.bash
などのシェルスクリプトが$(go env CC)
や${CC:-gcc}
を使用するように変更されたことと合わせて、Goのビルドシステムがより汎用的なCコンパイラ選択メカニズムを持つようになったことを意味します。
また、src/cmd/cgo/gcc.go
でclang
固有のコンパイラフラグ(-ferror-limit=0
, -Wno-unneeded-internal-declaration
)が追加されたことは、clang
がgcc
とは異なるデフォルトの挙動や警告レベルを持つことへの対応を示しています。これにより、cgo
が生成するCコードがclang
でコンパイルされる際に、不必要な警告やエラーでビルドが中断されることを防ぎます。
デバッグ情報の生成に関する変更(src/cmd/dist/build.c
)も重要です。gcc
とclang
では、デバッグ情報を生成するための推奨されるフラグが異なる場合があります。このコミットでは、コンパイラの種類に応じて適切なデバッグフラグ(-g
または-ggdb
)を動的に選択することで、両方のコンパイラで最適なデバッグ情報が生成されるようにしています。
最後に、src/run.bash
におけるレース検出器テストの条件付けは、当時のclang
とレース検出器の間の既知の非互換性に対処するための実用的な措置です。これにより、clang
を使用している場合にテストが失敗するのを防ぎ、ビルドの安定性を保っています。
これらの変更は、Goのビルドシステムが特定のCコンパイラに依存するのではなく、より広範なCコンパイラ環境に対応できるように進化していることを示しています。
関連リンク
- Go Issue #4713: https://github.com/golang/go/issues/4713
- Gerrit Change-Id:
7323068
(Goプロジェクトのコードレビューシステム)
参考にした情報源リンク
- Go言語の公式ドキュメント (cgo): https://pkg.go.dev/cmd/cgo
- GCC公式ウェブサイト: https://gcc.gnu.org/
- LLVM Clang公式ウェブサイト: https://clang.llvm.org/
- 環境変数
CC
について: (一般的なUnix/Linuxのドキュメントやmake
のドキュメントを参照) - リンカオプション
-Wl,-(
と-Wl,-)
について: (GCC/Clangのドキュメントやリンカのmanページを参照) - Goのビルドシステムに関する情報: (Goのソースコードリポジトリ内の
doc/go1.txt
やsrc/cmd/go/
以下のコード)