【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
复制代码