[インデックス 11971] ファイルの概要
コミット
commit 7c2bfa4f2cd591c618353bc3099678b0db6e8750
Author: Bobby Powers <bobbypowers@gmail.com>
Date: Thu Feb 16 13:31:46 2012 -0500
dist: add clang specific -Wno options
Clang 3.1 has more warnings enabled by default than GCC.
Combined with -Werror, they cause the build to fail
unnecessarily. if the name of our compiler ends in "clang",
add the necessary extra -Wno options. Ideally we would add
these flags unconditionally, as GCC is supposed to ignore
unknown -Wno flags, but apple's llvm-gcc doesn't.
Fixes #2878.
R=rsc, dave
CC=golang-dev
https://golang.org/cl/5673055
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/7c2bfa4f2cd591c618353bc3099678b0db6e8750
元コミット内容
dist: add clang specific -Wno options
このコミットは、Go言語のビルドシステムにおいて、Clangコンパイラに特化した警告抑制オプション(-Wno
)を追加するものです。
変更の背景
この変更の背景には、当時のClang 3.1コンパイラがGCC(GNU Compiler Collection)と比較して、デフォルトでより多くの警告を有効にしていたという問題があります。Go言語のビルドプロセスでは、しばしば-Werror
というコンパイラフラグが使用されます。このフラグは、コンパイラの警告をエラーとして扱い、警告が発生した場合にはビルドを失敗させるようにします。
Clang 3.1のデフォルトの警告設定と-Werror
の組み合わせにより、Goのビルドが不必要に失敗する事態が発生していました。これは、コード自体に問題がないにもかかわらず、コンパイラの警告設定の違いによってビルドが中断されるという非効率な状況を生み出していました。
特に、Appleのllvm-gcc
というコンパイラが、未知の-Wno
フラグを無視しないという特性も問題の一因でした。理想的には、-Wno
フラグはコンパイラが認識しない場合でも無視されるべきですが、llvm-gcc
はそのように動作しなかったため、Clangに特化した警告抑制オプションを条件付きで追加する必要がありました。
この問題は、GoのIssue #2878として報告され、このコミットによって解決されました。
前提知識の解説
Clang
Clangは、C、C++、Objective-C、Objective-C++言語のコンパイラフロントエンドです。LLVMプロジェクトの一部として開発されており、高速なコンパイル、優れた診断機能、モジュール性などが特徴です。特に、警告メッセージが非常に分かりやすいことで知られています。
GCC (GNU Compiler Collection)
GCCは、GNUプロジェクトによって開発されているコンパイラ群です。C、C++、Objective-C、Fortran、Ada、Goなど、多くのプログラミング言語をサポートしています。長年にわたり、Unix系システムにおける標準的なコンパイラとして広く利用されてきました。
-Werror
コンパイラフラグ
-Werror
は、コンパイラに渡されるオプションの一つで、すべてのコンパイラ警告をエラーとして扱うように指示します。このフラグが有効な場合、コードに警告があるだけでコンパイルが失敗します。これは、コード品質を高く保ち、潜在的な問題を早期に発見するために使用されることが多いです。しかし、異なるコンパイラやバージョン間で警告の厳しさが異なる場合、ビルドの互換性問題を引き起こす可能性があります。
-Wno-
コンパイラフラグ
-Wno-
は、特定の警告を抑制するためのコンパイラフラグです。例えば、-Wno-unused-variable
は未使用変数の警告を抑制します。これにより、開発者は特定の警告がコードの意図的な部分である場合や、一時的に無視したい場合に、ビルドを中断せずに作業を進めることができます。
Go言語の dist
ツール
Go言語のソースコードには、src/cmd/dist
というディレクトリが存在します。このdist
ツールは、Go言語自身のビルドプロセスを管理するための内部ツールです。Goのコンパイラ、リンカ、標準ライブラリなどをビルドし、インストールする役割を担っています。Goのビルドシステムは、C言語で書かれた部分(特に初期のブートストラップコンパイラやビルドツール)とGo言語で書かれた部分が混在しており、dist
ツールはそのC言語部分のビルドも調整します。
src/cmd/dist/build.c
ファイル
src/cmd/dist/build.c
は、Go言語のdist
ツールの一部であり、C言語で書かれたソースファイルです。このファイルは、GoのビルドプロセスにおけるCコードのコンパイルオプションや、ビルド対象のディレクトリ構造などを定義・管理しています。このコミットでは、このファイル内のコンパイラ引数を設定するロジックが変更されています。
技術的詳細
このコミットの技術的な核心は、Go言語のビルドプロセスにおいて、使用されているCコンパイラがClangであるかどうかを検出し、Clangの場合にのみ特定の警告抑制オプションを追加するという点です。
具体的には、src/cmd/dist/build.c
ファイル内で、コンパイラの実行ファイル名(gccargs.p[0]
に格納されていると推測される)に"clang"という文字列が含まれているかどうかをxstrstr
関数でチェックしています。xstrstr
は、Goの内部ツールで使われる文字列検索関数で、C標準ライブラリのstrstr
に相当します。
もしコンパイラ名に"clang"が含まれていれば、以下の2つの警告抑制オプションがvadd
関数(可変引数リストに要素を追加するGo内部ツール用の関数)を使ってコンパイラ引数リストに追加されます。
-Wno-dangling-else
: この警告は、if
文とelse
文の対応が曖昧な場合に発生します。例えば、ネストされたif
文でelse
がどのif
に対応するかが不明瞭な場合に警告されます。Clangはこのようなケースに対してGCCよりも厳しく警告を出すことがあります。-Wno-unused-value
: この警告は、式の結果が使用されていない場合に発生します。例えば、関数が値を返すにもかかわらず、その戻り値が変数に代入されたり、他の式で使用されたりしない場合に警告されます。これもClangがより積極的に警告する傾向があります。
コミットメッセージにあるように、理想的にはこれらのフラグは無条件に追加されるべきでした。なぜなら、GCCのような他のコンパイラは、通常、認識しない-Wno
フラグを無視するように設計されているからです。しかし、Appleのllvm-gcc
がこの理想的な動作をせず、未知の-Wno
フラグでビルドが失敗する可能性があったため、Clangに特化した条件付きの追加が必要とされました。
この変更により、Clang 3.1を使用した場合でも、Goのビルドが不必要な警告によって中断されることなく、正常に完了するようになりました。
コアとなるコードの変更箇所
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -582,8 +582,12 @@ 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) {
+ vadd(&gccargs, "-Wno-dangling-else");
+ vadd(&gccargs, "-Wno-unused-value");
+ }
}
-
+
islib = hasprefix(dir, "lib") || streq(dir, "cmd/cc") || streq(dir, "cmd/gc");
ispkg = hasprefix(dir, "pkg");
isgo = ispkg || streq(dir, "cmd/go") || streq(dir, "cmd/cgo");
コアとなるコードの解説
変更はsrc/cmd/dist/build.c
ファイルのinstall
関数内で行われています。
-
if(xstrstr(gccargs.p[0], "clang") != nil)
:gccargs.p[0]
は、コンパイラの実行ファイル名(例:gcc
,clang
,llvm-gcc
など)を指す文字列であると推測されます。xstrstr
は、第一引数の文字列内に第二引数の文字列が含まれているかを検索する関数です。!= nil
は、xstrstr
が文字列を見つけた場合に非NULL値を返すため、"clang"という文字列がコンパイラ名に含まれているかどうかをチェックしています。- この条件文により、現在使用されているコンパイラがClangベースである場合にのみ、以下のコードブロックが実行されるようになります。
-
vadd(&gccargs, "-Wno-dangling-else");
:vadd
は、gccargs
という引数リストに新しい要素を追加するGo内部ツール用の関数です。- ここで、
-Wno-dangling-else
というコンパイラフラグが追加されます。このフラグは、else
がどのif
に対応するか曖昧な場合に発生する警告を抑制します。Clangはこのような構造に対して厳しく警告を出す傾向があります。
-
vadd(&gccargs, "-Wno-unused-value");
:- 同様に、
-Wno-unused-value
というコンパイラフラグが追加されます。このフラグは、式の結果が使用されていない場合に発生する警告を抑制します。例えば、戻り値を持つ関数を呼び出しても、その戻り値をどこにも代入しない場合に警告されます。
- 同様に、
これらの変更により、Clangコンパイラを使用した場合にのみ、Goのビルドが不必要に失敗する原因となっていた特定の警告が抑制され、ビルドが正常に完了するようになります。また、コードの整形(空行の追加)も行われています。
関連リンク
- Go Issue #2878: このコミットが修正した問題のトラッキングイシュー。
- https://golang.org/issue/2878 (ただし、このリンクは現在のGoのイシュートラッカーでは見つからない可能性があります。古いイシュートラッカーの形式かもしれません。)
- Go CL 5673055: このコミットに対応するGoのコードレビュー(Change List)。
- https://golang.org/cl/5673055 (こちらも現在のGoのCLシステムでは見つからない可能性があります。古いCLの形式かもしれません。)
参考にした情報源リンク
- Clang Compiler User's Manual: Clangの警告オプションに関する一般的な情報。
- GCC Command Options: GCCの警告オプションに関する一般的な情報。
- Go言語のソースコード構造に関する一般的な知識。