本章ではLLVMのインストール方法について説明します.LLVMの公式ページではバイナリで配布されていますし,一部ディストリビューションではパッケージで配布されていたりもしますが,実際にLLVMを利用して開発を進める際には頻繁にLLVMのソースコードを参照しますので,今回はソースコードからインストールしていきます.なお,本書では以降C/C++を例に話を進めていきますので,フロントエンドとしてClangを使用します.
LLVMをインストールする環境には様々な構成が考えられます.LLVMの公式ドキュメント,Getting Started with the LLVM System*3によると,LLVMは下記の環境で動作確認済みとのことです.*1
表3.1: LLVMの動作環境
| OS | アーキテクチャ | コンパイラ |
|---|---|---|
| AuroraUX | x86 | GCC |
| Linux | x86 | GCC |
| Linux | amd64 | GCC |
| Solaris | V9 (UltraSPARC) | GCC |
| FreeBSD | x86 | GCC |
| FreeBSD | amd64 | GCC |
| MacOS X | PowerPC | GCC |
| MacOS X | x86 | GCC |
| Cygwin/Win32 | x86 | GCC 3.4.X, binutils 2.20 |
また,表3.2の環境についても部分的にサポートしているとのことです.表3.1,および表3.2の環境における制限事項についてはここでは省略しますが,Getting Started with the LLVM System内に記載されていますので必要に応じて参照してください.
表3.2: LLVMが部分的にサポートする環境
| OS | アーキテクチャ | コンパイラ |
|---|---|---|
| Windows | x86 | Visual Studio 2000以上 |
| AIX | PowerPC | GCC |
| Linux | PowerPC | GCC |
| Linux | Alpha | GCC |
| Linux | Itanium (IA-64) | GCC |
| HP-UX | Itanium (IA-64) | HP aCC |
| Windows x64 | x86-64 | mingw-w64 の GCC-4.5.x |
上記に示したように,LLVMのインストール環境は様々なケースが想像されますが,とりあえず本書では私の手元の環境にあわせ,Windows上のVMwareにUbuntuをインストールし,さらにその上にLLVMをインストールする,という環境を想定して話を進めさせていただきます.今回私の方で使用した環境を表3.3に示しますが,他のディストリビューションや他のバージョンのインストールも基本的には変わらないと思いますので,それぞれの環境に合わせて適宜読みかえてください.なお,本書執筆開始時点の最新バージョンがLLVM 3.2であったため,本書では表3.3の環境にLLVM 3.2をインストールし,本章以降の解説ではLLVM 3.2の仕様をベースに,可能な限りLLVM 3.3,LLVM 3.4での変更点を補足しながら解説を進めていきたいと思います.
表3.3: 検証環境
| ホストOS | Windows 7 64bit |
| ゲストOS | Ubuntu 12.04 32bit |
| VMware | VMware 4.0.3 |
それではLLVMをインストールしていきましょう.インストールは以下の手順で行います.
今回は上記の手順でLLVM 3.2をインストールしますが,他のバージョンでも基本的には同じ手順でインストールできるはずです.なお,インストール先は/usr/local/llvm以下とします.
LLVMのインストールを始める前に,インストールに必要となるパッケージをインストールします.LLVMのビルドには表3.4のパッケージが必要となります.
表3.4: ビルドに必要なパッケージ
| パッケージ名 | バージョン | 使用目的 |
|---|---|---|
| GNU Make | 3.79, 3.79.1 | Makefile(ビルド)の実行 |
| GCC | 3.4.2 | C/C++ コンパイラとして利用 |
| Texinfo | 4.5 | Clangのビルドに必要 |
| SVN | 1.3以上 | LLVMのSubversionへのアクセス |
| python | 2.4以上 | テストスイートの実行 |
| perl | 5.6.0以上 | ユーティリティ |
| GNU M4 | 1.4 | マクロプロセッサ |
| GNU Autoconf | 2.60 | configureスクリプト生成 |
| GNU Automake | 1.9.6 | マクロ生成 |
| libtool | 1.5.22 | 共有ライブラリ管理 |
LLVM 3.2の公式ドキュメント,Getting Started with the LLVM SystemにはDejaGnu,tcl,expectが必要とされていますが,これらはpythonで置き換えられたため不要の様です.GNU M4,GNU Autoconf,GNU Automakeはconfigureに変更を加える場合に必要になります.なお,今回はホームページからソースコードを取得するためsvnは使用しません.trunkから最新のソースコードを取得したい場合はインストールしてください.また,今回は上記の他に,下記のパッケージもインストールします.
graphviz,xdotはLLVMのビルドには直接必要ないのですが,後でグラフの表示等に使用するのでインストールしておきます.
各パッケージのインストールは以下のコマンドで行います.
# GNU Make $ sudo apt-get install make # # GCC はインストールされていると思いますがされていなければ以下のコマンドを投入 $ sudo apt-get install gcc g++ # # ライブラリ $ sudo apt-get install libtool # # テスト用のパッケージ # pythonはUbuntu 12.04の場合デフォルトでインストールされているはず # インストールされていなければ以下のコマンドを投入 $ sudo apt-get install python # # その他ドキュメントやconfigure作成用 $ sudo apt-get install m4 autoconf automake texinfo # # グラフ表示等に使用 $ sudo apt-get install graphviz xdot
なお,表3.4のバージョンは“動作確認済み”のバージョンが記載されているとのことなのですが,一部情報が少し古い様に思われます.実際にLLVM/Clang とGCC 等の各種パッケージのバージョンの組み合わせによってはビルド時に問題が発生するのですが,Getting Started with the LLVM System にはLLVM のビルドに問題があるGCC のバージョンなどの情報が記載されていますので,うまくいかない場合は一度確認してみてもよいかもしれません.
パッケージのインストールが完了したらLLVMのビルド/インストールにはいります.LLVMのインストールは以下の手順で行います.
まずはLLVMのダウンロードからClangとLLVMのソースコードをダウンロードします.今回はバージョン3.2をソースコードからビルドするので,次の3つのファイルをダウンロードします.
wgetでさくっと取得してしまいましょう.ダウンロード場所は任意の場所で構いません.
$ wget http://llvm.org/releases/3.2/llvm-3.2.src.tar.gz $ wget http://llvm.org/releases/3.2/clang-3.2.src.tar.gz $ wget http://llvm.org/releases/3.2/compiler-rt-3.2.src.tar.gz
ダウンロードが完了すれば,次はアーカイブファイルの展開と移動です.
$ tar xzf llvm-3.2.src.tar.gz $ tar xzf clang-3.2.src.tar.gz $ tar xzf compiler-rt-3.2.src.tar.gz # # 作業ディレクトリを作成して移動(今回はホームディレクトリ配下のllvmディレクトリ) $ mkdir ~/llvm $ mv llvm-3.2.src ~/llvm/ $ mv clang-3.2.src ~/llvm/llvm-3.2.src/tools/clang $ mv compiler-rt-3.2.src ~/llvm/llvm-3.2.src/projects/compiler-rt
本書では基本的にLLVM 3.2をベースに話を進めますが,常に最新版を使用したいという方はtrunkのソースコードを取得する必要があります.そういった方のために,念のためtrunkのソースコードを取得する際の手順についても記載しておきます.trunkからのソースコード取得手順は次の通りです.
# subversionのインストール $ sudo apt-get install subversion # # 作業ディレクトリへ移動 $ cd ~/llvm/ # LLVMの取得 $ svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm # # Clangの取得 $ cd llvm/tools $ svn co http://llvm.org/svn/llvm-project/cfe/trunk clang # # compiler-rtの取得 $ cd ../projects $ svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk compiler-rt
ファイルの展開,配置が完了したのでビルドとインストールに移ります.実際に投入するコマンドを下記に示すので,皆さんの環境にあわせて適宜置き換えてください*2.
# ビルドディレクトリの作成と移動 $ mkdir ~/llvm/llvm-build/ $ cd ~/llvm/llvm-build/ # # --enable-optimizedをつけないとDebugでビルドされます $ ../llvm-3.2.src/configure --prefix=/usr/local/llvm --enable-optimized # # -jオプションは後ろに指定した数値分並列で動作します # 自分の環境に合わせて任意の値を指定してください $ make -j2 # # 一応テストをしてみる $ make check # # インストール $ sudo make install
ビルドにはそれなりの時間がかかりますので,コーヒーでも飲みながら気長に待ちましょう.なお,今回はRelease版でビルドしますが,Debug版でビルドしたい場合はconfigure時のオプションを次のように指定します.DebugビルドにするとDebugシンボルを含めてコンパイルされます.
# デフォルトでDebugですが--disable-optimizedをつけて明示的にDebugビルドを指定
$ ../llvm-3.2.src/configure --prefix=/usr/local/llvm --disable-optimized \
--enable-assertions --enable-debug-runtime --enable-debug-symbols
LLVMのDebugビルドではかなりのメモリを使用します.そのため,メモリが不足しているとOOM Killerによってmakeが異常終了してしまうことがあります.詳細にメモリ使用量を計測したわけではありませんが,最大でおおよそ2GB程度のメモリを使用する様ですので,メモリとスワップを合わせて3GB程度は確保しておいた方が良いと思われます.もしもシグナル9,もしくはシグナル2でビルドが終了してしまうことがある場合はsyslogを確認してみることをおすすめします.メモリ不足が原因であればOut of memory というログメッセージが確認できるはずです.
普通は最新のLLVMをインストールすれば良いと思いますが,わけあって過去のバージョンをインストールする場合は注意点があります.過去のLLVM(筆者は3.0で確認)ではOCamlがインストールされているとmake install時に,META.llvmでNo rule to make targetというエラーが出ます.その場合,下記のコマンドでMETA.llvmをコピーする必要があります.コピー後再度make installを実行すればインストールは正常に完了します.
$ cp -p bindings/ocaml/llvm/META.llvm bindings/ocaml/llvm/Release/META.llvm
ビルドとインストールが完了したら最後にパスの設定を行います.下記コマンドを投入し,パスを設定します.
$ echo 'export PATH=$PATH:/usr/local/llvm/bin' >> ~/.bashrc $ source ~/.bashrc
インストールが完了しましたので,実際にClangとLLVMのツールを試してみましょう.llvmのコマンドは複数ありますが,本節では代表的な各ツールについて簡単な説明と使用例を紹介します.
ClangはC/C++/Objective-C/Objective-C++のコンパイラ(コンパイラドライバ)です.Clangは内部で適切なモジュールを選択し,アセンブリや実行ファイルを生成することができます.Clangの代表的なオプションを以下に示します.
表3.5: Clangのオプション
| オプション | 概要 |
|---|---|
| –help | ヘルプ情報の出力 |
| -o | 出力ファイル名を指定 |
| -c | プリプロセス,コンパイル,アセンブルのみ実行 |
| -emit-llvm | LLVM IR形式で出力 |
| -S | プリプロセス,コンパイルのみを実行 |
| -cc1 | ドライバを使用せずコンパイラとして動作する |
特に-emit-llvmと-Sオプションは頻繁に使用します.-emit-llvmと-Sを併用することで,人間が読める形式のLLVM IR(LLVMアセンブリ)を出力され,-emit-llvmのみを指定した場合は,LLVM IRのビットコード形式(LLVMビットコード)が出力されます.その他にも多くのオプションがありますので,気になる方は–helpで確認してください.
# Clangで実行ファイルを生成する場合 $ clang -o hoge.o hoge.c # # ClangでLLVMビットコードを出力する場合 $ clang -emit-llvm -c -o hoge.bc hoge.c # # ClangでLLVMアセンブリを出力する場合 $ clang -emit-llvm -S -o hoge.ll hoge.c
lliはLLVMのインタプリタ兼JITコンパイラです.lliはデフォルトではJITコンパイラ(Lazy)で動作します.オプションとして-disable-lazyを指定するとEagerで起動できます.また,-force-interpreterを指定するとインタプリタとして実行します.
# LLVMビットコードを作成してインタプリタで実行する場合 $ clang -emit-llvm -c -o hoge.bc hoge.c $ lli -force-interpreter hoge.bc
llvm-asはLLVM IRのアセンブラです.llvm-asはLLVMアセンブリを入力として受け取り,LLVMビットコードへ変換します.入力ファイル名が省略された場合や-が指定された場合は,標準入力の情報を読み取ります.
# ソースコードを一度LLVMアセンブリに変換しVMで実行 $ clang -emit-llvm -S -o hoge.ll hoge.c $ llvm-as -o hoge.bc hoge.ll $ lli hoge.bc
llcはLLVM IRを入力として受け取り,指定されたアーキテクチャのアセンブリまたオブジェクトを出力します.アーキテクチャは-marchオプションで指定できますが,指定しない場合は入力ファイルから自動的に選択されます.オブジェクトを出力する場合は-filetype=objを指定します.
# LLVMアセンブリを経由してアセンブリ出力 $ clang -emit-llvm -S -o hoge.ll hoge.c $ llvm-as -o hoge.bc hoge.ll $ llc -o hoge.s hoge.bc # オブジェクト出力 $ llc -filetype=obj -o hoge.o hoge.ll
optはLLVMのLLVM IRに対して各種最適化や解析を行うモジュール(Pass)を適用するツールです.LLVM IRを入力として受け取り,指定された最適化,もしくは解析を適用して結果を出力します.LLVMでは様々なPassが用意されており,optコマンドを使用することでそれらを自由にLLVM IRに適用することが出来ます.また,LLVMのライブラリを利用すればユーザ独自のPassを作成し,optコマンドで使用することが可能です.なお,LLVMで用意されているPassについてはLLVMの公式ドキュメント,LLVM’s Analysis and Transform Passesにて紹介されています.
# LLVMアセンブリに最適化を施してJITコンパイラで実行 $ clang -emit-llvm -S -o hoge.ll hoge.c $ opt -O3 -o hoge.bc hoge.ll $ lli hoge.bc
llvm-linkは複数のLLVM IRを一つのファイルにまとめるためのツールです.-oオプションが指定されなければ標準出力に結果を出力します.
# hoge.cとlib.llをLLVMアセンブリにして結合する場合 $ clang -emit-llvm -S -o hoge.ll hoge.c $ clang -emit-llvm -S -o lib.ll lib.c $ llvm-link -o a.ll hoge.ll lib.ll
llvm-objdumpはオブジェクトファイルをディスアセンブルするためのツールです.-archオプションで任意のアーキテクチャを指定できます.
# hoge.oをディスアセンブルする場合 $ llvm-objdump -d hoge.o
llvm-configはLLVMを使用したプログラムをコンパイルする際に必要なコンパイルオプションを出力するツールです.LLVMを用いて開発するときに使用します.表3.6に代表的なオプションを示します.
表3.6: llvm-configのオプション
| オプション | 概要 |
|---|---|
| –help | ヘルプ情報の出力 |
| –includedir | LLVMのヘッダファイルのパスを表示する |
| –libdir | LLVMのライブラリファイルのパスを表示する |
| –cxxflags | LLVMのヘッダを使用するために必要なC++のflagを出力する |
| –ldflags | LLVMのライブラリをリンクするために必要なC++のflagを出力する |
| –libs | 指定されたLLVMコンポーネントをリンクするために必要なライブラリを全て表示する |
llvm-configの使用方法は実際にコンパイルを行う第5章で説明しますので, とりあえず今は深く考えず“LLVMを使用して何かを開発する時に用いるおまじない”程度に考えておけば良いと思います.
[*1] 何だか情報が古そうですが,筆者はLinux,x86,GCCという環境にしかインストールしたことがないのでこの情報がどこまで正確かわからないのです.
[*2] svnでcheckoutした場合はtopディレクトリでmake happiness を実行するとsvn update,ビルド,testを自動で行ってくれます
[*3] http://llvm.org/releases/3.2/docs/GettingStarted.html