<> 翻譯 2.2 CMake 編程

<<Modern CMake>> 翻譯 2.2 CMake 編程

流程控制

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

  • 一元關鍵字: NOTTARGETEXISTS (文件), DEFINED, 等等
  • 二元關鍵字: STREQUALANDORMATCHES (正則表達式), VERSION_LESSVERSION_LESS_EQUAL(CMake 3.7+), 等等
  • 括號能夠用於分組

生成器表達式 (Generator-expressions)

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

生成器表達式的其餘常見用法:翻譯

  • 將項目限制爲僅限某種語言(例如 CXX),以免它與 CUDA 等混在一塊兒,或者根據目標語言將其包裝以使其不一樣。
  • 訪問配置相關屬性,例如目標文件位置。
  • 爲構建和安裝目錄提供不一樣的位置。

最後一個很常見。幾乎每一個支持安裝的軟件包都會看到相似的內容: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 中。

相關文章
相關標籤/搜索