CMake の「これはバグではなく、機能です」というかなり厄介な動作に遭遇しました。if コマンドのドキュメントで説明されているように:
The if command was written very early in CMake's history, predating the ${}
variable evaluation syntax, and for convenience evaluates variables named
by its arguments as shown in the above signatures.
さて、便利さが不便であることが判明しました。あなたの例では、文字列はコマンドによって名前が"d"
付けられた変数として扱われます。変数がたまたま空の文字列に定義されている場合、メッセージ ステートメントは「oops...」を出力します。次に例を示します。d
if
d
set (d "")
if("d" STREQUAL "")
# this branch will be taken
message("oops...")
else()
message("fine")
endif()
これは、次のようなステートメントに対して驚くべき結果をもたらす可能性があります
if("${A}" STREQUAL "some string")
A
変数がたまたま CMake 変数の名前でもある文字列に定義されている場合、最初の引数の意図しない二重展開が発生する可能性があるためです。
set (A "d")
set (d "some string")
if("${A}" STREQUAL "some string")
# this branch will be taken
message("oops...")
else()
message("fine")
endif()
考えられる回避策:
展開後に文字列にサフィックス文字を追加して${}
、if ステートメントが自動評価を実行するのを防ぐことができます。
set (A "d")
set (d "some string")
if("${A} " STREQUAL "some string ")
message("oops...")
else()
# this branch will be taken
message("fine")
endif()
${}
拡張を使用しない:
set (A "d")
set (d "some string")
if(A STREQUAL "some string")
message("oops...")
else()
# this branch will be taken
message("fine")
endif()
代わりにCMake 正規表現STREQUAL
を使用MATCHES
して、使用の右側で意図しない評価を防ぐには:
if(A MATCHES "^value$")
...
endif()
補遺: CMake 3.1 は、引用符で囲まれた引数の二重展開を行わなくなりました。新しいポリシーを参照してください。