ParaView (v5.1.2) のビルド

## はじめに
卒業研究でCentOS7.2でParaView5.1.2をビルドすることが必要になりました。
「ParaViewのWikiにやり方が載ってるみたいだし余裕でしょ」とか思ってたんですが、いざやってみたら地獄を見ました。コンパイルに何度挑戦しても途中でエラーで止まる。ようやくコンパイルが通っても、使ってみるとエラーが出て使い物にならずやり直し。
Wikiの情報がガバガバ過ぎです。なんで肝心な部分は抜けてるんですかね…。

かなりしんどかったのでここにやり方をメモっときます。ParaViewをビルドして使う羽目になった方の参考になれば幸いです。
(他のディストリビューションでも同様にやればできるかと思います)

__正直なところ、この記事に誤りが全く無いと断言できないのが実情です。筆者の勘違いやネットで拾った情報の誤りなどがあるかもしれません。(筆者がチェックした範囲内では動作は正常でした)__

(2017/3/13追記)
最近になってParaViewのSuperBuildというものができたようです。
これを使ったほうが楽にビルドできるかもしれません。
https://gitlab.kitware.com/paraview/paraview-superbuild/

## ParaViewのビルド
ParaViewは公式ページ([http://www.paraview.org/download/](http://www.paraview.org/download/))からインストーラをダウンロードしてあげれば、簡単にインストールできます。普通に使う分にはこれで問題ありません。

しかし、場合によってはソースコードからビルドして使わなければならない場合があります。例えば、OSMesaを使ったレンダリングをしたい場合や、レンダリングサーバのみが必要でParaViewのGUIは不要だという場合、自分でソースコードを改変して使いたい場合などです。
__今回はGUI無しでレンダリングサーバのみのビルドを行います。__

### OSMesa
ParaViewはレンダリングにOpenGL (コンピュータグラフィックスのライブラリ) を利用しています。さらにOpenGLUというOpenGLの機能を拡張するためのライブラリも利用しています。
ParaViewはこれらをGPUが搭載された環境で使用することを前提としているため、GPUが搭載されていない環境では利用できません。
そのようなときに利用するのがOSMesaというライブラリです。これを使うことでGPUではなくCPUを用いてOpenGLによるレンダリングを行うことができます。

### 共有ライブラリ
ParaViewに限った話ではないですが、ビルドする際には「共有ライブラリ」というものをよく扱います。これは拡張子が".so"となっているライブラリのファイルです。
このファイルの中にはコンパイル済みのいろいろな処理を行うための関数が格納されていて、プログラムの実行時にロードされて使われます。これは複数のプログラム間で共有して使われるようになっています。
".so.0"のように拡張子がちょっと違っているライブラリもありますが、基本的には拡張子が".so"となっているファイルを選んで使ってください。

前置きが長くなりましたが、具体的な手順を以下に書いていきます。
かなり時間がかかる (多めに見積もって2~3時間程度) ので、時間に余裕のあるときに行ってください。

## ビルドの手順
ParaViewのビルドは、以下のような手順で行います。

1. ビルドに必要なソフトウェアのインストール
2. 依存関係にあるライブラリのインストール
3. ParaViewのソースコードの入手・サブモジュールのコンパイル
4. ParaView本体のコンパイル

余談ですが、筆者が地獄を見たのは3.と4.でした。(2.でも割と苦しみましたが…)
### 1. ビルドに必要なソフトウェアのインストール
#### 必要なソフトウェア
ParaViewのコンパイルに必要なのは以下のソフトウェアです。
　GCC, GCC-C++, Make, CMake, Git, MPICH or OpenMPI

__＊重要＊__
__MPICHとOpenMPIは両方インストールしてしまうと競合して不具合が出ます。どちらか片方だけを選んでインストールしてください。__

#### (1) yumでインストール
CMake以外をyumコマンドでインストールしていきます。(__develパッケージを忘れずに！__)

```bash
# 必要なパッケージをインストール
$ sudo yum -y update
$ sudo yum -y install gcc gcc-c++ llvm llvm-devel make git
# MPICHを利用する場合
$ sudo yum -y install mpich mpich-devel
# OpenMPIを利用する場合
$ sudo yum -y install openmpi openmpi-devel
```

#### (2) CMakeのインストール
CMakeのダウンロードページ([https://cmake.org/download/](https://cmake.org/download/))にあるCMakeのインストーラを使います。(筆者はcmake-3.6.2.tar.gzを使用しました)

CMakeはyumコマンドでもインストール可能ですが、2016年10月現在ではバージョンが2.8.11とちょっと古いみたいです。このバージョンでも正常にインストールできるかは確かめていません。(多分上手く動かないかも)

```bash
# ソースコードのダウンロード
$ curl -O https://cmake.org/files/v3.6/cmake-3.6.2.tar.gz
$ tar -xvf cmake-3.6.2.tar.gz
$ cd cmake-3.6.2
# ビルドしてインストール
$ ./configure
$ gmake
$ sudo gmake install
```

これでCMakeのインストールは終了です。インストール後はcmake-3.6.2のディレクトリを削除しても構いません。

### 2. 依存関係にあるライブラリのインストール
#### 必要なライブラリ
ParaViewのビルドに必要なのは以下のライブラリです。
　Python, Boost, FFmpeg, OpenGLとOpenGLU or OSMesa

__＊重要＊__
__特に希望が無いならOpenGLを使うのが普通です。
GPUがない環境でレンダリングを行いたい場合にのみ、OSMesaを使ってください。
GPUがあるのにわざわざOSMesaを使うのは避けたほうが無難です。 (CPUレンダリングはGPUレンダリングに比べて格段にパフォーマンスが落ちます)__
#### (1) yumでインストール
まずFFmpegとOpenGL(OSMesa)以外のライブラリをyumコマンドでインストールしていきます。(__develパッケージを忘れずに！__)

```bash
$ sudo yum -y install python python-devel boost boost-devel
```

#### (2) FFmpegの共有ライブラリのインストール
__FFmpegはyumコマンドでインストールしてはいけないということに注意が必要です。__ ParaViewのコンパイルに必要なのはFFmpegのソフトウェアではなく共有ライブラリなので、ソースコードからコンパイルして共有ライブラリを作ってあげることが必要だからです。

この操作は以下のコマンドで行います。

```bash
# ソースコードをダウンロード
$ git clone https://github.com/FFmpeg/FFmpeg FFmpeg
$ cd FFmpeg
# 共有ライブラリのインストール
$ ./configure --disable-x86asm --enable-shared
$ make -j4
$ sudo make install
```

configureの実行の際に--enable-sharedというオプションをつけることで、FFmpegの共有ライブラリが作られます。インストール後は、GithubからダウンロードしたFFmpegのディレクトリは消してしまってOKです。

#### (3) OpenGL or OSMesaのインストール
次にOpenGL or OSMesaをインストールします。自分の希望にあった方を選んで行ってください。
##### OpenGLを利用する場合
OpenGLのインストールは次のyumコマンドを実行するだけでOKです。\*(ワイルドカード)は必ず必要です。
MesaというのはOpenGLの実装の一つで、Linuxで使われるものだそうです。

```bash
$ sudo yum -y install mesa*
```

##### OSMesaを利用する場合
ParaViewに必要なOSMesaは、Gallium llvmpipeを組み込んでコンパイルされている必要があります。__yumコマンドでインストールしたOSMesaをそのまま使うことはできないので注意しましょう。__
Gallium llvmpipeというのはGallium3Dというライブラリを利用するグラフィックドライバの1種だそうです。(あんまり自信ないですが)

まずflex,bison,zlib, Autotools(autoconf, automake, libtool)をyumコマンドでインストールしておきます。これらが無いとコンパイルが通りません。(__zlibは必ずdevelとstaticも揃えましょう__)

```bash
$ sudo yum -y install flex flex-devel bison bison-devel zlib zlib-devel zlib-static autoconf automake libtool
```

次にOSMesaのソースコードをダウンロードし、解凍します。(筆者はmesa-12.0.3.tar.gzを利用しました)

```bash
$ curl -O https://mesa.freedesktop.org/archive/12.0.3/mesa-12.0.3.tar.gz
$ tar -xvf mesa-12.0.3.tar.gz
$ cd mesa-12.0.3
```

次にダウンロードしたディレクトリ内でautogen.shを実行します。オプションをたくさんつける必要があるので、以下のようにシェルスクリプト(install_mesa.sh)を書いて実行すると楽です。
(各オプションの意味はよく分かりませんでした…申し訳ありません)

__＊重要＊__
__configureを使うとpthread_stubs絡みのエラーが出ますので使わないでください。__(詳しくは以下で説明)
__また、スクリプト内において、autogen.shを実行する前に、以下のシェルスクリプト内にある2つのsedコマンドを実行するようにしてください。これが無いとエラーが出てコンパイルできません。__
1行目のsedは`pthread_stubs`というパッケージへの依存を無効化するためのものです。(`pthread_stubs`はLinuxでは不要です)
2行目のsedは`libtool`からのWarningを無視するためのものだそうです。(これについてはよく分かりません…)

```sh:install_mesa.sh
#!/bin/bash
sed -i "/pthread-stubs/d" configure.ac
sed -i "/seems to be moved/s/^/: #/" bin/ltmain.sh
bash autogen.sh --disable-xvmc \
                --disable-glx \
                --disable-dri \
                --with-dri-drivers= \
                --with-gallium-drivers=swrast \
                --disable-shared-glapi \
                --enable-texture-float \
                --disable-egl \
                --with-egl-platforms= \
                --enable-gallium-osmesa \
                --enable-gallium-llvm=yes \
                --disable-gles1 \
                --disable-gles2 \
                --prefix=<install prefix>
```

上記のスクリプトを実行することでMakefileを生成します。
上手くいったらmakeコマンドを実行してインストールしましょう。

```bash
$ bash install_mesa.sh
$ make -j4
$ sudo make install
```

これでGallium llvmpipeが組み込まれたOSMesaをインストールできます。
最後にlibGLUと、libGLUとlibOSMesaのdevelパッケージをインストールしておきます。
__OSMesaを使う場合はlibGLは不要ですが、libGLUは必要になります。
develパッケージも忘れずに。__

```bash
$ sudo yum -y install mesa-libGLU mesa-libGLU-devel mesa-libOSMesa-devel
```

### 3. ParaViewのソースコードの入手・サブモジュールのコンパイル
ParaViewのソースコードはGitHubからクローンしてくればOKです。

```bash
$ git clone https://github.com/Kitware/ParaView.git  ParaView_src
```

__＊重要＊__
__クローンした後は必ず以下のコマンドを実行しましょう。__
(これを忘れるとコンパイルに必要なモジュールが不足してエラーが出たり、コンパイル後にバージョン不明瞭が原因のエラーが出たりします)

```bash
# コンフィグとバージョン指定
$ cd ParaView_src
$ git config submodule.VTK.url https://github.com/Kitware/VTK.git
$ git checkout v5.1.2 # ここで所望のバージョンを指定してください
# サブモジュールのコンパイル
$ git submodule init
$ git submodule update
```

git checkoutを実行すると警告メッセージが表示されますが、無視しても大丈夫です。
git submodule updateによって、先にParaViewのモジュールのコンパイルが行われます。このモジュールにはIceT(タイルドディスプレイへの描画処理を行うライブラリ)・VisItBridge(扱えるデータの種類を増やすためのプラグイン)・VTK(レンダリング処理を行うソフトウェア)などがあります。(この辺の細かい中身については分からなくても問題ありません)

### 4. ParaView本体のコンパイル
最後にParaView本体のコンパイルを行います。
__まずParaViewのソースコードが入ったディレクトリ(ParaView_src)の外に、新しいディレクトリを作ってその中に移動しておきます。__
新しいディレクトリ内で作業しないとエラーが出ます。
(筆者はbuildという名前のディレクトリを作りました)

```bash
$ cd ..
$ mkdir build
$ cd build
```

次に、Makefileを作るためにCMakeを実行します。
OpenGLを使う場合とOSMesaを使う場合とで内容が違うので注意してください。
cmakeコマンドに大量のオプション(-D)をつける必要があるので、やり直しや確認がしやすいように以下のようなシェルスクリプト(install.sh)を書いて実行するようにしましょう。

__＊重要＊__
__人によって各ライブラリやディレクトリのパスが異なっている可能性大です。
下のスクリプトをただコピペするのではなく、一通り目を通して、書き換えるべき箇所があれば書き換えてください。
オプション中のパスがおかしいときはエラーが出ます。このときは、エラーで指摘されたライブラリやディレクトリのパスを自分の環境に合わせて書き換えてやり直してください。
特に、OpenMPI使ってる人はMPI関連のオプションを必ず書き換えておいてください。__

__注意1：実行する際は各オプション横の\の隣の\#コメントを消してください。__ (そのままだとオプションが無効になります)
__注意2：\の右側に余計な空白やタブが入っていると、そこでオプションの読み込みが止まってしまい、エラーの原因になります。(気づきにくいので注意)__

#### OpenGLを使う場合

```sh:install.sh
#!/bin/bash
cmake -D BUILD_DOCUMENTATION:BOOL=OFF \ # ドキュメントのビルド(任意)
      -D BUILD_EXAMPLES:BOOL=ON \ # サンプルファイルのビルド(任意)
      -D BUILD_SHARED_LIBS:BOOL=ON \ # 共有ライブラリのビルド(ON)
      -D BUILD_TESTING:BOOL=OFF \ # ビルドのテスト(OFF)
      -D CMAKE_BUILD_TYPE=Release \ # ビルドのタイプ(リリース版)
      -D CMAKE_INSTALL_PREFIX=/home/kkk627 \ # ビルドの生成物が置かれるパス(任意)
      -D PARAVIEW_BUILD_QT_GUI:BOOL=OFF \ # GUIのビルド(OFF)
      -D PARAVIEW_DATA_ROOT=/home/kkk627 \ # データを開く際のデフォルトの参照先(任意)
      -D PARAVIEW_ENABLE_COPROCESSING:BOOL=ON \ # コプロセシングの許可(ON)
      -D PARAVIEW_INSTALL_DEVELOPMENT_FILES:BOOL=ON \ # develファイルのインストール(ON)
      -D PARAVIEW_USE_VISITBRIDGE:BOOL=ON \ # VisItBridgeの利用(ON)
      -D PARAVIEW_USE_BOOST:BOOL=ON \ # Boostの利用(ON)
      -D VTK_RENDERING_BACKEND=OpenGL2 \ # レンダリングに使うライブラリ(OpenGL2)
      -D VTK_USE_X:BOOL=ON \ # X Window Systemの利用(ON)
      -D OPENGL_INCLUDE_DIR=/usr/include \ # OpenGLのヘッダファイルを含むディレクトリ
      -D OPENGL_gl_LIBRARY=/usr/lib64/libGL.so \ # OpenGLの共有ライブラリ
      -D OPENGL_glu_LIBRARY=/usr/lib64/libGLU.so \ # OpenGLUの共有ライブラリ
      -D PARAVIEW_ENABLE_PYTHON:BOOL=ON \ # Pythonの利用(ON)
      -D PYTHON_LIBRARY=/usr/lib64/libpython2.7.so \ # Pythonの共有ライブラリ
      -D PYTHON_INCLUDE_DIR=/usr/include/python2.7 \ # Pythonのヘッダファイルを含むディレクトリ
      -D PYTHON_EXECUTABLE=/usr/bin/python \ # Pythonの実行ファイル
      -D PARAVIEW_USE_MPI:BOOL=ON \ # MPIの利用(ON)
      -D MPI_C_LIBRARIES=/usr/lib64/mpich/lib/libmpich.so \ # CのMPI共有ライブラリ
      -D MPI_C_INCLUDE_PATH=/usr/include/mpich-x86_64 \ # CのMPIヘッダファイルを含むディレクトリ
      -D MPI_Fortran_LIBRARIES=/usr/lib64/mpich/lib/libmpichf90.so \ # FotranのMPI共有ライブラリ
      -D MPI_Fortran_INCLUDE_PATH=/usr/include/mpich-x86_64 \ # FortranのMPIヘッダファイルを含むディレクトリ
      -D MPI_CXX_INCLUDE_PATH=/usr/include/mpich-x86_64 \ # C++のMPIヘッダファイルを含むディレクトリ
      -D MPI_CXX_LIBRARIES=/usr/lib64/mpich/lib/libmpichcxx.so \ # C++のMPI共有ライブラリ
      -D PARAVIEW_ENABLE_FFMPEG:BOOL=ON \ # FFmpegの利用(ON)
      -D VTK_USE_FFMPEG_ENCODER:BOOL=ON \ # FFmpegエンコーダの利用(ON)
      -D FFMPEG_INCLUDE_DIR=/usr/local/include \ # FFmpegのヘッダファイルを含むディレクトリ
      -D Boost_INCLUDE_DIR=/usr/include \ # Boostのヘッダファイルを含むディレクトリ
      /root/ParaView_src # ParaViewのソースコードを含むディレクトリを指定(これはオプションではなく引数)
```

#### OSMesaを使う場合
```sh:install.sh
#!/bin/bash
cmake -D BUILD_DOCUMENTATION:BOOL=OFF \ # ドキュメントのビルド(任意)
      -D BUILD_EXAMPLES:BOOL=ON \ # サンプルファイルのビルド(任意)
      -D BUILD_SHARED_LIBS:BOOL=ON \ # 共有ライブラリのビルド(ON)
      -D BUILD_TESTING:BOOL=OFF \ # ビルドのテスト(OFF)
      -D CMAKE_BUILD_TYPE=Release \ # ビルドのタイプ(リリース版)
      -D CMAKE_INSTALL_PREFIX=/home/kkk627 \ # ビルドの生成物が置かれるパス(任意)
      -D PARAVIEW_BUILD_QT_GUI:BOOL=OFF \ # GUIのビルド(OFF)
      -D PARAVIEW_DATA_ROOT=/home/kkk627 \ # デフォルトのデータ読込の参照先(任意)
      -D PARAVIEW_ENABLE_COPROCESSING:BOOL=ON \ # コプロセシングの許可(ON)
      -D PARAVIEW_INSTALL_DEVELOPMENT_FILES:BOOL=ON \ # develファイルのインストール(ON)
      -D PARAVIEW_USE_VISITBRIDGE:BOOL=ON \ # VisItBridgeの利用(ON)
      -D PARAVIEW_USE_BOOST:BOOL=ON \ # Boostの利用(ON)
      -D OPENGL_INCLUDE_DIR=/mesa-12.03/include \ # mesaのincludeを指定
      -D OPENGL_xmesa_INCLUDE_DIR= \ #OpenGL_xmesaは指定しない
      -D OPENGL_gl_LIBRARY= \ # OpenGLは指定しない
      -D OPENGL_glu_LIBRARY=/lib64/libGLU.so \ # OpenGLUは指定する
      -D VTK_USE_X:BOOL=OFF \ # X Window Systemの利用(OFF)
      -D VTK_OPENGL_HAS_OSMESA:BOOL=ON \ # OSMesaの有無(ON)
      -D VTK_USE_OFFSCREEN:BOOL=ON \ # オフスクリーンレンダリング(ON)
      -D OSMESA_INCLUDE_DIR=/usr/include \ # OSMesaのヘッダファイルを含むディレクトリ
      -D OSMESA_LIBRARY=/mesa-12.0.3/lib/gallium/libOSMesa.so \ # OSMesaの共有ライブラリ
      -D PARAVIEW_ENABLE_PYTHON:BOOL=ON \ # Pythonの利用(ON)
      -D PYTHON_LIBRARY=/usr/lib64/libpython2.7.so \ # Pythonの共有ライブラリ
      -D PYTHON_INCLUDE_DIR=/usr/include/python2.7 \ # Pythonのヘッダファイルを含むディレクトリ
      -D PYTHON_EXECUTABLE=/usr/bin/python \ # Pythonの実行ファイル
      -D PARAVIEW_USE_MPI:BOOL=ON \ # MPIの利用(ON)
      -D MPI_C_LIBRARIES=/usr/lib64/mpich/lib/libmpich.so \ # CのMPI共有ライブラリ
      -D MPI_C_INCLUDE_PATH=/usr/include/mpich-x86_64 \ # CのMPIヘッダファイルを含むディレクトリ
      -D MPI_Fortran_LIBRARIES=/usr/lib64/mpich/lib/libmpichf90.so \ # FortranのMPI共有ライブラリ
      -D MPI_Fortran_INCLUDE_PATH=/usr/include/mpich-x86_64 \ # FortranのMPIヘッダファイルを含むディレクトリ
      -D MPI_CXX_INCLUDE_PATH=/usr/include/mpich-x86_64 \ # C++のMPIヘッダファイルを含むディレクトリ
      -D MPI_CXX_LIBRARIES=/usr/lib64/mpich/lib/libmpichcxx.so \ # C++のMPI共有ライブラリ
      -D PARAVIEW_ENABLE_FFMPEG:BOOL=ON \ # FFmpegの利用(ON)
      -D VTK_USE_FFMPEG_ENCODER:BOOL=ON \ # FFmpegエンコーダの利用(ON)
      -D FFMPEG_INCLUDE_DIR=/usr/local/include \ # FFmpegの共有ライブラリを含むディレクトリ
      -D Boost_INCLUDE_DIR=/usr/include \ # Boostのヘッダファイルを含むディレクトリ
      /root/ParaView_src # ParaViewのソースコードを含むディレクトリを指定
```

#### インストールの実行
上のスクリプトを使ってCMakeを実行します。

```bash
$ bash install.sh
```

上手くいけばMakefileが生成されるはずです。
次にmakeコマンドを実行してコンパイルしていきましょう。
量が非常に多いのでかなり時間がかかります。(多めに見て1時間くらい？)

```bash
$ make -j4
$ sudo make install
```

これでParaViewのビルドは終了です。お疲れ様でした。

## おわりに
筆者はQiitaの記事の執筆が初めてだったので、分かりにくい点等あったかもしれません。事前にCentOS7.2のVM上でコマンドを実行してエラーが出ないことを確認しましたが、万が一間違っている点がございましたら、ご連絡お願いします。