Cmake

この文書は CMake – Linux Makefiles と make のクロスプラットフォームな代替品- の簡単な概要を提供します。 CMake なしで make や Makefile を使うためのヘルプは、 Prof. Newhall のドキュメントを参照してください。 このドキュメントは、研究室のマシンに stow でインストールされている cmake バージョン 2.6 用に書かれています(2009年1月現在)。

Why CMake

CMake が個人的に好きな理由は、標準の Makefile を書くよりも直感的であるように思われるからです。 基本的で一般的なことはとても簡単で、難しいことは可能ですが、私が作るもののほとんどはかなり基本的なものです。 CMakeのデモを行うために、私はcmake.tgzファイル(4KB)にいくつかのサンプルコードを含んでいます。 このファイルを保存して、ディレクトリの任意の場所に中身を解凍してください。 例:

$ tar xzvf cmake.tgz$ cd cmake$ lsCMakeLists.txt w01-cpp/
CMakeLists.txt

CMake は CMakeLists.txt ファイルに指示を書き込むことで制御されます。 プロジェクト内の各ディレクトリには、CMakeLists.txt ファイルがあるはずです。 CMakeの良いところは、サブディレクトリのCMakeLists.txtファイルは、親ディレクトリで設定されたプロパティを継承するので、コードの重複が少なくなることです。 今回のサンプルプロジェクトでは、サブディレクトリはw01-cppの1つだけです。 トップレベルの cmake ディレクトリの CMakeLists.txt ファイルは、非常にシンプルですが、いくつかの重要な機能を示しています。

cmake_minimum_required(VERSION 2.6)project(CMAKEDEMO)#There are lots of scripts with cmake#for finding external libraries. #see /usr/local/share/cmake-2.6/Modules/Find*.cmake for more examplesfind_package(GLUT)find_package(OpenGL)set(CMAKE_CXX_FLAGS "-g -Wall")add_subdirectory(w01-cpp)

このデモ コードには、グラフィックに外部 OpenGL ライブラリを必要とするコードが含まれています。 典型的な Makefile の設定では、OpenGL ヘッダー ファイルの場所 (例: -I/usr/local/include) や使用するライブラリ (例: -lGL -lGLU -lglut)、ライブラリの場所を指定する必要があると思われます。 ヘッダーファイルとライブラリの場所は、インストールごとに、またプラット フォームごとに異なる可能性があります。 しかし、通常は標準的な場所があり、CMakeはfind_packageマクロを使用してこの検索を自動化します。 このように find_package(GLUT) と find_package(OpenGL) はヘッダーファイルとライブラリの場所を見つけ、典型的な OpenGLプロジェクトでリンクされている最も一般的なライブラリをセットアップします。 CMakeはたくさんのパッケージを見つけるためのサポートを持っています。 usr/local/share/cmake-2.6/Modules/Find*.cmake に例があります。 これらのスクリプトの一つを使用するには、CMake スクリプトの名前が FindPKGname.cmake であれば find_package(PKGname) を使用します。

外部ライブラリの検索や独自の find パッケージマクロの作成については、このテーマに関する KitWare wiki を参照してください。

通常の Makefile で設定する共通のフラグはingset(VARNAME VALUE) で設定することが可能です。 この例では、デバッグ用シンボル (-g) とすべての警告 (-Wall) を有効にしました。 また、このCMakeプロジェクトにproject(CMAKEDEMO)という名前を付けています。 プロジェクト名は好きなようにつけてください。 この情報は、w01-cppディレクトリにあるCMakeLists.txtファイルで使用します。 最後に、トップレベルの CMakeLists.txt ファイルに add_subdirectory(w01-cpp)

サブディレクトリ w01-cpp にある CMakeLists.txt ファイルを見てみましょう:

include_directories(${CMAKEDEMO_SOURCE_DIR}/w01-cpp)link_directories(${CMAKEDEMO_BINARY_DIR}/w01-cpp)#the one C fileadd_executable(cdemo cdemo.c)target_link_libraries(cdemo m) #link the math library#these are all compiled the same wayset(PROGRAMS oglfirst pointers)set(CORELIBS ${GLUT_LIBRARY} ${OPENGL_LIBRARY} m)foreach(program ${PROGRAMS}) add_executable(${program} ${program}.cpp) target_link_libraries(${program} ${CORELIBS})endforeach(program)#building just a library. add_library(geometry geometry.cpp)add_executable(test_geometry test_geometry.cpp)#linking against a custom librarytarget_link_libraries(test_geometry ${CORELIBS} geometry)

include_directories マクロにより CMake にどこでソースファイルを探すか指示します。 トップレベルの CMakeLists.txt ファイルでプロジェクト名 CMAKEDEMO を宣言することにより、コードの現在の場所とビルド ディレクトリの現在の場所に応じて変数 CMAKEDEMO_SOURCE_DIR と CMAKEDEMO_BINARY_DIR が設定されます(この後の場所については後で詳しく説明します)。 新しいバイナリ実行ファイルのターゲットを追加するのは簡単です。 add_executable(cdemo cdemo.c)の一行を追加するだけです。 CMake はファイルタイプの拡張子からコンパイラを自動的に判断します。 もし、追加のライブラリが必要なら、target_link_libraries(cdemo m)を使ってCMakeにリンクするように指示できます。 これは、cdemo プログラムが math ライブラリに対してリンクする必要があることを CMake に伝えます。 ライブラリをリストで指定することにより、複数のライブラリにリンクすることができます。 例えば set(CORELIBS ${GLUT_LIBRARY} ${OPENGL_LIBRARY} m) を見てください。 GLUT_LIBRARY と OPENGL_LIBRARY という変数は、CMake が find_package(GLUT) と find_package(OpenGL) を使用したときに設定されます。 find_package を使ったときにどの変数が設定されるかを知るには、おそらく適切な Find*.cmake ファイルを開いて、通常は役立つが簡潔なドキュメントを読む必要があるでしょう。

この w01-cpp フォルダー内の複数のプログラムは、同じ方法でコンパイルされ、同じライブラリに対してリンクされているので、CMake の foreach マクロを使用して、上記の単純なループでそれらすべてを処理することができます。 最後に、add_library(geometry geometry.cpp) で独自のライブラリを作成し、 target_link_libraries(test_geometry ${CORELIBS} geometry) でこのライブラリにリンクする方法を紹介します。

CMake でビルドする

CMakeLists.txt ファイルの束をセットアップしても、すぐにプロジェクトをビルドできるわけではありません。 CMake は、より伝統的なビルド システムのクロス プラットフォーム ラッパーにすぎません。 linux の場合、これは make を意味します。 簡単な前処理のステップで、CMakeLists.txtの記述を従来のmakeのビルドシステムに自動的に変換してくれます。 CMakeの素晴らしい、そして強く推奨される機能の一つは、ソースからのビルドを行うことができることです。 この方法では、ソースツリーを乱雑にすることなく、すべての .o ファイル、様々な一時的な依存ファイル、そしてバイナリ実行ファイルを作ることができます。 ソース外ビルドを使用するには、トップレベルのフォルダーにビルドディレクトリを作成します(技術的には、これはどこでもかまいませんが、トップレベルのプロジェクトフォルダーが論理的な選択であるように思われます)。 次に、ビルドディレクトリに移動して、cmake を実行し、トップレベルの CMakeLists.txt のディレクトリを指定します。 例えば、

cumin$ cd cmake/cumin$ lsCMakeLists.txt w01-cpp/cumin$ mkdir buildcumin$ lsCMakeLists.txt build/ w01-cpp/cumin$ cd build/cumin$ cmake ..

Build ディレクトリで、ファイル自体ではなく、トップレベルの CMakeLists.txt ファイルを含むディレクトリにのみ cmake を指定することに注意してください。 すべてがうまくいけば、cmake は CMakeLists.txt ファイルを処理し、すべてのライブラリとインクルードパスの場所を見つけ、ビルドディレクトリに従来の Makefile を含む設定情報の束を吐き出します。 (autotools/autohell に詳しい人なら、この cmake の処理は ./configure に似ています)。 これで、伝統的な make システムを使ってビルドする準備ができました。 ビルドディレクトリで make を実行し、すべてをコンパイル、リンクします。 CMake はきれいな色やプログレスバーを表示し、gcc の出力を抑えてくれます。 冗長な出力が必要な場合は、VERBOSE=1 make と入力します (何か問題が発生したときに便利です)。

ソースからのビルドと link_directories(${CMAKEDEMO_BINARY_DIR}/w01-cpp) を設定したため、コンパイルしたばかりのバイナリは make を実行したビルド ディレクトリの w01-cpp フォルダに格納されます。

cumin$ cd w01-cpp/cumin$ lsCMakeFiles/ cdemo* libgeometry.a pointers*Makefile cmake_install.cmake oglfirst* test_geometry*cumin$ ./cdemo Sqrt(2) = 1.4142 This concludes a short C democumin$ ./oglfirst cumin$ ./test_geometry 

ESC キーを押して OpenGL デモを終了します。

まとめ

CMakeLists.txt ファイルも含めてソース ディレクトリのコードを変更し、構築ディレクトリで make を再度実行すると、 make と cmake は必要な変更をリコンパイルおよび再構築してくれます。 サブディレクトリに変更を加えるだけであれば、ビルドツリーの対応するサブディレクトリで make を実行するだけで、更新を処理することができます。

ソース外ビルドの最初の混乱の原因は、基本的にソースツリーの 2 つのコピー、1 つは実際のソースコード、もう 1 つは Makefile と (ビルドツリーの) バイナリ実行ファイルを持っていることです。

ソース外ビルドのよいところは、オブジェクト ファイル、makedepend ファイル、バイナリ、およびその他の雑多なビルドのゴミを、ソースがないためビルド ディレクトリ全体を削除するだけで片付けることができる点です。 make clean を使用して実際のオブジェクト ファイルやバイナリ ファイルをクリーンアップすることもできますが、ソースを tar でアップロードしたり、コードを大衆に配布しようと考えている場合は、単に

cumin$ cd cmakecumin$ lsCMakeLists.txt build/ w01-cpp/cumin$ rm -rf build/cumin$ lsCMakeLists.txt w01-cpp/

してコードをクリーンアップしてパッケージ化することが可能です。

More to explore

This is only touches the surface of what CMake can do. より多くの情報のために CMake Wiki をチェックしてください。 また、CMake を使用している他のコースからのフィードバックやヒントを喜んでお受けします。 CMakeには、Ubuntu/Debian (.deb), Red Hat (.rpm), OSXX11, tgz, CygWin, Nullsoftシステム用のバイナリやソースを自動的にパッケージングするCPackというコンパニオンプログラムもあり、上級ユーザ向けになっています。

コメントを残す

メールアドレスが公開されることはありません。