cmake使用教程(七)-流程和循環

【cmake系列使用教程】linux

cmake使用教程(一)-起步git

cmake使用教程(二)-添加庫github

cmake使用教程(三)-安裝、測試、系統自檢正則表達式

cmake使用教程(四)-文件生成器shell

cmake使用教程(五)-cpack生成安裝包express

cmake使用教程(六)-蛋疼的語法macos

cmake使用教程(七)-流程和循環api

cmake使用教程(八)-macro和functionbash

這個系列的文章翻譯自官方cmake教程:cmake tutorialcurl

示例程序地址:github.com/rangaofei/t…

不會僅僅停留在官方教程。本人做爲一個安卓開發者,實在是沒有linux c程序開發經驗,望大佬們海涵。教程是在macos下完成,大部分linux我也測試過,有特殊說明的我會標註出來。本教程基於cmake-3.10.2,同時認爲你已經安裝好cmake。

流程判斷

cmake中的流程判斷相對簡單,與c語言接近。

形式以下:

if(expression)
  # then section.
  COMMAND1(ARGS ...)
  COMMAND2(ARGS ...)
  #...
elseif(expression2)
  # elseif section.
  COMMAND1(ARGS ...)
  COMMAND2(ARGS ...)
  #...
else(expression)
  # else section.
  COMMAND1(ARGS ...)
  COMMAND2(ARGS ...)
  #...
endif(expression)
複製代碼

此處有一點注意:else和endif中的表達式是能夠省略的,看到如今大部分網上的教程有必須加SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)這句才能省略表達式,一臉懵逼,關於那個變量,我也查不到api,包括廢棄的,因此我都不寫這句。

if表達式能夠用長表達式,優先級順序以下:

> EXISTS, COMMAND, DEFINED 
> EQUAL, LESS, LESS_EQUAL, GREATER, GREATER_EQUAL, STREQUAL, STRLESS, STRLESS_EQUAL, STRGREATER, STRGREATER_EQUAL, VERSION_EQUAL, VERSION_LESS, VERSION_LESS_EQUAL, VERSION_GREATER, VERSION_GREATER_EQUAL, MATCHES
> NOT,AND,OR
複製代碼

別看下面這張表很長,其實沒什麼內容:

表達式 true false 說明
<constant> 1, ON, YES, TRUE, Y,或者是非0數字 0, OFF, NO, FALSE, N, IGNORE, NOTFOUND,空字符串,或者帶-NOTFOUND後綴 布爾判斷值大小寫不敏感
<variable|string> 已經定義且不是false的變量 未定義或者是false的變量 變量就是字符串
<NOT expression> expression爲false expression爲true
AND 兩個條件所有成立 至少有一個爲假
COMAND command-name 已經定義的command,macro或者function 未定義
POLICY policy-id policy存在 policy不存在 形式爲CMP
TARGET target-name 已經用add_executable(), add_library(), or add_custom_target()定義過的target 未定義
TEST test-name add_test()建立過的測試名稱 未建立
EXISTS path-to-file-or-directory 文件或者路徑存在 文件或者路徑不存在 此處是全路徑
file1 IS_NEWER_THAN file2 file1的時間戳大於file2的時間戳
其中一個文件不存在
兩個文件時間戳相同
其餘狀況 文件路徑必須是全路徑
IS_DIRECTORY path-to-directory 給定的變量是文件夾 不是文件夾 全路徑
IS_SYMLINK file-name 變量是連接 不是 全路徑
IS_ABSOLUTE path 是絕對路徑 不是
<variable|string> MATCHES regex 正則表達式匹配成功 匹配失敗
<variable|string> LESS <variable|string> 給定的變量是數字而且左邊小於右邊 左邊大於右邊 用於比較數字的大小
LESS:小於
GREATER:大於
EQUAL:等於
GREATER_EQUAL:大於等於
LESS_EQUAL:小於等於
<variable|string> STRLESS <variable|string> 按字典順序左邊小於右邊 左邊大於右邊 用於比較字符串
LESS:小於
STRGREATER:大於
STREQUAL:等於
STRLESS_EQUAL:小於等於
STRGREATER_EQUAL:大於等於
<variable|string> VERSION_LESS <variable|string> 左邊的版本號小於右邊的版本號 大於 用於版本號的比較
LESS:小於
VERSION_GREATER:大於
VERSION_EQUAL:等於
VERSION_LESS_EQUAL:小於等於
VERSION_GREATER_EQUAL:大於等於
<variable string> IN_LIST 右邊的item中有左邊 沒有
DEFINED 已定義變量 未定義變量
(expr1) AND (expr2 OR (expr3)) 1爲真且2或者3至少有一個爲真 其餘狀況

在if條件表達式中,是沒必要用${var}來取變量的值的,系統會自動轉換。例如設置兩個變量,而後比較各類取值的狀況:

set(var1 OFF)
set(var2 "var1")
複製代碼

if(var2)實際是判斷var1是否爲false; if(${var2})至關於if(var1),實際是判斷OFF;

foreach循環

1. 第一種形式

foreach(loop_var arg1 arg2 ...)
  COMMAND1(ARGS ...)
  COMMAND2(ARGS ...)
  ...
endforeach(loop_var)
複製代碼

此處注意endforeach(loop_var)的變量最好不要省略,由於foreach循環是依靠變量來跳出循環的。

foreach和匹配endforeach之間的全部命令都會被系統記錄而不被調用。 一旦找到了了endforeach,則會執行原來記錄的命令。在循環的每次迭代以前,${loop_var}將被設置爲具備列表中當前值的變量。

foreach(i 0 1 2 3)
    message(STATUS "current is ${i}")
endforeach(i)
    message(STATUS "end")
endforeach(i)
複製代碼

一個簡單的循環,可是多了一個endforeach。看一下結果

➜  StepTest git:(master) ✗ cmake -P foreach.cmake
-- current is 0
-- current is 1
-- current is 2
-- current is 3
-- end
CMake Error at foreach.cmake:5 (endforeach):
  endforeach An ENDFOREACH command was found outside of a proper FOREACH
  ENDFOREACH structure.  Or its arguments did not match the opening FOREACH
  command.
複製代碼

報錯了。沒有匹配的foreach。

2. 第二種形式

foreach(loop_var RANGE total)
複製代碼

從0開始直到total結束(包含total)

foreach(i RANGE 3)
    message(STATUS "current is ${i}")
endforeach(i)
複製代碼

範圍將會是0-3,查看一下結果:

➜  StepTest git:(master) ✗ cmake -P foreach.cmake
-- current is 0
-- current is 1
-- current is 2
-- current is 3
複製代碼

3. 第三種形式

foreach(loop_var RANGE start stop [step])
複製代碼

從start開始直到stop結束之間的值,能夠設置步進值step。

foreach(i RANGE 0 3 1)
message(STATUS "current is ${i}")
endforeach(i)
複製代碼

輸出結果和上面的同樣.

注意一點:最後的結果不會大於stop值,步進值是浮點數時會被轉爲整形

4. 第四種形式

foreach(loop_var IN [LISTS [list1 [...]]]
                    [ITEMS [item1 [...]]])
複製代碼

也比較簡單,多了LIST關鍵字來循環list。很少講。

while循環

while(condition)
  COMMAND1(ARGS ...)
  COMMAND2(ARGS ...)
  ...
endwhile(condition)
複製代碼

注意endwhile中的條件最好不要省略。這個條件和if中的表達式是同樣的規則。 循環形式和foreach循環相似,直到碰到endwhile纔開始執行每一條指令。

在while和foreach循環中,取變量的值請用${var}。break和continue的用法基本與c同樣,放心使用。

在實際項目中,常常使用option來和if搭配。 option使用比較簡單:

option(<option_variable> "help string describing option"
       [initial value])
複製代碼

initial value只能使用ON或者OFF,假如未設定,默認爲false。 cmake_dependent_option是cmake內置的一個module,用來生成依賴其餘option的option,這個至關蛋疼。

看一個簡單的例子:

include(${CMAKE_ROOT}/Modules/CMakeDependentOption.cmake)
option(USE_CURL "use libcurl" ON)
option(USE_MATH "use libm" ON)
cmake_dependent_option(DEPENT_USE_CURL "this is dependent on USE_CURL" ON "USE_CURL;NOT USE_MATH" OFF)
if(DEPENT_USE_CURL)
    message(STATUS "using lib curl")
else()
    message(STATUS "not using lib curl")
endif()
複製代碼

第一行包含了咱們須要的依賴模塊。

第二行第三行定義了兩個optionUSE_CURL,USE_MATH全爲ON

第四行定義了一個optionDEPENT_USE_CURL,後邊緊跟的是它的說明 this is dependent on USE_CURL,再後邊至關於一個三元判斷式,假如USE_CURL;NOT USE_MATH爲真時,取前邊的值,不然取後邊的值。

5-9行是一個if語句,用來輸出咱們想要的結果。

輸出結果:

➜  StepTest git:(master) ✗ cmake -P optionc.cmake
-- not using lib curl
複製代碼
相關文章
相關標籤/搜索