cmake常用命令(2)——流程控制

条件控制

一、概览

if(<condition>)
  <commands>
elseif(<condition>) # optional block, can be repeated
  <commands>
else()              # optional block
  <commands>
endif()

else和endif中可不带参数,如果要带则需要与if中的条件参数一样。

二、优先级

  1. 括号
  2. 一元测试如EXISTS、COMMAND和DEFINED
  3. 二元测试如EQUAL、LESS等
  4. 一元操作符NOT
  5. 二元操作符AND和OR

三、基础表达式

1.常量

if(<constant>)

1, ON, YES, TRUE, Y, 或者非0数字(包括浮点数)表示TRUE。

0, OFF, NO, FALSE, N, IGNORE, NOTFOUND, 空字符串,以-NOTFOUND结尾的常量表示FALSE。

常量大小写不敏感。

#constant 大小写不敏感
##constant true
if(1 AND ON AND YES AND TRUE AND Y AND 0.1 )#AND ""
    message("constant true")
endif()

##constant false
if(NOT(0 OR OFF OR NO OR fALSE OR N OR IGNORE OR "" OR NOTFOUND))
#以及以-NOTFOUND结尾的常量
    message("constant false")
endif()

2.变量

if(<variable>)

如果变量的值不是表示false的常量都为TRUE,否则都是false,包括未定义。

注意:宏参数不是变量。

注意:环境变量不能通过此检测,即都是false。


#variable
set(VAR "1")  
#变量在条件中是直接使用var的,而使用${VAR}实际上走的是constant逻辑
#两者在这里没有什么明显区别,但是在macro中使用就有区别了,macro中,使用参数为false,而使用$则根据参数值确定
#其值只要不是const fasle,且定义了,都是true

if(VAR)
    message("variable ")   
endif()

if(${VAR})  
    message("variable value" )   
endif()

#注意宏参数不是变量
macro(test mvar)
    if(${mvar})
        message("macro argument" ${mvar})   
    endif()
endmacro(test mvar)
test(${VAR})

#env varaiable不能被检测。
set(ENV{CXXFLAGS} "test")
message("-------->" $ENV{CXXFLAGS})
if(ENV{CXXFLAGS})  
    message("variable env " )   
endif()

#print:
#variable
#variable value
#macro argument1
#-------->test

3.字符串

if(<string>)

带引号的字符串除了以下的场景外都是false:

  • 字符串值是为true的常量值。
  • CMP0054没被设置为NEW,且字符串值为变量名。
#string
#除非等于constant true或者cmp0054为new,并且字符串值为变量名,否则都是false
set(VAR "111")
if(NOT "test")  
    message("string" )   
endif()

cmake_policy(SET CMP0054 OLD)
if("VAR")  
   message("string var" )   
endif()

#print:
#string
#string var

四、逻辑操作符

NOT、AND、OR

五、存在检测

1.COMMAND

 if(COMMAND <command-name>)

存在名字为command-name的命令、函数、宏则为true,

2.POLICY

if(POLICY <policy-id>)

如果存在policy-id则为true,形式如CMP0054

3.TARGET

if(TARGET <target-name>)

已经存在通过add_executable(), add_library(), or add_custom_target()创建的目标名则为true

4.TEST

if(TEST <test-name>)

已经存在通过add_test()创建的测试名则返回true。

5.DEFINED

if(DEFINED <name>|CACHE{<name>}|ENV{<name>})

如果定义了变量、缓存变量、环境变量name,则返回true。注意name和CACHE{name}是不一样的。

6.IN_LIST

 if(<variable|string> IN_LIST <variable>)

判断变量或字符串是否在variable中。

六、文件操作

1.EXISTS

if(EXISTS <path-to-file-or-directory>)

文件或目录是否存在。注意需要传入全路径,如~/开始的目录则不回被扩展为家目录并作为相对目录(即找不到)。

如果路径为符号链接,那么结果由实际目标确定,即如果目标不存在则返回false,否则返回true

字符串为空则为false

2.IS_NEWER_THAN

if(<file1> IS_NEWER_THAN <file2>)

判断file1是否比file2新

3.IS_DIRECTORY

if(IS_DIRECTORY <path>)

判断是否是目录,要求全路径。

4.IS_SYMLINK

if(IS_SYMLINK <path>)

判断是否是软链接,要求全路径。

5.IS_ABSOLUTE

if(IS_ABSOLUTE <path>)

判断是否是绝对路径。注意一些特殊场景:

  • 空路径为false
  • 在Windows主机上,任何以驱动器号和冒号(例如C:)、正斜杠或反斜杠开头的路径都将计算为true。这意味着像C:no\base\dir这样的路径将计算为true,即使路径的非驱动器部分是相对的。
  • 在非windows主机上,任何以波浪号(~)开头的路径都计算为true

七、比较

1.正则

if(<variable|string> MATCHES <regex>)

如果变量或字符串符合正则regex规则,则为true

2.数值判断

if(<variable|string> Comparisons <variable|string>)

Comparisons包括LESS、GREATER、EQUAL、LESS_EQUAL、GREATER_EQUAL。

只有当指定变量或字符串的值为合法数字,并且前者小于、大于、等于、小于等于、大于等于时为true。

3.字符串比较

 if(<variable|string> strComparisons <variable|string>)¶

Comparisons包括STRLESS、STRGREATER、STREQUAL、STRLESS_EQUAL、STRGREATER_EQUAL。

只有左侧变量或者字符串值的字母顺序小于、、大于、等于、小于等于、大于等于右侧时为true。

八、版本比较

 if(<variable|string> version_Comparisons <variable|string>)¶

Comparisons包括VERSION_LESS、VERSION_GREATER、VERSION_EQUAL、VERSION_LESS_EQUAL、VERSION_GREATER_EQUAL。

只有左侧变量或者字符串的版本小于、大于、等于、小于等于、大于等于右侧时为true。

九、路径比较

if(<variable|string> PATH_EQUAL <variable|string>)

只有左侧路径等于右侧时为true。

比较时,是按路径的逐个部分进行比较,多个分隔符会被合并,斜杠和反斜杠两种分隔符也不会区分。

# comparison is TRUE
if ("/a//b/c" PATH_EQUAL "/a/b/c")
   ...
endif()
# comparison is TRUE
if ("/a//b/c" PATH_EQUAL "/a\\b/c")
message("path equal" )   
endif()

# comparison is FALSE
if ("/a//b/c" STREQUAL "/a/b/c")
   ...
endif()

十、变量扩展

if命令在CMake的历史中很早就被编写出来了,早于${}变量求值语法,为了方便,它求值由其参数命名的变量,如上面的签名所示。注意,在if命令接收参数之前,使用${}进行正常的变量求值。因此下面的代码

set(var1 OFF)
set(var2 "var1")
if(${var2})

等同于

if(var1)

并且会以if的变量形式处理,即判断var1变量的值,为OFF,因此为false。

而如果我们移除${}

if(var2)

则条件为true,因为var2的变量值不是为false的常量值。

循环一(foreach)

遍历列表中的所有值,并执行一系列命令

一、items

foreach(<loop_var> <items>)
  <commands>
endforeach()

items是以分号或者空格分隔的列表。

#items:;或者空格分隔的列表,不要加引号,否则认为是一个
foreach(it  a;b;c;d)  #"a;b;c;d" print:string list:abcd
    message("string list:" ${it})
endforeach(it "a;b;c;d")

#print
#string list:a
#string list:b
#string list:c
#string list:d

二、range

foreach(<loop_var> RANGE <stop>)

从0开始到stop的数字(包含stop),stop是非负整数

foreach(<loop_var> RANGE <start> <stop> [<step>])

指定遍历的起始数字、结束数字以及步长。

foreach(it RANGE 5)
message("range 5:"${it})
endforeach(it RANGE 5)

foreach(it RANGE 5 12 2)
message("5-12,step 2:"${it})
endforeach()

print:

range 5:0
range 5:1
range 5:2
range 5:3
range 5:4
range 5:5
5-12,step 2:5
5-12,step 2:7
5-12,step 2:9
5-12,step 2:11

三、IN

foreach(<loop_var> IN [LISTS [<lists>]] [ITEMS [<items>]])

可以通过LISTS或ITEMS将多个列表合并遍历。

set(A 0;1)
set(B 2 3)
set(C "4 5")
set(D 6;7 8)
set(E "")
foreach(X IN LISTS A B C D E)
    message(STATUS "X=${X}")
endforeach()

print:

-- X=0
-- X=1
-- X=2
-- X=3
-- X=4 5
-- X=6
-- X=7
-- X=8

四、IN ZIP_LISTS

foreach(<loop_var>... IN ZIP_LISTS <lists>)

将多个list压缩,类似于多个map。

list(APPEND English one two three four)
list(APPEND Bahasa satu dua tiga)

foreach(num IN ZIP_LISTS English Bahasa)
    message(STATUS "num_0=${num_0}, num_1=${num_1}")
endforeach()

foreach(en ba IN ZIP_LISTS English Bahasa)
    message(STATUS "en=${en}, ba=${ba}")
endforeach()

print:

-- num_0=one, num_1=satu
-- num_0=two, num_1=dua
-- num_0=three, num_1=tiga
-- num_0=four, num_1=
-- en=one, ba=satu
-- en=two, ba=dua
-- en=three, ba=tiga
-- en=four, ba=

遍历次数为最长的那个列表长度。

循环二(while)

while(<condition>)
  <commands>
endwhile()

condition与if相同,为true时重复执行command,可以使用break和continue命令。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值