<Linux开发> linux开发工具-之-CMake语法[细见3]

<Linux开发> linux开发工具-之-CMake语法[细见]3

Cmake相关文章如下:
<Linux开发> linux开发工具-之-CMake简单例程[初见]
<Linux开发> linux开发工具-之-CMake简单例程[再见]
<Linux开发> linux开发工具-之-CMake语法[细见1]
<Linux开发> linux开发工具-之-CMake语法[细见2]
<Linux开发> linux开发工具-之-CMake语法[细见3]

本片是衔接 <Linux开发> linux开发工具-之-CMake语法[细见2] 继续补充的。

九、双引号的作用

在前面编写的一些例程中有些使用到了双引号,有些没有;那么就来聊聊双引号是咋回事;
比较常见的就是在命令(command) 和 变量(variable)中的使用,下面举个例子:
例1:命令(command)中:

#带双引号
message("WATER")

#不带双引号
message(WATER)

例2 : 变量(variable)中:

#带双引号
set(MY_LIST Water Hello World China)
message(${MY_LIST})

#不带双引号
set(MY_LIST Water Hello World China)
message("${MY_LIST}")

1、命令(command)中的双引号


基于例1,我们在将内容加长一些,更改后内容如下:

#带双引号
message("WATER")
#不带双引号
message(WATER)


#带双引号
message("Water Hello World")
#不带双引号
message(Water Hello World)

运行输出如下:
在这里插入图片描述
有输出的内容可看出,对于单个单词来说,看不出什么区别;那我们就来看下多个单词 用空格隔开的情况;

在多个单词连用的情况下:

加双引号时:相当于把双引号的内容作为一个整体,即当作一个参数来使用。所以输出的内容就是双引号里的内容,包括空格也会输出。此方法在其它命令(command)中同样适用;

不加双引号时:相当于每个单词作为一个参数,空格就是作为参数的划分符号。因此在不加双引号的情况下,上述例程相当于输入了3个参数,因此输出时相当于三个参数连续输出,而空格作为参数的分隔符号就不再输出的内容中了。

所以在命令(command)中 双引号引起来的内容相当于一个整体,一个参数;未使用双引号时,以空格作为参数的分隔符号。

2、 变量(variable)中的双引号


基于例2,内容如下:

#带双引号
set(MY_LIST Water Hello World China)
message("${MY_LIST}")

#不带双引号
set(MY_LIST Water Hello World China)
message(${MY_LIST})

运行结果如下:
在这里插入图片描述
在使用双引号时,此时 ${MY_LIST}是一个列表,我们用"${MY_LIST}"这种形式的时候,表示要让 CMake 把这个数组的所有元素当成一个整体,而不是分散的个体。于是,为了保持数组的含义,又提供一个整体的表达方式,CMake 就会用分号“;”把这数组的多个元素连接起来。
而如果不加双引号时,CMake 不会数组当成一个整体看待,而是会将数组中的各个元素提取出进行打印输出。

上述变量中实际使用列表时可使用list命令对列表进行操作。

十、条件判断


在 cmake 中可以使用if条件判断,if条件判断形式如下:

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

根据下面描述的condition语法计算if子句的条件参数。如果结果为true,则执行If块中的命令。否则,以相同的方式处理可选的elseif块。最后,如果没有条件为true,则执行可选else块中的命令。
其实仔细看一下,if条件判断的使用格式 与c/c++相关代码中的使用方法格式是差不多的。
else 和 endif 括号中的可写可不写,如果写了,就必须和 if 中的一致。
condition 就是一个进行判断的表达式,表达式对照表如下:

表达式truefalse说明
<*constant>如果constant为1、ON、YES、TRUE、Y 或非零数,则为真如果constant为0、OFF 、 NO 、FALSE 、 N 、IGNORE 、NOTFOUND、空字符串或以后缀-NOTFOUND 结尾,则为 False。布尔值大小写不敏感;如果与这些常量都不匹配,则将其视为变量或字符串
<variable/string>已 经 定 义 并 且 不 是false 的变量未 定 义 或 者 是false 的变量变量就是字符串
NOT <*expression>expression 为 falseexpression 为 true
<*expr1> AND <*expr2>expr1 和 expr2 同时为trueexpr1 和 expr2 至少有一个为 false
<*expr1> OR <*expr2>expr1 和 expr2 至少有一个为 trueexpr1 和 expr2 都 是 false
COMMAND namename 是一个已经定义的命令、宏或者函数name 未定义
TARGET namename 是add_executable() 、add_library() 或add_custom_target() 定义的目标name 未定义
TEST namename 是由 add_test()命令创建的现有测试名称name 未创建
EXISTS pathpath 指定的文件或目录存在path 指定的文件或目录不存在仅适用于完整路径
IS_DIRECTORY pathpath 指定的路径为目录path 指定的路径不为目录仅适用于完整路径
IS_SYMLINK pathpath 为符号链接path 不是符号链接仅适用于完整路径
IS_ABSOLUTE pathpath 为绝对路径path 不是绝对路径
<variable/string> MATCHES regexvariable 与正则表达式regex 匹配成功variable 与正则表达式 regex 匹配失 败
<variable/string> IN_LIST <*variable>右边列表中包含左边的元素右边列表中不含左边的元素
DEFINED <*variable>如果给定的变量已定义,则为真。如果给定的变量未定义只要变量已经被设置,它是真还是假并不重要。(注意宏不是变量。)
<variable/string> LESS <variable/string>如果给定的字符串或变量的值是有效数字且小于右侧的数字则为真。左侧的数字大于或等于右侧的数字
<variable/string> GREATER <variable/string>如果给定的字符串或变量的值是有效数字且大于右侧的数字,则为真。左侧的数字小于或等于右侧的数字
<variable/string> EQUAL <variable/string>如果给定的字符串或变量的值是有效数字并且等于右侧值,则为真左侧的数字不等于右侧的数字

上 表 中 只是 列 出其 中一 部 分 表达 式 ,还 有其 它 一 些表 达 式这 里并 未 列 出, 大 家可以到官网查看:camke_if ,下面我们对上表中的表达式进行详解。

1、<*constant>


在 if(constant)条件判断中,如果 constant 是 1、ON、YES、TRUE、Y 或非零数字,那么这个 if 条件就是 true;如果 constant 是 0、OFF、NO、FALSE、N、IGNORE、NOTFOUND、空字符串或以后缀-NOTFOUND结尾,那么这个条件判断的结果就是 false。 在 cmake 中,可以把 1、ON、YES、TRUE、Y 或非零数字以及 0、OFF、NO、FALSE、N、IGNORE、NOTFOUND、空字符串或以后缀-NOTFOUND 结尾这些理解为常量,类似于布尔值,而且它们不区分大小写;如果参数不是这些特定常量之一,则将其视为变量或字符串,并使用除<*constant>之外的表达式。

if(ON)
message(true)
else()
message(false)
endif()
if(YES)
message(true)
else()
message(false)
endif()
if(true)
message(true)
else()
message(false)
endif()
if(100)
message(true)
else()
message(false)
endif()

以上4个输出内容均为:true

if(0)
message(true)
else()
message(false)
endif()
if(N)
message(true)
else()
message(false)
endif()
if(NO)
message(true)
else()
message(false)
endif()

上述3个输出均为:false

2、<*variable/string>


在 if(<variable/string>)条件判断中,如果变量已经定义,并且它的值是一个非假常量,则条件为真;否则为假,注意宏参数不是变量(在 cmake 中也可以使用宏,这个后面再给大家介绍)。

set(WATER Hello)
if(WATER)
message(true)
else()
message(false)
endif()
set(WATER NO)
if(WATER)
message(true)
else()
message(false)
endif()

上述2个均输出:true

if(WATER)
message(true)
else()
message(false)
endif()

上述由于没有定义变量WATER,所以输出:false

3、NOT <*expression>


NOT 其实就类似于 C 语言中的取反,在 if(NOT <*expression>)条件判断中,如果表达式 expression 为真,则条件判断为假;如果表达式 expression 为假,则条件判断为真。

if(WATER GG)
message(true)
else()
message(false)
endif()
if(NOT 0)
message(true)
else()
message(false)
endif()

上述输出为:true
因为 WATER 变量没有定义,所以 WATER 表达式为假,但因为前面有 NOT 关键字,进行取反操作,整个 if 条件判断为真。

if(NOT YES)
message(true)
else()
message(false)
endif()

输出为:false
因为前面有 NOT 关键字,进行取反操作,整个 if 条件判断为真。

4、<*expr1> AND <*expr2>


这个就类似于 C 语言中的逻辑与(&&),只有 expr1 和 expr2 同时为真时,条件判断才为真;否则条件判断为假。

if(yes AND on)
message(true)
else()
message(false)
endif()

上述输出为:true

if(yes AND no)
message(true)
else()
message(false)
endif()

上述输出为:false

if(false AND no)
message(true)
else()
message(false)
endif()

上述输出为:false

5、<*expr1> OR <*expr2>


类似于 C 语言中的逻辑或(||),当 expr1 或 expr2 至少有一个为真时,条件判断为真;否则为假。

if(false OR no)
message(true)
else()
message(false)
endif()

上述输出为:false

if(yes OR no)
message(true)
else()
message(false)
endif()

上述输出为:true

if(ON OR yes)
message(true)
else()
message(false)
endif()

上述输出为:true

6、COMMAND command-name


如果 command-name 是一个已经定义的命令、宏或函数时,条件判断为真;否则为假。除了宏之外,在 cmake 中还可以定义函数,这个我们也会在后面向大家介绍。

if(COMMAND OnefU)
message(true)
else()
message(false)
endif()

上述输出为:false

if(COMMAND project)
message(true)
else()
message(false)
endif()

上述输出为:true

7、TARGET target-name


如果 target-name 是 add_executable()、add_library()或 add_custom_target()定义的目标(这些目标在整个工程中必须是唯一的,不可出现两个名字相同的目标),则条件判断为真;否则为假。

if(TARGET OnefU)
message(true)
else()
message(false)
endif()

上述输出为:false

add_library(hello hello.c)
if(TARGET hello)
message(true)
else()
message(false)
endif()

上述输出为:true

8、EXISTS path


如果 path 指定的文件或目录存在,则条件判断为真;否则为假。需要注意的是,path 必须是文件或目录的全路径,也就是绝对路径。
如工程目录结构如下所示:

├── build
├── CMakeLists.txt
├── OneFu
│ ├── OneFu.c
│ └── OneFu.h
└── main.c

在顶层 CMakeLists.txt 文件中使用 if(EXISTS path)进行判断:

if(EXISTS ${PROJECT_BINARY_DIR})
message(true)
else()
message(false)
endif()
if(EXISTS ${PROJECT_BINARY_DIR}/OneFu)
message(true)
else()
message(false)
endif()
if(EXISTS ${PROJECT_BINARY_DIR}/OneFu/OneFu.c)
message(true)
else()
message(false)
endif()

上述3个均输出:true

if(EXISTS ${PROJECT_BINARY_DIR}/hello/)
message(true)
else()
message(false)
endif()

输出为:false

9、IS_DIRECTORY path


如果 path 指定的路径是一个目录,则条件判断为真;否则为假,同样,path 也必须是一个绝对路径。
还是以第8点中的工程目录结构为例:

if(IS_DIRECTORY ${PROJECT_SOURCE_DIR}/OneFu)
message(true)
else()
message(false)
endif()

上述输出:true

if(IS_DIRECTORY ${PROJECT_SOURCE_DIR}/OneFu/hello.c)
message(true)
else()
message(false)
endif()

上述输出:false

10、IS_ABSOLUTE path


如果给定的路径 path 是一个绝对路径,则条件判断为真;否则为假。还是以上例中的工程目录结构为例:

if(IS_ABSOLUTE ${PROJECT_SOURCE_DIR}/OneFu)
message(true)
else()
message(false)
endif()

上述输出:true

if(IS_ABSOLUTE ./OneFu/)
message(true)
else()
message(false)
endif()

上述输出:false

11、<*variable|string> MATCHES regex


这个表达式用的比较多,可以用来匹配字符串,可以使用正则表达式进行匹配。
如果给定的字符串或变量的值与给定的正则表达式匹配,则为真,否则为假。
如下:

set(MY_STR "Water Hello World")
if(MY_STR MATCHES "Water Hello World")
message(true)
else()
message(false)
endif()

上述输出:true
也可以引用变量的形式,如下:

set(MY_STR "Water Hello World")
if(${MY_STR} MATCHES "Water Hello World")
message(true)
else()
message(false)
endif()

上述输出:true

12、<*variable|string> IN_LIST <*variable>


如果左边给定的变量或字符串是与右边列表中的某个元素相同,则条件判断为真;否则为假。

project(water)

cmake_policy(SET CMP0057 NEW)

set(MY_LIST Water Hello World China)

if("Hello" IN_LIST MY_LIST)
message(true)
else()
message(false)
endif()

上述输出:true
注:需要调用cmake_policy设置CMP0057;
CMake中的命令cmake_policy用于管理CMake策略设置(Manage CMake Policy settings)。它通常被添加到project的CMakeLists.txt文件中,以改变CMake本身的行为,通常能够用新版本的CMake处理旧版本CMakeLists.txt features。

13、DEFINED <*variable>


如果给定的变量已经定义,则条件判断为真,否则为假;只要变量已经被设置(定义),if 条件判断就是真,至于变量的值是真还是假并不重要。

set(Water "Water")
if(DEFINED Water)
message(true)
else()
message(false)
endif()

上述输出:true

14、<*variable|string> LESS <*variable|string>


如果左边给定的字符串或变量的值是有效数字并且小于右侧的值,则为真。否则为假。
注:只是进行数字的比较。即使是数字的字符串也行,非数字的字符串不行。

if(100 LESS 20)
message(true)
else()
message(false)
endif()

上述输出:false

if(10 LESS 20)
message(true)
else()
message(false)
endif()

上述输出:true

if("123" LESS "1234")
message(true)
else()
message(false)
endif()

上述输出:true

15、<*variable|string> GREATER <*variable|string>


如果左边给定的字符串或变量的值是有效数字并且大于右侧的值,则为真。否则为假。
注:只是进行数字的比较。即使是数字的字符串也行,非数字的字符串不行。

if(20 GREATER 100)
message(true)
else()
message(false)
endif()

上述输出:false

if(100 LESS 20)
message(true)
else()
message(false)
endif()

上述输出:true

16、<*variable|string> EQUAL <*variable|string>


如果左边给定的字符串或变量的值是有效数字并且等于右侧的值,则为真。否则为假。
注:只是进行数字的比较。即使是数字的字符串也行,非数字的字符串不行。

if(200 EQUAL 20)
message(true)
else()
message(false)
endif()

上述输出:false

if(10 LESS 10)
message(true)
else()
message(false)
endif()

上述输出:true

17、elseif 分支


可以使用 elseif 组成多个不同的分支:

set(MY_LIST Water Hello World China)
if(Water IN_LIST MY_LIST)
message(Water)
elseif(Hello IN_LIST MY_LIST)
message(Hello)
elseif(China IN_LIST MY_LIST)
message(China)
else()
message(false)
endif()

十一、循环语句


前面介绍了判断语句,下面来介绍循环语句,循环语句包括foreach()循环、while()循环。

1、foreach循环


foreach循环的语法格式如下:

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

foreach(<loop_var> RANGE <stop>)
  <commands>
endforeach()

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

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

foreach 循环之 RANGE 关键字
测试例程如下:

project(water)


# foreach 循环测试
#停止是10 
foreach(loop_var RANGE 4)
 message("${loop_var}")
endforeach()

message(" ")

# foreach 循环测试
#起始是2,停止是10 
foreach(loop_var RANGE 2 7)
 message("${loop_var}")
endforeach()

message(" ")

# foreach 循环测试
#起始是4,停止是10 步进是1
foreach(loop_var RANGE 5 10 1)
 message("${loop_var}")
endforeach()

运行结果如下:
在这里插入图片描述

foreach 循环之 IN 关键字
测试例程如下:

project(water)

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()

运行结果如下:
在这里插入图片描述

2、while循环


while循环的语法格式如下:

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

cmake 中 while 循环的含义与 C 语言中 while 循环的含义相同,但条件 condition 为真时,执行循环体中的命令,而条件 condition 的语法形式与 if 条件判断中的语法形式相同。

# while 循环测试
set(loop_var 4)
while(loop_var GREATER 0)
 message("${loop_var}")
 math(EXPR loop_var "${loop_var} - 1")
endwhile()

运行结果如下:
在这里插入图片描述
上例中,while 循环的条件是(loop_var GREATER 0),等价于(loop_var > 0),当 loop_var 变量的有效数值大于 0 时,执行 while 循环体;在 while 循环体中使用到了 cmake 中的数学运算命令 math(),关于数学运算下小节会向大家介绍。
在 while 循环体中,打印 loop_var,之后将 loop_var 减一。

3、break、continue


cmake 中,也可以在循环体中使用类似于 C 语言中的 break 和 continue 语句。

break()命令用于跳出循环,和在 C 语言中的作用是一样的,测试如下:

# while...break 测试
set(loop_var 10)
while(loop_var GREATER 0) #loop_var>0 时 执行循环体
 message("${loop_var}")
 if(loop_var LESS 6) #当 loop_var 小于 6message("break")
 break() #跳出循环
 endif()
 math(EXPR loop_var "${loop_var} - 1")#loop_var--
endwhile()

运行结果如下:
在这里插入图片描述

continue()命令用于结束本次循环,执行下一次循环,测试如下:

project(water)

# while...continue 测试
# 打印所有偶数
set(loop_var 10)
while(loop_var GREATER 0) #loop_var>0 时 执行循环体
 math(EXPR var "${loop_var} % 2") #求余
 if(var EQUAL 0) #如果 var=0,表示它是偶数
 message("${loop_var}") #打印这个偶数
 math(EXPR loop_var "${loop_var} - 1")#loop_var--
 continue() # 执行下一次循环
 endif()
 math(EXPR loop_var "${loop_var} - 1")#loop_var--
endwhile()

这段 cmake 代码是求 0 到 10 之间的偶数(左闭右开),并将偶数打印出来,使用到了 continue()命令,
代码不再解释,注释已经写得很清楚了。
打印结果如下:
在这里插入图片描述

十二、数学运算 math


在 cmake 中如何使用数学运算呢?其实,cmake 提供了一个命令用于实现数学运算功能,这个命令就是 math(),如下所示:

math(EXPR <variable> "<expression>" [OUTPUT_FORMAT <format>])

官网:math
math 命令中,第一个参数是一个固定的关键字 EXPR,第二个参数是一个返回参数,将数学运算结果存放在这个变量中;而第三个参数则是一个数学运算表达式,支持的运算符包括:+(加)、-(减)、*(乘)、/(除)、%(求余)、|(按位或)、&(按位与)、^(按位异或)、~(按位取反)、<<(左移)、>>(右移)以及这些运算符的组合运算,它们的含义与 C 语言中相同。
测试例程如下:

project(water)

# math()命令测试
math(EXPR out_var "100 + 200")
message("${out_var}")
math(EXPR out_var "100 - 46")
message("${out_var}")
math(EXPR out_var "110 * 48")
message("${out_var}")
math(EXPR out_var "900 / 50")
message("${out_var}")
math(EXPR out_var "(200 & 100) * 50 - 2")
message("${out_var}")

运行如下:
在这里插入图片描述

十三、总结


对于cmake的基本语法介绍就讲那么多,当前还有很多很多cmake语法没有讲解到,读者想更加深入的了解和到cmake的 官网去查看。后面将会进入更深层次对cmake的运用分析,欢迎继续关注。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

waterfxw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值