Professional CMake: A Practical Guideの無料部分を読む　～その４～

# PROFESSINAL CMAKE : A PRACTICAL GUIDEとは
CMake参考書紹介(2022年時点)という記事で，この電子書籍を読んでクロスプラットフォームの環境構築ができたということが書いてありました．
これを受けて，試しに無料で公開されている部分を読んで要約してみたというものです．
この本は全部で7パートから構成されており，そのうち1パート目が無料で公開されています．
その無料で公開されている部分の各チャプターに何が書いてあるのかをメモの代わりに要約しています．
概要を理解し読む気を起こすための記事なので，きちんとした内容は実際にこの公開されているものを読みに行ってください．

[その１](https://qiita.com/ciao_kaokawa/items/4b4ba99a2119fa1cf838)
[その２](https://qiita.com/ciao_kaokawa/items/b418599ad8d41986a1cd)
[その３]()

## その4
その3では，Chapter5をまとめます．
ここでは，CMakeのテストとパッケージングについて説明しています．

## Chapter 5: Basic Testing And Deployment

CMakeは、プロジェクトのテスト、インストール、およびパッケージ作成のためのさまざまな機能を提供する。これらの活動に関連する機能は非常に多岐にわたり、活動自体が複雑であるため、圧倒されることがある。CMakeは、より一貫したインターフェースと制御セットを提供しつつ、必要に応じて低レベルの機能にもアクセスできるようにすることで、その複雑さを簡素化することを目指している。その結果、いくつかの基本を理解するだけで、これらのトピックを探索し、有用な結果を得ることができる。

### 5.1 Testing

CMakeは、ctestという別のコマンドラインツールを提供している。これは、テストのスケジューリングとレポート作成ツールとして考えることができ、CMakeと密接に統合されており、テストを便利かつ柔軟に定義することができる。通常、CMakeはプロジェクトによって提供された詳細に基づいて、ctestに必要な入力ファイルを生成する。

以下の最小限の例は、いくつかの簡単なテストケースを持つプロジェクトを定義する方法を示している。

```cmake
cmake_minimum_required(VERSION 3.19)
project(MyProj VERSION 4.7.2)
enable_testing()
add_executable(testSomething testSomething.cpp)
add_test(NAME SomethingWorks COMMAND testSomething)
add_test(NAME ExternalTool COMMAND /path/to/tool someArg moreArg)
```

enable_testing()の呼び出しは、CMakeにctestのための入力ファイルを生成するよう指示するために必要である。これは通常、project()の直後に呼び出されるべきである。add_test()コマンドは、プロジェクトがテストケースを定義する方法である。これはいくつかの異なる形式をサポートしているが、上記のNAMEとCOMMANDキーワードを使用した形式が推奨される。

テストはデフォルトで、終了コードが0であれば合格と見なされる。より詳細で柔軟な基準を定義することもできるが、簡単な終了コードのチェックで十分な場合が多い。

以下の手順は、プロジェクトを構成、ビルド、およびテストするシーケンスを示している。任意のCMakeジェネレータを使用できるが、この例ではNinjaを使用している。

```bash
cmake -G Ninja -B build -DCMAKE_BUILD_TYPE=Debug
cd build
cmake --build .
ctest
```

マルチコンフィギュレーションジェネレータ（Xcode、Visual Studio、Ninja Multi-Configなど）を使用する場合、ビルドおよびテスト時に構成を指定する必要がある。

```bash
cmake -G "Ninja Multi-Config" -B build
cd build
cmake --build . --config Debug
ctest --build-config Debug
```

テストが多く、実行に時間がかかる場合、並列実行することができる。

```bash
ctest --parallel 16
```

ctestのデフォルト出力はかなり簡潔である。合格および失敗したテストの出力は隠され、結果のみが表示される。完全な出力を得るには、-Vまたは--verboseオプションを使用するか、失敗したテストの出力のみを表示するには--output-on-failureオプションを使用する。

CMakeはまた、テストビルドターゲットを定義しており、デフォルトのオプションセットでctestを実行する。これらのデフォルト設定はすべてのテストを実行し、テスト出力やテストの実行方法に対する制御は限られている。

### 5.2 Installing

プロジェクトによってビルドされたものは、ビルドディレクトリから直接使用できることが多いが、それはプロジェクトをデプロイするためのステップに過ぎない。デプロイメントはさまざまな形を取ることができるが、共通の要素はインストールステップである。インストール中に、ファイルはビルドディレクトリ（および場合によってはソースディレクトリ）からインストール場所にコピーされる。ファイルはコピー前後に何らかの形で変換されることがある。

CMakeは、さまざまな種類のアーティファクトをインストールするための直接的なサポートを提供している。install()コマンドはその機能の大部分を提供し、いくつかの異なる形式を持っている。以下の最小限の例は、いくつかのCMakeターゲットをインストールするためのinstall(TARGETS)形式を使用している。

```cmake
cmake_minimum_required(VERSION 3.14)
project(MyProj VERSION 4.7.2)
add_executable(MyApp ...)
add_library(AlgoRuntime SHARED ...)
add_library(AlgoSDK STATIC ...)
install(TARGETS MyApp AlgoRuntime AlgoSDK)
```

上記の例は、CMake 3.14で追加された機能を利用している。ターゲットをインストールする場所が指定されていない場合、CMakeはほとんどのUnixシステムで使用される慣習に対応するデフォルトの場所を使用する。Windowsでも同様のレイアウトが通常問題なく動作するため、Appleプラットフォームのアプリケーションバンドルを除いて、一般的にどこでも使用できる。

CMake 3.13以前を使用している場合、デフォルトのインストール先は提供されず、プロジェクトが明示的に指定する必要がある。

```cmake
install(TARGETS MyApp AlgoRuntime AlgoSDK RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)
```

ファイルやディレクトリもインストールできる。以下は、ヘッダーファイルをインストールする従来の方法を示している。

```cmake
install(FILES things.h algo.h DESTINATION include/myproj)
install(DIRECTORY headers/myproj DESTINATION include)
```

CMake 3.23以降では、ヘッダーを扱うより強力で便利な方法としてファイルセットを使用できる。ファイルセットはターゲットにヘッダーを関連付け、ターゲットと一緒にインストールできる。

```cmake
add_library(AlgoSDK ...)
target_sources(AlgoSDK PUBLIC FILE_SET api TYPE HEADERS BASE_DIRS headers FILES headers/myproj/sdk.h headers/myproj/sdk_version.h)
install(TARGETS AlgoSDK FILE_SET api)
```

他のプロジェクトがビルドに使用するライブラリやヘッダーをインストールする場合、CMake固有の設定パッケージファイルを提供することが推奨される。これらのファイルは、消費プロジェクトがリンクできるCMakeターゲットを提供し、そのターゲットにはヘッダー検索パスの詳細が含まれる。

### 5.3 Packaging

かつては、ソースからビルドされたプロジェクトをユーザーがインストールすることが一般的であった。しかし、現在では多くのプロジェクトがユーザーにソースファイルを提供できない。また、ユーザーは事前にビルドされたパッケージを期待することが多い。

CMakeは、cpackツールを提供しており、さまざまな形式のバイナリパッケージを生成できる。これには、.zip、.tar.gz、.7zのような単純なアーカイブや、RPM、DEB、MSI、スタンドアロンのグラフィカルインストーラーなどのプラットフォーム固有のパッケージングシステムが含まれる。

基本的なパッケージングは、いくつかの関連するCMake変数を設定し、CPackというCMakeモジュールを含めることで実装される。以下の最小限の例は、これらを組み合わせて比較的簡単な方法でパッケージを作成する方法を示している。

```cmake
cmake_minimum_required(VERSION 3.14)
project(MyProj VERSION 4.7.2)
add_executable(MyApp ...)
add_library(AlgoRuntime SHARED ...)
add_library(AlgoSDK STATIC ...)
install(TARGETS MyApp AlgoRuntime AlgoSDK)
set(CPACK_PACKAGE_NAME MyProj)
set(CPACK_PACKAGE_VENDOR MyCompany)
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "An example project")
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
set(CPACK_VERBATIM_VARIABLES TRUE)
include(CPack)
```

以下のコマンドは、プロジェクトを構成、ビルド、およびパッケージするシーケンスを示している。

```bash
cmake -G Ninja -B build -DCMAKE_BUILD_TYPE=Release
cd build
cmake --build .
cpack -G "ZIP;WIX"
```

マルチコンフィギュレーションジェネレータを使用する場合、ビルドおよびパッケージ時に構成を指定する必要がある。

```bash
cmake -G "Ninja Multi-Config" -B build
cd build
cmake --build . --config Release
cpack -G "ZIP;WIX" --config Release
```

### 5.4 Recommended Practices

**ctest**および**cpack**コマンドラインツールに慣れること。これらは、対応するテストおよびパッケージターゲットをビルドする際に利用できないさまざまなオプションをサポートしている。特に**ctest**ツールは、テストを実行する際に日常的に役立つ多くの有用なオプションを持っている。

プロジェクトを開発し、install()コマンドを変更する際には、一時的なステージングエリアにテストインストールを行うことが有用である。ビルドツリーから直接システム全体の場所にインストールすることは避けるべきである。代わりに、バイナリパッケージを生成し、それをインストールすることを検討する。

プロジェクトがCMakeの最低バージョンを3.23以上に設定できる場合、CMakeファイルセットについて学ぶことに時間を費やす価値がある。プロジェクトのヘッダーファイルをすべてファイルセットに入れ、PRIVATEおよびPUBLICファイルセットを分けて定義することで、インストールするものとしないものを明確にすることができる。

# 感想
現在は他のツールで代替するものが多そうなイメージを持った。
実際にCIツールに組み込むと、どうこれらを動かせばいいのか想像できない。

以上で無料部分は終了です。
予想以上に深淵が深そうなツールだということが理解できました。