エンドユーザ向け、CMakeの使い方


たまにオープンソースライブラリを自前ビルドするときにcmakeを使う必要があるので、そのための覚書。

コンセプト

GNUのツールチェーンの場合

$ cd /path/to/sourcedir
$ ./configure --some-option --another-option
...
$ make
$ sudo make install

のようにするけれど、CMakeの場合はconfigureに対応する部分を対話的・逐次的に行なっていくことができる。CMakeは最終産物としてビルドスクリプト(Makefileなど)を生成するので、以降はほぼGNUの場合と同じで、makeからsudo make installすればよい。

configureにありがちな、長ったらしいオプションをいちいち入力する必要がないのは特長といえば特長。ただ使い方(特にエンドユーザ向けの)がいまいち充実していないのが問題といえば問題。

ビルドの時に進捗状況がパーセンテージで出てきたり、ターゲットやらプロセスやらによって色が変わったりするのも特色かもしれないけれど、これは人を選ぶと思う。

インストール

方法はいくつかある:

  1. 公式サイトからソースあるいはバイナリをダウンロード (Download | CMake)
  2. OSのパッケージマネージャ(apt、homebrewなど)からcmakeパッケージをインストール

ソースからのビルドで特筆すべきは、自分が今持っているQtを使ったGUIを作ってくれること(バイナリを落とした場合は、代わりにQtのdllが一緒についてくる)。ただ少なくともMacでビルドしようとしたところ、どうもQtライブラリとのリンクがうまくいっていないらしく".app"バンドルが起動できなかった。どこかでライブラリの場所を設定する項目があったのか、地道にライブラリパスを更新したりする必要があるのかは不明…。

一般的なビルドの流れ

繰り返しになるけれど、これはエンドユーザ(ビルドするだけの人)向け。自分のプロジェクトにCMakeを使う場合は、使い方が詳しく説明されたサイトがそれなりにあるので、そちらを見るべし。

参考:Building VTK with python bindings in linux (arch)

CMakeLists.txt

CMakeでの構成に必要な情報は、ソースディレクトリ中のCMakeLists.txtという名前のスクリプトに保存されている。中身を見れば、だいたい何をしているのかわかるはず。

このファイルがなければ、cmakeはエラーを吐くので注意。

ビルドディレクトリ

GNUツールチェーンの場合、ビルドされるプログラムやオブジェクトファイルはソースディレクトリと同じ場所に暗黙的に生成されていくため、これらを一掃したいときに面倒が起きることがある(このため、一般的にmakeにはcleanというターゲットがある)。

これに対してCMakeでは、ビルド用に別のディレクトリを作ることを推奨している。これはソースディレクトリ内に作ってもよいし、ソースディレクトリとは全く別の場所に作っても構わない。こうすることで、

  • ソースディレクトリを常にソース・リソースファイルのみの状態に保てる
  • ビルド産物を一掃したいときには、ビルドディレクトリを削除すればよい

という関心の分離が実現できる。

またこのような事情から、cmakeあるいはccmake(後述)の起動の際には「ビルドディレクトリに移動して」「ソースディレクトリの参照を引数に」プログラムを呼ぶ、という操作が一般的になる:

$ cd /path/to/builddir && cmake /path/to/sourcedir

大まかな流れ

CMakeでは、逐次的に"configure"を実行していくことでビルド構成を設定していく。設定後、"generate"によってビルドスクリプト(Makefileなど)を生成する。環境によっては、Visual Studioのソリューションファイルを作ることもできる。

  1. 最初の"configure"で、デフォルトの構成オプションが設定される。
  2. 構成オプションを変更する。
  3. "configure"を呼び直すと、その構成オプションのためにさらに必要なオプションが改めて読み込まれる。
  4. 上2ステップを繰り返していき、最終的にオプションが更新されなくなったら「構成が固まった」ということになる。
  5. "generate"でビルドスクリプトを生成する。
  6. コマンドライン上でmake && sudo make installを行う。

"Configure"の仕方は、コマンドライン上で行うやり方とGUIで行うやり方の2通りがある。

コマンドラインからの"configure"

ビルドディレクトリでcmake <sourcedir>を実行した後、改めてccmake ..を呼ぶ。変更したい構成が特にない場合は、次のステップに直接進んでよい。

  1. curses的なCUIが表示されるので、キーボードを用いてスクロール・編集していく。
  2. 上2/3くらいが構成オプションのリスト、下1/3がコマンドのヘルプ。間の黒地・白抜きのところがステータスメッセージ。
  3. よく見ると、オプションのリストの上の方(多分黒いところ)にカーソルがある。そこが、現在編集モードになっているオプションを表している。
  4. 矢印キーで移動、Enterキーで決定。トグルタイプ(ON/OFF)の場合は、Enterを押すたびに状態が変わる。
  5. 構成を変更せずに中止したい場合、'q' (quit)のキーを押す。
  6. 編集した構成を適用したい場合、'c' (configure)のキーを押す。CMakeは与えられたオプションに応じた環境変数の更新を行なってくれる。問題があればエラーが表示され、構成の適用が中止される。

構成に問題がなければ、ccmake上で'g' (generate)のキーを押してMakefileを作成する。(自分の環境では、構成が終わるとまた編集モードに戻ってしまいMakefileの作成ができなかった。'c'と'g'をほぼ同時に続けて押すことで作成できた)

GUIを使った"configure"

  1. GUIを起動し、ソースディレクトリとビルドディレクトリを設定。この状態では、何の構成オプションも出てきていないはず。
  2. 下の方にある"Configure"ボタンをクリックすると、ソースディレクトリ中のCMakeLists.txtが読み込まれ、構成オプションが出てくる(ccmakeでのcキーに相当)。左側のカラムにオプションの名前が、右側のカラムにその設定値が表示されているはず。個々の設定値のところにカーソルを持っていくと、そのオプションの説明が(望むらくは)表示される。
  3. 必要に応じて構成オプションを更新・変更する。例えばどういう種類のライブラリを作るかとか、どういうモジュールを作るか、という項目が更新可能なはず。
  4. 更新・変更のたびに、"Configure"ボタンを押し直す。その都度CMakeLists.txtが実行され、新しく設定されたオプションについてより詳細な設定項目が現れることがある。新しく読み込まれた項目・エラーの出た項目は、赤地で表示される。

"Configure"してもオプションが新しく表示されなくなったら構成の設定が終わったということになるので、隣にある"Generate"ボタンを押す。以降はmake && sudo make installで構わないのだけれど、これはコマンドライン上で行わないといけない…?XcodeあるいはVisual Studioのプロジェクトとして生成すれば、そちらを使用することはできるはず。

うまくいかないとき

上記の方法でうまくいけば御の字だけれども、たまにCMakeのスクリプトの挙動や本人の勘違いのせいで構成あるいはビルドがうまくいかないときがある。ほぼ全ての問題は、以下の問題に帰着する:

  • 必要なライブラリがインストールされていない
  • インクルードディレクトリとして、不適切なディレクトリが指定されている。
  • リンク先ライブラリとして、不適切なライブラリが指定されている。

最初の問題の場合はなんとかインストールするか、インストールせずにすむ方法を考える。あと2つの問題が生じるのはたいがい、バージョンの異なるライブラリが別々の場所にインストールされている場合。PATHやらなんやらの関係で、「見つからない」あるいは「バージョンの古い方が先に見つかる」ということが起こる。

一応インクルードディレクトリとリンクディレクトリの役割も、念のため。

  • インクルードディレクトリは、コンパイルの際に必要になる。
  • リンクディレクトリは、リンクの際に必要になる。

PATHやLD_LIBRARY_PATHのチェック

当然といえば当然だが、当該ライブラリがあるディレクトリにパスが通っていなければライブラリは見つからない。環境変数エディタを使うなり、shrcを編集するなりexportを使うなりしてパスを更新する。パスの編集によって、見つかる順序が変わるということも起こりうる。

CMakeCache.txtのチェック

基本的な環境変数は、ビルドディレクトリ内にあるCMakeCache.txtというファイルに保存され、makeのたびに参照されている。特定のライブラリに問題がある(コンパイルやリンクがうまくいかない)ときは、CMakeCacheから該当するエントリーを探す(以下は仮のライブラリlibXXの場合):

CMakeCache.txt
...
XX_INCLUDE_PATH:path=/your/include/path
XX_LIBRARY:FILEPATH=/path/to/your/libXX.so
...

自分が現在使っている(あるいは使わせたい)ライブラリと違う場所を指している場合、まずはccmake上でうまく指定できそうか調べてみる。無理そうならCMakeCacheを編集・保存してから改めてmakeを実行する。

ちなみにXX_LIBRARY(というよりもFILEPATH型)の場合、ライブラリを内包するディレクトリではなくライブラリそのもののパスを指定する必要があることに注意。