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

2018-02-24 10:16:10来源:https://juejin.im/post/5a8677cf6fb9a0634514c026作者:稀土掘金人点击

分享

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
说明


1, ON, YES, TRUE, Y,或者是非0数字
0, OFF, NO, FALSE, N, IGNORE, NOTFOUND,空字符串,或者带-NOTFOUND后缀
布尔判断值大小写不敏感

<variable|string>
已经定义且不是false的变量
未定义或者是false的变量
变量就是字符串

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}



在实际项目中,经常使用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

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台