Hello World から始める CMake (2)

# 例

　前回は cmake 自身に "Hello, world!" を表示してもらった。

https://qiita.com/yynet2022/items/a466ae7cba580df08c5e

　今回はもう少し実用的に、C++ プログラムから表示してもらい、そのプログラムを cmake にコンパイルしてもらう。

```C++:main.cxx
#include <iostream>
int main(int argc, char *argv[])
{
  std::cout << "Hello, world!" << std::endl;
  return 0;
}
```

```CMake:CMakeLists.txt
# まずはプロジェクト名とコンパイル言語などを指定
project(HelloWorld CXX)

# 実行ファイル a.out は main.cxx から作成されることを指定。
add_executable(a.out main.cxx)
```

```Bash:実行
$ ls
CMakeLists.txt  main.cxx
$ cmake -S . -B build    (初期化。build は構築用ディレクトリ)
...
$ cmake --build build    (構築)
...
$ ./build/a.out
Hello, world!
```

# 解説

　cmake は初期化、構築、インストールの三段階で使うことが多い。

　ここではインストールまではせず、初期化と構築について、少しメモを記す。あと、CMakeLists.txt の内容についても少し。

## 1. 初期化 &mdash; Generate a Project Buildsystem

　構築する前に、CMake 向けの初期化を行う必要がある。
よく使う方法は、以下の２つのうち、どちらかだろう。

### 1-1. ソースディレクトリと構築用ディレクトリを指定

　これは先の例と同じだが、もう一度記載しておく。

- ソースディレクトリと構築用ディレクトリ、両方を指定するやり方。
- 構築用ディレクトリは作成してくれる。

```Bash:実行
$ ls
CMakeLists.txt  main.cxx
$ cmake -S . -B build     (ソースディレクトリと構築用ディレクトリを指定）
...
$ cmake --build build    (構築用ディレクトリを指定して構築）
...
$ ./build/a.out
Hello, world!
```

### 1-2. ソースディレクトリだけを指定（構築用ディレクトリ＝カレントディレクトリ）

- 構築用ディレクトリを先に用意し、そこに移動しておく。
- ソースディレクトリだけを指定して cmake の初期化を行う方法。

```Bash:実行
$ ls
CMakeLists.txt  main.cxx
$ mkdir build    (構築用ディレクトリを用意)
$ cd build/    (構築用ディレクトリに移動）
$ cmake ..    (ソースディレクトリを指定、カレントディレクトリが構築用)
...
$ cmake --build .    (構築。カレントディレクトリを構築用として指定）
...
$ ./a.out
Hello, world!
```

### 1-3. 補足

　ソースディレクトリと構築用ディレクトリの指定方法にはいくつか組み合わせがある。それを以下に記す。（下記[参考リンク 3.][link-3]からの抜粋）

|コマンドライン|ソースディレクトリ|構築用ディレクトリ|
|:--------------|:--------------|:-----------------|
|cmake -B build|カレントディレクトリ|build|
|cmake -B build src|src|build|
|cmake -B build -S src|src|build|
|cmake src|src|カレントディレクトリ|
|cmake build (existing)|loaded|build|
|cmake -S src|src|カレントディレクトリ|
|cmake -S src build|src|build|
|cmake -S src -B build|src|build|

## 2. 構築 &mdash; Build a Project

　初期化が済めば、次は構築になる。
　構築は、コマンド引数 `--build` と構築用ディレクトリを指定する。

```Bash:構築方法
$ cmake --build 構築用ディレクトリ
```

　今回は小さいサンプルプログラムなので関係無いが、構築時にお世話になるコマンド引数は並列化指定だろう。参考までに記しておく。

`--parallel [<jobs>]` または `-j [<jobs>]`

　最大並列数を指定する。

　指定されなかった場合の動作はよく分からない。cmake ではなく、cmake から呼ばれる構築ツール (make とか ninja とか）に依るのかもしれない。

　なお、環境変数 `CMAKE_BUILD_PARALLEL_LEVEL` が用意されている。この環境変数が設定されていれば、上記コマンド引数の指定がなかった場合に使用される。

## 3. CMakeLists.txt の内容について

### 3-1. project文

　プロジェクト名などを設定する文。
　書式は二つある。

```CMake:書式１
project(<PROJECT-NAME> [<language-name>...])
```
```CMake:書式２
project(<PROJECT-NAME>
        [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
        [DESCRIPTION <project-description-string>]
        [HOMEPAGE_URL <url-string>]
        [LANGUAGES <language-name>...])
```

　書式１は以前から、書式２は比較的新しい方法。

　書式２を使う場合には少しコツがいる。
　自分がよく使うのは下限バージョンを指定する `cmake_minimum_required()` 文で `VERSION 3.16` を指定する方法。(Qt6 などを使うので）

```CMake:CMakeLists.txt
# 下限バージョンを 3.16 に指定する
cmake_minimum_required(VERSION 3.16)

# プロジェクト名、バージョン、コンパイル言語などを指定
project(HelloWorld VERSION 0.0.1 LANGUAGES CXX)

# プロジェクト名とバージョンを表示する
message("This project is ${PROJECT_NAME} version ${PROJECT_VERSION}")

# 実行ファイル a.out は main.cxx から作成されることを指定
add_executable(a.out main.cxx)
```

```Bash:実行
$ cmake -S . -B build
...
This project is HelloWorld version 0.0.1
...
$
```
　その他、詳細は[参考リンク 4.][link-4]を参照のこと。

### 3-2. add_executable文

```CMake:書式
add_executable(<name> [WIN32] [MACOSX_BUNDLE]
               [EXCLUDE_FROM_ALL]
               [source1] [source2 ...])
```

　基本的には実行ファイル名 `<name>` を指定し、その後にソースファイル名を続ける。

　詳細は[参考リンク 5.][link-5]を参照のこと。

# 参考リンク：
1. [CMake](https://cmake.org/)
2. [CMake Documentation and Community](https://cmake.org/documentation/)
3. [cmake(1) &mdash; CMake Documentation][link-3]
4. [project &mdash; CMake Documentation][link-4]
5. [add_executable &mdash; CMake Documentation][link-5]

[link-3]: https://cmake.org/cmake/help/latest/manual/cmake.1.html
[link-4]: https://cmake.org/cmake/help/latest/command/project.html
[link-5]: https://cmake.org/cmake/help/latest/command/add_executable.html