はじめに
CMakeは、C / C ++でのプロジェクトパッケージのテスト、コンパイル、作成を自動化するように設計された、オープンでクロスプラットフォームなユーティリティセットです。 すべての人が理解できる小さなスクリプトを一度書くだけで、CMakeが利用可能なプラットフォーム上でプロジェクトのビルドを同じにすることができます。
CMake言語は、ネイティブアセンブリファイル(MakefileやNinjaなど)に翻訳され、すべてのプロジェクト管理のプロセスを定義します。 機能面では、かなり複雑な構造に形成できるチームしかありません。 それらから始めます。
CMake発売
以下は、実践すべきCMake言語の使用例です。 既存のコマンドを変更し、新しいコマンドを追加して、ソースコードを試してください。 これらの例を実行するには、 公式WebサイトからCMakeをインストールしてください 。
チーム
CMakeのコマンドは、多くのプログラミング言語の機能に似ています。 コマンドを呼び出すには、その名前を記述し、スペースで区切られた括弧で囲まれた引数を渡す必要があります。 上記の例では、コンソールへの出力のために、6つの引数がmessage
コマンドに渡されmessage
。
# "CMake is the most powerful buildsystem!" message("CMake " "is " "the " "most " "powerful " "buildsystem!")
引数
二重引用符で囲まれた引数により、内部でシールドと変数置換が可能になります。 フレーム化されていない引数はそのようなものの生成を許可せず、文字()#"\
およびスペースを含めることはできませんが、使用する方が便利です。例:
# "Hello, my lovely CMake", "!": message("Hello, my lovely CMake\t!") # "Hello,_my_lovely_CMake!" : message(Hello,_my_lovely_CMake!)
引数Walk;around;the;forest
はリストに展開されることに注意する価値がありますWalk;around;the;forest
このような変換は引数として引用符で囲まれません(セミコロン文字は消えます)。 この機能はコメントで言及されました。
コメント
コメントはポンド記号で始まり、印刷された行の終わりで終わります。 コメントに含まれるテキストはビルドシステムによって無視され、その動作には影響しません。 上記の例は、コメントの使用方法も示しています。
変数
変数はset
コマンドを呼び出すことで定義でき、 unset
を呼び出すことで削除できます。 ${VARIABLE}
構築することにより、変数の値を取得できます。 変数がまだ定義されておらず、値を取得する必要がある場所にある場合、この変数は空の文字列になります。 例:
# VARIABLE "Mr. Thomas": set(VARIABLE "Mr. Thomas") # "His name is: Mr. Thomas": message("His name is: " ${VARIABLE}) # "'BINGO' is equal to: []", "BINGO" : message("'BINGO' is equal to: [${BINGO}]") # VARIABLE: unset(VARIABLE)
オプション
CMakeは、ユーザーが変更するオプションの設定をサポートしています。 オプションは変数に似ており、 option
コマンドによって設定されoption
コマンドは、変数の名前、変数の文字列の説明、変数のデフォルト値( ON
またはOFF
)の3つの引数のみを取ります。
# `USE_ANOTHER_LIBRARY` # "Do you want to use an another library?" "OFF": option(USE_ANOTHER_LIBRARY "Do you want to use an another library?" OFF)
論理式
条件演算子と循環構造の研究を始める前に、論理式の働きを理解する必要があります。 論理式は、条件をチェックするときに使用され、trueまたはfalseの2つの値のいずれかを取ることができます。 たとえば、52 <58であるため、式52 LESS 58
は真になります。式88 EQUAL 88
は真になり、 63 GREATER 104
は偽になります。 数値だけでなく、文字列、バージョン、ファイル、リストメンバーシップ、および正規表現も比較できます。 論理式の完全なリストはここにあります 。
条件文
CMakeの条件演算子は、他のプログラミング言語とまったく同じように機能します。 この例では、最初の条件演算子のみが機能し、5> 1であることを確認します。5は1以下にできないため、2番目と3番目の条件は偽です。 elseif
およびelse
コマンドブロックはオプションであり、 endif
必須であり、以前のチェックの完了を通知します。
# "Of course, 5 > 1!": if(5 GREATER 1) message("Of course, 5 > 1!") elseif(5 LESS 1) message("Oh no, 5 < 1!") else() message("Oh my god, 5 == 1!") endif()
サイクル
CMakeのループは、他のプログラミング言語のループに似ています。 上記の例では、 VARIABLE
変数の値がAirport
に設定され、 VARIABLE
変数の値がAirport
等しくなるまで、4つのネストされたコマンドが順番に実行されます。 最後の4番目のset(VARIABLE "Police station")
コマンドset(VARIABLE "Police station")
はset(VARIABLE "Police station")
のチェックされた変数の値を設定するため、ループは2番目の反復に到達する直前に停止します。 endwhile
コマンドは、ループ内にネストされたコマンドのリストの完了をendwhile
します。
# "VARIABLE is still 'Airport'": set(VARIABLE Airport) while(${VARIABLE} STREQUAL Airport) message("VARIABLE is still '${VARIABLE}'") message("VARIABLE is still '${VARIABLE}'") message("VARIABLE is still '${VARIABLE}'") set(VARIABLE "Police station") endwhile()
このforeach
例は次のように機能します。このループの各反復で、 VARIABLE
変数にはリストから次の値が割り当てられますGive me the sugar please!
、 message(${VARIABLE})
コマンドが実行され、 VARIABLE
変数の現在の値が表示されます。 リストに値がない場合、ループは実行を終了します。 endforeach
コマンドは、ループ内にネストされたコマンドのリストの完了をendforeach
します。
# "Give me the sugar please!" : foreach(VARIABLE Give me the sugar please!) message(${VARIABLE}) endforeach()
foreach
の記述には、さらに3つの形式がありforeach
。 この例の最初のサイクルはリストの代わりに0〜10の整数を生成し、2番目のサイクルは3〜15の範囲で生成し、3番目のサイクルは50〜90のセグメントで動作しますが、ステップは10です。
# "0 1 2 3 4 5 6 7 8 9 10" : foreach(VARIABLE RANGE 10) message(${VARIABLE}) endforeach() # "3 4 5 6 7 8 9 10 11 12 13 14 15" : foreach(VARIABLE RANGE 3 15) message(${VARIABLE}) endforeach() # "50 60 70 80 90" : foreach(VARIABLE RANGE 50 90 10) message(${VARIABLE}) endforeach()
関数とマクロ
CMake構文を使用すると、組み込みコマンドとまったく同じように呼び出すことができる独自のコマンドを定義できます。 次の例は、関数とマクロの使用方法を示しています。最初に、関数とマクロは独自のコマンドで定義され、呼び出されると、それらのコマンドは順番に実行されます。
# "print_numbers": function(print_numbers NUM1 NUM2 NUM3) message(${NUM1} " " ${NUM2} " " ${NUM3}) endfunction() # "print_words": macro(print_words WORD1 WORD2 WORD3) message(${WORD1} " " ${WORD2} " " ${WORD3}) endmacro() # "print_numbers", "12 89 225": print_numbers(12 89 225) # "print_words", "Hey Hello Goodbye": print_words(Hey Hello Goodbye)
function
コマンドは、将来の関数の名前を最初の引数として受け取り、残りの引数は通常の変数として使用できるパラメーターの名前です。 パラメーターは定義されている関数にのみ表示されます。つまり、関数の外部からパラメーターにアクセスすることはできません。 さらに、関数内で定義および再定義された他のすべての変数は、それ自体にのみ表示されます。
マクロは、独自のスコープを持たないことを除いて、関数に似ています。マクロ内のすべての変数はグローバルと見なされます。 マクロと関数の違いについては、 こちらをご覧ください 。
コメントで述べたように、CMakeのマクロはCプリプロセッサのマクロに似ています。この例が示すように、マクロ本体にreturn
コマンドを入れると、呼び出し関数(またはスクリプト全体)を終了します。
# , : macro(demonstrate_macro) return() endmacro() # , : function(demonstrate_func) demonstrate_macro() message("The function was invoked!") endfunction() # "Something happened with the function!" demonstrate_func() message("Something happened with the function!")
上記の例では、関数demonstrate_func
は、メッセージThe function was invoked!
する時間がありませんThe function was invoked!
、以前と同様に、マクロdemosive_macroを呼び出す場所が置き換えられ、exitコマンドが実行されます。
引数の解析
コメントで述べたように、強力なcmake_parse_arguments
メカニズムにより、関数またはマクロに渡された引数を解析できます。
このコマンドは、変数の定義で使用されるプレフィックス(次の段落を参照)、後続の値なしで使用されるオプションのリスト、単一の値が続くキーワードのリスト、値のセットが続くキーワードのリスト、および関数に渡されるすべての値のリストを受け入れますまたはマクロ。
引数解析メカニズムの機能は、受け取った引数を変数値に変換することです。 したがって、各オプションとキーワードの考慮されるコマンドは、特定の値をカプセル化する<Prefix>_<OptionOrKeyword>
という形式の独自の変数を定義します。 オプションの場合、これらはブール値(true-オプションが示され、それ以外の場合はfalse)です。キーワードの場合、転送されたすべての値はそれらの後にあります。
custom_function
関数にはcmake_parse_arguments
呼び出しが含まれ、特定の変数の値を出力します。 次に、引数LOW NUMBER 30 COLORS red green blue
て関数が呼び出された後、画面に印刷されます。
function(custom_function) # : cmake_parse_arguments(CUSTOM_FUNCTION "LOW;HIGH" "NUMBER" "COLORS" ${ARGV}) # "'LOW' = [TRUE]": message("'LOW' = [${CUSTOM_FUNCTION_LOW}]") # "'HIGH' = [FALSE]": message("'HIGH' = [${CUSTOM_FUNCTION_HIGH}]") # "'NUMBER' = [30]": message("'NUMBER' = [${CUSTOM_FUNCTION_NUMBER}]") # "'COLORS' = [red;green;blue]": message("'COLORS' = [${CUSTOM_FUNCTION_COLORS}]") endfunction() # "custom_function" : custom_function(LOW NUMBER 30 COLORS red green blue)
スコープ
前のセクションで、CMakeの一部の構成体が独自のスコープを定義できることを学びました。 実際、関数で定義および再定義された変数を除き、すべての変数はデフォルトでグローバルと見なされます(変数へのアクセスはどこにでもあります)。 独自のスコープを持つキャッシュ変数もありますが、それほど頻繁には使用されません。
コメントで述べたように、変数はset(VARIABLE ... PARENT_SCOPE)
コマンドset(VARIABLE ... PARENT_SCOPE)
を使用して「親」スコープで定義できます。 この例は、この機能を示しています。
# , "VARIABLE" # "In the parent scope..." : function(demonstrate_variable) set(VARIABLE "In the parent scope..." PARENT_SCOPE) endfunction() # "VARIABLE" : demonstrate_variable() # "VARIABLE" : message("'VARIABLE' is equal to: ${VARIABLE}")
PARENT_SCOPE
VARIABLE
変数の定義から削除されると、変数PARENT_SCOPE
関数からのみアクセス可能になり、グローバルスコープでは空の値を取得します。
おわりに
これでCMakeの構文は終わりです。 次の記事は数日でリリースされ、CMakeビルドシステムの使用法が紹介されます。 じゃあね!