CMake有一個 if
語句, 經年累月以後,如今它已經至關複雜。 您能夠在 if
語句中使用全大寫字母書寫一系列關鍵字,而且您一般能夠直接經過名稱(if語句在歷史上出現早於變量擴展)或使用 ${}
語法來引用變量。 下面是 if
語句的示例:html
if(variable) # If variable is `ON`, `YES`, `TRUE`, `Y`, or non zero number else() # If variable is `0`, `OFF`, `NO`, `FALSE`, `N`, `IGNORE`, `NOTFOUND`, `""`, or ends in `-NOTFOUND` endif() # If variable does not expand to one of the above, CMake will expand it then try again
若是您明確地進行變量擴展(例如 ${variable}
,因爲擴展的潛在擴展),這可能會有點混亂。 在CMake 3.1+ 中添加了一個策略(CMP0054),使得被引號引發來的變量擴展不被遞歸擴展。 所以,只要 CMake 的最低版本是 3.1+,您就能夠:正則表達式
if("${variable}") # True if variable is not false-like else() # Note that undefined variables would be `""` thus false endif()
這裏還有一些能夠在 if
命令中使用的關鍵字,例如:express
NOT
, TARGET
, EXISTS
(文件), DEFINED
, 等等STREQUAL
, AND
, OR
, MATCHES
(正則表達式), VERSION_LESS
, VERSION_LESS_EQUAL
(CMake 3.7+), 等等Generator-expressions 很是強大,但也有點奇怪和專業。 大多數 CMake 命令在配置時運行,包括上面看到的 if
語句。 可是若是你須要在構建時甚至安裝時間執行邏輯呢? 爲了這個目的 CMake 添加了生成器表達式(Generator-expressions)。1 它們在目標屬性中進行計算和執行。編程
最簡單的生成器表達式是信息表達式,具備這樣 $<KEYWORD>
的形式; 他們評估(計算和執行)一條與當前配置相關的信息。 另外一種形式是 $<KEYWORD:value>
,KEYWORD 關鍵字控制評估,value
是要評估的項目(這裏也容許使用信息表達式關鍵字)。 若是 KEYWORD
是一個計算結果爲 0 或 1 的生成器表達式或變量,value
則替換爲 0 或 1。 您能夠嵌套生成器表達式,而且可使用變量來使嵌套變量可讀。 某些表達式容許使用逗號分隔的多個值。2緩存
例如,若是你想要設置僅在 DEBUG
配置下生效的編譯標誌,則能夠這樣寫:函數
target_compile_options(MyTarget PRIVATE "$<$<CONFIG:Debug>:--my-flag>")
這是一種比使用專用 *_DEBUG
變量更新,更好的方式,而且能夠推廣到生成器表達式支持的全部狀況。 請注意,您永遠不該該使用配置時的值做爲當前配置,由於 IDE 之類的多配置生成器並無「當前」配置,僅在構建時經過生成器表達式和自定義的 *_<CONFIG>
變量起做用。spa
生成器表達式的其餘常見用法:翻譯
最後一個很常見。幾乎每一個支持安裝的軟件包都會看到相似的內容:code
target_include_directories(
MyTarget
PUBLIC
$<BUILD_INTERFACE:"${CMAKE_CURRENT_SOURCE_DIR}/include"> $<INSTALL_INTERFACE:include> )
1. 它們就像在構建/安裝時評估它們同樣,但實際上它們是針對每一個構建配置分別進行評估的。 ↩
2. CMake 文檔將表達式拆分爲信息,邏輯和輸出。 ↩
你能夠方便的定義你本身的 CMake 函數 function
和宏 macro
。 函數和宏之間的惟一區別是做用範圍:宏沒有做用範圍。 所以,若是您在函數中設置了變量並但願它在外部可見,那麼您將須要用 PARENT_SCOPE
。 因爲您必須在每一個函數中明確用 PARENT_SCOPE
設置您但願外部世界可見的變量,嵌套函數有點兒煩。 可是,函數不會像宏同樣 「泄漏」 變量。 在如下示例中,我將使用函數。htm
一個簡單使用函數的例子以下:
function(SIMPLE REQUIRED_ARG) message(STATUS "Simple arguments: ${REQUIRED_ARG}, followed by ${ARGV}") set(${REQUIRED_ARG} "From SIMPLE" PARENT_SCOPE) endfunction() simple(This) message("Output: ${This}")
若是你想用位置參數,它們須要明確列出,而且全部其餘參數都被放在 ARGN
中(ARGV
中保存有全部參數,甚至那些你已經列出的參數)。 您只能經過設置變量來解決 CMake 中函數沒有返回值的問題。 在上面的示例中,您能夠顯式指定要設置的變量名稱。
你已經在 CMake 函數的大部分使用中看到,CMake 有一個命名變量系統。 您能夠將它與 cmake_parse_arguments
函數一塊兒使用。 若是要支持 3.5 如下的 CMake 版本,您還須要包含 CMakeParseArguments 模塊,該模塊在成爲內置命令以前就已存在。
如下是如何使用它的示例:
function(COMPLEX) cmake_parse_arguments( COMPLEX_PREFIX "SINGLE;ANOTHER" "ONE_VALUE;ALSO_ONE_VALUE" "MULTI_VALUES" ${ARGN} ) endfunction() complex(SINGLE ONE_VALUE value MULTI_VALUES some other values)
在此調用 cmake_parse_arguments
函數後,在 complex
函數內部,給咱們產生了這些變量:
COMPLEX_PREFIX_SINGLE = TRUE COMPLEX_PREFIX_ANOTHER = FALSE COMPLEX_PREFIX_ONE_VALUE = "value" COMPLEX_PREFIX_ALSO_ONE_VALUE = <UNDEFINED> COMPLEX_PREFIX_MULTI_VALUES = "some;other;values"
若是你查看官方頁面,你會看到一個稍微不一樣的使用 set
的方法避免在列表中明確寫分號的方法; 隨意使用您最喜歡的結構。 您也能夠將它與上面列出的位置參數混合使用; 任何剩餘的參數(包括可選的位置參數)都會保存在 COMPLEX_PREFIX_UNPARSED_ARGUMENTS
中。