mcommit's message

ソフトウェア開発の仕事をしているsimotinといいます。記事の内容でご質問やご意見がありましたらお気軽にコメントしてください\^o^/

LLVMのビルドについてまとめてみる

f:id:simotin13:20180105144554p:plain

2018年早々、LLVMのビルドで消耗しておりました。
なんとなくlibToolingを使ってみようとしたらソースのビルドが必要そうな感じだったので始めたのですが、LLVMには複数のプロジェクトがあり、各プロジェクトの役割とかいまいちピンと来ておらず、ビルドにあたっていろいろドキュメント読んだりする必要がありました。

ドキュメントを熟読せずに始めるといろいろと躓くようなので、LLVMのビルドに関する情報をまとめておきたいと思います。

といってもまだまとめ切れていない点が多いので恐らく後から次々と追記・訂正することになりそうな気がします。

必読ページ達

LLVMプロジェクトはドキュメントが充実しています。
この充実したドキュメントをしっかり読むことが大切のようです。
ビルドに関する情報だけでもいくつかのページで役経つ情報が書かれています。

ビルドに関しては以下3ページが役に立ちます。

まずは一番上のLLVMのGettingStartedのページから読むのがお勧めのようです。

LLVM System GettingStarted

読めよ、絶対読めよ。

このGettingStartedはちょっとしたジョークから始まります。

1.Read the documentation.
2.Read the documentation.
3.Remember that you were warned twice about reading the documentation.
In particular, the relative paths specified are important.

f:id:simotin13:20180104004944j:plain

これを訳すと、

手順
1. ドキュメント読めよ
2. ドキュメント読めよ
3.ドキュメント読めって2回忠告されたことを忘んなよ!
特に相対パスで指定しているとこ注意な!

といった感じでしょうか。
個人的には「ドキュメントは読むなよ!分かりやすいから絶対読むなよ」みたいに書かれていても面白いなと思いましたが、ああいう出川スタイルのギャグは欧米にはないのでしょうか。

開発環境のC++のツールチェインについて

GettinStartedを読み進めるとさらっと重要なことが書いてあります。
Getting Started with the LLVM System — LLVM 7 documentation

LLVM is very demanding of the host C++ compiler, and as such tends to expose bugs in the compiler. We are also planning to follow improvements and developments in the C++ language and library reasonably closely. As such, we require a modern host C++ toolchain, both compiler and standard library, in order to build LLVM.

For the most popular host toolchains we check for specific minimum versions in our build systems:

Clang 3.1
GCC 4.8
Visual Studio 2015 (Update 3)

要するに、

LLVMC++のモダンな機能を使って開発をしていて、開発環境のC++コンパイラは厳密さが求められるので、コンパイラのバグを曝け出しがち。ということで俺らも頑張ってC++のツールチェインと標準ライブラリ作ってるから・・・

あっ、ちなみに俺らがLLVMの最低限の確認に使っている一般的な開発環境は、

だからそこんとこよろしく。

ということでしょう。

most popular host toolchains」という表現がありますが、これは、2018年の早々からLLVMのビルド地獄に落ちた身としては、

このリストうちのどれかでビルドしろよ!

という最後通牒として受け取ることをおすすめします。

また、ビルドに失敗するツールチェインとして、

が挙げられています。

ツール・プロジェクトについて

LLVMLLVM本体以外にclangなど複数のプロジェクトから構成されています。

compiler-rt

"compiler-rt" Runtime Library

低レベルのライブラリ。どうもCPU依存部での最適なビルドイン関数とかSanitizerの機能を提供するプロジェクトのようです。

lld

LLD - The LLVM Linker — lld 7 documentation

リンカプロジェクト。

LLDB

デバッガプロジェクト。


まだ他にもいろいろあるけど調べ切れていません。

は必須でそれ以外はoptionalとあるのでビルド時に必須ではない模様。

結論

ということでここまで各ページの概要について見てみましたが、私が試したLinux環境でLLVMをビルドする手順をここで書いておきたいと思います。

注意事項

以下、ビルドしていて大変だったこととか、注意点とかです。

LLVMのビルドは結構ディスク容量食います。

ソース一式展開すると500MB程度ありました。ビルドしたディレクトリで1.7GB程度。
私はVM環境上でビルドしたので、同じことをされる方は仮想マシンのディスクサイズを多めに確保されることをお勧めします。
VMだと削除したファイルの領域が確保されっぱなしになるのであっという間にディスクサイズが膨れ上がってしまいました。

ディスクサイズの圧縮は、VMWareToolでできるようですので、こちらの記事を参考にさせて頂き試してみました。

gendosu.jp
参考にさせて頂きありがとうございます。
手元の環境では、圧縮のコマンド実行後、19GBのvmdkファイルが10GB程度に圧縮されました。

LLVMのビルドはすごく時間かかります。

2時間程度でしょうか・・・カーネルビルドと比べると短いかな。

LLVMのビルドではすごくメモリ使います。

2GBとかじゃダメです。4GB以上確保してください。

mcommit.hatenadiary.com

リンクがかえってこない!?

メモリ増やすのとHDDじゃなくてSSDを使うことで何とかなるっぽい。
リンカが返ってこない(ディスクアクセスしっぱなし)って初めて見ました。

やること

ざっくりと、

  1. clangをインストール
  2. 必要なパッケージ
  3. LLVMのソース一式をゲット
  4. ソース一式の展開
  5. cmakeの実行
  6. ビルド実行
  7. インストール
clangをインストール

ビルドするためにとりあえずclangをインストールします。


$sudo apt install clang

手元の環境だと3.8がインストールされました。

あとOpenMPやLLDBのプロジェクトをビルドする場合はいくつか依存しているパッケージのインストールが必要になるようです。


# OpenMP関係のパッケージをインストール
# OpenMPのビルドをしないのであれば不要
sudo apt install openmpi-bin openmpi-common libopenmpi-dev

# LLDBで必要になるパッケージのインストール
# LLDBをビルドしないのであれば不要
sudo apt-get install build-essential subversion swig python2.7-dev libedit-dev libncurses5-dev

LLVMのソースの取得と展開

Download LLVM releases

からビルドしたいバージョンのソースをダウンロードします。

LLVM本体以外のソースは既定の場所に既定のフォルダ名で配置する必要があるようです。
基本的にはtoolsディレクトリかprojectsディレクトリのどちらかのようです。

ドキュメントではビルドの手順として、svnやgitからtrunkのコードを落としてきてビルドする形で書かれていますが一応リリースされたバージョンでビルドを試したいと思います。

この記事を書いている時点だと5.0.1が最新になります。

コマンド実行例

ソースの取得・展開とか、cmakeのコマンドは長くなるので試してみたコマンド例を挙げておきます。
以下、試したコマンド実行例です。
LLDBはビルドにこけたのでとりあえず除外してみました。
LLDB以外の全部入りですが、とりあえずビルドしてみたいという方は以下のコマンドをシェルスクリプトとして保存して叩いてもらえればビルドできると思います。私の手元の環境では、32bitと64bitのMintの環境でビルドが通りました。


# ビルドに必要なパッケージをインストール
sudo apt-get install clang cmake git g++

# OpenMP関係のパッケージをインストール
# OpenMPのビルドをしないのであれば不要
sudo apt install openmpi-bin openmpi-common libopenmpi-dev

# LLDBで必要になるパッケージのインストール
# LLDBをビルドしないのであれば不要
sudo apt-get install build-essential subversion swig python2.7-dev libedit-dev libncurses5-dev

# LLVM作業用ディレクトリの作成・移動
mkdir ~/clang-llvm
cd ~/clang-llvm

# ninjaのビルド
# ninja は apt で install するバージョンが古いのでgitから最新版を使った方がよいみたい
# ninjaを使わない場合は不要(makeより早いらしいけど違いはいまいちよくわかっていない)

cd ~/clang-llvm
git clone https://github.com/martine/ninja.git
cd ninja
git checkout release
./bootstrap.py
sudo cp ninja /usr/bin/


cd ~/clang-llvm
# ソースの取得 version5.01の場合
wget http://releases.llvm.org/5.0.1/llvm-5.0.1.src.tar.xz
wget http://releases.llvm.org/5.0.1/cfe-5.0.1.src.tar.xz
wget http://releases.llvm.org/5.0.1/compiler-rt-5.0.1.src.tar.xz
wget http://releases.llvm.org/5.0.1/libcxx-5.0.1.src.tar.xz
wget http://releases.llvm.org/5.0.1/libcxxabi-5.0.1.src.tar.xz
wget http://releases.llvm.org/5.0.1/libunwind-5.0.1.src.tar.xz
wget http://releases.llvm.org/5.0.1/lld-5.0.1.src.tar.xz
wget http://releases.llvm.org/5.0.1/lldb-5.0.1.src.tar.xz
wget http://releases.llvm.org/5.0.1/openmp-5.0.1.src.tar.xz
wget http://releases.llvm.org/5.0.1/polly-5.0.1.src.tar.xz
wget http://releases.llvm.org/5.0.1/clang-tools-extra-5.0.1.src.tar.xz
wget http://releases.llvm.org/5.0.1/test-suite-5.0.1.src.tar.xz


# 展開
tar xfv llvm-5.0.1.src.tar.xz
tar xfv cfe-5.0.1.src.tar.xz
tar xfv compiler-rt-5.0.1.src.tar.xz
tar xfv libcxx-5.0.1.src.tar.xz
tar xfv libcxxabi-5.0.1.src.tar.xz
tar xfv libunwind-5.0.1.src.tar.xz
tar xfv lld-5.0.1.src.tar.xz
tar xfv lldb-5.0.1.src.tar.xz
tar xfv openmp-5.0.1.src.tar.xz
tar xfv polly-5.0.1.src.tar.xz
tar xfv clang-tools-extra-5.0.1.src.tar.xz
tar xfv test-suite-5.0.1.src.tar.xz

# 各プロジェクトをllvmソースディレクトリへ移動
# プロジェクトによってllvm以下への配置先が異なるので注意
mv cfe-5.0.1.src llvm-5.0.1.src/tools/clang
mv compiler-rt-5.0.1.src llvm-5.0.1.src/projects/compiler-rt
mv libcxx-5.0.1.src llvm-5.0.1.src/projects/libcxx
mv libcxxabi-5.0.1.src llvm-5.0.1.src/projects/libcxxabi
mv libunwind-5.0.1.src llvm-5.0.1.src/runtimes/libunwind
mv lld-5.0.1.src llvm-5.0.1.src/tools/lld

# 注意 lldbはビルドに失敗するようなのでの配置は行わない
#mv lldb-5.0.1.src llvm-5.0.1.src/projects/lldb
mv openmp-5.0.1.src llvm-5.0.1.src/projects/openmp
mv polly-5.0.1.src llvm-5.0.1.src/tools/polly
mv clang-tools-extra-5.0.1.src llvm-5.0.1.src/tools/clang/tools/extra
mv test-suite-5.0.1.src llvm-5.0.1.src/projects/test-suite

mkdir build
cd build

# ######################################################
# cmakeコマンドの実行
# ビルドに使用するコンパイラにclangを指定
# ######################################################
# ninjaを使うビルドの場合
cmake -G "Ninja" -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=Release -DLLVM_USE_LINKER=gold -DLLVM_BUILD_TEST=ON CMAKE_INSTALL_PREFIX=/usr/local ../llvm-5.0.1.src
# makeの場合
# cmake -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=Release -DLLVM_USE_LINKER=gold -DLLVM_BUILD_TEST=ON -DCMAKE_INSTALL_PREFIX=/usr/local ../llvm-5.0.1.src

# ビルド実行
ninja

# インストールするとき(ninja は make 互換なんだろうか)
#ninja install

cmakeコマンドのオプションについて

LLVMのビルドで使用するオプションはたくさんあります。
なので上記のコマンドの実行例では「とりあえずこれでいいかな!?」程度に指定しています。不要な設定とか、逆に不足したりしているオプションがあるかもしれません。

オプションの解説

cmakeを実行するときのオプションについて少し解説・補足を書いておきたいと思います。

-G "Ninja"
これはcmakeで出力するファイルの形式を指定するオプションです。LLVMではninja(ninjaってnanja!?)というビルドシステムを利用することが推奨されています。
でも別にmakeでもビルドはできるのでmakeを使いたい人はこのオプションは不要です。

-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang


これはビルドで使用するコンパイラの指定です。
gccでビルドしたいという場合は不要ですが、GCCだとビルドがバグ落ちするようなのでこれは必須と考えていいでしょう。C言語で書かれているコードはなさそうですので恐らくDCMAKE_C_COMPILERは要らないと思いますが念のためつけています。

-DCMAKE_BUILD_TYPE=Release
リリースビルドの指定です。
リンクエラー(リンカがかえってこない)対応として、このオプションをつけた方がよいようです。

-DLLVM_USE_LINKER=gold
リンク時に使用するリンカの指定です。
こちらもldだとリンクエラー(リンカがかえってこない)対応としての指定です。


-DLLVM_BUILD_TEST=ON
LLVMユニットテストを有効にする場合のオプションです。デフォルトだとOFFになっており必須ありません。
OFFにするとビルド時間が短縮できると思います。

-DCMAKE_INSTALL_PREFIX=/usr/local

インストール先のプレフィックスです。
デフォルトだと/usr/ 以下に展開されるので/usr/localに指定しています。

参考書籍

LLVMに関する参考書籍は日本語ではあまり出ていないようですが、手元にLLVM/Clang実践活用ハンドブックという書籍があります。
2014年に出版された書籍で、書籍で扱われているLLVMのバージョンは3.4になります。
ですので、今回の記事で書いたビルドに関する内容は現状と異なりますが、ビルド時のオプションなどは変わっていないものも多いので参考になりました。またLLVM IRやlibtooling等に関して丁寧に記載してくださっているので分かりやすかったです。

LLVM/Clang実践活用ハンドブック

LLVM/Clang実践活用ハンドブック

感想

libLTO.so というお化けライブラリ

リンカが返ってこなくなってシグナルにビルドプロセスが殺されるのを初めてみた・・・
libLTO.soはリリースビルドしたモジュールで45MB程度ありました。

やたらといろんなアーカイブファイルをまとめているのがこのlibLTO.soというファイルのようですが、なんでこんなでかいのか・・
とりあえずこいつのリンクエラーのせいでビルドが止まる場合は、ビルドマシンのメモリサイズを増やしたり、あとHDDじゃなくてSDD使うのが効果的のようです。

C++の現在と未来

LLVMは基本的にC++で開発されています。
C++のモダンな機能はなにかと便利ですが、GettingStartedでも触れられているように、

「仕様に厳密に追従できているコンパイラってあるの!?」

という疑問がどうしても湧いてきます。

C++の使用は今後も拡張されていくのでしょうけど、拡張された仕様に対して「コンパイラにバグが無いこと」はどの程度保証されるのかは興味深い点です。
あとClangにはC++コンパイラが当然含まれますが、C++コンパイラC++で書くっていうのはC++まともに使えない自分からすると、攻めてるなぁと感じます。

まとめ

LLVMプロジェクトは巨大すぎてどっから手をつけていいのかよく分からんというのが正直なところです。
いろいろ試してみましたが、とりあえず遊ぶ分にはビルドせず、パッケージインストールして使うのが正解かもしれません。

そもそもやりたかったことはlibToolingとか使ってみたかっただけなのになんでこんなことしているんだろう・・・