cMake整理早見表

# cMake整理早見表
C, C++のコードをコンパイルする。
CMakeはコンパイラに依存しないビルド自動化のためのフリーソフトウェアであり、様々なOSで動作させることができる。CMakeは階層化ディレクトリや複数のライブラリを利用するアプリをサポートするよう設計されている。

実際のビルドにおいては、make、Xcode、Visual Studioのようなネイティブのビルド環境が利用される。

CMake自身は最小限の依存関係を持つよう設計されており、ビルドするにはC++コンパイラのみを必要とする[4]。

## コンパイルの手段

#### １．普通のコマンド使用

こちらにまとめました。
https://qiita.com/okinaofficial/items/db3abab1da3d782ba45d

|  コマンド  |    |    |
| ---- | ---- | ---- | ---- | ---- |
|  gcc  |  Linux  |  GNU C Compiler  |    |
|  g++  |  Linux  |  GNU C++ Compiler  |    |
|  cl  |  windows  |  windowsのc++コンパイル  |    |

|  コマンド  |    |
| ---- | ---- | ---- | ---- | ---- |
|  cc  |  Linuxでは，あればCCはおそらくg++へのリンク  |    |    |
|  cc  |  Linuxでは，ccはgccへのリンク  |    |    |



#### ２．cMakeを使用
以下記事を参照

## ０．cMake環境構築

Windows

>Windows用のダウンロードページ（.zip, .msi）
https://cmake.org/download/

Linux

```
sudo yum install cmake
sudo apt install cmake
```




## １．cMakeの流れ

#### １－１．CMakeLists.txt作製
以下詳細

#### ２－２．コマンド実行

```
//in-sourceビルド
//「成果物 + CMakeCache.txt, CMakeFiles等ビルド用のファイル達」を各ディレクトリ内に作成します。
1. 各ディレクトリにCMakeList.txtを置く
2. トップでcmake .を実行
3. make, make install

//out-sourceビルド
//cmakeはビルド成果物を格納する場所を変えることが出来ます。buildという空のディレクトリを用意しておいて、以下手順でビルドします。
1. 各ディレクトリにCMakeList.txtを置く
2. buildディレクトリに移動して、cmake ../を実行
3. make, make install
```

```php:/build
//out-sourceビルド出力結果例
$ ls
CMakeCache.txt  cmake_install.cmake  lib       script
CMakeFiles      conf                 Makefile  src
```


## ２．CMakeLists.txt具体例

```php:CMakeLists.txt
# CMakeのバージョンを設定
cmake_minimum_required(VERSION 2.8)
# プロジェクト名と使用する言語を設定
project(test_cmake CXX)
# a.outという実行ファイルをmain.cppとhello.cppから作成
add_executable(a.out main.cpp hello.cpp)
```

１．cMake静的ライブラリを作成


```php:CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(test_cmake CXX)
# hello.cppとgood_morning.cppをコンパイルして静的ライブラリlibgreetings.aを作成
add_library(greetings STATIC hello.cpp good_morning.cpp)
# a.outという実行ファイルをmain.cppから作成
add_executable(a.out main.cpp)
# a.outを作成する際にlibgreetings.aをリンク
target_link_libraries(a.out greetings)
```

２．cMake共有ライブラリを作成


```php:CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(test_cmake CXX)
# hello.cppとgood_morning.cppをコンパイルして共有ライブラリlibgreetings.soを作成
add_library(greetings SHARED hello.cpp good_morning.cpp)
add_executable(a.out main.cpp)
# a.outを作成する際にlibgreetings.soをリンク
target_link_libraries(a.out greetings)
```

##　おまけ: CMakeLists.txtのRef

#### 共通

```php:CMakeLists.txt
//cmakeの保証最低バージョンを指定する。
cmake_minimum_required(VERSION 2.8)
```

#### 



```php:CMakeLists.txt
//defineの指定（コンパイルオプションや独自変数を定義する。
//コンパイルオプションはadd_definitionsで、独自変数はsetで指定。
add_definitions("-Wall -g -O2")

set(DPPATH "/usr/local/lib")
setで定義した変数は、通常のスクリプトと同様${DPPATH}で利用できます。

//サブディレクトリ指定
add_subdirectory(src)
```

#### 変数情報

```php:CMakeLists.txt
変数名	意味
CMAKE_SOURCE_DIR	ソースコードのトップディレクトリ。cmake ../とかで指定された場所。
CMAKE_BINARY_DIR	cmakeの成果物が置かれるトップディレクトリ
PROJECT_SOURCE_DIR	projectオプションで指定されたプロジェクトのトップディレクトリ。
CMAKE_INSTALL_PREFIX	インストール先のprefix。デフォルトは/usr/local。
cmake -DCMAKE_INSTALL_PREFIX=pwd/../localといったオプション指定で変更可能
```


#### -srcビルド-

###### バイナリを作成する

ここではlan_routerが作成されます。
オプションがある場合はadd_definitionsを使ってください。

```php:CMakeLists.txt
//add_executable(バイナリ名 ソース達)。
add_executable(lan_router DHCPConfigurator.cpp GWConfigurator.cpp LANIPManager.cpp LANManager.cpp main.cpp JsonParser.cpp DHCPConfigurator_dnsmasq.cpp)
```

setでソースをまとめておく楽ですかね。複数バイナリも作れます。この場合はlan_router_dhcpd, lan_routerが作成されます。

```php:CMakeLists.txt
#SRCS_BASEセット
set(SRCS_BASE DHCPConfigurator.cpp GWConfigurator.cpp LANIPManager.cpp LANManager.cpp main.cpp JsonParser.cpp)

#for dhcpd
set(SRCS_DHCPD ${SRCS_BASE} DHCPConfigurator_dhcpd.cpp)
add_executable(lan_router_dhcpd ${SRCS_DHCPD})

#for dnsmasq
set(SRCS_DNSMASQ ${SRCS_BASE} DHCPConfigurator_dnsmasq.cpp)
add_executable(lan_router ${SRCS_DNSMASQ})
```

ヘッダーパスを追加するなら以下で出来ます。

```php:CMakeLists.txt
INCLUDE_DIRECTORIES("/usr/local/include")
```

###### ライブラリをリンクする
ライブラリパス: link_directories

```php:CMakeLists.txt
link_directories("/usr/local/lib")
```

ライブラリのリンク: target_link_libraries
1点注意として、この定義はadd_executableの後に。

```php:CMakeLists.txt
//target_link_libraries(バイナリ名 ライブラリ達)
target_link_libraries(lan_router lower_layer_director dputil jansson)
```

#### -ライブラリビルド-
srcビルドとの違いはバイナリの指定方法だけ。add_executable⇒ADD_LIBRARYに変わります。
この例ではlibeth_landevice.soが作成されます。

```php:CMakeLists.txt
ADD_LIBRARY(eth_landevice SHARED ether_device.c device_json_parser.c)
```

#### インストール設定
基本はINSTALLコマンドを使用。
インストール先は${prefix}/DESTINATIONで指定したフォルダか、もしくはフルパス指定です。

```php:CMakeLists.txt
//バイナリ: 引数3個目にRUNTIMEを指定する。
INSTALL(TARGETS lan_router RUNTIME DESTINATION bin)

//ライブラリ: 引数3個目にLIBRARY を指定する。
INSTALL(TARGETS eth_landevice LIBRARY DESTINATION lib)

//それ以外(スクリプトやconfファイル): 引数1個目にFILESを指定する。
INSTALL(FILES lan_interface.conf DESTINATION conf PERMISSIONS OWNER_READ GROUP_READ WORLD_READ)

//パーミッションの指定も可能です。
#read only
INSTALL(FILES lan_interface.conf DESTINATION conf PERMISSIONS OWNER_READ GROUP_READ WORLD_READ)
/#read write
INSTALL(FILES setting.json DESTINATION conf PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)

//パーミッションが同じなら複数指定も可能です。
#read/write/execute
INSTALL(FILES firewall.sh firewall_BLACKLIST.sh countryip.sh DESTINATION /root/script PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE)
```

#### おまけ:

###### スクリプト実行
こんな感じにmake実行時にスクリプトを実行することが出来ます。
ここではconfの中身をインストール先のprefixに合わせ置換しています。

```php:CMakeLists.txt
add_custom_target(create_setting ALL COMMAND "sed" "-e" "\"s@PREFIX@${CMAKE_INSTALL_PREFIX}@g\"" "setting.json.ini" ">" "setting.json")

//最初ソースに対しても同じことをしようかと思いましたが、こちらはadd_definitionsで十分ですね。
add_definitions(-DCONF_PATH="${CMAKE_INSTALL_PREFIX}/conf/")
```