【cmake系列使用教程】linux
cmake使用教程(二)-添加庫github
cmake使用教程(四)-文件生成器shell
cmake使用教程(五)-cpack生成安裝包express
cmake使用教程(六)-蛋疼的語法macos
cmake使用教程(八)-macro和functionbash
這個系列的文章翻譯自官方cmake教程:cmake tutorial。curl
示例程序地址: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(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。
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
複製代碼
foreach(loop_var RANGE start stop [step])
複製代碼
從start開始直到stop結束之間的值,能夠設置步進值step。
foreach(i RANGE 0 3 1)
message(STATUS "current is ${i}")
endforeach(i)
複製代碼
輸出結果和上面的同樣.
注意一點:最後的結果不會大於stop值,步進值是浮點數時會被轉爲整形
foreach(loop_var IN [LISTS [list1 [...]]]
[ITEMS [item1 [...]]])
複製代碼
也比較簡單,多了LIST關鍵字來循環list。很少講。
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()
複製代碼
第一行包含了咱們須要的依賴模塊。
第二行第三行定義了兩個option
,USE_CURL
,USE_MATH
全爲ON
。
第四行定義了一個option
,DEPENT_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
複製代碼