if

有條件地執行一組命令。

概要

if(<condition>)
  <commands>
elseif(<condition>) # optional block, can be repeated
  <commands>
else()              # optional block
  <commands>
endif()

根據下方描述的條件語法評估 if 子句的 condition 參數。 如果結果為 true,則會執行 if 區塊中的 commands。 否則,會以相同方式處理可選的 elseif 區塊。 最後,如果沒有 condition 為 true,則會執行可選的 else 區塊中的 commands

依照傳統,else()endif() 命令接受一個可選的 <condition> 參數。 如果使用,它必須是開頭 if 命令的參數的逐字重複。

條件語法

以下語法適用於 ifelseifwhile() 子句的 condition 參數。

複合條件會依下列優先順序評估

  1. 括號.

  2. 一元測試,例如 COMMANDPOLICYTARGETTESTEXISTSIS_READABLEIS_WRITABLEIS_EXECUTABLEIS_DIRECTORYIS_SYMLINKIS_ABSOLUTEDEFINED

  3. 二元測試,例如 EQUALLESSLESS_EQUALGREATERGREATER_EQUALSTREQUALSTRLESSSTRLESS_EQUALSTRGREATERSTRGREATER_EQUALVERSION_EQUALVERSION_LESSVERSION_LESS_EQUALVERSION_GREATERVERSION_GREATER_EQUALPATH_EQUALIN_LISTIS_NEWER_THANMATCHES

  4. 一元邏輯運算子 NOT

  5. 二元邏輯運算子 ANDOR,從左到右,不進行任何短路。

基本表達式

if(<constant>)

如果常數是 1ONYESTRUEY 或非零數字(包括浮點數),則為 true。 如果常數是 0OFFNOFALSENIGNORENOTFOUND、 空字串或以 -NOTFOUND 字尾結尾,則為 false。 具名的布林常數不區分大小寫。 如果引數不是這些特定常數之一,則會將其視為變數或字串(請參閱下方的變數展開),並採用下列兩種形式之一。

if(<variable>)

如果給定的變數定義為非 false 常數的值,則為 True。 否則為 False,包括如果變數未定義。 請注意,巨集引數不是變數。 也無法以這種方式測試環境變數,例如,if(ENV{some_var}) 將始終評估為 false。

if(<string>)

除非下列情況,否則帶引號的字串始終評估為 false

  • 字串的值是 true 常數之一,或者

  • 策略 CMP0054 未設定為 NEW,並且字串的值恰好是受到 CMP0054 行為影響的變數名稱。

邏輯運算子

if(NOT <condition>)

如果條件不為 true,則為 true。

if(<cond1> AND <cond2>)

如果兩個條件分別被視為 true,則為 true。

if(<cond1> OR <cond2>)

如果任一條件分別被視為 true,則為 true。

if((condition) AND (condition OR (condition)))

先評估括號內的條件,然後評估剩餘的條件,如其他範例所示。 在有巢狀括號的情況下,最內層的括號會評估為評估包含它們的條件的一部分。

存在檢查

if(COMMAND <command-name>)

如果給定的名稱是可以叫用的命令、巨集或函式,則為 true。

if(POLICY <policy-id>)

如果給定的名稱是現有策略(格式為 CMP<NNNN>),則為 true。

if(TARGET <target-name>)

如果給定的名稱是由呼叫 add_executable()add_library()add_custom_target() 命令所建立的現有邏輯目標名稱(在任何目錄中)且已經被調用,則為真。

if(TEST <test-name>)

在 3.3 版本中新增。

如果給定的名稱是由 add_test() 命令所建立的現有測試名稱,則為真。

if(DEFINED <name>|CACHE{<name>}|ENV{<name>})

如果已定義具有給定 <name> 的變數、快取變數或環境變數,則為真。 變數的值並不重要。 請注意以下注意事項:

  • 巨集引數不是變數。

  • 無法直接測試 <name> 是否為非快取變數。 如果存在快取或非快取變數 someName,則運算式 if(DEFINED someName) 將評估為 true。 相比之下,如果存在快取變數 someName,則運算式 if(DEFINED CACHE{someName}) 才會評估為 true。 如果您需要知道是否存在非快取變數,則需要測試兩個運算式:if(DEFINED someName AND NOT DEFINED CACHE{someName})

在 3.14 版本中新增:新增對 CACHE{<name>} 變數的支援。

if(<variable|string> IN_LIST <variable>)

在 3.3 版本中新增。

如果給定的元素包含在指定的列表變數中,則為真。

檔案操作

if(EXISTS <path-to-file-or-directory>)

如果指定的檔案或目錄存在且可讀取,則為真。 僅對於明確的完整路徑(前導 ~/ 不會展開為家目錄,並被視為相對路徑)才定義行為。 解析符號連結,即如果指定的檔案或目錄是符號連結,則如果符號連結的目標存在,則傳回 true。

如果給定的路徑為空字串,則為 False。

注意

建議使用 if(IS_READABLE) 檢查檔案的可讀性。 if(EXISTS) 未來可能會變更為僅檢查檔案是否存在。

if(IS_READABLE <path-to-file-or-directory>)

在 3.29 版本中新增。

如果指定的檔案或目錄可讀取,則為真。 僅對於明確的完整路徑(前導 ~/ 不會展開為家目錄,並被視為相對路徑)才定義行為。 解析符號連結,即如果指定的檔案或目錄是符號連結,則如果符號連結的目標可讀取,則傳回 true。

如果給定的路徑為空字串,則為 False。

if(IS_WRITABLE <path-to-file-or-directory>)

在 3.29 版本中新增。

如果指定的檔案或目錄可寫入,則為真。 僅對於明確的完整路徑(前導 ~/ 不會展開為家目錄,並被視為相對路徑)才定義行為。 解析符號連結,即如果指定的檔案或目錄是符號連結,則如果符號連結的目標可寫入,則傳回 true。

如果給定的路徑為空字串,則為 False。

if(IS_EXECUTABLE <path-to-file-or-directory>)

在 3.29 版本中新增。

如果指定的檔案或目錄可執行,則為真。 僅對於明確的完整路徑(前導 ~/ 不會展開為家目錄,並被視為相對路徑)才定義行為。 解析符號連結,即如果指定的檔案或目錄是符號連結,則如果符號連結的目標可執行,則傳回 true。

如果給定的路徑為空字串,則為 False。

if(<file1> IS_NEWER_THAN <file2>)

如果 file1file2 新,或者如果其中一個檔案不存在,則為真。 僅對於完整路徑才定義行為。 如果檔案的時間戳記完全相同,則 IS_NEWER_THAN 比較會傳回 true,以便在出現平手的情況下執行任何相依的建置操作。 這包括為 file1 和 file2 傳遞相同檔案名稱的情況。

if(IS_DIRECTORY <path>)

如果 path 是目錄,則為真。 僅對於完整路徑才定義行為。

如果給定的路徑為空字串,則為 False。

如果給定的路徑是符號連結,則為真。 僅對於完整路徑才定義行為。

if(IS_ABSOLUTE <path>)

如果給定的路徑是絕對路徑,則為真。 請注意以下特殊情況:

  • 空的 path 評估為 false。

  • 在 Windows 主機上,任何以磁碟機代號和冒號(例如 C:)、正斜線或反斜線開頭的 path 都會評估為 true。 這表示像 C:no\base\dir 這樣的路徑將會評估為 true,即使路徑的非磁碟機部分是相對的。

  • 在非 Windows 主機上,任何以波浪號 (~) 開頭的 path 都會評估為 true。

比較

if(<variable|string> MATCHES <regex>)

如果給定的字串或變數的值與給定的正規表示式相符,則為真。 有關正規表示式格式,請參閱 正規表示式規格

在 3.9 版本中新增: () 群組會被捕獲到 CMAKE_MATCH_<n> 變數中。

if(<變數|字串> LESS <變數|字串>)

如果給定的字串或變數的值解析為實數(如 C 的 double),且小於右邊的值,則為 True。

if(<變數|字串> GREATER <變數|字串>)

如果給定的字串或變數的值解析為實數(如 C 的 double),且大於右邊的值,則為 True。

if(<變數|字串> EQUAL <變數|字串>)

如果給定的字串或變數的值解析為實數(如 C 的 double),且等於右邊的值,則為 True。

if(<變數|字串> LESS_EQUAL <變數|字串>)

在 3.7 版本中新增。

如果給定的字串或變數的值解析為實數(如 C 的 double),且小於或等於右邊的值,則為 True。

if(<變數|字串> GREATER_EQUAL <變數|字串>)

在 3.7 版本中新增。

如果給定的字串或變數的值解析為實數(如 C 的 double),且大於或等於右邊的值,則為 True。

if(<變數|字串> STRLESS <變數|字串>)

如果給定的字串或變數的值在詞彙上小於右邊的字串或變數,則為 True。

if(<變數|字串> STRGREATER <變數|字串>)

如果給定的字串或變數的值在詞彙上大於右邊的字串或變數,則為 True。

if(<變數|字串> STREQUAL <變數|字串>)

如果給定的字串或變數的值在詞彙上等於右邊的字串或變數,則為 True。

if(<變數|字串> STRLESS_EQUAL <變數|字串>)

在 3.7 版本中新增。

如果給定的字串或變數的值在詞彙上小於或等於右邊的字串或變數,則為 True。

if(<變數|字串> STRGREATER_EQUAL <變數|字串>)

在 3.7 版本中新增。

如果給定的字串或變數的值在詞彙上大於或等於右邊的字串或變數,則為 True。

版本比較

if(<變數|字串> VERSION_LESS <變數|字串>)

組件式整數版本號碼比較(版本格式為 major[.minor[.patch[.tweak]]],省略的組件被視為零)。任何非整數的版本組件或版本組件的非整數尾部部分都會有效地將字串在那一點截斷。

if(<變數|字串> VERSION_GREATER <變數|字串>)

組件式整數版本號碼比較(版本格式為 major[.minor[.patch[.tweak]]],省略的組件被視為零)。任何非整數的版本組件或版本組件的非整數尾部部分都會有效地將字串在那一點截斷。

if(<變數|字串> VERSION_EQUAL <變數|字串>)

組件式整數版本號碼比較(版本格式為 major[.minor[.patch[.tweak]]],省略的組件被視為零)。任何非整數的版本組件或版本組件的非整數尾部部分都會有效地將字串在那一點截斷。

if(<變數|字串> VERSION_LESS_EQUAL <變數|字串>)

在 3.7 版本中新增。

組件式整數版本號碼比較(版本格式為 major[.minor[.patch[.tweak]]],省略的組件被視為零)。任何非整數的版本組件或版本組件的非整數尾部部分都會有效地將字串在那一點截斷。

if(<變數|字串> VERSION_GREATER_EQUAL <變數|字串>)

在 3.7 版本中新增。

組件式整數版本號碼比較(版本格式為 major[.minor[.patch[.tweak]]],省略的組件被視為零)。任何非整數的版本組件或版本組件的非整數尾部部分都會有效地將字串在那一點截斷。

路徑比較

if(<變數|字串> PATH_EQUAL <變數|字串>)

在 3.24 版本中新增。

逐個組件比較兩個路徑。只有當兩個路徑的每個組件都匹配時,兩個路徑才會被視為相等。多個路徑分隔符會有效地摺疊為單個分隔符,但請注意反斜線不會轉換為正斜線。不執行其他路徑正規化

由於處理多個路徑分隔符的方式,組件式比較優於基於字串的比較。在以下範例中,使用 PATH_EQUAL 時,運算式會評估為 true,但使用 STREQUAL 時,則會評估為 false。

# comparison is TRUE
if ("/a//b/c" PATH_EQUAL "/a/b/c")
   ...
endif()

# comparison is FALSE
if ("/a//b/c" STREQUAL "/a/b/c")
   ...
endif()

有關詳細資訊,請參閱 cmake_path(COMPARE)

變數展開

if 命令是在 CMake 歷史的早期編寫的,早於 ${} 變數評估語法,為了方便起見,它會評估其引數所命名的變數,如上述簽章所示。請注意,使用 ${} 的正常變數評估會在 if 命令甚至接收引數之前套用。因此,類似以下的程式碼:

set(var1 OFF)
set(var2 "var1")
if(${var2})

對 if 命令而言,會顯示為:

if(var1)

並根據上述記錄的 if(<變數>) 案例進行評估。結果是 OFF,這是 false。但是,如果我們從範例中移除 ${},則命令會看到:

if(var2)

這是 true,因為 var2 定義為 var1,而 var1 不是 false 常數。

只要上述記錄的條件語法接受 <變數|字串>,自動評估就會在其他情況下套用。

  • MATCHES 的左側引數會先檢查是否為已定義的變數。如果是,則使用變數的值,否則使用原始值。

  • 如果 MATCHES 的左側引數遺失,則會傳回 false 而不出現錯誤。

  • LESSGREATEREQUALLESS_EQUALGREATER_EQUAL 的左右兩側引數都會獨立測試,以查看是否為已定義的變數。如果是,則使用其定義的值,否則使用原始值。

  • STRLESSSTRGREATERSTREQUALSTRLESS_EQUALSTRGREATER_EQUAL 的左右兩側引數都會獨立測試,以查看是否為已定義的變數。如果是,則使用其定義的值,否則使用原始值。

  • VERSION_LESSVERSION_GREATERVERSION_EQUALVERSION_LESS_EQUALVERSION_GREATER_EQUAL 的左右兩側引數都會獨立測試,以查看是否為已定義的變數。如果是,則使用其定義的值,否則使用原始值。

  • IN_LIST 的左側引數會測試以查看是否為已定義的變數。如果是,則使用變數的值,否則使用原始值。

  • NOT 的右側引數會測試以查看是否為布林常數。如果是,則使用該值,否則會假設為變數並解除參照。

  • ANDOR 的左右兩側引數都會獨立測試,以查看是否為布林常數。如果是,則會使用它們,否則會假設為變數並解除參照。

在 3.1 版本中變更:為了避免模稜兩可,可以在引號引數方括號引數中指定潛在的變數或關鍵字名稱。帶引號或方括號的變數或關鍵字將會被解譯為字串,而不會被解除參照或解譯。請參閱原則CMP0054

環境或快取變數參考沒有自動評估。它們的值必須以 $ENV{<name>}$CACHE{<name>} 的形式參考,只要上述記錄的條件語法接受 <變數|字串>

另請參閱