CMake 023:if 语句一元、二元判断与正则实战
- 前言🎯
- [Bilibili 同步视频](#Bilibili 同步视频)
- [一、初识 CMake if 逻辑体系📜](#一、初识 CMake if 逻辑体系📜)
- 二、一元判断:单元素状态校验⚙️
- 三、二元判断:双对象比对运算🔍
- [四、高阶玩法:matches 正则表达式匹配🎨](#四、高阶玩法:matches 正则表达式匹配🎨)
-
- [4.1 正则基础语法说明](#4.1 正则基础语法说明)
- [4.2 正则匹配实战代码](#4.2 正则匹配实战代码)
- [4.3 运行结果 & 场景落地](#4.3 运行结果 & 场景落地)
- [五、if 语句综合总结与现存局限⚠️](#五、if 语句综合总结与现存局限⚠️)
-
- [5.1 语法体系复盘](#5.1 语法体系复盘)
- [5.2 CMake if 语句现存短板](#5.2 CMake if 语句现存短板)
- [5.3 解决方案](#5.3 解决方案)
- 六、写在最后📝
前言🎯
在 CMake 工程构建体系中,if 条件判断语句是逻辑分支控制 的核心基石。无论是变量校验、文件探测、命令识别,还是数值比对、字符串匹配、内容规则校验,都离不开 if 语句的加持。
很多开发者仅会使用基础的布尔值判断,却对 CMake if 内置的一元判断 、二元判断 以及正则匹配功能一知半解。本文将由浅入深,逐层拆解 CMake if 各类判断语法,搭配实战代码、原理解析与场景落地,带你吃透这一核心语法,规避日常开发中的隐性坑点📚。
Bilibili 同步视频
一、初识 CMake if 逻辑体系📜
常规代码中的 if,大多仅支持变量、布尔表达式、逻辑运算符组合判断,最终依托 true/false 布尔结果执行分支逻辑。而 CMake 针对工程构建的专属场景,对 if 语句做了深度扩展,将条件判断划分为一元判断 与二元判断两大体系,同时额外加持正则表达式匹配能力,覆盖构建过程中绝大多数逻辑校验场景。
整体逻辑架构梳理:
-
一元判断:单对象校验,聚焦存在性、定义状态、身份识别;
-
二元判断:双对象比对,涵盖数值运算、字符串比对、版本比较;
-
拓展能力:
matches正则匹配,实现复杂内容规则校验。
下面我们由简至繁,结合代码逐一详解每一类用法、特性与使用场景。
二、一元判断:单元素状态校验⚙️
所谓一元判断 ,即仅针对单个目标 做状态、属性、存在性校验,CMake 内置三类高频一元判断指令:exist、command、defined,三者各司其职,是工程构建中使用率极高的基础语法。
2.1 三类一元指令基础释义
-
exist:文件 / 路径存在性校验专门用于判断指定路径下文件、目录是否真实存在,是文件预处理、资源探测的常用指令。
-
command:命令合法性校验判断后跟的内容是否为 CMake 原生支持的内置命令,多用于动态命令分发、插件化构建场景,日常基础工程中使用频次偏低。
-
defined:变量定义状态校验重中之重 ,专门判断一个变量是否被显式定义 ,与变量本身的值无关,这也是它和直接判断变量布尔值最核心的区别。
2.2 defined 深度解析 + 实战代码💡
在初学阶段,很多人会混淆「变量值判断」与「变量定义判断」,这里先抛出一个核心结论:
CMake 中,若变量被定义且值为
OFF、空值等,直接判断变量会返回false;但defined只关心变量是否被定义,忽略变量具体取值。
场景模拟
定义两个变量:
-
VR_DF:主动定义,赋值为OFF; -
NOT_DF:全程不定义。
完整测试代码
cmake
# 定义变量 VR_DF,赋值为 OFF
set(VR_DF OFF)
# 1. 使用 defined 判断变量是否被定义(一元判断标准用法)
if(defined VR_DF)
message("✅ 变量 VR_DF 已被定义")
else()
message("❌ 变量 VR_DF 未被定义")
endif()
if(defined NOT_DF)
message("✅ 变量 NOT_DF 已被定义")
else()
message("❌ 变量 NOT_DF 未被定义")
endif()
# 2. 直接判断变量布尔值(对比测试)
if(VR_DF)
message("👉 直接判断:VR_DF 结果为 true")
else()
message("👉 直接判断:VR_DF 结果为 false")
endif()
运行结果解析
Plain
✅ 变量 VR_DF 已被定义
❌ 变量 NOT_DF 未被定义
👉 直接判断:VR_DF 结果为 false
业务应用场景💼
工程开发中,大量参数由外部用户传参 、跨脚本传参引入,此时变量存在「已定义 / 未定义」两种状态。借助 defined,我们可以实现变量默认值预设:未定义则赋予初始值,已定义则沿用原有配置,完美适配灵活化的构建参数设计。
补充:
exist、command语法格式与defined完全一致,格式为if(exist 目标路径)、if(command 命令名),可举一反三自行测试。
三、二元判断:双对象比对运算🔍
二元判断 ,顾名思义是对两个对象 做大小、相等、顺序等比对运算,适配数值、字符串、版本号三类比对场景。CMake 将二元判断细分为数值比对 与字符串比对两大分支,语法不同、底层实现不同,使用时需严格区分。
3.1 基础比对规则总览
二元判断支持的运算符号:EQUAL(等于)、LESS(小于)、LESS_EQUAL(小于等于)、GREATER(大于)、GREATER_EQUAL(大于等于)。
额外拓展:版本号比对逻辑与普通数值比对一致,遵循语义化版本规则(如 3.1.2 > 3.1.1)。
3.2 数值比对:EQUAL 系列(纯数字运算)
EQUAL/LESS 等原生比对指令,底层基于整型数值运算,仅标准数字可正常比对,纯文本字符串会判定为不匹配。
测试代码
cmake
# 定义数字变量
set(VAR_E 123)
# 数字相等判断
if(${VAR_E} EQUAL 123)
message("🔢 数值比对:VAR_E 等于 123")
else()
message("🔢 数值比对:VAR_E 不等于 123")
endif()
# 测试纯文本字符串(数值比对不生效)
set(VAR_STR test)
if(${VAR_STR} EQUAL test)
message("🔢 数值比对:字符串匹配成功")
else()
message("🔢 数值比对:字符串匹配失败")
endif()
运行结果
Plain
🔢 数值比对:VAR_E 等于 123
🔢 数值比对:字符串匹配失败
3.3 字符串比对:STREQUAL 系列(文本全匹配)
STREQUAL、STRLESS 等指令,专门用于字符串内容比对 ,底层逻辑为逐字符字典序匹配,兼容性更强。
测试代码
cmake
set(VAR_STR test)
# 字符串相等判断
if(${VAR_STR} STREQUAL test)
message("📝 字符串比对:匹配成功")
else()
message("📝 字符串比对:匹配失败")
endif()
# 字符串比对兼容数字格式
set(VAR_NUM 123)
if(${VAR_NUM} STREQUAL "123")
message("📝 字符串比对:数字格式字符串匹配成功")
endif()
运行结果
Plain
📝 字符串比对:匹配成功
📝 字符串比对:数字格式字符串匹配成功
3.4 两者性能与使用取舍⚡
-
底层差异
-
数值比对:直接对整型数据运算,执行效率更高;
-
字符串比对:逐字符遍历匹配,性能略低。
-
-
使用建议
-
纯数字大小 / 相等判断:优先使用
EQUAL数值比对; -
文本、混合字符、单纯相等校验:统一使用
STREQUAL,语法通用、不易出错; -
大小比较(大于 / 小于):必须使用原生数值比对指令,字符串无大小运算意义。
-
四、高阶玩法:matches 正则表达式匹配🎨
在常规比对之外,CMake if 提供了 matches 关键字,原生支持正则表达式匹配 ,这也是 if 语句中灵活性最强、功能最丰富的高阶用法。
借助正则,我们不再局限于简单相等 / 大小判断,可实现格式校验、内容筛选、规则拦截,常用于用户输入校验、网址匹配、命名规范检测等复杂场景。
4.1 正则基础语法说明
本文不展开全量正则语法,仅结合案例讲解核心规则:
-
[a-z]+:匹配1 个及以上小写英文字母; -
^:匹配字符串开头; -
$:匹配字符串结尾; -
^[a-z]+$:整串严格匹配,从头到尾只能是小写字母。
4.2 正则匹配实战代码
cmake
# 测试字符串1:纯字母
set(STR1 "abcd")
# 测试字符串2:字母+数字混合
set(STR2 "abcd123")
# 1. 模糊匹配:包含小写字母即可
if(${STR1} matches "[a-z]+")
message("🔍 模糊正则:STR1 匹配成功")
endif()
if(${STR2} matches "[a-z]+")
message("🔍 模糊正则:STR2 匹配成功")
endif()
# 2. 严格整串匹配:从头到尾必须全为小写字母
if(${STR1} matches "^[a-z]+$")
message("🔍 严格正则:STR1 纯字母,匹配成功")
else()
message("🔍 严格正则:STR1 匹配失败")
endif()
if(${STR2} matches "^[a-z]+$")
message("🔍 严格正则:STR2 纯字母,匹配成功")
else()
message("🔍 严格正则:STR2 含数字,匹配失败")
endif()
4.3 运行结果 & 场景落地
Plain
🔍 模糊正则:STR1 匹配成功
🔍 模糊正则:STR2 匹配成功
🔍 严格正则:STR1 纯字母,匹配成功
🔍 严格正则:STR2 含数字,匹配失败
实际工程应用💼
-
校验用户传入的参数命名是否符合规范;
-
拦截非法格式的路径、网址、版本号;
-
对配置项内容做规则过滤,提升工程健壮性。
提示:正则语法属于通用技术,若需复杂规则,可自行拓展正则知识库。
五、if 语句综合总结与现存局限⚠️
5.1 语法体系复盘
-
一元判断 :
defined(变量定义)、exist(文件)、command(命令),聚焦单元素状态; -
二元判断 :区分数值比对 与字符串比对,按需选用,兼顾效率与兼容性;
-
正则匹配 :
matches赋能复杂格式校验,拓展if语句边界。
以上语法并非孤立存在,后续 CMake 学习中,列表操作、文件处理、版本迭代、策略配置 等模块,都会频繁嵌套 if 条件判断,它将贯穿整个工程构建流程。
5.2 CMake if 语句现存短板
-
代码冗余 :多层
if-else嵌套会导致代码层级冗长,可读性下降; -
场景受限 :在 Windows + Visual Studio 编译环境下,无法直接通过
if区分Debug/Release模式,进而不能自动设置差异化调试路径; -
嵌套能力弱 :复杂多分支逻辑下,原生
if嵌套体验较差。
5.3 解决方案
CMake 后续提供表达式语句 ,可简化冗长的条件分支代码;而针对 VS 不同模式调试路径的问题,若无深入学习表达式语句,也可采用手动配置的方式规避,不影响常规工程使用。
六、写在最后📝
CMake if 条件判断是构建脚本的逻辑骨架,从基础的变量校验,到进阶的正则规则匹配,每一类语法都对应着真实的工程场景。

分清一元与二元判断的使用边界、吃透数值与字符串比对的底层差异、灵活运用正则匹配,便能写出简洁、高效、健壮的 CMake 脚本。希望本文的代码案例与原理解析,能帮大家扫清 CMake 条件判断的知识盲区,在实际项目中灵活运用✨。