流程控制
- 1. 條件判斷
- 1.1 基本表達式
- 1.2 邏輯判斷
- 1.3 比較
- 基于數值的比較
- 基于字符串的比較
- 1.4 文件操作
- 1.5 其他
- 2. 循環
- 2.1 foreach
- 方法1
- 方法2
- 方法3
- 方法4
- 2.2 while
在 CMake 的 CMakeLists.txt 中也可以進行流程控制,也就是說可以像寫 shell 腳本那樣進行條件判斷和循環。
1. 條件判斷
關于條件判斷其語法格式如下:
if(<condition>)<commands>
elseif(<condition>) # 可選快, 可以重復<commands>
else() # 可選快<commands>
endif()
在進行條件判斷的時候,如果有多個條件,那么可以寫多個elseif,最后一個條件可以使用else,但是開始和結束是必須要成對出現的,分別為:if和endif。
1.1 基本表達式
if(<expression>)
如果是基本表達式,expression 有以下三種情況:常量、變量、字符串。
- 如果是1, ON, YES, TRUE, Y, 非零值,非空字符串時,條件判斷返回True
- 如果是 0, OFF, NO, FALSE, N, IGNORE, NOTFOUND,空字符串時,條件判斷返回False
1.2 邏輯判斷
if(NOT <condition>)
if(<cond1> AND <cond2>)
if(<cond1> OR <cond2>)
- NOT:其實這就是一個取反操作,如果條件condition為True將返回False,如果條件condition為False將返回True。
- AND:如果cond1和cond2同時為True,返回True否則返回False。
- or:如果cond1和cond2兩個條件中至少有一個為True,返回True,如果兩個條件都為False則返回False。
1.3 比較
基于數值的比較
if(<variable|string> LESS <variable|string>)
if(<variable|string> GREATER <variable|string>)
if(<variable|string> EQUAL <variable|string>)
if(<variable|string> LESS_EQUAL <variable|string>)
if(<variable|string> GREATER_EQUAL <variable|string>)
- LESS:如果左側數值小于右側,返回True
- GREATER:如果左側數值大于右側,返回True
- EQUAL:如果左側數值等于右側,返回True
- LESS_EQUAL:如果左側數值小于等于右側,返回True
- GREATER_EQUAL:如果左側數值大于等于右側,返回True
基于字符串的比較
if(<variable|string> STRLESS <variable|string>)
if(<variable|string> STRGREATER <variable|string>)
if(<variable|string> STREQUAL <variable|string>)
if(<variable|string> STRLESS_EQUAL <variable|string>)
if(<variable|string> STRGREATER_EQUAL <variable|string>)
- STRLESS:如果左側字符串小于右側,返回True
- STRGREATER:如果左側字符串大于右側,返回True
- STREQUAL:如果左側字符串等于右側,返回True
- STRLESS_EQUAL:如果左側字符串小于等于右側,返回True
- STRGREATER_EQUAL:如果左側字符串大于等于右側,返回True
1.4 文件操作
if(EXISTS path-to-file-or-directory)
判斷文件或者目錄是否存在:如果文件或者目錄存在返回True,否則返回False。
if(IS_DIRECTORY path)
判斷是不是目錄:此處目錄的 path 必須是絕對路徑。如果目錄存在返回True,目錄不存在返回False。
if(IS_SYMLINK file-name)
此處的 file-name 對應的路徑必須是絕對路徑。如果軟鏈接存在返回True,軟鏈接不存在返回False。
軟鏈接相當于 Windows 里的快捷方式
if(IS_ABSOLUTE path)
關于絕對路徑:如果是Linux,該路徑需要從根目錄開始描述;如果是Windows,該路徑需要從盤符開始描述。
如果是絕對路徑返回True,如果不是絕對路徑返回False。
1.5 其他
if(<variable|string> IN_LIST <variable>)
判斷某個元素是否在列表中。如果這個元素在列表中返回True,否則返回False。
if(<variable|string> PATH_EQUAL <variable|string>)
比較兩個路徑是否相等。關于路徑的比較其實就是兩個字符串的比較,如果路徑格式書寫沒有問題也可以通過下面這種方式進行比較:
if(<variable|string> STREQUAL <variable|string>)
我們在書寫某個路徑的時候,可能由于誤操作會多寫幾個分隔符,比如把/a/b/c寫成/a//b///c,此時通過STREQUAL對這兩個字符串進行比較肯定是不相等的,但是通過PATH_EQUAL去比較兩個路徑,得到的結果確實相等的。
在進行路徑比較的時候,如果使用 PATH_EQUAL 可以自動剔除路徑中多余的分割線然后再進行路徑的對比,使用 STREQUAL 則只能進行字符串比較。
2. 循環
在 CMake 中循環有兩種方式,分別是:foreach和while。
2.1 foreach
使用 foreach 進行循環,語法格式如下:
foreach(<loop_var> <items>)<commands>
endforeach()
通過foreach我們就可以對items中的數據進行遍歷,然后通過loop_var將遍歷到的當前的值取出,在取值的時候有以下幾種用法。
方法1
foreach(<loop_var> RANGE <stop>)
- RANGE:關鍵字,表示要遍歷范圍
- stop:這是一個正整數,表示范圍的結束值,在遍歷的時候從 0 開始,最大值為 stop。
- loop_var:存儲每次循環取出的值
cmake_minimum_required(VERSION 3.2)
project(test)
# 循環
foreach(item RANGE 10)message(STATUS "當前遍歷的值為: ${item}" )
endforeach()
結果:在對一個整數區間進行遍歷的時候,得到的范圍是這樣的 【0,stop】,右側是閉區間包含 stop 這個值。
$ cmake ..
-- 當前遍歷的值為: 0
-- 當前遍歷的值為: 1
-- 當前遍歷的值為: 2
-- 當前遍歷的值為: 3
-- 當前遍歷的值為: 4
-- 當前遍歷的值為: 5
-- 當前遍歷的值為: 6
-- 當前遍歷的值為: 7
-- 當前遍歷的值為: 8
-- 當前遍歷的值為: 9
-- 當前遍歷的值為: 10
-- Configuring done
-- Generating done
-- Build files have been written to: /home/robin/abc/a/build
方法2
foreach(<loop_var> RANGE <start> <stop> [<step>])
- RANGE:關鍵字,表示要遍歷范圍
- start:這是一個正整數,表示范圍的起始值,也就是說最小值為 start
- stop:這是一個正整數,表示范圍的結束值,也就是說最大值為 stop
- step:控制每次遍歷的時候以怎樣的步長增長,默認為1,可以不設置
- loop_var:存儲每次循環取出的值
cmake_minimum_required(VERSION 3.2)
project(test)foreach(item RANGE 10 30 2)message(STATUS "當前遍歷的值為: ${item}" )
endforeach()
結果:
$ cmake ..
-- 當前遍歷的值為: 10
-- 當前遍歷的值為: 12
-- 當前遍歷的值為: 14
-- 當前遍歷的值為: 16
-- 當前遍歷的值為: 18
-- 當前遍歷的值為: 20
-- 當前遍歷的值為: 22
-- 當前遍歷的值為: 24
-- 當前遍歷的值為: 26
-- 當前遍歷的值為: 28
-- 當前遍歷的值為: 30
-- Configuring done
-- Generating done
-- Build files have been written to: /home/robin/abc/a/build
方法3
foreach(<loop_var> IN [LISTS [<lists>]] [ITEMS [<items>]])
- IN:關鍵字,表示在 xxx 里邊
- LISTS:關鍵字,對應的是列表list,通過set、list可以獲得
- ITEMS:關鍵字,對應的也是列表
- loop_var:存儲每次循環取出的值
cmake_minimum_required(VERSION 3.2)
project(test)
# 創建 list
set(WORD a b c d)
set(NAME ace sabo luffy)
# 遍歷 list
foreach(item IN LISTS WORD NAME)message(STATUS "當前遍歷的值為: ${item}" )
endforeach()
結果:
$ cd build/
$ cmake ..
-- 當前遍歷的值為: a
-- 當前遍歷的值為: b
-- 當前遍歷的值為: c
-- 當前遍歷的值為: d
-- 當前遍歷的值為: ace
-- 當前遍歷的值為: sabo
-- 當前遍歷的值為: luffy
-- Configuring done
-- Generating done
-- Build files have been written to: /home/robin/abc/a/build
接下來看另外一種方式:
cmake_minimum_required(VERSION 3.2)
project(test)set(WORD a b c "d e f")
set(NAME ace sabo luffy)
foreach(item IN ITEMS ${WORD} ${NAME})message(STATUS "當前遍歷的值為: ${item}" )
endforeach()
遍歷過程中將關鍵字LISTS改成了ITEMS,后邊跟的還是一個或者多個列表,只不過此時需要通過${}將列表中的值取出。其輸出的信息和上一個例子是一樣的。
方法4
foreach(<loop_var>... IN ZIP_LISTS <lists>)
- loop_var:存儲每次循環取出的值,可以根據要遍歷的列表的數量指定多個變量,用于存儲對應的列表當前取出的那個值。
- 如果指定了多個變量名,它們的數量應該和列表的數量相等
- 如果只給出了一個 loop_var,那么它將一系列的 loop_var_N 變量來存儲對應列表中的當前項,也就是說 loop_var_0 對應第一個列表,loop_var_1 對應第二個列表,以此類推…
- 如果遍歷的多個列表中一個列表較短,當它遍歷完成之后將不會再參與后續的遍歷(因為其它列表還沒有遍歷完)。
- IN:關鍵字,表示在 xxx 里邊
- ZIP_LISTS:關鍵字,對應的是列表list,通過set 、list可以獲得
cmake_minimum_required(VERSION 3.17)
project(test)
# 通過list給列表添加數據
list(APPEND WORD hello world "hello world")
list(APPEND NAME ace sabo luffy zoro sanji)
# 遍歷列表
foreach(item1 item2 IN ZIP_LISTS WORD NAME)message(STATUS "當前遍歷的值為: item1 = ${item1}, item2=${item2}" )
endforeach()message("=============================")
# 遍歷列表
foreach(item IN ZIP_LISTS WORD NAME)message(STATUS "當前遍歷的值為: item1 = ${item_0}, item2=${item_1}" )
endforeach()
結果:
$ cd build/
$ cmake ..
-- 當前遍歷的值為: item1 = hello, item2=ace
-- 當前遍歷的值為: item1 = world, item2=sabo
-- 當前遍歷的值為: item1 = hello world, item2=luffy
-- 當前遍歷的值為: item1 = , item2=zoro
-- 當前遍歷的值為: item1 = , item2=sanji
=============================
-- 當前遍歷的值為: item1 = hello, item2=ace
-- 當前遍歷的值為: item1 = world, item2=sabo
-- 當前遍歷的值為: item1 = hello world, item2=luffy
-- 當前遍歷的值為: item1 = , item2=zoro
-- 當前遍歷的值為: item1 = , item2=sanji
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: /home/robin/abc/a/build
2.2 while
while(<condition>)<commands>
endwhile()
while循環比較簡單,只需要指定出循環結束的條件即可。
cmake_minimum_required(VERSION 3.5)
project(test)
# 創建一個列表 NAME
set(NAME luffy sanji zoro nami robin)
# 得到列表長度
list(LENGTH NAME LEN)
# 循環
while(${LEN} GREATER 0)message(STATUS "names = ${NAME}")# 彈出列表頭部元素list(POP_FRONT NAME)# 更新列表長度list(LENGTH NAME LEN)
endwhile()
結果:
$ cd build/
$ cmake ..
-- names = luffy;sanji;zoro;nami;robin
-- names = sanji;zoro;nami;robin
-- names = zoro;nami;robin
-- names = nami;robin
-- names = robin
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: /home/robin/abc/a/build