第3章 環境構築

3.1 本章の概要と構成

本章ではLLVMのインストール方法について説明します.LLVMの公式ページではバイナリで配布されていますし,一部ディストリビューションではパッケージで配布されていたりもしますが,実際にLLVMを利用して開発を進める際には頻繁にLLVMのソースコードを参照しますので,今回はソースコードからインストールしていきます.なお,本書では以降C/C++を例に話を進めていきますので,フロントエンドとしてClangを使用します.

3.2 環境

LLVMをインストールする環境には様々な構成が考えられます.LLVMの公式ドキュメント,Getting Started with the LLVM System*3によると,LLVMは下記の環境で動作確認済みとのことです.*1

表3.1: LLVMの動作環境

OSアーキテクチャコンパイラ
 AuroraUXx86GCC
 Linuxx86GCC
 Linuxamd64GCC
 SolarisV9 (UltraSPARC)GCC
 FreeBSDx86GCC
 FreeBSDamd64GCC
 MacOS XPowerPCGCC
 MacOS Xx86GCC
 Cygwin/Win32x86GCC 3.4.X, binutils 2.20

また,表3.2の環境についても部分的にサポートしているとのことです.表3.1,および表3.2の環境における制限事項についてはここでは省略しますが,Getting Started with the LLVM System内に記載されていますので必要に応じて参照してください.

表3.2: LLVMが部分的にサポートする環境

OSアーキテクチャコンパイラ
 Windowsx86Visual Studio 2000以上
 AIXPowerPCGCC
 LinuxPowerPCGCC
 LinuxAlphaGCC
 LinuxItanium (IA-64) GCC
 HP-UXItanium (IA-64)HP aCC
 Windows x64x86-64mingw-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: 検証環境

ホストOSWindows 7 64bit
ゲストOSUbuntu 12.04 32bit
VMwareVMware 4.0.3

3.3 インストール

それではLLVMをインストールしていきましょう.インストールは以下の手順で行います.

今回は上記の手順でLLVM 3.2をインストールしますが,他のバージョンでも基本的には同じ手順でインストールできるはずです.なお,インストール先は/usr/local/llvm以下とします.

3.3.1 ビルドに必要なパッケージのインストール

LLVMのインストールを始める前に,インストールに必要となるパッケージをインストールします.LLVMのビルドには表3.4のパッケージが必要となります.

表3.4: ビルドに必要なパッケージ

パッケージ名バージョン使用目的
 GNU Make3.79, 3.79.1Makefile(ビルド)の実行
 GCC3.4.2C/C++ コンパイラとして利用
 Texinfo4.5Clangのビルドに必要
 SVN1.3以上LLVMのSubversionへのアクセス
 python2.4以上テストスイートの実行
 perl5.6.0以上ユーティリティ
 GNU M41.4マクロプロセッサ
 GNU Autoconf2.60configureスクリプト生成
 GNU Automake1.9.6マクロ生成
 libtool1.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 のバージョンなどの情報が記載されていますので,うまくいかない場合は一度確認してみてもよいかもしれません.

3.3.2 LLVMのビルド/インストール

パッケージのインストールが完了したらLLVMのビルド/インストールにはいります.LLVMのインストールは以下の手順で行います.

  1. LLVMのソースを取得
  2. LLVMのソースを展開
  3. LLVM のソースコードを配置するディレクトリを作成し、手順2で展開したディレクトリを移動
  4. ClangのソースをLLVMの所定ディレクトリへ移動
  5. オブジェクトファイルを展開するディレクトリを作成
  6. configure
  7. make及びmake install

ソースコードの取得

まずは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

trunkからソースコードを取得する場合

本書では基本的に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

Debugビルドに失敗する場合

LLVMのDebugビルドではかなりのメモリを使用します.そのため,メモリが不足しているとOOM Killerによってmakeが異常終了してしまうことがあります.詳細にメモリ使用量を計測したわけではありませんが,最大でおおよそ2GB程度のメモリを使用する様ですので,メモリとスワップを合わせて3GB程度は確保しておいた方が良いと思われます.もしもシグナル9,もしくはシグナル2でビルドが終了してしまうことがある場合はsyslogを確認してみることをおすすめします.メモリ不足が原因であればOut of memory というログメッセージが確認できるはずです.

過去のLLVMをインストールする場合の注意点

普通は最新の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

3.3.3 パスの設定

ビルドとインストールが完了したら最後にパスの設定を行います.下記コマンドを投入し,パスを設定します.

$ echo 'export PATH=$PATH:/usr/local/llvm/bin' >> ~/.bashrc
$ source ~/.bashrc

3.4 ツールの種類と確認

インストールが完了しましたので,実際にClangとLLVMのツールを試してみましょう.llvmのコマンドは複数ありますが,本節では代表的な各ツールについて簡単な説明と使用例を紹介します.

3.4.1 Clang

ClangはC/C++/Objective-C/Objective-C++のコンパイラ(コンパイラドライバ)です.Clangは内部で適切なモジュールを選択し,アセンブリや実行ファイルを生成することができます.Clangの代表的なオプションを以下に示します.

表3.5: Clangのオプション

オプション概要
–helpヘルプ情報の出力
-o出力ファイル名を指定
-cプリプロセス,コンパイル,アセンブルのみ実行
-emit-llvmLLVM IR形式で出力
-Sプリプロセス,コンパイルのみを実行
-cc1ドライバを使用せずコンパイラとして動作する

特に-emit-llvmと-Sオプションは頻繁に使用します.-emit-llvmと-Sを併用することで,人間が読める形式のLLVM IR(LLVMアセンブリ)を出力され,-emit-llvmのみを指定した場合は,LLVM IRのビットコード形式(LLVMビットコード)が出力されます.その他にも多くのオプションがありますので,気になる方は–helpで確認してください.

Clangの使用例

# 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

3.4.2 lli

lliはLLVMのインタプリタ兼JITコンパイラです.lliはデフォルトではJITコンパイラ(Lazy)で動作します.オプションとして-disable-lazyを指定するとEagerで起動できます.また,-force-interpreterを指定するとインタプリタとして実行します.

lliの使用例

# LLVMビットコードを作成してインタプリタで実行する場合
$ clang -emit-llvm -c -o hoge.bc hoge.c
$ lli -force-interpreter hoge.bc

3.4.3 llvm-as

llvm-asはLLVM IRのアセンブラです.llvm-asはLLVMアセンブリを入力として受け取り,LLVMビットコードへ変換します.入力ファイル名が省略された場合や-が指定された場合は,標準入力の情報を読み取ります.

llvm-asの使用例

# ソースコードを一度LLVMアセンブリに変換しVMで実行
$ clang -emit-llvm -S -o hoge.ll hoge.c
$ llvm-as -o hoge.bc hoge.ll
$ lli hoge.bc

3.4.4 llc

llcはLLVM IRを入力として受け取り,指定されたアーキテクチャのアセンブリまたオブジェクトを出力します.アーキテクチャは-marchオプションで指定できますが,指定しない場合は入力ファイルから自動的に選択されます.オブジェクトを出力する場合は-filetype=objを指定します.

llcの使用例

# 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

3.4.5 opt

optはLLVMのLLVM IRに対して各種最適化や解析を行うモジュール(Pass)を適用するツールです.LLVM IRを入力として受け取り,指定された最適化,もしくは解析を適用して結果を出力します.LLVMでは様々なPassが用意されており,optコマンドを使用することでそれらを自由にLLVM IRに適用することが出来ます.また,LLVMのライブラリを利用すればユーザ独自のPassを作成し,optコマンドで使用することが可能です.なお,LLVMで用意されているPassについてはLLVMの公式ドキュメント,LLVM’s Analysis and Transform Passesにて紹介されています.

optの使用例

# LLVMアセンブリに最適化を施してJITコンパイラで実行
$ clang -emit-llvm -S -o hoge.ll hoge.c
$ opt -O3 -o hoge.bc hoge.ll
$ lli hoge.bc

3.4.6 llvm-link

llvm-linkは複数のLLVM IRを一つのファイルにまとめるためのツールです.-oオプションが指定されなければ標準出力に結果を出力します.

llvm-linkの使用例

# 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

3.4.7 llvm-objdump

llvm-objdumpはオブジェクトファイルをディスアセンブルするためのツールです.-archオプションで任意のアーキテクチャを指定できます.

llvm-objdumpの使用例

# hoge.oをディスアセンブルする場合
$ llvm-objdump -d hoge.o

3.4.8 llvm-config

llvm-configはLLVMを使用したプログラムをコンパイルする際に必要なコンパイルオプションを出力するツールです.LLVMを用いて開発するときに使用します.表3.6に代表的なオプションを示します.

表3.6: llvm-configのオプション

オプション概要
–helpヘルプ情報の出力
–includedirLLVMのヘッダファイルのパスを表示する
–libdirLLVMのライブラリファイルのパスを表示する
–cxxflagsLLVMのヘッダを使用するために必要なC++のflagを出力する
–ldflagsLLVMのライブラリをリンクするために必要な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