百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

【CMake】(13)流程控制 流程控制语句包括哪些语句

liebian365 2024-11-09 13:41 23 浏览 0 评论

条件判断

基本语法

条件判断的基本语法如下:

if(<condition>)
  <commands>
elseif(<condition>)
  <commands>
else()
  <commands>
endif()
  • if(<condition>):检查条件是否满足。如果满足,则执行随后的命令直到遇到 elseifelseendif
  • elseif(<condition>):可选。如果前面的 ifelseif的条件不满足,将检查这里的条件。可以有多个 elseif块。
  • else():可选。如果所有的 ifelseif条件都不满足,则执行 else块中的命令。
  • endif():结束条件判断块。

在CMake中,基本表达式用于 if语句中,以决定是否执行特定的代码块。这些表达式可以是常量、变量或字符串,CMake会根据这些表达式的值来判断条件为真(True)或假(False)。

判定表达式

当表达式的值为以下之一时,条件被认为是真(True):

  • 数值 1:代表真。
  • 字符串 ON:明确表示启用或真。
  • 字符串 YES:同样表示肯定或真。
  • 字符串 TRUE:布尔真值。
  • 字符串 Y:简短的肯定回答,表示真。
  • 非零数值:在大多数编程语言中,非零值通常被解释为真。
  • 非空字符串:任何非空的字符串都被视为真,除了下面将要提到的特定假值字符串外。

当表达式的值为以下之一时,条件被认为是假(False):

  • 数值 0:代表假。
  • 字符串 OFF:明确表示禁用或假。
  • 字符串 NO:表示否定或假。
  • 字符串 FALSE:布尔假值。
  • 字符串 N:简短的否定回答,表示假。
  • 字符串 IGNORE:有时用于特定的设置中,解释为假。
  • 字符串 NOTFOUND:特别在查找库或程序时,如果未找到,这个值表示假。
  • 空字符串:表示没有值,解释为假。
# 示例:变量设置为非零值
set(MY_VAR 42)
if(MY_VAR)
  message("MY_VAR is true")
endif()

# 示例:变量设置为假值字符串
set(MY_VAR "FALSE")
if(NOT MY_VAR)
  message("MY_VAR is false")
endif()

# 示例:使用未定义的变量
if(UNDEFINED_VAR)
  message("This will not be printed")
else()
  message("UNDEFINED_VAR is considered false")
endif()

逻辑判断

逻辑操作符 NOTANDOR允许你根据一个或多个条件来执行特定的代码块。这些操作符的行为与大多数编程语言中的逻辑操作符类似,非常直观。

NOT

NOT操作符用于取反一个条件的结果。如果原条件为真(True),则 NOT后的结果为假(False);如果原条件为假(False),则 NOT后的结果为真(True)。

set(VAR1 ON)

if(NOT VAR1)
  message("VAR1 is false")
else()
  message("VAR1 is true")
endif()

在这个例子中,因为 VAR1被设置为 ON(即真), NOT VAR1的结果为假,所以执行 else分支,输出"VAR1 is true"。

AND

AND操作符用于检查两个或更多条件是否都为真。只有当所有条件都为真时,整个 AND表达式的结果才为真(True);否则为假(False)。

set(VAR1 ON)
set(VAR2 OFF)

if(VAR1 AND VAR2)
  message("Both VAR1 and VAR2 are true")
else()
  message("At least one of VAR1 or VAR2 is false")
endif()

在这个例子中,因为 VAR1为真而 VAR2为假,整个条件表达式的结果为假,所以执行 else分支。

OR

OR操作符用于检查两个或更多条件中至少有一个是否为真。如果至少有一个条件为真,整个 OR表达式的结果就为真(True);只有当所有条件都为假时,结果才为假(False)。

set(VAR1 ON)
set(VAR2 OFF)

if(VAR1 OR VAR2)
  message("At least one of VAR1 or VAR2 is true")
else()
  message("Both VAR1 and VAR2 are false")
endif()

在这个例子中,因为至少有一个条件( VAR1)为真,所以整个条件表达式的结果为真,执行 if分支。

比较

数值比较

数值比较用于比较两个变量或字符串代表的数值,包括:

  • LESS:检查左侧的数值是否小于右侧的数值。
  • GREATER:检查左侧的数值是否大于右侧的数值。
  • EQUAL:检查两个数值是否相等。
  • LESS_EQUAL:检查左侧的数值是否小于或等于右侧的数值。
  • GREATER_EQUAL:检查左侧的数值是否大于或等于右侧的数值。
set(NUM1 10)
set(NUM2 20)

if(NUM1 LESS NUM2)
  message("NUM1 is less than NUM2")
endif()

字符串比较

字符串比较根据字符串的字典顺序来比较两个变量或字符串的大小,包括:

  • STRLESS:如果左侧字符串在字典顺序上小于右侧,返回True。
  • STRGREATER:如果左侧字符串在字典顺序上大于右侧,返回True。
  • STREQUAL:如果两个字符串相等,返回True。
  • STRLESS_EQUAL:如果左侧字符串小于等于右侧,返回True。
  • STRGREATER_EQUAL:如果左侧字符串大于等于右侧,返回True。
set(STR1 "apple")
set(STR2 "banana")

if(STR1 STRLESS STR2)
  message("apple comes before banana")
endif()

文件判断

判断文件或目录是否存在

  • EXISTS 操作用于检查指定路径的文件或目录是否存在。如果路径存在,条件为真(True),否则为假(False)。
if(EXISTS "${PROJECT_SOURCE_DIR}/myfile.txt")
  message("myfile.txt exists.")
else()
  message("myfile.txt does not exist.")
endif()

判断是否为目录

  • IS_DIRECTORY 用于检查给定的路径是否是一个目录。这要求提供的路径是绝对路径。
if(IS_DIRECTORY "${PROJECT_SOURCE_DIR}/mydir")
  message("mydir is a directory.")
else()
  message("mydir is not a directory.")
endif()

判断是否为软链接

  • IS_SYMLINK 操作用于检查指定的文件名是否是一个软链接。这同样要求文件名对应的路径是绝对路径。
if(IS_SYMLINK "/path/to/mylink")
  message("mylink is a symlink.")
else()
  message("mylink is not a symlink.")
endif()

判断是否为绝对路径

  • IS_ABSOLUTE 用于检查给定的路径是否是绝对路径。在Linux上,绝对路径以根目录( /)开始;在Windows上,它以盘符开始(如 C:/)。
if(IS_ABSOLUTE "/usr/local/bin")
  message("This is an absolute path.")
else()
  message("This is not an absolute path.")
endif()

其他

判断元素是否在列表中

CMake 3.3及更高版本支持 IN_LIST查询,这允许开发者检查一个变量或字符串是否在一个给定的列表中。

set(MY_LIST apple banana cherry)
set(MY_ITEM apple)

if(MY_ITEM IN_LIST MY_LIST)
  message("${MY_ITEM} is in the list.")
else()
  message("${MY_ITEM} is not in the list.")
endif()

比较两个路径是否相等

CMake 3.24及更高版本引入了 PATH_EQUAL,这对于比较两个路径是否相等非常有用,特别是在路径可能包含多余的分隔符时。 PATH_EQUAL会在比较前标准化路径,从而忽略多余的分隔符。

if("/path/to//directory" PATH_EQUAL "/path/to/directory")
  message("Paths are equal.")
else()
  message("Paths are not equal.")
endif()

STREQUAL相比, PATH_EQUAL在处理路径时更加智能,能够识别并处理路径中的冗余分隔符。这在跨平台开发中特别有用,因为不同操作系统的路径分隔符习惯可能不同。

以下示例演示了 PATH_EQUALSTREQUAL在处理包含多余分隔符的路径时的行为差异:

cmake_minimum_required(VERSION 3.26)
project(test)

if("/home//user///directory" PATH_EQUAL "/home/user/directory")
  message("Paths are equal using PATH_EQUAL.")
else()
  message("Paths are not equal using PATH_EQUAL.")
endif()

if("/home//user///directory" STREQUAL "/home/user/directory")
  message("Paths are equal using STREQUAL.")
else()
  message("Paths are not equal using STREQUAL.")
endif()

输出结果将展示 PATH_EQUAL成功地忽略了路径中的多余分隔符,而 STREQUAL则没有。

循环

有两种循环方式,分别是 foreachwhile

foreach

使用 foreach可以执行重复的任务,如设置变量、打印信息、或者根据列表中的每个项目执行特定的命令。

基本的 foreach循环语法如下:

foreach(loop_var IN ITEMS item1 item2 ... itemN)
  # 执行的命令
endforeach()
  • loop_var是循环变量,在每次循环中,它被设置为当前项的值。
  • ITEMS后面跟着的是一系列要遍历的项目。

遍历数值范围

  1. 单一终止值:
foreach(loop_var RANGE stop)
  # 执行的命令
endforeach()
  • 这里 loop_var从0遍历到 stop,包括 stop
  1. 指定起始、终止值(可选步长):
foreach(loop_var RANGE start stop [step])
  # 执行的命令
endforeach()
  • start:遍历开始的值。
  • stop:遍历结束的值。
  • step:(可选)遍历的步长,默认为1。

示例

当需要遍历一个从0开始到指定终止值的整数序列时,可以使用 RANGE关键字。

foreach(item RANGE 10)
    message(STATUS "当前遍历的值为: ${item}")
endforeach()

这将输出从0到10的数值,包括10。

示例2

如果需要从特定的起始值开始遍历,到特定的终止值结束,并且还可以指定步长(默认为1),可以使用增强版的 RANGE

foreach(item RANGE 10 30 2)
    message(STATUS "当前遍历的值为: ${item}")
endforeach()

这将从10开始,到30结束,步长为2,输出10, 12, 14, ..., 30。

遍历列表

foreach还可以遍历一个或多个列表,通过 IN LISTSITEMS关键字。

  1. 遍历单一或多个列表:
foreach(loop_var IN LISTS list1 [list2 ...])
  # 执行的命令
endforeach()
  • IN LISTS后面可以指定一个或多个列表变量。
  1. 遍历一系列项目:
foreach(loop_var IN ITEMS item1 [item2 ...])
  # 执行的命令
endforeach()
  • IN ITEMS后面跟着要直接遍历的项目序列。

示例:遍历列表或多个列表

  • 使用 IN LISTS直接遍历一个或多个列表变量:
set(WORD a b c d)
set(NAME ace sabo luffy)
foreach(item IN LISTS WORD NAME)
    message(STATUS "当前遍历的值为: ${item}")
endforeach()
  • 使用 IN ITEMS遍历一个或多个通过变量展开的列表:
set(WORD a b c "d e f")
set(NAME ace sabo luffy)
foreach(item IN ITEMS ${WORD} ${NAME})
    message(STATUS "当前遍历的值为: ${item}")
endforeach()

遍历多个列表(CMake 3.17及以上)

foreach(loop_var1 loop_var2 ... IN ZIP_LISTS list1 list2 ...)
  # 执行的命令
endforeach()
  • IN ZIP_LISTS允许同时遍历多个列表, loop_var1loop_var2等变量分别对应每个列表中当前位置的元素。

示例:ZIP_LISTS

在CMake 3.17及以上版本中, foreach命令引入了 IN ZIP_LISTS,这允许你同时遍历多个列表,并在每次迭代中从每个列表中取出相应位置的元素。

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

这种方式特别适用于需要同时处理多个相关列表的情况,如同时遍历文件名列表和对应的目标名列表。

while

foreach循环相比, while循环更加灵活,因为它允许你在每次循环结束时基于复杂的逻辑来更新循环条件。这使得 while循环特别适合于处理那些在循环开始前不能确定迭代次数的情况。

基本语法:

while(<condition>)
    <commands>
endwhile()
  • <condition>:这是循环继续执行的条件。只要条件评估为真(即,非0或非空字符串,或特定的CMake真值,如 ONTRUE等),循环就会继续。
  • <commands>:在每次循环迭代中执行的命令集。

示例:遍历列表并逐个移除元素

在你提供的示例中, while循环用于遍历一个列表,并在每次迭代中从列表的头部移除一个元素,直到列表为空:

cmake_minimum_required(VERSION 3.5)
project(test)

# 创建一个列表
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()

每次循环迭代都会更新列表 NAME,并重新计算其长度 LEN。循环继续执行直到 LEN为0,即列表中不再有元素。

相关推荐

“版本末期”了?下周平衡补丁!国服最强5套牌!上分首选

明天,酒馆战棋就将迎来大更新,也聊了很多天战棋相关的内容了,趁此机会,给兄弟们穿插一篇构筑模式的卡组推荐!老规矩,我们先来看10职业胜率。目前10职业胜率排名与一周前基本类似,没有太多的变化。平衡补丁...

VS2017 C++ 程序报错“error C2065:“M_PI”: 未声明的标识符&quot;

首先,程序中头文件的选择,要选择头文件,在文件中是没有对M_PI的定义的。选择:项目——>”XXX属性"——>配置属性——>C/C++——>预处理器——>预处理器定义,...

东营交警实名曝光一批酒驾人员名单 88人受处罚

齐鲁网·闪电新闻5月24日讯酒后驾驶是对自己和他人生命安全极不负责的行为,为守护大家的平安出行路,东营交警一直将酒驾作为重点打击对象。5月23日,东营交警公布最新一批饮酒、醉酒名单。对以下驾驶人醉酒...

Qt界面——搭配QCustomPlot(qt platform)

这是我第一个使用QCustomPlot控件的上位机,通过串口精确的5ms发送一次数据,再将读取的数据绘制到图表中。界面方面,尝试卡片式设计,外加QSS简单的配了个色。QCustomPlot官网:Qt...

大话西游2分享赢取种族坐骑手办!PK趣闻录由你书写

老友相聚,仗剑江湖!《大话西游2》2021全民PK季4月激燃打响,各PK玩法鏖战齐开,零门槛参与热情高涨。PK季期间,不仅各种玩法奖励丰厚,参与PK趣闻录活动,投稿自己在PK季遇到的趣事,还有机会带走...

测试谷歌VS Code AI 编程插件 Gemini Code Assist

用ClaudeSonnet3.7的天气测试编码,让谷歌VSCodeAI编程插件GeminiCodeAssist自动编程。生成的文件在浏览器中的效果如下:(附源代码)VSCode...

顾爷想知道第4.5期 国服便利性到底需优化啥?

前段时间DNF国服推出了名为“阿拉德B计划”的系列改版计划,截至目前我们已经看到了两项实装。不过关于便利性上,国服似乎还有很多路要走。自从顾爷回归DNF以来,几乎每天都在跟我抱怨关于DNF里面各种各样...

掌握Visual Studio项目配置【基础篇】

1.前言VisualStudio是Windows上最常用的C++集成开发环境之一,简称VS。VS功能十分强大,对应的,其配置系统较为复杂。不管是对于初学者还是有一定开发经验的开发者来说,捋清楚VS...

还嫌LED驱动设计套路深?那就来看看这篇文章吧

随着LED在各个领域的不同应用需求,LED驱动电路也在不断进步和发展。本文从LED的特性入手,推导出适合LED的电源驱动类型,再进一步介绍各类LED驱动设计。设计必读:LED四个关键特性特性一:非线...

Visual Studio Community 2022(VS2022)安装图文方法

直接上步骤:1,首先可以下载安装一个VisualStudio安装器,叫做VisualStudioinstaller。这个安装文件很小,很快就安装完成了。2,打开VisualStudioins...

Qt添加MSVC构建套件的方法(qt添加c++11)

前言有些时候,在Windows下因为某些需求需要使用MSVC编译器对程序进行编译,假设我们安装Qt的时候又只是安装了MingW构建套件,那么此时我们该如何给现有的Qt添加一个MSVC构建套件呢?本文以...

Qt为什么站稳c++GUI的top1(qt c)

为什么现在QT越来越成为c++界面编程的第一选择,从事QT编程多年,在这之前做C++界面都是基于MFC。当时为什么会从MFC转到QT?主要原因是MFC开发界面想做得好看一些十分困难,引用第三方基于MF...

qt开发IDE应该选择VS还是qt creator

如果一个公司选择了qt来开发自己的产品,在面临IDE的选择时会出现vs或者qtcreator,选择qt的IDE需要结合产品需求、部署平台、项目定位、程序猿本身和公司战略,因为大的软件产品需要明确IDE...

Qt 5.14.2超详细安装教程,不会来打我

Qt简介Qt(官方发音[kju:t],音同cute)是一个跨平台的C++开库,主要用来开发图形用户界面(GraphicalUserInterface,GUI)程序。Qt是纯C++开...

Cygwin配置与使用(四)——VI字体和颜色的配置

简介:VI的操作模式,基本上VI可以分为三种状态,分别是命令模式(commandmode)、插入模式(Insertmode)和底行模式(lastlinemode),各模式的功能区分如下:1)...

取消回复欢迎 发表评论: