clang, llvm-gccの関係

clangとllvm-gccがごっちゃになってはまったので整理してみた。
Mac上でXcodeを使わずにObjective-Cのプログラムを書いた時のお話。
前提はMac OS X 10.7.3, Xcode 4.3.2です。

以下のようなmain関数からいくつかのクラスを呼び出すコードを書いて、
gccを使ってコンパイルした所エラーが発生。

#import "Song.h"
#import "Singer.h"

int main(void) {
  id song;
  id singer;

  song = [[Song alloc] init];
  [song setLyrics:@"HaHaHa"];

  singer = [[Singer alloc] init];
  [singer setSong:song];
  [singer sing];

  return 0;
}

$ gcc -o app main.m Song.m Singer.m -framework Foundation
objc[14770]: Object 0x100414a50 of class __NSCFData autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug

LLVM-compiler3.0からARCが導入されているので、@autoreleasepool {}を使えばOKではないかと思い、

#import "Song.h"
#import "Singer.h"
#import 

int main(void) {
  @autoreleasepool {
    id song;
    id singer;

    song = [[Song alloc] init];
    [song setLyrics:@"Lala"];

    singer = [[Singer alloc] init];
    [singer setSong:song];
    [singer sing];

   }
  return 0;
}            

うまくいくかと思いきや、コンパイル時にエラー。
もしやgccがLLVM-compilerを使っていないかなと思いみてみると、

$ ls -l /usr/bin/gcc
lrwxr-xr-x  1 root  wheel  12  4 21 06:32 /usr/bin/gcc -> llvm-gcc-4.2
$ ls -l /usr/bin/llvm-gcc-4.2
lrwxr-xr-x  1 root  wheel  32  4 21 06:32 /usr/bin/llvm-gcc-4.2 -> ../llvm-gcc-4.2/bin/llvm-gcc-4.2
$ ls -l /usr/llvm-gcc-4.2/bin
rwxr-xr-x  1 root  wheel  127840  4 21 06:32 gcov-4.2
rwxr-xr-x  1 root  wheel  544448  4 21 06:32 i686-apple-darwin11-llvm-g++-4.2
rwxr-xr-x  1 root  wheel  544448  4 21 06:32 i686-apple-darwin11-llvm-gcc-4.2
rwxr-xr-x  1 root  wheel  117152  4 21 06:32 llvm-c++-4.2
rwxr-xr-x  1 root  wheel  257600  4 21 06:32 llvm-cpp-4.2
rwxr-xr-x  1 root  wheel  117152  4 21 06:32 llvm-g++-4.2
rwxr-xr-x  1 root  wheel  117152  4 21 06:32 llvm-gcc-4.2

うーん。ちゃんとllvmのgccを見ているもよう。ただ、i686-apple-darwin11-llvm-gcc-4.2がバイナリサイズも違うし怪しいと
思ったので念のためバージョンを確認。

$ /usr/llvm-gcc-4.2/bin/i686-apple-darwin11-llvm-gcc-4.2 -v
Using built-in specs.
Target: i686-apple-darwin11
Configured with: /private/var/tmp/llvmgcc42/llvmgcc42-2336.9~22/src/configure --disable-checking --enable-werror --prefix=/Applications/Xcode.app/Contents/Developer/usr/llvm-gcc-4.2 --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-prefix=llvm- --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin11 --enable-llvm=/private/var/tmp/llvmgcc42/llvmgcc42-2336.9~22/dst-llvmCore/Developer/usr/local --program-prefix=i686-apple-darwin11- --host=x86_64-apple-darwin11 --target=i686-apple-darwin11 --with-gxx-include-dir=/usr/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.9.00)

$ /usr/bin/llvm-gcc -v
Using built-in specs.
Target: i686-apple-darwin11
Configured with: /private/var/tmp/llvmgcc42/llvmgcc42-2336.9~22/src/configure --disable-checking --enable-werror --prefix=/Applications/Xcode.app/Contents/Developer/usr/llvm-gcc-4.2 --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-prefix=llvm- --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin11 --enable-llvm=/private/var/tmp/llvmgcc42/llvmgcc42-2336.9~22/dst-llvmCore/Developer/usr/local --program-prefix=i686-apple-darwin11- --host=x86_64-apple-darwin11 --target=i686-apple-darwin11 --with-gxx-include-dir=/usr/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.9.00)

中は同じっぽい??
遅ればせながらここでclangの存在を思い出したので、clangでコンパイル&実行したところエラーが解消。
$ clang -o app main.m Song.m Singer.m -framework Foundation

追加で調査したところ、以下のエントリーがよくまとまっていた。
http://blog.fenrir-inc.com/jp/2011/07/llvm.html

プロジェクトのビルド設定の Compiler Version に「LLVM Compiler 2.0」を指定すれば Clang をフロントエンドとして高速コンパイルや親切なエラーメッセージの恩恵を受けられます。

なぁにー、紛らわしい!結論としては、

  • Apple LLVM-Compilerというのはllvm-gccを指すのではなく、clangを指す。(clangもコンパイル時にはllvm-gccを利用しているのだろうけど、そのあたりの関係は引き続き調査が必要。)
  • @autoreleasepool {}などのARC関連の機能を利用するためには、clangでコンパイルする必要がある
  • 紛らわしいが、LLVM GCCApple LLVM-Compilerとは別ものでllvm-gccを指す。
  • MacOSXのデフォルトのコンパイラはllvm-gccとなっている。

ということですね。

慣れていればなんてことないのでしょうが、@autoreleasepool周りのエラーを調べてもおそらくXCode4.3以降では
Apple LLVM-Compilerを使っている人が多いせいか、海外の文献もあまり適切なものがなくハマってしまったので共有です。