Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 12305] ファイルの概要

このコミットは、Go言語のビルドシステムの一部である src/cmd/dist/build.c ファイルに対する変更です。cmd/dist はGoのソースコードからツールチェーンを構築するためのプログラムであり、Cコンパイラ(CC)の検出と利用を管理しています。build.c は、このビルドプロセスにおけるCコンパイラの引数処理や特定のコンパイラ(Clangなど)の識別ロジックを担っています。

コミット

このコミットは、GoのビルドシステムがCコンパイラを識別するロジックを改善するものです。具体的には、環境変数 CC"ccache clang" のように設定されている場合に、Goのビルドシステムがこれを正しく clang コンパイラとして認識できるように修正しています。これにより、clang に特有のコンパイラフラグ(例: -Wno-dangling-else, -Wno-unused-value)が適切に適用されるようになります。

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/03769efe414863be778b80eac7425d5f382d87cf

元コミット内容

cmd/dist: recognize CC="ccache clang" as clang

R=golang-dev, gri
CC=golang-dev
https://golang.org/cl/5711052

変更の背景

Go言語のビルドプロセスでは、C言語で書かれた部分(例: ランタイム、一部の標準ライブラリ)をコンパイルするためにCコンパイラを使用します。このCコンパイラは、通常、環境変数 CC で指定されます。

以前の cmd/dist の実装では、CC 環境変数の値が直接 clang を含んでいるかどうかをチェックしていました。しかし、開発環境によっては、コンパイル時間を短縮するために ccache のようなコンパイラキャッシュツールをCコンパイラのフロントエンドとして使用することが一般的です。この場合、CC"ccache clang" のように設定されます。

この設定では、従来の cmd/dist のロジックでは clang が直接 CC の先頭にないため、clang であると正しく認識されませんでした。その結果、clang に特有の警告抑制フラグ(-Wno-dangling-else, -Wno-unused-value)が適用されず、ビルド時に不要な警告が発生したり、最悪の場合、ビルドが失敗する可能性がありました。

このコミットは、このような ccache を介した clang の利用シナリオに対応し、Goのビルドシステムがより堅牢にCコンパイラを識別できるようにするために行われました。

前提知識の解説

  • cmd/dist: Go言語のソースコードからGoツールチェーン(コンパイラ、リンカ、アセンブラなど)をビルドするためのプログラムです。Goの自己ホスト型コンパイラがまだ存在しない初期段階や、新しいGoのバージョンをビルドする際に使用されます。cmd/dist は、C言語で書かれたGoのランタイムや一部のライブラリをコンパイルするために、システムにインストールされているCコンパイラ(GCCやClangなど)を利用します。
  • CC 環境変数: Cコンパイラを指定するための標準的な環境変数です。例えば、export CC=clang と設定すると、ビルドシステムは clang をCコンパイラとして使用します。
  • clang: LLVMプロジェクトの一部であるC、C++、Objective-C、Objective-C++コンパイラのフロントエンドです。GCCと互換性のあるコマンドラインオプションを持ち、高速なコンパイルと詳細な診断メッセージが特徴です。
  • ccache: コンパイラキャッシュツールです。コンパイル結果をキャッシュすることで、同じソースコードを再コンパイルする際の時間を大幅に短縮します。ccache を使用する場合、実際のコンパイラ(例: clang)の前に ccache を呼び出すように設定します。例えば、CC="ccache clang" のように設定します。ccache は引数を解析し、キャッシュヒットすればキャッシュされた結果を返し、そうでなければ実際のコンパイラを呼び出します。
  • xstrstr: Goのビルドシステム内で使用されるユーティリティ関数で、文字列 haystack 内に needle が含まれているかを検索します。標準Cライブラリの strstr に似ています。
  • bstr(&b): b はおそらく文字列バッファのような構造体で、bstr(&b) はそのバッファの内容を文字列として取得する関数呼び出しです。
  • gccargs.p[0]: gccargs はCコンパイラに渡される引数を格納する配列またはリストのような構造体で、gccargs.p[0] はその最初の引数、つまりCコンパイラの実行ファイル名(例: "clang", "gcc", "ccache" など)を指します。

技術的詳細

このコミットの核心は、Cコンパイラの識別ロジックの変更にあります。

変更前のコードでは、install 関数内でCコンパイラの引数を処理する際に、gccargs.p[0]、つまりCコンパイラの実行ファイル名そのものが "clang" を含んでいるかどうかを xstrstr でチェックしていました。

// 変更前
if(xstrstr(gccargs.p[0], "clang") != nil) {
    vadd(&gccargs, "-Wno-dangling-else");
    vadd(&gccargs, "-Wno-unused-value");
}

このロジックの問題点は、CC="ccache clang" のように設定されている場合、gccargs.p[0] の値は "ccache" となり、"clang" を直接含まないため、clang 特有の警告抑制フラグが適用されませんでした。

変更後のコードでは、xstrstr の検索対象を bstr(&b) に変更しています。ここで bstr(&b) は、CC 環境変数から取得された元のCコンパイラコマンドライン全体、またはその一部を表す文字列であると推測されます。つまり、"ccache clang" という文字列全体に対して "clang" が含まれているかをチェックするようになります。

// 変更後
if(xstrstr(bstr(&b), "clang") != nil) {
    vadd(&gccargs, "-Wno-dangling-else");
    vadd(&gccargs, "-Wno-unused-value");
}

これにより、CC="ccache clang" の場合でも、bstr(&b)"ccache clang" を返し、その中に "clang" が含まれているため、条件が真となり、clang に必要な警告抑制フラグが正しく追加されるようになります。これは、ccache のようなラッパーを使用している場合でも、実際のコンパイラが clang であることを正確に識別するための重要な修正です。

コアとなるコードの変更箇所

--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -586,7 +586,7 @@ install(char *dir)
 		splitfields(&gccargs, bstr(&b));
 		for(i=0; i<nelem(proto_gccargs); i++)
 			vadd(&gccargs, proto_gccargs[i]);
-		if(xstrstr(gccargs.p[0], "clang") != nil) {
+		if(xstrstr(bstr(&b), "clang") != nil) {
 			vadd(&gccargs, "-Wno-dangling-else");
 			vadd(&gccargs, "-Wno-unused-value");
 		}

コアとなるコードの解説

変更は src/cmd/dist/build.c ファイルの install 関数内、具体的には588行目で行われています。

  • 変更前:

    if(xstrstr(gccargs.p[0], "clang") != nil) {
    

    ここでは、gccargs.p[0]、つまりCコンパイラコマンドの最初の要素(通常は実行ファイル名、例: gccclang、または ccache)に対して、文字列 "clang" が含まれているかを検索していました。CC="ccache clang" の場合、gccargs.p[0]"ccache" となるため、この条件は偽となり、clang 特有のフラグが追加されませんでした。

  • 変更後:

    if(xstrstr(bstr(&b), "clang") != nil) {
    

    変更後では、検索対象が bstr(&b) になっています。bstr(&b) は、CC 環境変数から取得された元のCコンパイラコマンドライン全体(例: "ccache clang")を表す文字列を返します。この文字列に対して "clang" が含まれているかを検索することで、ccache のようなラッパーが介在していても、実際のコンパイラが clang であることを正確に識別できるようになりました。これにより、clang に必要な警告抑制フラグが適切に適用されるようになります。

この修正により、Goのビルドシステムは、ccache を使用している開発環境においても、clang コンパイラを正しく認識し、適切なコンパイラオプションを適用できるようになり、ビルドの堅牢性と互換性が向上しました。

関連リンク

参考にした情報源リンク