CMake覚え書き

# はじめに

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

[^1]: https://ja.wikipedia.org/wiki/CMake

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

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

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

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

# Getting Started

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

- https://cmake.org/cmake-tutorial/
- https://cmake.org/documentation/
  - https://cmake.org/cmake/help/v3.8/

英語が苦手な方は、 [CMake Advent Calendar 2014 - Qiita](http://qiita.com/advent-calendar/2014/cmake) ――この辺りから始めるのもよさそうです。

# cmake-variables

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

## &lt;PROJECT-NAME&gt;\_SOURCE\_DIR

https://cmake.org/cmake/help/v3.8/variable/PROJECT-NAME_SOURCE_DIR.html

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

## CMAKE_CXX_STANDARD

https://cmake.org/cmake/help/v3.8/variable/CMAKE_CXX_STANDARD.html

デフォルトの `CXX_STANDARD` の値。  
下の `CXX_STANDARD` と併せて、CMake v3.1で導入されたようだ。

## CXX_STANDARD

https://cmake.org/cmake/help/v3.8/prop_tgt/CXX_STANDARD.html

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

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

# cmake-commands

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

## project

https://cmake.org/cmake/help/v3.8/command/project.html

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

## option

https://cmake.org/cmake/help/v3.8/command/option.html

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

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

例:

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

参考:

- [cmakeでオプションを定義する方法 - tuedaの日記](http://d.hatena.ne.jp/tueda_wolf/20110223/p1 "cmakeでオプションを定義する方法 - tuedaの日記")


## message

https://cmake.org/cmake/help/v3.8/command/message.html

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

```cmake: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

https://cmake.org/cmake/help/v3.8/command/add_library.html

プロジェクトにライブラリを追加する。  
ライブラリをリンクしたいときなど事前にこれを行う。

利用例:

```cmake: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 : out-of-sourceビルドで幸せになる - Qiita](http://qiita.com/osamu0329/items/7de2b190df3cfb4ad0ca)
- [CMakeを使ってみた (6) ソース外ビルド - wagavulin's blog](http://blog.wagavulin.jp/entry/2011/11/27/222658 "CMakeを使ってみた (6) ソース外ビルド - wagavulin's blog")

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

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

https://cmake.org/cmake/help/v3.8/variable/CMAKE_CXX_STANDARD.html

```CMake:CMakeLists.txt
set(CMAKE_CXX_STANDARD, 11)
```

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

```CMake: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()
```

# 参考

- [CMake Advent Calendar 2014 - Qiita](http://qiita.com/advent-calendar/2014/cmake) ... 少し情報が古くなってしまいましたが、CMakeの機能について幅広く解説されており、初学者にやさしいドキュメントとして価値がありそうです。
- [c++11 - How to activate C++ 11 in CMake? - Stack Overflow](https://stackoverflow.com/questions/10851247/how-to-activate-c-11-in-cmake "c++11 - How to activate C++ 11 in CMake? - Stack Overflow")

# 脚注