Clang と GCC の主な相違点
Clang と GCC は大部分で互換性がありますが、ここでは異なる部分を解説します。細かい所まで含めると膨大になるので、ここでは SOLID プロジェクトで実際に問題になったものだけを記載しています。
コンパイラドライバ
GCC は、コンパイラドライバである gcc.exe
や g++.exe
が渡されたオプションを解析し、実際のコンパイラ cc1.exe
(C) や cc1plus.exe
(C++)、アセンブラ (Binutils の as.exe
)、リンカ (Binutils の ld.exe
) に応じた形に変換して呼び出すという構造になっています。
一方 Clang コンパイラはオプションによって、単一の exe (C の場合は clang.exe
、C++ の場合は clang++.exe
) がコンパイラドライバ、コンパイラ、アセンブラの役割を果たすという構造になっています。また、SOLID ツールチェーンの設定では、リンク時には gcc.exe
あるいは g++.exe
を呼び出してリンクを行います。そのため、リンク時に、GCC がサポートしないオプションを渡すとエラーになる場合があります。
注釈
s007 より Clang コンパイラのみ LLVM のリンカ ld.lld.exe をサポートしました。リンクに lld を使用する場合、GCC は呼び出されません。
文字コード
GCC は -finput-charset
/-fexec-charset
で cp932
(Shift_JIS) 等を指定し、ソースコードやアセンブラ出力の文字コードをデフォルトの UTF-8 から変更できますが、Clang は常に UTF-8 のみとなります。
pragma, attribute 拡張機能
-mthumb-interwork
オプション
このオプションは Clang には存在しないので、Clang にパッチを当て、無視するようにしています。Clang では常に ARM/Thumb interworking が有効なコードが生成されます。
-marm
オプション
Clang にこのオプションを渡すと、内部で -mno-thumb
と解釈されます。SOLID ツールチェーンの Clang は GCC をリンカとして使用しているため、GCC が未サポートの -mno-thumb
オプションが GCC に渡されてしまうとリンクエラーになるため、Clang にパッチを当て、無視するようにしています。そのため Clang では、デフォルトで -mthumb
を指定しておいて、ARM でコンパイルしなければいけないファイルのみ -marm
を付けるということはできなくなっています。その場合は -mno-thumb
を指定してください。(s002 以降)
specs ファイル
GCC は specs ファイルによりコンパイラのデフォルト設定を変更可能ですが、Clang には specs ファイル機能が存在しないので -specs
オプションは無視されます。
ただし、exeGCC の Clang は GCC をリンカとして使用するため、-specs
は Clang から呼び出された GCC にそのまま渡され(リンカに関する設定のみ)期待通りに機能します。GCC に渡されるオプションは Clang に -v
オプションを渡すことで確認できます。(Clang のリンカに LLVM の lld を使用した場合は specs ファイルは機能しません。)
arm-*-eabi
ターゲット時の enum サイズの仕様
GCC は arm-*-eabi
ターゲット時は aapcs ABI となり、enum が取り得る値の範囲に応じた可変長バイトとなりますが、Clang は固定長(4 もしくは 8 バイト)です。これは Linux(arm-*-gnueabi*
ターゲット)の aapcs-linux ABI と同等の設定になっています。SOLID ではわかりやすさや互換性等を考慮し、Clang の方に合わせた設定となっています。(s002 以降)