CMake入門

# CMakeLists.txt

CMakeプロジェクトはCMakeLists.txtにより動作が設定されます。ソースツリーのルートに少なくとも1つ用意する必要があります。必須の設定項目は`cmake_minimum_required`と`project`の2つです。

## cmake_minimum_required()

CMakeの最小バージョンを指定します。システムが正しいCMakeのバージョンを持っているかどうかをチェックします

:::note warn
もし指定したバージョンより低いバージョンしかインストールされていなければエラーが出ます。

```
$ cmake -S . -B build
CMake Error at CMakeLists.txt:1 (cmake_minimum_required):
  CMake 3.26 or higher is required.  You are running version 3.25.1


-- Configuring incomplete, errors occurred!
See also "/work/work/build/CMakeFiles/CMakeOutput.log".
```
:::

## project()

言語とメタデータの設定をします。<PROJECT_NAME>は必須項目で、その他は任意です。2つの形式のうちどちらかを使用します。

```
project(<PROJECT_NAME> [<language-name>])
```

```
project(<PROJECT_NAME>
    [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
    [DESCRIPTION <project-description-string>]
    [HOMEPAGE_URL <url-string>]
    [LANGUAGES <language-name>]
)
```

VERSIONを設定すると以下の変数が利用できるようになります。

- PROJECT_VERSION
- PROJECT_VERSION_MAJOR
- PROJECT_VERSION_MINOR
- PROJECT_VERSION_PATCH
- PROJECT_VERSION_TWEAK

## message()

指定されたメッセージの文字列をログに記録します。

## 変数

変数はパッケージの設定や、ソースファイルに渡して最終的な実行ファイルで利用することができます。

## 変数の利用

`${<変数>}`のように変数は’${'と'}'で囲えば利用することができます。

たとえば以下のようなCMakeLists.txtを用意して`cmake -S . -B build`コマンドを実行すると変数の値を表示することができます。

```cmake:CMakeLists.txt
cmake_minimum_required(VERSION 3.25)
project(hello
    VERSION 0.1.0.0
    DESCRIPTION "sample hello project"
    HOMEPAGE_URL "https://github.com/yoshiyasu1111/cmake-from-source_template"
    LANGUAGES CXX
)
message("プロジェクトの名前： ${PROJECT_NAME}")
message("プロジェクトの名前： ${CMAKE_PROJECT_NAME}")
message("プロジェクトのソースディレクトリ： ${PROJECT_SOURCE_DIR}")
message("プロジェクトのビルドディレクトリ： ${PROJECT_BINARY_DIR}")
message("プロジェクトのバージョン： ${PROJECT_VERSION}")
message("プロジェクトのバージョン： ${CMAKE_PROJECT_VERSION}")
message("プロジェクトのメジャーバージョン： ${PROJECT_VERSION_MAJOR}")
message("プロジェクトのマイナーバージョン： ${PROJECT_VERSION_MINOR}")
message("プロジェクトのパッチーバージョン： ${PROJECT_VERSION_PATCH}")
message("プロジェクトのツイークバージョン： ${PROJECT_VERSION_TWEAK}")
message("プロジェクトの説明： ${PROJECT_DESCRIPTION}")
```

```bash
$ cmake -S . -B build
-- The CXX compiler identification is GNU 11.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
プロジェクトの名前： hello
プロジェクトの名前： hello
プロジェクトのソースディレクトリ： /work/work
プロジェクトのビルドディレクトリ： /work/work/build
プロジェクトのバージョン： 0.1.0.0
プロジェクトのバージョン： 0.1.0.0
プロジェクトのメジャーバージョン： 0
プロジェクトのマイナーバージョン： 1
プロジェクトのパッチーバージョン： 0
プロジェクトのツイークバージョン： 0
プロジェクトの説明： sample hello project
-- Configuring done
-- Generating done
-- Build files have been written to: /work/work/build
```

## file()

ファイルシステムへのアクセスを必要とするファイル操作やパス操作を実行します。

ファイル名: \<filename\>に内容:\<content\>を書き込みます。

```
file({WRITE | APPEND} <filename> <content>)
```

ファイル名:\<filename\>内容を文字列として変数:\<variable\>に読み込みます。

```
file(STRINGS <filename> <variable>)
```

```cmake:CMakeLists.txt
cmake_minimum_required(VERSION 3.25)
project(hello
    VERSION 0.1.0.0
    DESCRIPTION "sample hello project"
    HOMEPAGE_URL "https://github.com/yoshiyasu1111/cmake-from-source_template"
    LANGUAGES CXX
)
file(WRITE hello.txt "I write a contents.")
file(STRINGS hello.txt STRING_READ_FILE)
message("${STRING_READ_FILE}")
```

```bash
$ cmake -S . -B build
I write a contents.
$ cat hello.txt 
I write a contents.
```

## add_executable()

指定されたソースファイルを使用して、プロジェクトに実行ファイルを追加します。

```
add_executable(<name>
    [EXCLUDE_FROM_ALL]
    [source1] [source2 ...]
)
```

[source]で指定したソースファイルからビルドする実行形式ターゲット \<name\> を追加します。\<name\>はプロジェクト内で一意でなければならない。

`EXCLUE_FROM_ALL`にtrue値を設定すると、そのターゲットが含まれるディレクトリと、祖先のすべてのターゲットから除外されます。

### 実行例

次のようなCMakeLists.txtとhello.cppを用意します。

```bash
$ tree
.
├── CMakeLists.txt
└── hello.cpp
```

```cmake:CMakeLists.txt
cmake_minimum_required(VERSION 3.25)
project(greeting
    VERSION 0.1.0.0
    DESCRIPTION "sample hello project"
    HOMEPAGE_URL "https://github.com/yoshiyasu1111/cmake-from-source_template"
    LANGUAGES CXX
)
add_executable(hello
    hello.cpp
)
```

```cpp:hello.cpp
#include <iostream>

int main(void)
{
    std::cout << "Hello World!" << std::endl;

    return 0;
}
```

プロジェクトのビルドシステムの生成とビルドを実行します。

```bash
$ cmake -S . -B build
$ cmake --build build
```

./buildディレクトリに`hello`が生成されています。

```bash
$ ./build/hello 
Hello World!
```

## add_library()

指定されたソースファイルを使用して、プロジェクトにライブラリを追加します。

### 静的ライブラリ

```
add_library(<name> STATIC [source ...])
```

静的ライブラリ\<name\>をソースコード[source ...]から生成します。

### 実行例〜静的ライブラリ〜

次のようなCMakeLists.txtとhello.cppを用意します。

```bash
$ tree
.
├── CMakeLists.txt
└── hello.cpp
```

```cmake:CMakeLists.txt
cmake_minimum_required(VERSION 3.25)
project(greeting
    VERSION 0.1.0.0
    DESCRIPTION "sample hello project"
    HOMEPAGE_URL "https://github.com/yoshiyasu1111/cmake-from-source_template"
    LANGUAGES CXX
)
add_library(hello
    STATIC
        hello.cpp
)
```

```cpp:hello.cpp
#include <iostream>

int main(void)
{
    std::cout << "Hello World!" << std::endl;

    return 0;
}
```

プロジェクトのビルドシステムの生成とビルドを実行します。

```bash
$ cmake -S . -B build
-- The CXX compiler identification is GNU 11.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /work/build
```

```bash
$ cmake --build build
[ 50%] Building CXX object CMakeFiles/hello.dir/hello.cpp.o
[100%] Linking CXX static library libhello.a
[100%] Built target hello
```

./buildディレクトリにライブラリlibhello.aが生成されています。

```bash
$ ls -lh ./build/libhello.a 
-rw-r--r-- 1 gccuser gccuser 2.9K Dec  8 08:30 ./build/libhello.a
```

### 共有ライブラリ

```
add_library(<name> SHARED [source ...])
```

共有ライブラリ\<name\>をソースコード[source ...]から生成します。

### 実行例〜共有ライブラリ〜

次のようなCMakeLists.txtとhello.cppを用意します。

```bash
$ tree
.
├── CMakeLists.txt
└── hello.cpp
```

```cmake:CMakeLists.txt
cmake_minimum_required(VERSION 3.25)
project(greeting
    VERSION 0.1.0.0
    DESCRIPTION "sample hello project"
    HOMEPAGE_URL "https://github.com/yoshiyasu1111/cmake-from-source_template"
    LANGUAGES CXX
)
add_library(hello
    SHARED
        hello.cpp
)
```

```cpp:hello.cpp
#include <iostream>

int main(void)
{
    std::cout << "Hello World!" << std::endl;

    return 0;
}
```

プロジェクトのビルドシステムの生成とビルドを実行します。

```bash
$ cmake -S . -B build
-- The CXX compiler identification is GNU 11.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /work/build
```

```bash
$ cmake --build build
[ 50%] Building CXX object CMakeFiles/hello.dir/hello.cpp.o
[100%] Linking CXX shared library libhello.so
[100%] Built target hello
```

./buildディレクトリにライブラリlibhello.soが生成されています。

```bash
$ ls -lh ./build/libhello.so 
-rwxr-xr-x 1 gccuser gccuser 16K Dec  8 08:54 ./build/libhello.so
```