ClangをMacでビルドする

ClangはLLVMのC/C++フロントエンドで、静的解析のコードを追加することがで きる。LLVMについては最適化処理に注目が集まっている。今回はClangに静的 解析コードを追加する為の前準備としてMac上にsvnで取得したClang/LLVMをコ ンパイルしてインストールする(Xcodeに梱包されているものとは別に導入)。

 

1. Clang

Clangのページに手順が記載されている。 

1.1. ソースコードの取得

Clangのページに記載されている手順でソースコードを取得する。

$ svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
$ cd llvm/tools
$ svn co http://llvm.org/svn/llvm-project/cfe/trunk clang
$ cd ../..
$ cd llvm/tools/clang/tools
$ svn co http://llvm.org/svn/llvm-project/clang-tools-extra/trunk extra
$ cd ../../../..
$ cd llvm/projects
$ svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk compiler-rt
$ cd ../..

1.2. ビルド

configureを実行してmake。

$ mkdir llvm.build
$ cd llvm.build/
$ ../llvm/configure --prefix=$HOME --enable-optimized
$ make
$ make install

--enable-optimizedを入れないと出来上がったClangによるビルドは時間が掛 かってしまう。Clang/LLVM内部をデバッグするつもりがない場合は指定した方 が良い。

2. デフォルトのインクルードパスの問題

下記のソースコードclang++でビルド。

$ cat hello.cpp 
#include <iostream>
 
int main()
{
  std::cout << "hello, world\n";
  return 0;
}

Xcodeのclang++のデフォルトのインクルードパス。

$ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -v hello.cpp 
<snip>
ignoring nonexistent directory "/usr/include/c++/v1"
#include "..." search starts here:
#include <...> search starts here:
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1
 /usr/local/include
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/5.0/include
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
 /usr/include
 /System/Library/Frameworks (framework directory)
 /Library/Frameworks (framework directory)
End of search list.
<snip>

今回導入したclang++のデフォルトのインクルードパス。

$ ~/bin/clang++ -v hello.cpp 
<snip>
ignoring nonexistent directory "<HOME>/bin/../include/c++/v1"
ignoring nonexistent directory "/usr/include/c++/v1"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/include
 /<HOME>/bin/../lib/clang/3.5/include
 /usr/include
 /System/Library/Frameworks (framework directory)
 /Library/Frameworks (framework directory)
End of search list.
hello.cpp:1:10: fatal error: 'iostream' file not found
#include <iostream>
         ^
1 error generated.

xcode配下のclang++は以下のヘッダを使用している。

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/c++/v1/iostream

LLVMのconfigureでXcodeと同じインクルードパスを見るようにしてやればいい はずだが、オプションがよく分からずじまい。応急処置としてclang++のラッ パースクリプトで-Iオプションを使って読みにいく手もできそうだが、ここで はLLVM向けのlibcxxを$HOME配下に別途インストールする。

3. libcxxのインストール

こちらのページに記載されている手順でソースコードを取得する。 

3.1. ソースコードの取得

$ svn co http://llvm.org/svn/llvm-project/libcxx/trunk libcxx

3.2. ビルド

$ mkdir libcxx.build
$ cd libcxx.build
$ cmake -G "Unix Makefiles" ../libcxx \
-DCMAKE_INSTALL_PREFIX="$HOME"
$ make install

3.3. 実行

先ほどのhello.cppをclang++でビルド。

$ clang++ -v hello.cpp 
<snip>
ignoring nonexistent directory "/usr/include/c++/v1"
#include "..." search starts here:
#include <...> search starts here:
 /<HOME>/bin/../include/c++/v1
 /usr/local/include
 /<HOME>/bin/../lib/clang/3.5/include
 /usr/include
 /System/Library/Frameworks (framework directory)
 /Library/Frameworks (framework directory)
End of search list.
 "<HOME>/bin/ld" -demangle -dynamic -arch x86_64 -macosx_version_min 10.9.0 -o a.out /var/folders/69/sm58mrhx0bvg0qbgvljzgs0r0000gn/T/hello-a55cfc.o -lc++ -lSystem /<HOME>/bin/../lib/clang/3.5/lib/darwin/libclang_rt.osx.a
$ ./a.out 
hello, world
$

<HOME>/bin/ldについてはMacの/usr/bin/ldへのシンボリックリンクを使用し ている。PATHからldを探して、システムのldを使うのがデフォルト動作なんだ ろうか? llvm-ldがないのでllvm-linkとかのコマンド群を使うのが正当な気 がするが。そもそもllvm-ldがldの置き換えという訳ではないのかな。

$ /usr/bin/ld -v
@(#)PROGRAM:ld  PROJECT:ld64-224.1
configured to support archs: armv6 armv7 armv7s arm64 i386 x86_64
armv6m armv7m armv7em
LTO support using: LLVM version 3.3svn, from Apple Clang 5.0 (build
500.2.79)

4. The LLVM Linker(上手く実行できてない)

LLVM向けのリンカのThe LLVM Linkerというものがあった。

4.1. ソースコードの取得

Clangと同様にLLVMのソースツリー配下に置く。

$ cd llvm/tools/
$ svn co http://llvm.org/svn/llvm-project/lld/trunk lld

4.2. ビルド

Clangと同様にLLVMのソースツリーと一緒にビルドする。lldはcmakeでビルド する必要があるのでLLVMをcmakeでビルドする(cmakeによるLLVMビルド方法)。 http://llvm.org/docs/CMake.html

$ cd ../..
$ mkdir llvm.build
$ cd llvm.build
$ cmake -G "Unix Makefiles" ../llvm/ \
-DCMAKE_CXX_FLAGS="-std=c++11" \
-DCMAKE_INSTALL_PREFIX="$HOME" \
-DCMAKE_BUILD_TYPE="Release"
$ make
$ make install

CMAKE_CXX_FLAGSに"-std=c++11"を設定しない場合、以下のエラーが発生した。

CMake Error at tools/lld/CMakeLists.txt:99 (message):
  lld requires c++11.  Clang and gcc require -std=c++0x or -std=c++11 to
  enter this mode.  Please set CMAKE_CXX_FLAGS accordingly.

4.3. 実行

$HOME/bin/ldを$HOME/bin/lldへのシンボリックリンクに変更して実行。う まくいかず。少なくともmacosx_version_minオプションを解析するコードは lldにあるのだが・・・。使い方の問題か?

 "/<HOME>/bin/ld" -dynamic -arch x86_64 -macosx_version_min 10.9.0 -o a.out /var/folders/69/sm58mrhx0bvg0qbgvljzgs0r0000gn/T/hello-5908c6.o -lc++ -lSystem /<HOME>/bin/../lib/clang/3.5/lib/darwin/libclang_rt.osx.a
warning: ignoring unknown argument: -arch
warning: ignoring unknown argument: -macosx_version_min
lld: unknown input file format for file x86_64
clang-3.5: error: linker command failed with exit code 1 (use -v to see invocation)

ノイズの多い内容だが、とりあえずldは/usr/bin/ldを使うようにする。