[解決済み】変数を設定・使用するCMakeの構文とは?
質問
今度CMakeを使うときの自分への戒めのために質問させていただきます。決して定着しないし、Googleの検索結果もよくない。
CMakeで変数を設定・使用するための構文を教えてください。
どのように解決するのですか?
CMakeスクリプトを書くとき、構文やCMakeでの変数の使用方法について知っておく必要があることがたくさんあります。
構文
を使った文字列
set()
:
-
set(MyString "Some Text")
-
set(MyStringWithVar "Some other Text: ${MyString}")
-
set(MyStringWithQuot "Some quote: \"${MyStringWithVar}\"")
または
string()
:
-
string(APPEND MyStringWithContent " ${MyString}")
を使用したリスト
set()
:
-
set(MyList "a" "b" "c")
-
set(MyList ${MyList} "d")
または、より良い
list()
:
-
list(APPEND MyList "a" "b" "c")
-
list(APPEND MyList "d")
ファイル名のリスト。
-
set(MySourcesList "File.name" "File with Space.name")
-
list(APPEND MySourcesList "File.name" "File with Space.name")
-
add_excutable(MyExeTarget ${MySourcesList})
ドキュメンテーション
- CMake/言語構文
- CMake: 変数一覧 文字列
- CMake: 便利な変数
-
CMake
set()
コマンド -
CMake
string()
コマンド -
CMake
list()
コマンド - Cmake: ジェネレータ式
スコープまたは "私の変数が持っている値は何ですか?
まず、通常の変数と、そのスコープについて知っておくべきことがあります。
-
通常の変数は
CMakeLists.txt
に設定され、そこからすべてが呼び出されます (add_subdirectory()
,include()
,macro()
とfunction()
). -
は
add_subdirectory()
とfunction()
コマンドは、独自のスコープを開くので、特別です。-
意味のある変数
set(...)
はそこでしか見ることができず、呼び出されたスコープレベル(親スコープと呼ばれます)のすべての正常な変数のコピーを作成します。 -
そのため、サブディレクトリや関数内にいる場合、親スコープにすでに存在する変数を
set(... PARENT_SCOPE)
-
関数のパラメータとして変数名を渡すことで、例えば関数内でこれを利用することができます。例えば、以下のようになります。
function(xyz _resultVar)
が設定されているset(${_resultVar} 1 PARENT_SCOPE)
-
意味のある変数
-
一方
include()
またはmacro()
スクリプトは、呼び出された先のスコープで直接変数を変更します。
2つ目は、グローバル変数キャッシュ(Global Variables Cache)です。キャッシュについて知っておくべきこと。
- 与えられた名前の通常の変数が現在のスコープで定義されていない場合、CMake は一致する Cache エントリーを探します。
-
キャッシュの値は
CMakeCache.txt
ファイルをバイナリ出力ディレクトリに作成します。 -
Cache内の値を変更するには CMakeのGUI アプリケーションで生成されます。したがって、通常の変数と比較して、これらは
type
とdocstring
. 普段はGUIを使わないのでset(... CACHE INTERNAL "")
を使用して、グローバル値とパーシステント値を設定します。なお
INTERNAL
キャッシュ変数型はFORCE
-
CMake スクリプトでは、既存の Cache エントリを変更できるのは
set(... CACHE ... FORCE)
の構文があります。この動作は、例えば CMake 自身が通常 Cache エントリを強制しないため、別の値で事前に定義しておくことで利用されています。 -
コマンドラインを使用して、Cache のエントリを設定するには、次の構文を使用します。
cmake -D var:type=value
ただcmake -D var=value
またはcmake -C CMakeInitialCache.cmake
. -
できること
アンセット
のエントリをキャッシュに保存するには
unset(... CACHE)
.
Cache はグローバルであり、CMake スクリプトの事実上どこにでも設定することができます。しかし、Cache変数を使う場所についてはよく考えることをお勧めします(グローバルであるため、永続的である)。私は通常
set_property(GLOBAL PROPERTY ...)
と
set_property(GLOBAL APPEND PROPERTY ...)
構文を使って、私独自の非固定グローバル変数を定義しています。
変数の落とし穴と"変数の変更をデバッグする方法"
落とし穴を避けるために、変数について以下のことを知っておく必要があります。
- ローカル変数が同じ名前の場合、キャッシュされた変数を隠します。
-
は
find_...
コマンドは、成功した場合、キャッシュされた変数として結果を書き込みます(" so no call will search again") -
CMake のリストは、セミコロンで区切られた単なる文字列です。
したがって、クォーテーションマークは重要です。
-
set(MyVar a b c)
は"a;b;c"
とset(MyVar "a b c")
は"a b c"
- 推奨は、常に引用符を使用することですが、リストをlistと表記する場合は例外です。
-
一般的には
list()
コマンドはリストを処理するために
-
-
上記で説明したスコープ全体の問題。特に推奨されるのは
functions()
の代わりにmacros()
というのも、ローカル変数を親スコープに表示させたくないからです。 -
CMake で使用される多くの変数が
project()
とenable_language()
を呼び出します。そのため、これらのコマンドを使用する前に、いくつかの変数を設定することが重要になる可能性があります。 -
環境変数は、CMake が make 環境を生成した場所と make ファイルを使用するときとで異なる場合があります。
- 環境変数が変更されても、生成プロセスが再トリガーされることはありません。
- 特に、生成されたIDE環境は、コマンドラインと異なる場合がありますので、環境変数をキャッシュされるものに転送することをお勧めします。
変数のデバッグだけが役立つこともあります。以下が参考になるかもしれません。
-
単純に古い
printf
を使用したデバッグスタイルです。message()
コマンドを使用します。また、CMake自体に同梱されている、すぐに使えるモジュールもあります。 CMakePrintHelpers.cmake , CMakePrintSystemInformation.cmake -
調べる
CMakeCache.txt
ファイルをバイナリ出力ディレクトリに作成します。このファイルは、make環境の実際の生成に失敗した場合にも生成されます。 - 使用方法 変数ウォッチ() を使えば、変数の読み書きが行われる場所を確認することができます。
- ディレクトリのプロパティを調べる キャッシュ変数 と バリアブル
-
コール
cmake --trace ...
をクリックすると、CMake の完全なパース処理を見ることができます。これは、多くの出力を生成するため、最後の準備のようなものです。
特殊な構文
-
環境変数
-
を読み取ることができます。
$ENV{...}
と書きset(ENV{...} ...)
環境変数
-
を読み取ることができます。
-
ジェネレータ式
-
ジェネレータ式
$<...>
は CMake のジェネレーターが make 環境を書き込むときにのみ評価されます (パーサーが "インプレースで置き換える通常の変数と比較します)。 - コンパイラやリンカのコマンドラインや、複数のコンフィギュレーションがある環境では、非常に便利です。
-
ジェネレータ式
-
参考文献
-
と
${${...}}
で変数名を与え、その内容を参照することができます。 - 関数/マクロのパラメータとして変数名を与えるときによく使われます。
-
と
-
定数値 (参照
if()
コマンド)-
とともに
if(MyVariable)
を使用すると、変数に対して直接真偽をチェックすることができます。${...}
) -
が定数なら真
1
,ON
,YES
,TRUE
,Y
または0でない数。 -
定数が
0
,OFF
,NO
,FALSE
,N
,IGNORE
,NOTFOUND
または空文字列、あるいは末尾が-NOTFOUND
. -
この構文は、次のような場合によく使われます。
if(MSVC)
しかし、この構文のショートカットを知らない人は混乱する可能性があります。
-
とともに
-
再帰的置換
-
変数を用いて変数名を構成することができます。CMake は変数を代入した後、その結果が変数そのものであるかどうかを再度チェックします。これは、例えばテンプレートのようなものとして CMake 自身で使用される非常に強力な機能です。
set(CMAKE_${lang}_COMPILER ...)
-
しかし
気がつく
で頭が痛くなることがあります。
if()
コマンドを使用します。以下はその例です。CMAKE_CXX_COMPILER_ID
は"MSVC"
とMSVC
は"1"
:-
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
と評価されるので、真となります。if("1" STREQUAL "1")
-
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
と評価されるため、偽となります。if("MSVC" STREQUAL "1")
-
したがって、ここでの最良の解決策は、上記を参照し、直接的に
if(MSVC)
-
-
良いニュースは、CMake 3.1 でこの問題が修正されたことです。
ポリシー CMP0054
. を常に設定することをお勧めします。
cmake_policy(SET CMP0054 NEW)
を解釈するのみです。if()
引数が引用されていない場合は、変数またはキーワードとして扱われます。
-
変数を用いて変数名を構成することができます。CMake は変数を代入した後、その結果が変数そのものであるかどうかを再度チェックします。これは、例えばテンプレートのようなものとして CMake 自身で使用される非常に強力な機能です。
-
は
option()
コマンド
参考文献
関連
-
[解決済み] CMake でモジュールディレクトリが見つからない
-
[解決済み] CMAKE_SOURCE_DIRはどこですか?
-
[解決済み] cmake --verbose=1` は冗長なcmake出力をしますが、`cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON` はそうならないのはなぜですか?
-
[解決済み] .cmakeファイルの目的は何ですか?
-
[解決済み] MakefileとCMakeを使ったコンパイルの違いについて
-
[解決済み】CMakeでGCCとClang/LLVMの切り替えを行う。
-
[解決済み】CMake:スクリプト内のアクセス可能なすべての変数を出力する
-
[解決済み】変数を設定・使用するCMakeの構文とは?
-
[解決済み】CMAKE_MODULE_PATHを指定する必要がある場合、find_package()はどのように使用するのでしょうか?
-
[解決済み】CMakeは具体的にどのように動作するのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】CMakeでソースディレクトリからバイナリディレクトリにファイルをコピーする
-
[解決済み] CMakeは "make uninstall "をサポートしていますか?
-
[解決済み] プロジェクトでCMAKE_CXX_FLAGSを変更する
-
[解決済み] CMake でモジュールディレクトリが見つからない
-
[解決済み] CMakeでポータブルパラレルビルドを設定するには?
-
[解決済み] CMAKE_SOURCE_DIRはどこですか?
-
[解決済み] cmakeのincludeコマンドにおいて、ファイルとモジュールの違いは何ですか?
-
[解決済み] CMakeのオプション()をコマンドラインで設定する方法
-
[解決済み】CMakeをGNU Makeと一緒に使う:正確なコマンドを見るにはどうすればいい?
-
[解決済み】変数を設定・使用するCMakeの構文とは?