Help us understand the problem. What is going on with this article?

CMakeの構文調べてみた

More than 1 year has passed since last update.

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 引数の評価時などでは、;で区切られた文字列はリストとして扱われる。
;そのものをリスト内の文字列に服見たい場合は\;のようにエスケープする。

なお、リストは「単純なユースケース」を意図して設計されているので、複雑なデータ処理に使うべきではない。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away