clangでc++を試して四苦八苦したメモ

何の変哲もないHelloWorld。

#include <iostream>

int main()
{
    std::cout << "Hello, おにいちゃん!!" << std::endl;
    return 0;
}

こいつをclangをつかってコンパイル

# clang -xc++ hello.cpp
/tmp/cc-x0SPbV.o: In function `__cxx_global_var_init':
hello.cpp:(.text+0xc): undefined reference to `std::ios_base::Init::~Init()'
hello.cpp:(.text+0x30): undefined reference to `std::ios_base::Init::Init()'
/tmp/cc-x0SPbV.o: In function `main':
hello.cpp:(.text+0x61): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
hello.cpp:(.text+0x69): undefined reference to `std::cout'
hello.cpp:(.text+0x84): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
hello.cpp:(.text+0x90): undefined reference to `std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))'
collect2: ld returned 1 exit status
clang: error: linker (via gcc) command failed with exit code 1 (use -v to see invocation)

まったく、君たちコンパイラはいつもそうだね。わけがわからないよ。-vを出してもインクルードパスが列挙されるばかりだというのに。それで何がわかるというんだい?
なーんて絶望しながらググってたら、どうやらgccに対するg++みたいに、clangにもclang++があると知る。

% clang++ hello.cpp
hello.cpp:1:10: fatal error: 'iostream' file not found
#include <iostream>
         ^
1 error generated.

おお、やっと理解できるエラーメッセージ。しかしまあ、iostreamが無いとか言われても知らん。
まさかほんとに無かったりする?と調べてみるも、

% g++ hello.cpp 
% ./a.out
Hello, おにいちゃん!!

ちゃんとあるじゃねえかこの野郎。
ということで今度こそインクルードパスを確認。

% clang++ -v hello.cpp
clang version 2.8 (branches/release_28)
Target: x86_64-pc-linux-gnu
Thread model: posix
 "/usr/bin/clang" -cc1 -triple x86_64-pc-linux-gnu -S -disable-free -disable-llvm-verifier -main-file-name hello.cpp -mrelocation-model static -mdisable-fp-elim -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-linker-version 2.21.0.20110216 -v -resource-dir /usr/lib/clang/2.8 -ferror-limit 19 -fmessage-length 0 -fexceptions -fgnu-runtime -fdiagnostics-show-option -o /tmp/cc-HWm9oj.s -x c++ hello.cpp
clang -cc1 version 2.8 based upon llvm 2.8rc hosted on x86_64-pc-linux-gnu
ignoring nonexistent directory "/usr/include/c++/4.4"
ignoring nonexistent directory "/usr/include/c++/4.4/x86_64-linux-gnu/"
ignoring nonexistent directory "/usr/include/c++/4.4/backward"
ignoring nonexistent directory "/usr/include/c++/4.4"
ignoring nonexistent directory "/usr/include/c++/4.4/i486-linux-gnu/64"
ignoring nonexistent directory "/usr/include/c++/4.4/backward"
ignoring nonexistent directory "/usr/include/c++/4.3"
 :
(中略)
 :
ignoring nonexistent directory "/usr/include/c++/4.3.1"
ignoring nonexistent directory "/usr/include/c++/4.3.1/x86_64-unknown-linux-gnu/"
ignoring nonexistent directory "/usr/include/c++/4.3.1/backward"
ignoring nonexistent directory "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4"
ignoring nonexistent directory "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/i686-pc-linux-gnu/"
ignoring nonexistent directory "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/backward"
ignoring nonexistent directory "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4"
 :
(中略)
 :
ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.2/include/g++-v4/x86_64-pc-linux-gnu/"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.2/include/g++-v4/backward"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/x86_64-pc-linux-gnu/"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/backward"
ignoring nonexistent directory "/usr/lib/llvm-gcc-4.2-9999/include/c++/4.2.1"
ignoring nonexistent directory "/usr/lib/llvm-gcc-4.2-9999/include/c++/4.2.1/x86_64-pc-linux-gnu/"
ignoring nonexistent directory "/usr/lib/llvm-gcc-4.2-9999/include/c++/4.2.1/backward"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/include
 /usr/lib/clang/2.8/include
 /usr/include
End of search list.
hello.cpp:1:10: fatal error: 'iostream' file not found
#include <iostream>
         ^
1 error generated.

4.5という数字がない。とても嫌な予感。

% ls /usr/include/c++
4.5/  4.5.2@

なるほど。ということでclangのインクルードパスをどうにかしてやらないといけない。

  • Iオプションで実験。
% clang++ -I /usr/include/c++/4.5/ -I /usr/include/c++/4.5/x86_64-linux-gnu hello.cpp
% ./a.out
Hello, おにいちゃん!!

それじゃあclangにこれらのパスを通そうか・・・と思ったら、clangはインクルードパスを直書きしてるらしい。自前dpkg作ってもいいけど、わりとめんどくさい。

ということで手抜き。たぶん危険でないこともないハズなので真似するときは自己責任で。

% cd /usr/include/c++
% ln -s 4.5 4.4

・・・やっぱ後でdpkg作ろう。こわい。