CMake覚え書き


はじめに

CMakeはコンパイラに依存しないビルド自動化のためのOSSで、クロスプラットフォームで利用することができます。1

特に、ビルドチェーンが複雑化して保守性が悪くなってきたときに威力を発揮すると思います。2
そこそこ大きくなりそうなプロジェクトであれば、最初からCMakeでビルドするように構成しておくのも良いと思います。

執筆時点で筆者が主に使用しているCMakeのバージョンはv3.8系です。

本稿は筆者が出くわした機能やTipsについて記したり、筆者がよく参照するリソースを紹介する記事となります。
従って、随時更新します。

Getting Started

英語が苦でない方は、公式ドキュメントから始めるのが良いと思います:

英語が苦手な方は、 CMake Advent Calendar 2014 - Qiita ――この辺りから始めるのもよさそうです。

cmake-variables

CMake 設定ファイル CMakeLists.txt の中で利用できる変数です。

<PROJECT-NAME>_SOURCE_DIR

(例) add_subdirectory(path/to/foo)foo-project を追加したとき foo-project_SOURCE_DIR と参照できる。

CMAKE_CXX_STANDARD

デフォルトの CXX_STANDARD の値。

下の CXX_STANDARD と併せて、CMake v3.1で導入されたようだ。

CXX_STANDARD

コンパイラに指定するC++バージョン。

  • 指定可能な値 ... 98, 11, 14, 17

cmake-commands

CMake 設定ファイル CMakeLists.txt の中で利用できるコマンドです。
コマンドによってビルド構成を記述します。

project

CMakeLists.txt
project(<PROJECT-NAME> [LANGUAGES] ...)

option

CMakeLists.txt
option(<option_variable> "help string describing option" [ON or OFF])

optionを指定するときは、cmakeコマンド実行時に -D<option_variable>=ON などとして渡す。

例:

# shell
# FOOオプションをONでビルド実行
cmake -DFOO=ON path/to/project_dir

参考:

message

ログメッセージを出力する関数。

CMakeLists.txt
message([<mode>] "message to display" ...)

省略可能な <mode> には以下のようなものがある(一部):

mode description 処理の継続 出力先
(none) 重要な情報 Yes STDERR
STATUS INFO的なやつ Yes STDOUT
WARNING 警告 Yes STDERR
FATAL_ERROR 致命的エラー No STDERR

出力先は、STATUS以外は STDOUT である。

add_library

プロジェクトにライブラリを追加する。

ライブラリをリンクしたいときなど事前にこれを行う。

利用例:

CMakeLists.txt
add_library(mylib MyLib.cpp)
add_executable(myapp Main.cpp)
target_link_libraries(myapp mylib)

トピック

out-of-sourceビルド

build/ などビルド用のディレクトリを作って、その中で cmake を実行するやり方。

対義語は「in-sourceビルド」で、 cmake . でカレントディレクトリの CMakeLists.txt に基づきビルドするやり方。

out-of-sourceビルドの方が好ましい。

参考:

CMakeでC++11以上のビルド

上で示した CMAKE_CXX_STANDARD 変数を利用することができる。

CMakeLists.txt
set(CMAKE_CXX_STANDARD, 11)

CMakeのバージョンが古い、かつ、GCCであれば、下のような記述でコンパイラオプション(-std=c++11 or -std=c++0x)を指定できる:

CMakeLists.txt
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
  message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()

参考

脚注


  1. https://ja.wikipedia.org/wiki/CMake 

  2. 何かの記事で、「大きなプロジェクトでautotoolsは使うな。CMakeかSConsを使え」という記述を見た記憶がありますが、ソースを忘れました。。