空飛ぶロボットのつくりかた

ロボットをつくるために必要な技術をまとめます。ロボットの未来についても考えたりします。

CMakeのお勉強(1)

やりたいこと

cmakeについて調べることが多いし、理解も浅いので、理解を深める

教科書

ja/catkin/CMakeLists.txt - ROS Wiki

CMakeLists.txtとは

ファイルCMakeLists.txtは、ソフトウエアパッケージをビルドするためのCMakeビルドシステムへのインプットです。

フォーマット(順序も大事)

  1. 必要な CMake Versionの指定 (cmake_minimum_required)

  2. Package Name (project())

  3. ビルドに必要な他の CMake/Catkin packages を見つける (find_package())

  4. Message/Service/Action の生成 (add_message_files(), add_service_files(), add_action_files())

  5. message/service/action generation の呼び出し (generate_messages())

  6. パッケージのビルドに必要な情報の指定 (catkin_package())

  7. ライブラリや実行ファイルのビルド (add_library()/add_executable()/target_link_libraries())

  8. テストコードのビルド (catkin_add_gtest())

  9. Install ルール (install())

CMake Version

cmake_minimum_required(VERSION 2.8.3)

Package name

project(robot_brain)

Tips: CMakeスクリプトの中で、どこで必要であっても ${PROJECT_NAME} 変数を使って、後からこのプロジェクト名を参照出来ます。

CMake Packages

find_package(catkin REQUIRED COMPONENTS nodelet)

Tips:

  • find_packageにはビルドに必要なコンポーネントだけを指定してください。ランタイムで依存するパッケージを指定するべきでありません。

  • catkin_INCLUDE_DIRSはcatkinのincludeパスだけではなく、nodeletのincludeパスも含みます

参考: CMakeを使ってみた (7) find_packageとpkg_check_modulesによるライブラリ探索 - wagavulin's blog

find_package() は何をしているのか?

find_packageを通してCMakeがパッケージを見つけたら、そのパッケージについての情報を与えるいくつかのCMake環境変数が生成されます。

↓以下環境変数

  1. _FOUND - ライブラリが見つかったかどうか。見つかればtrueをセット、見つからなければ出力されない

  2. INCLUDE_DIRS or INCLUDES - パッケージによってエクスポートされたインクルードパス

  3. LIBRARIES or LIBS - パッケージによってエクスポートされたライブラリ

  4. _DEFINITIONS - 追加のコンパイルフラグ

catkin_package()

catkin_package()はcatkinで提供されたCMakeマクロです。pkg-configとCMakeファイルを生成するのに必要なcatkin固有の情報をビルドシステムに伝えるために必要です。

ex

catkin_package(
   INCLUDE_DIRS include
   LIBRARIES ${PROJECT_NAME}
   CATKIN_DEPENDS roscpp nodelet
   DEPENDS eigen opencv)
  1. INCLUDE_DIRS - このパッケージのためのエクスポートされるinclude パス (i.e. cflags)

  2. LIBRARIES - プロジェクトからエクスポートされるライブラリ

  3. CATKIN_DEPENDS - このプロジェクトが依存している他のcatkinプロジェクト

  4. DEPENDS - このプロジェクトが依存している非catkin CMakeのプロジェクト

  5. CFG_EXTRAS - 追加の設定オプション

ビルドターゲットの指定

ビルドターゲットの指定方法にはいろいろありますが、通常は以下の2つのどちらかです:

  1. Executable Target - 実行可能プログラム

  2. Library Target - 実行可能なターゲットがビルド時または実行時に使用するライブラリ

Include パスと Library パス

ターゲットを指定する前に、ターゲットのためのリソース、特にヘッダファイルおよびライブラリをどこで見つけることができるのかを指定する必要があります。

  1. Include Paths - (一般的にC/C++の)コードをビルドするためのヘッダファイルがどこで見つけられるか

  2. Library Paths - 実行可能なターゲットをビルドするのに必要なライブラリがどこにあるか?

  3. include_directories(, , ..., )

  4. link_directories(, , ..., )

include_directories()

include_directoriesへの引数は、find_package呼び出しによって生成される*_INCLUDE_DIRS変数と、インクルードする必要がある

include_directories(include ${Boost_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS})

一番最初の引数 "include" は、パッケージ内のinclude/ディレクトリがパスの一部でもあることを示しています。

link_directories()

CMakelink_directories()機能は、追加のライブラリパスを追加するために使われることができます。

link_directores(~/my_libs)

例:

  • LINK_DIRECTORIES( ${LINK_DIRECTORIES} /absPath/libtourtre/)

推奨:

  • FIND_LIBRARY(TOURTRE_LIBRARY tourtre /absPath/libtourtre)
  • TARGET_LINK_LIBRARIES(testOVAS ${TOURTRE_LIBRARY})
実行ファイルのターゲット

ビルドすべき実行可能なターゲットを指定するために、CMake関数のadd_executable()を使わなければなりません。

add_executable(myProgram src/main.cpp src/some_file.cpp src/another_file.cpp)

これは、3つのソースファイル src/main.cpp、src/some_file.cppとsrc/another_file.cppからビルドされるmyProgramと呼ばれる実行可能なターゲットをビルドします。

ライブラリターゲット

CMake関数add_library()は、ビルドする際のライブラリを指定するために使います。デフォルトで、catkinは共有ライブラリをビルドします。

add_library(${PROJECT_NAME} ${${PROJECT_NAME}_SRCS})
target_link_libraries

実行可能なターゲットがどのライブラリにリンクするかを指定するために、target_link_libraries_functionを使ってください。これは一般にadd_executable()の呼びだしの後に実行されます。

add_executable(foo src/foo.cpp)
add_library(moo src/moo.cpp)
target_link_libraries(foo moo)  -- これはfooを libmoo.soにリンクする

Tips: リンクすべきディレクトリ情報がfind_package()経由で自動的に取り込まれるので、ほとんどの使用事例においてlink_directories()を使う必要がないことに注意してください。

インストール可能なターゲットを指定する

自分のコードの"make install" を実行できるようにしたいなら、ターゲットがどこに収まるべきかを指定する必要があります.

これはCMake のinstall() 関数を使い、引数を伴って行われます。

  1. TARGETS - どのターゲットをインストールするか

  2. ARCHIVE DESTINATION - 静的ライブラリとDLL (Windows) .lib のスタブ

  3. LIBRARY DESTINATION - 非DLL 共有ライブラリとモジュール

  4. RUNTIME DESTINATION - 実行可能ターゲットと DLL (Windows) 形式の共有ライブラリ

install(TARGETS ${PROJECT_NAME}
  ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
  LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
  RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
ヘッダファイルのインストール

ヘッダファイルも"include"フォルダにインストールされ、これはしばしばフォルダ全体のファイルのインストールによって行われます(ファイル名パターンで部分的にフィルタされ、SVNのサブフォルダ群を除きます)。これは以下の様なインストール規則によって行われます:

install(DIRECTORY include/${PROJECT_NAME}/
  DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
  PATTERN ".svn" EXCLUDE
)
install(DIRECTORY include/
  DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION}
  PATTERN ".svn" EXCLUDE
)
roslaunch ファイルやその他のリソースのインストール

launchファイルといったその他のリソースは、${CATKIN_PACKAGE_SHARE_DESTINATIONにインストールされます

install(DIRECTORY launch/
  DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
  PATTERN ".svn" EXCLUDE)

所感

まだひとつひとつのコマンドが実行された時に内部でどのようにつながったり動いているのかが理解できていない。

引き続き学ぶべし