CMake: コマンド引数の種類

## はじめに

みなさん、こんにちは。前回の記事で、CMake言語がコマンド呼び出しの羅列であることを書きました。今回は、そのコマンドに渡す引数についてです。

## コマンド引数の種類

CMakeのコマンド引数には以下に示す複数の種類があり、それぞれに特徴があります。

### Unquated Argument

まずは、Unquated Argument について述べます。Unquated Argument は以下のように記述します。

```cmake
message(arg)
```

そして、次の特徴を持っています。

#### 空白文字や`(`や`#`といった特殊な文字を含むことはできない

コマンド引数の区切り文字が空白文字となっているため、Unquated Argument では、半角スペースや改行といったものを含むことはできません。

```cmake
# 値が a と b の別の引数となる
message(a b)
message(a
b)
```

また、`(`や`#`のように文法上特殊な意味が割り当てられている文字も使用することができません。

```cmake
message(a() # エラー
message(a#b) # エラー
```

以下、Unquated Argument で使用できない文字となります。

* 空白文字
* `(`
* `)`
* `#`
* `"`
* `\`

#### 変数の参照ができる

Unquated Argument では、変数の参照をすることができます。

```cmake
set(filename foo)
message(hoge/${filename}) # hoge/foo
```

#### エスケープシーケンスを使用できる

Unquated Argument では、エスケープシーケンスを使用できます。上記で、空白文字を含むことができないと述べましたが、エスケープシーケンスを用いれば使用することができます。

```cmake
message(a\ b) # a b
message(a\nb) # a
              # b
```

これは、`(`などの特殊な文字でも同様です。

```cmake
message(a\() # a(
message(a\#b) # a#b
```

### Quated Argument

つぎは、Quated Argument です。Quated Argument は、ダブルクォーテーション`"`で囲まれたものです。

```cmake
message("arg")
```

次の特徴を持っています。

#### ダブルクォーテーション`"`を含むことはできない

Quated Argument において、ダブルクォーテーション`"`は、特別な意味を持つので含むことができません。

```cmake
message("value: "1"") # エラー
```

#### 変数の参照ができる

Quated Argument では、変数の参照をすることができます。

```cmake
set(value 1)
message("value: ${value}") # value: 1
```

#### エスケープシーケンスを使用できる

Quated Argument では、以下のようにエスケープシーケンスを使用できます。

```cmake
message("value\t3") # value	3
```

また、これによって、ダブルクォーテーション`"`も含む事ができます。

```cmake
message("value: \"1\"") # value: "1"
```

#### 複数行に渡って記述できる

Quated Argument では、複数行に渡って記述できます。このとき改行はそのまま表示されますが、行末に`\`を記述すると同じ行と認識されます。

```cmake
# 一行目。
# 二行目。ここも二行目。
message("一行目。
二行目。\
ここも二行目。")
```

### Bracket Argument

最後に、Bracket Argument です。これは、Lua言語の`long bracket`という構文を参考にして、CMake 3.0 から追加されたもので、二重の対となるブラケット`[[`・`]]`で囲われています。ブラケットの間には任意の数の等号`=`をいれることができますが、対となるブラケットで`=`の数は同じでなければなりません。

```cmake
message([[arg]])
message([=[arg]=])
message([==[arg]==])
```

次の特徴を持っています。

#### すべての文字を利用できる

Bracket Argument では、引数の終了を表す二重のブラケット`]]`は使用することができません。しかし、ブラケット間の等号`=`の数を変更すればこの制約を回避できるので、実質すべての文字を使うことができます。

```cmake
message([=[[[aaa]]]=]) # [[aaa]]
```

#### 複数行に渡って記述できる

Bracket Argument では、複数行に渡って記述することができます。このとき、改行はそのまま表示されますが、最初の改行は無視されます。

```cmake
# 一行目。
# 二行目。
message([[
一行目。
二行目。]])
```

#### 変数の参照をすることができない

Bracket Argument では、変数の参照はできません。ただの文字列として扱われます。

```cmake
set(value 1)
message([[value: ${value}]]) # value: ${value}
```

#### エスケープシーケンスを使用することができない

Bracket Argument では、エスケープシーケンスを使用することができません。ただの文字列として扱われます。

```cmake
message([[value\t3]]) # value\t3
```

## 各種コマンド引数の使い分け

さて、いろいろなコマンド引数を見てきましたが、どれを使えばいいのでしょうか？

いろいろなケースが考えられますが、一般的に次のように使い分けることができます。

### Unquated Argument

#### 数値・識別子

数値や識別子などは、余計なものがない Unquated Argument がすっきり記述できます。

```cmake
set(value 1)
string(TOUPPER "hoge" output_variable)
```

#### リスト

Unquated Argument を使うと、リストというセミコロン`;`で区切られた、値のコレクションを表す特殊な値を表現することができます。

```cmake
# a
# b
# c
foreach(v a;b;c)
  message(${v})
endforeach()
```

#### 変数に格納されているリストをリストとして使いたい

Unquated Argument を使えば、変数に格納されているリストをリストとして使うことができます。

```cmake
set(value "a;b")
message(${value}) # 値が a と b の２つの引数を渡したことになる
```

なお、変数`value`が空の場合は、引数をひとつも渡していないと判断されます。

### Quated Argument

#### 文字列

Quated Argument を使うと文字列や、変数が埋め込まれた文字列を分かりやすく表現できます。

```cmake
message("Hello, world!")

set(value 1)
message("value: ${value}") # value: 1
```

#### 変数の値をただの文字列として渡したい

Quated Argument を使うと、リストが格納されている変数を引数に渡す場合でも、常にひとつの文字列として引数として扱うことができます。

```cmake
set(value "a;b")
message("${value}") # 値が "a;b" の引数をひとつ渡す
```

変数`value`が空の場合は、空文字列が渡されることになります。

### Bracket Argument

#### 文章

Bracket Argument をつかうと文章を分かりやすく表現できます。

```cmake
message([[
CMake input files are written in the "CMake Language"
in source files named CMakeLists.txt or ending in a .cmake file name extension.
]])
```

## おわりに

以上、各種コマンド引数についてでした。用途に応じて使い分けることで、意図せぬ動作やわかりにくい表現を回避できます。

明日は、mrk_21 さんの『CMake: コメント』です。