CMake入門-基本概念と主な関数

# この記事は
CMakeというビルドマネジメントツールの入門的解説です。

# CMakeとは

- 公式サイト： https://cmake.org/
- 主にC言語、C++などC系言語のビルドに利用される
- CMake以前、C系言語のビルドには多数のビルドシステム(MakefileやNinjaやIDEなど)が乱立していた。これを隠蔽し包括的に扱える様にしたのがCMake
- cmakeにはコマンド版とGUI版がある
  - ここではコマンド版のみ扱います。

# CMakeの基本的な使い方

1. ビルド対象のソースコード(`*.c`や`*.cpp`など)を書く
2. `CMakeLists.txt`を書く
3. `cmake`コマンドを利用して**プロジェクトファイル**(※)を[Generate](#ジェネレータgenerator)する
4. `cmake`コマンドまたは各ビルドシステムを利用して、プロジェクトファイルからビルドする

> ※**プロジェクトファイル**とは上記ビルドシステムがビルドする際の設定&指示ファイル
> ビルドシステムによって異なり、`Makefile`や`*.sln`や`*.xcodeproj`、`*.ninja`などがある。
> cmake以前はこのプロジェクトファイル自体を直接記述してビルドしていたが、cmakeによりこのプロジェクトファイル生成が自動化されるようになった。

## 割愛(1. ビルド対象のソースコード(`*.c`や`*.cpp`など)を書く)
ソースコード自体はこの記事のスコープ外なので割愛します。

## 2. CMakeLists.txtを書く
例えば、

```
プロジェクトルート/
 |- sample.cpp
 |- CMakeLists.txt
```
の様にファイルを用意し

```:CMakeLists.txt
cmake_minimum_required(VERSION 3.2 FATAL_ERROR)

# set the project name and version
project(MyProject VERSION 1.0)

add_executable(sample.exe sample.cpp)
```
のようにCMakeLists.txtを記述します。

`CMakeLists.txt`には実行ファイルやライブラリファイルを生成する際に必要なソースファイルや手順(依存関係など)を記述しています。
なお、書き方は多岐に渡るため、詳細はこの記事では説明しません。


## 3. `cmake`コマンドを利用してプロジェクトファイルを[Generate](#ジェネレータgenerator)する
```
cmake [<options>] <path-to-source>
cmake [<options>] <path-to-existing-build>
cmake [<options>] -S <path-to-source> -B <path-to-build>
```
この様にcmakeコマンドを実行することでプロジェクトファイルを生成します。
<options>の中には[ジェネレータ](#ジェネレータgenerator)を指定する`-G`などもあります。

```:例
cmake -S . -B build/ -G"Unix Makefiles"
```

すると、 `build`ディレクトリにプロジェクトファイルであるMakefileやCMake関連のファイルが生成されます。

### 4. `cmake`コマンドまたは各ビルドシステムを利用して、プロジェクトファイルからビルドする
```
cmake --build <dir> [<options>] [-- <build-tool-options>]
cmake --build <dir> --target <tgt>... [<options>] [-- <build-tool-options>]
```
のようなコマンドでビルドします。

> cmakeコマンドで実行することも、ジェネレータで指定したビルドシステムのコマンド(makeなど)で実行することもできます。

- `<dir>`は`3`で指定した`<path-to-build>`を指定する。
  - `<path-to-build>`を指定していない場合はカレントディレクトリになっているはず。
- targetについて
  - 明示的に指定すると指定した[ターゲット](#ターゲットtarget)のみビルドされる
  - 指定しなかった場合は`all`ターゲットが指定される

```:例
cmake --build build/ --target sample.exe
```
とするとsample.exeが生成されます。
> ここで指定しているのは`ターゲット名`であり、出力したいファイル名ではありませんので、やっぱり`sample1.exe`という名前のファイルで出力したいからと言って`--target sample1.exe`としてもエラーになります。

# CMakeの主な概念
## プロジェクト
https://cmake.org/cmake/help/latest/command/project.html

一纏まりのソースコードにつける名前。
通常一つ設定される。(使い方によっては複数のプロジェクトを含んだようなものもある。)
上述のビルドシステム用**プロジェクトファイル**のプロジェクトとは若干異なるもの。

CMakeLists.txtの中で`project`関数を読んでプロジェクト名やバージョンなどを設定する。


## ターゲット(target)
ビルドと言っても、一つのプロジェクトで複数の実行ファイルやライブラリファイルを作成したり、テスト実行したり、様々なタスクがある。
この一つ一つのタスクを指定したものがターゲット。

ターゲットには大きく以下の3種類がありCMakeLists.txt内に記述される。

1. 実行ファイルの生成(add_executable)
2. ライブラリファイルの生成(add_library)
3. カスタムターゲットの実行(add_custom_target)

その他：

- ターゲット間に依存性を定義出来る
- デフォルトで`all`というターゲットがある。add_executableなどで`EXCLUDE_FROM_ALL`を明示的に指定していない場合はallターゲットに組み込まれる。
- 参照：[cmake-buildsystem](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html)
- 参照：[Qiita| CMake: カスタムターゲットによるグループ化](https://qiita.com/mrk_21/items/6d7c70edb6a64fa1a28b)


## ジェネレータ(Generator)
https://cmake.org/cmake/help/v3.0/manual/cmake-generators.7.html

各ビルドシステム(※)毎のプロジェクトファイルを生成するモジュールでCMakeでのプロジェクトファイル生成時には内部的に利用される。
>※Makefile(Borland Makefiles, Unix Makefilesなど)やNinja、VisualStudioやXcodeなどIDEなどがある。

明示的にどのジェネレータを利用するかも指定可能。

## プロパティと変数

- 変数は[set関数](#set)を参照
- プロパティは[set_property関数](#set_property)を参照

## *.cmakeファイル
(概念とはちょっと違うけど書いておきます。)

cmakeを利用しているプロジェクトではCMakeLists.txtだけでなく、`*.cmake`といったファイルを作成しているものがあります。

出来ること/使える関数はCMakeLists.txtも`*.cmake`も大差ありませんが、
CMakeList.txtファイルはCMakeList.txtファイルが配置されたディレクトリ毎の設定やターゲットや依存関係を書くのに対し、
`*.cmake`ファイルはディレクトリに依存しないので、CMakeList.txtで利用する関数やパラメータを定義やディレクトリに依存しないようなカスタムターゲットを作成するにに利用されます。

CMakeList.txtファイルから`include`や`find_package`といった関数を通して読み込まれます。

## Makefileからcmake実行
(これも概念ではないですが書いておきます)

プロジェクトファイルを生成するためのCMakeですが、CMakeコマンド実行にもオプションがあり、そのコマンドを生成するためにMakefile/makeを利用しているオープンソースプロジェクトなどがあります。
生成対象のビルドシステムもMakefileだったりすると

```
(cmake実行用の)Makefileを用意する
↓
(makeコマンドから)cmake実行する
↓
(ビルド用の)Makefileが作成される
```
のようなMakefileを作るためにMakefileを用意する、といったややこしい構図になるため、初見だと混乱します。(というか私が混乱した)

# 主な関数と使い方(アルファベット順)
(自分の関心のあるものについて書いています。時々追加していくかもです。)

## add_custom_target
https://cmake.org/cmake/help/latest/command/add_custom_target.html

他のターゲット作成関数の`add_library`や`add_executable`で作成されるターゲットでは実行ファイルやライブラリファイルを生成するが、この関数はそういったファイル生成を目的としないターゲットを作成する。

ターゲット間の依存関係を設定するのにも利用される

## add_dependencies
https://cmake.org/cmake/help/latest/command/add_dependencies.html
ターゲット間の依存性を設定する関数。
ターゲット実行時に依存性が設定されている場合、その依存先のターゲットが先立って実行されるようになる。


## add_executable
https://cmake.org/cmake/help/latest/command/add_executable.html
実行ファイル生成ターゲットを作成します。

- add_executableの使い方には以下の3種類があります。
  - Normal Executables
  - Imported Executables
  - Alias Executables

### Normal Executables
```
add_executable(<name> [WIN32] [MACOSX_BUNDLE]
               [EXCLUDE_FROM_ALL]
               [source1] [source2 ...])
```
一般的な実行ファイル(`*.exe`など)作成用のターゲットを作成します。

### Imported Executables
```
add_executable(<name> IMPORTED [GLOBAL])
```
外部で生成された実行ファイル読み込むターゲット。
他のターゲットやその内部処理で該当の実行ファイルを利用する際に利用される。

### Alias Executables
```
add_executable(<name> ALIAS <target>)
```
ターゲットに別名を付ける。

## add_library
https://cmake.org/cmake/help/latest/command/add_library.html
ライブラリ生成ターゲットを作成します。

- add_libraryの使い方には以下の5種類があります。
  - Normal Libraries
  - Object Libraries
  - Interface Libraries
  - Imported Libraries
  - Alias Libraries

### Normal Libraries
```
add_library(<name> [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            [<source>...])
```
一般的なライブラリファイル(`*.lib`や`*.a`など)作成用のターゲットを作成します。

STATIC,SHARED,MODULEについては[ライブラリのリンク方法をきっちり区別しよう](https://qiita.com/argama147/items/2f636a2f4fd76f6ce130#%EF%BC%93%E7%A8%AE%E9%A1%9E%E3%81%AE%E3%83%AA%E3%83%B3%E3%82%AF%E6%96%B9%E6%B3%95)が分かりやすいと思います。

#### STATIC
静的ライブラリ(ビルド時にリンクされるライブラリ)を作成する

#### SHARED
実行ファイルを実行するときに読み込まれる動的ライブラリを作成する

#### MODULE
プログラムが任意にライブラリをロードした時に読み込まれる動的ライブラリを作成する

### Object Libraries
```
add_library(<name> OBJECT [<source>...])
```
[オブジェクトライブラリ](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#object-libraries)を生成する。
オブジェクトライブラリは、ソースコードのコンパイルするが、ライブラリ間をリンクしたり、一纏めのファイルにしたりはしない。
例えば、

```
sample_lib1.cpp
sample_lib2.cpp
```
からライブラリ作成する際、Normal Librariesでは一つの`*.so`/`*.a`/`*.dylib`が生成されるが、オブジェクトライブラリとして作成すると、`sample_lib1.cpp`のライブラリファイルと`sample_lib2.cpp`のライブラリファイルの２つが生成される。

使い方としては、ここで指定したターゲットを最終生成物とするのではなく、他のターゲットが依存する先のターゲットとして利用する。

### Interface Libraries
```
add_library(<name> INTERFACE)
```
ソースコードもコンパイルせず、実体としてのファイル生成もしないライブラリ生成用ターゲット

ここで設定した`Interface Libraries`は
[`target_link_libraries(<target> INTERFACE <item>...)`](https://cmake.org/cmake/help/latest/command/target_link_libraries.html)や[`target_sources(<target> INTERFACE <item>...)`](http://cmake.org/cmake/help/latest/command/target_sources.html)などで他のターゲットと紐付けられた後、[target_link_libraries()](https://cmake.org/cmake/help/latest/command/target_link_libraries.html)で目的のターゲットに紐付けられます。(ライブラリの橋渡しを行うようなイメージです。)

例：

```
add_library(my_interface_lib INTERFACE)
```
で`Interface Libraries`を作成し

```
target_link_libraries(my_interface_lib INTERFACE some_lib)
```
で、`Interface Libraries`のmy_interface_libと(Interface Librariesではない)some_libとを紐付けた後、

```
target_link_libraries(main_target PRIVATE my_interface_lib)
```
のようにしてmain_targetとmy_interface_libを紐付けることで、
`main_target`と`some_lib`とを紐付けます。

### Imported Libraries
```
add_library(<name> <type> IMPORTED [GLOBAL])
```
プロジェクト外で用意されたライブラリを読み込みます。

`<type>`はそのライブラリがどのタイプかを指定する。
STATIC, SHARED, MODULE, UNKNOWN, OBJECT, INTERFACEがある

- STATIC, SHARED, MODULEについては上述の通り。
- UNKNOWNは[find_package()](https://cmake.org/cmake/help/latest/command/find_package.html)で見つけたモジュールに対して利用する。(たぶん)
- OBJECTは`IMPORTED_OBJECTS`というプロパティで指定したオブジェクトファイルの場所を元にオブジェクトライブラリターゲットを生成する
- INTERFACEは`INTERFACE_INCLUDE_DIRECTORIES`や`INTERFACE_COMPILE_DEFINITIONS`などの`INTERFACE_*`プロパティを元にInterface Libraryを生成する(たぶん)

### Alias Libraries
```
add_library(<name> ALIAS <target>)
```

## add_subdirectory
https://cmake.org/cmake/help/latest/command/add_subdirectory.html
ソースコードを置いているサブディレクトリ追加する

例えば

```
プロジェクトルート/
 |- src/
  |- main.cpp
  |- CMakeLists.txt ・・・[1]
  |- modules/
    |- CMakeLists.txt ・・・[2]
    |- module1.cpp
    |- module2.cpp
```
のような構成のプロジェクトの場合`CMakeLists.txt ・・・[1]`からは同じディレクトリにあるmain.cppしか読読み込めない。
modulesディレクトリにあるソースコードを読み込むために`CMakeLists.txt ・・・[1]`に

```
add_subdirectory(modules)
```
の様に指定する。

## cmake_parse_arguments
https://cmake.org/cmake/help/latest/command/cmake_parse_arguments.html
関数やマクロ定義の中で利用される。

例えば

```
function(my_install)
    set(options OPTIONAL FAST)
    set(oneValueArgs DESTINATION RENAME)
    set(multiValueArgs TARGETS CONFIGURATIONS)
    cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN} )
    :
endfunction()
```
の様に内部で`cmake_parse_arguments`を利用した`my_install`関数を定義し、

```
my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub CONFIGURATIONS)
```
の様に呼び出すと、以下の様に変数が設定される

```
MY_INSTALL_OPTIONAL = TRUE
MY_INSTALL_FAST = FALSE # optionsのFASTは呼び出し時に指定しなかったのでFALSEになる。
MY_INSTALL_DESTINATION = "bin"
MY_INSTALL_RENAME <UNDEFINED> # one_value_keywordsのRENAMEは呼び出し時に指定しなかったのでない。
MY_INSTALL_TARGETS = "foo;bar" # multi_value_keywordsのTARGETSにはlistとして複数の値が指定される。
MY_INSTALL_CONFIGURATIONS <UNDEFINED> # multi_value_keywordsのCONFIGURATIONSは呼び出し時に指定しなかったのでない。
MY_INSTALL_UNPARSED_ARGUMENTS = "blub" # optionsの"OPTIONAL"の後に指定された変数はOPTIONALに紐付けられたりしない。
MY_INSTALL_KEYWORDS_MISSING_VALUES = "CONFIGURATIONS" # "CONFIGURATIONS"に対して値指定はなかった
```


少々複雑、以下を参照するとよいかも：
[cmakeでオプション付きの関数を定義する](https://qiita.com/termoshtt/items/8b5249e858198f017f0c)

## configure_file
https://cmake.org/cmake/help/latest/command/configure_file.html

```
configure_file(<input> <output>
               [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
               [NO_SOURCE_PERMISSIONS]
               [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
```
ファイルをコピーしつつ、コピー元のファイルで`@VAR@`や`${VAR}`で書かれた部分を該当の変数値で置き換える


## file
https://cmake.org/cmake/help/latest/command/file.html

多数のモードが有るが幾つかかいつまんで。

### MAKE_DIRECTORY
```
file(MAKE_DIRECTORY [<directories>...])
```
ディレクトリを作成する

### GLOB, GLOB_RECURSE
```
file(GLOB <variable>
     [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS]
     [<globbing-expressions>...])
file(GLOB_RECURSE <variable> [FOLLOW_SYMLINKS]
     [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS]
     [<globbing-expressions>...])
```
`<globbing-expressions>`(正規表現に似たもの)に一致するファイルのリストを`<variable>`に代入する
`GLOB_RECURSE`だとサブディレクトリ以下もチェックする。その際`FOLLOW_SYMLINKS`が指定されているとシンボリックリンクの先もチェックされる

`RELATIVE`が指定されていると指定されているパスからの相対パスとして処理される。

通常GLOBではディレクトリも含むが、`LIST_DIRECTORIES`がfalseになっているとディレクトリは省略される

>なお、ソースコードを読み込むのにこのGLOBを利用するのは推奨されない。
>GLOBだとファイルが追加・削除されたときに追従できないので。
>(キャッシュを削除して処理すれば、、だが毎度時間がかかる)


### READ
```
file(READ <filename> <variable>
     [OFFSET <offset>] [LIMIT <max-in>] [HEX])
```
`<filename>`から読み取って`<variable>`の変数に代入する

なお、読み込んだファイルの変数をどう使うかというと、[string関数](https://cmake.org/cmake/help/latest/command/string.html)などで意図する文字列があるかをチェックして別の変数に代入したりする。

### RELATIVE_PATH
```
file(RELATIVE_PATH <variable> <directory> <file>)
```
`<directory>`から`<file>`への相対パスを計算して`<variable>`に代入する

### STRINGS
```
file(STRINGS <filename> <variable> [<options>...])
```
`<filename>`から読み取って一行毎を`<variable>`の変数にlistとして代入する

### TO_CMAKE_PATH
```
file(TO_CMAKE_PATH "<path>" <variable>)
```
`<path>`に指定されたパス表記をCMake表記のパスに変換して`<variable>`に代入する

### WRITE
```
file(WRITE <filename> <content>...)
```
`<filename>`に`<content>`の内容を書き込む


## find_package
https://cmake.org/cmake/help/latest/command/find_package.html

```:基本形
find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE]
             [REQUIRED] [[COMPONENTS] [components...]]
             [OPTIONAL_COMPONENTS components...]
             [NO_POLICY_SCOPE])
```
外部プロジェクトを探してその設定を読み込む。

主にcmakeインストール時に組み込まれて以下のコマンドで出てくる`Find***`というモジュールの読み込みに使う

```
cmake --help-module-list
```

- `<PackageName>`:読み込む対象のパッケージ
- `[version]`:必要とするパッケージバージョン
- `[EXACT]`:上記バージョンと完全一致する必要があるか。(上記バージョンの記述でも指定出来るの)
- `[QUIET]`:メッセージを出力するか否か
- `[MODULE]`:後述の`Module`モードか`Config`モードかの指定
- `[REQUIRED]`:REQUIRED指定して対象パッケージが存在しなかった場合はCMakeの処理を止める
- `[COMPONENTS]`:対象パッケージが必要とするコンポーネント
- `[OPTIONAL_COMPONENTS]`:対象パッケージが(必須ではなく)利用するコンポーネント
- `[NO_POLICY_SCOPE]`:割愛

### `Module`モードと`Config`モード
`Module`モードでは
`Find<PackageName>.cmake`
というファイルを探し、見つかれば実行され、見つからなければ`Config`モードに移行する。

`Config`モードは以下の様に検索対象を詳細指定して検索する。
なお、`Config`モードでも見つからなかったらエラーメッセージを出力する。

```
find_package(<PackageName> [version] [EXACT] [QUIET]
             [REQUIRED] [[COMPONENTS] [components...]]
             [OPTIONAL_COMPONENTS components...]
             [CONFIG|NO_MODULE]
             [NO_POLICY_SCOPE]
             [NAMES name1 [name2 ...]]
             [CONFIGS config1 [config2 ...]]
             [HINTS path1 [path2 ... ]]
             [PATHS path1 [path2 ... ]]
             [PATH_SUFFIXES suffix1 [suffix2 ...]]
             [NO_DEFAULT_PATH]
             [NO_PACKAGE_ROOT_PATH]
             [NO_CMAKE_PATH]
             [NO_CMAKE_ENVIRONMENT_PATH]
             [NO_SYSTEM_ENVIRONMENT_PATH]
             [NO_CMAKE_PACKAGE_REGISTRY]
             [NO_CMAKE_BUILDS_PATH] # Deprecated; does nothing.
             [NO_CMAKE_SYSTEM_PATH]
             [NO_CMAKE_SYSTEM_PACKAGE_REGISTRY]
             [CMAKE_FIND_ROOT_PATH_BOTH |
              ONLY_CMAKE_FIND_ROOT_PATH |
              NO_CMAKE_FIND_ROOT_PATH])
```

参考[CMakeを使ってみた (7) find_packageとpkg_check_modulesによるライブラリ探索](https://www.wagavulin.jp/entry/2017/02/20/082608)


## find_program
https://cmake.org/cmake/help/latest/command/find_program.html
`find_program (<VAR> name)`
例： `find_program(LCOV_PATH lcov)`
の様に利用

nameに該当するプログラムが(OS上に)存在する場合は<VAR>に指定した変数に、その実行ファイルパスを格納する。
なかった場合は`<VAR>-NOTFOUND`となる

## function
https://cmake.org/cmake/help/latest/command/function.html
独自の関数を定義するための関数

```
function(<name> [<arg1> ...])
  <commands>
endfunction()
```

```
function(foo)
  <commands>
endfunction()
```
と定義した関数は

```
foo()
Foo()
FOO()
cmake_language(CALL foo)
```
のいずれでも呼び出せるが、基本全て小文字で扱うことが推奨される

### 引数について
`ARGC`:渡された引数の数
`ARGV#`:"#"部分は数字(ARGV0,ARGV1,ARGV2,...)。渡された引数が入っている変数
`ARGN`:渡された引数がlistとして入っている変数。

#### 引数を明示的に定義した場合
```
function(<name> SAMP_ARG1 SAMP_ARG2)
  <commands>
endfunction()
```
の様に引数を変数定義していれば、
SAMP_ARG1,SAMP_ARG2にもそれぞれ渡された引数値が入る。
この場合は

```
${SAMP_ARG1} == ${ARGV0}
${SAMP_ARG2} == ${ARGV1}
```
となる。
また、明示的に引数定義されている場合は、呼び出し時に対応する引数を渡さないとエラーになる。


## get_filename_component
https://cmake.org/cmake/help/latest/command/get_filename_component.html

```
get_filename_component(<var> <FileName> <mode> [CACHE])
```
`<FileName>`に当てはまるファイル名やパス名を`<var>`の変数に代入する関数。

(`<mode>`では当てはまり方を指定する。)

> get_filename_componentはCMakeのversion 3.19から[cmake_path()](https://cmake.org/cmake/help/latest/command/cmake_path.html)に取って代わられています。

## include
https://cmake.org/cmake/help/latest/command/include.html
上述の"***.cmake"のようなCMake codeを読み込んで**実行**する


## list
https://cmake.org/cmake/help/latest/command/list.html

list変数を扱う関数で、様々なモードが有る。
なお、list変数の作成は通常変数と同じく[set](https://cmake.org/cmake/help/latest/command/set.html)関数を利用する
また、list変数は内部的には`;`で区切られた文字列群

## macro
https://cmake.org/cmake/help/latest/command/macro.html

```
macro(<name> [<arg1> ...])
  <commands>
endmacro()
```
マクロ作成関数

macroと[function](https://cmake.org/cmake/help/latest/command/function.html)は非常に似ているが以下の点で異なる

- 変数の意味合いが違い、macroでの`ARGN`,`ARGC`,`ARGV`,`ARGV#`といったものはCMakeとしての変数ではなく、C言語のプリプロセッサが置き換える場所になる。
  - 変数利用時の指定の仕方に注意が必要
- functionは呼び出し時にfunction側に移動して実行されるが、macroは該当のソースコードを利用先に埋め込む形になる。
  - 特にmacro利用時は[return](https://cmake.org/cmake/help/latest/command/return.html)のスコープに影響してややこしくなるので、macroではreturnは利用しない方が良い

## message
https://cmake.org/cmake/help/latest/command/message.html
`massage([<mode>] "message text")`

cmakeコマンド実行時にメッセージ出力する

例：`message(STATUS "Building for code coverage")`
の様に利用

- mode には幾つかあるが代表的なものだと
  - 指定無し or NOTICE: stderrに出力される 
  - STATUS: ユーザが必要とするだろう情報
  - FATAL_ERROR: メッセージを出しつつ、処理を停止する

## option
https://cmake.org/cmake/help/latest/command/option.html
CMakeLists.txt上で定義されたoptionは、`cmake`コマンド実行時に指定出来るようになる

例

```:CMakeLists.txt
option(PYTHON_COVERAGE "Python code coverage" OFF)
if(PYTHON_COVERAGE)
	message(STATUS "python coverage enabled")
	set(PYTHON_EXECUTABLE coverage run -p)
endif()
```
と記述しておき、cmakeコマンド実行時に

```
cmake -DPYTHON_COVERAGE=ON
```
の様に実行する 

## project
https://cmake.org/cmake/help/latest/command/project.html
プロジェクト名やバージョンなどを設定する。

## set
https://cmake.org/cmake/help/latest/command/set.html
通常変数、キャッシュ変数、環境変数を作成する。

```:通常変数例
set(VALUE_A a 1 2)
message(${VALUE_A})
→a12と表示される
```

```:キャッシュ変数例
set(VALUE_B 1234 CACHE STRING SampleCache)
message(${VALUE_B})
message($CACHE{VALUE_B})
→1234と表示される
通常変数と異なり、スクリプトのどこからでも生成・参照出来る
```

> 環境変数設定は利用例が少ないので割愛

## set_property
https://cmake.org/cmake/help/latest/command/set_property.html
cmakeには変数(通常変数、キャッシュ変数、環境変数)とは別に、プロパティという各種動作設定が格納される変数領域があり、それを設定するためのもの。
プロパティ取得関数の`get_property`と対になる。



## set_source_files_properties
https://cmake.org/cmake/help/latest/command/set_source_files_properties.html

```
set_source_files_properties(<files> ...
                            [DIRECTORY <dirs> ...]
                            [TARGET_DIRECTORY <targets> ...]
                            PROPERTIES <prop1> <value1>
                            [<prop2> <value2>] ...)
```
`<files>`に指定したソースファイルに[Properties on Source Files](https://cmake.org/cmake/help/latest/manual/cmake-properties.7.html#properties-on-source-files)のプロパティ(※)を設定する

>※例えば[GENERATED](https://cmake.org/cmake/help/latest/prop_sf/GENERATED.html)という、該当のソースファイルが、ビルド時に外部システムまたはCMake自身によって生成されるものかを指定することによって、非存在チェックを免除する設定などがある。

## target_compile_definitions
https://cmake.org/cmake/help/latest/command/target_compile_definitions.html

```
target_compile_definitions(<target>
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
```
`<target>`に指定したターゲット実行時に、
- `PUBLIC`と`PRIVATE`は[COMPILE_DEFINITIONS](https://cmake.org/cmake/help/latest/prop_tgt/COMPILE_DEFINITIONS.html)の埋め込みをおこなう。
  - COMPILE_DEFINITIONSとはターゲットのソースコードコンパイル時のプリプロセッサ定義。
- `PUBLIC`と`INTERFACE`は[INTERFACE_COMPILE_DEFINITIONS](https://cmake.org/cmake/help/latest/prop_tgt/INTERFACE_COMPILE_DEFINITIONS.html)の埋め込みを行う。

>要はソースコードの`#ifdef XXXXX`とかに埋め込む値の設定


```
target_compile_definitions(foo PUBLIC -DFOO)
```
の様に`-D`で指定すると該当の項目は削除される

## target_link_libraries
https://cmake.org/cmake/help/latest/command/target_link_libraries.html

```:基本形
target_link_libraries(<target> ... <item>... ...)
```

ターゲットにライブラリを紐付ける。

- `<target>`は`add_executable`や`add_library`で生成されたターゲットを指定する。
- `<item>`は幾つかパターンがある
  - add_libraryで生成された他のライブラリターゲット
  - ライブラリファイルへのフルパス
  - 素のライブラリ名(紐付けたいライブラリファイルがfoo.libだったら`foo`)
  - リンクフラグ
    - ビルドシステムによってリンク(ビルド)時に指定されるオプションの指定
  - generator expression
    - 評価計算され、上記(ライブラリターゲット、フルパス、ライブラリ名など)として扱われる
  - `debug`, `optimized`, `general`キーワードと上記の`<item>`
    - 詳細は割愛


```
target_link_libraries(<target>
                      <PRIVATE|PUBLIC|INTERFACE> <item>...
                     [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
```
というような使い方が多い。
PRIVATE|PUBLIC|INTERFACEがそれぞれなんなのかは以下が詳しい。
参考[CMake: target_link_libraries(PUBLIC/PRIVATE/INTERFACE) の実践的な解説](https://qiita.com/chapuni/items/7ddffb46fa327c5bef43)