https://cmake.org/cmake/help/v3.0/manual/cmake-language.7.html#grammar-token-newline
で、CMakeの構文しらべてみたのでメモ。
#全体の構文
file ::= file_element*
file_element ::= command_invocation line_ending |
(bracket_comment|space)* line_ending
line_ending ::= line_comment? newline
space ::= <match '[ \t]+'>
newline ::= <match '\n'>
-
file
は、file_element
の繰り返し -
file_element
は下記のいずれか-
コマンド呼び出し
+line_ending
-
bracket_comment
と空白の任意の繰り返し +line_ending
-
-
line_ending
は、`行コメント``` + 改行
ざっくりまとめると コメント以外はコマンド呼び出しですよということ。
条件分岐もif()
、else()
のように全てコマンド呼び出しの形となっている。
コマンド呼び出しの構文
command_invocation ::= space* identifier space* '(' arguments ')'
identifier ::= <match '[A-Za-z_][A-Za-z0-9_]*'>
arguments ::= argument? separated_arguments*
separated_arguments ::= separation+ argument? |
separation* '(' arguments ')'
separation ::= space | line_ending
コマンド呼び出しは下記の形
- コマンド名(引数) の形。(
hoge(arg)
の形)。 - コマンド名の前後に空白が入っていてもよい。
- コマンド名の先頭はアルファベット or アンダーバー。2文字目以降は数字でもOK。
- 引数無しも可。
- 引数は複数でも可。
- 複数の引数の間は、空白または改行で区切られる。
- 引数はネストして()で囲われている場合もある
コマンドの引数
argument ::= bracket_argument | quoted_argument | unquoted_argument
コマンドの引数には
- bracket引数
- quated引数
- unquated引数
の3種類がある。
bracket引数
bracket_argument ::= bracket_open bracket_content bracket_close
bracket_open ::= '[' '='{len} '['
bracket_content ::= <any text not containing a bracket_close
of the same {len} as the bracket_open>
bracket_close ::= ']' '='{len} ']'
- ブラケット引数は、
[[bracket_content]]
もしくは[=[bracket_content]=]
もしくは[==[bracket_content]==]
、、、の形 -
bracket_content
には、対応する「とじかっこ」以外の任意の文字列を含むことができる。
通常は
message([[
複数行にわたる文字列を
引数にいれたいぞ]])
のように、"[["、"]]"を使えば良い。
「"]]"を引数に入れたい」 という、超マニアックな要求がある場合にのみ
message([=[
こうすれば]]も含めることができるぞ]=])
のように、[=[
などを使う。
ブラケット引数はver 3.0より前では使えないので注意。
quated引数
quoted_argument ::= '"' quoted_element* '"'
quoted_element ::= <any character except '\' or '"'> |
escape_sequence |
quoted_continuation
quoted_continuation ::= '\' newline
- ダブルクオーテーション
"
で囲まれた引数 -
\
、"
以外のすべての文字と、エスケープシーケンスを含むことができる。 -
\
の直後に改行することで、改行後も連続できる
unquated 引数
unquoted_argument ::= unquoted_element+ | unquoted_legacy
unquoted_element ::= <any character except whitespace or one of '()#"\'> |
escape_sequence
unquoted_legacy ::= <see note in text>
- かっこで囲われてない引数。
- 空白、
(
、)
、#
、\
を含まない(エスケープされている場合をのぞく。 - ただし、過去の経緯によりダブルクオーテーションで囲われている文字列や、
$()
で囲われた文字列もエラーにはならない。
エスケープシーケンス
escape_sequence ::= escape_identity | escape_encoded | escape_semicolon
escape_identity ::= '\(' | '\)' | '\#' | '\"' | '\ ' |
'\\' | '\$' | '\@' | '\^'
escape_encoded ::= '\t' | '\r' | '\n'
escape_semicolon ::= '\;'
記号 | 意味 |
---|---|
'\t' | タブ文字 |
'\r' | 同じ行の先頭に戻る |
'\n' | 改行、復帰 |
'\;' | ';'文字 |
'\(' | '('文字 |
'\)' | ')'文字 |
'\#' | '#'文字 |
'\"' | '"'文字 |
'\ ' | ' '文字(空白文字) |
'\\' | '\'文字 |
'\$' | '$'文字 |
'\@' | '@'文字 |
'\^' | ';'文字 |
変数の参照
変数は、quqted 引数とunquated 引数の中で、${valuable}
の形式で参照される。bracket argumentの中では${}で囲んでも変数展開されない。
コメント
コメントは #
で開始される。
ただし、以下の場合はコメント開始されない
- bracket引数の中
- quated引数の中
- unquqted引数の中で、なおかつ
\
でエスケープされている場合
bracketコメント
bracket_comment ::= '#' bracket_argument
#
の直後にbracket引数の形が続く場合、bracket引数の終了までがコメントとなる。
これにより、複数行にわたるコメントを作ることが可能。
(C言語の/* */
に相当)。
行コメント
line_comment ::= '#' <any text not starting in a bracket_argument
and not containing a newline>
C言語//
に相当。
制御構造
条件分岐
if()
、elseif()
、else()
、endif()
で条件分岐可能。
Loop
foreach()
、 endforeach()
、while()
、endwhile()
、break()
でループを組むことが可能。
コマンド定義
macro()
、endmacro()
、function()
、endfunction()
でコマンド定義が可能。
変数
-
set()
で値を代入、unset()
で解除できる。 - 変数は、大文字/小文字 を区別する。(コマンドと違うので注意)
- 変数は任意の文字で作れるが、英数字と
_
、-
だけで作ることを推奨。 - 基本的には変数の型は文字列(数値型はない)だが、コマンドによっては文字列を他の型と認識する (例えば、
if()
はtrue
という文字を「真」として認識する。
変数のスコープ
変数には3種類のスコープがある
Function スコープ
- function()コマンドによって作られるコマンド内のスコープ
- コマンド内でset()/unset()された変数はコマンドの外からは見えない。
Directory スコープ
- 各ディレクトリのCMakeLists.txtを処理するときのスコープ。(つまり、最も普通のスコープ)
- 各ディレクトリのCMakeLists.txtを処理開始する前に、親ディレクトリのCMakeLists.txtで定義されていた全ての変数がコピーされる。
Persistent キャッシュ
- 最もグローバルなスコープ。CMakeをなんども繰り返しても保存されている特殊な変数。
- set()/unset() で
CACHE
オプションをつけるなどの方法で書き換え可能
変数の評価は、Function スコープ -> Directory スコープ -> Persistent キャッシュ の順に行われる。
リスト
Unquated 引数の評価時などでは、;
で区切られた文字列はリストとして扱われる。
;
そのものをリスト内の文字列に服見たい場合は\;
のようにエスケープする。
なお、リストは「単純なユースケース」を意図して設計されているので、複雑なデータ処理に使うべきではない。