CMake 023:if 语句一元、二元判断与正则实战

CMake 023:if 语句一元、二元判断与正则实战

  • 前言🎯
  • [Bilibili 同步视频](#Bilibili 同步视频)
  • [一、初识 CMake if 逻辑体系📜](#一、初识 CMake if 逻辑体系📜)
  • 二、一元判断:单元素状态校验⚙️
  • 三、二元判断:双对象比对运算🔍
    • [3.1 基础比对规则总览](#3.1 基础比对规则总览)
    • [3.2 数值比对:`EQUAL` 系列(纯数字运算)](#3.2 数值比对:EQUAL 系列(纯数字运算))
    • [3.3 字符串比对:`STREQUAL` 系列(文本全匹配)](#3.3 字符串比对:STREQUAL 系列(文本全匹配))
    • [3.4 两者性能与使用取舍⚡](#3.4 两者性能与使用取舍⚡)
  • [四、高阶玩法: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 023:if 语句一元、二元判断与正则实战

一、初识 CMake if 逻辑体系📜

常规代码中的 if,大多仅支持变量、布尔表达式、逻辑运算符组合判断,最终依托 true/false 布尔结果执行分支逻辑。而 CMake 针对工程构建的专属场景,对 if 语句做了深度扩展,将条件判断划分为一元判断二元判断两大体系,同时额外加持正则表达式匹配能力,覆盖构建过程中绝大多数逻辑校验场景。

整体逻辑架构梳理:

  • 一元判断:单对象校验,聚焦存在性、定义状态、身份识别

  • 二元判断:双对象比对,涵盖数值运算、字符串比对、版本比较

  • 拓展能力:matches 正则匹配,实现复杂内容规则校验。

下面我们由简至繁,结合代码逐一详解每一类用法、特性与使用场景。

二、一元判断:单元素状态校验⚙️

所谓一元判断 ,即仅针对单个目标 做状态、属性、存在性校验,CMake 内置三类高频一元判断指令:existcommanddefined,三者各司其职,是工程构建中使用率极高的基础语法。

2.1 三类一元指令基础释义

  1. exist :文件 / 路径存在性校验

    专门用于判断指定路径下文件、目录是否真实存在,是文件预处理、资源探测的常用指令。

  2. command :命令合法性校验

    判断后跟的内容是否为 CMake 原生支持的内置命令,多用于动态命令分发、插件化构建场景,日常基础工程中使用频次偏低。

  3. 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,我们可以实现变量默认值预设:未定义则赋予初始值,已定义则沿用原有配置,完美适配灵活化的构建参数设计。

补充:existcommand 语法格式与 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 系列(文本全匹配)

STREQUALSTRLESS 等指令,专门用于字符串内容比对 ,底层逻辑为逐字符字典序匹配,兼容性更强。

测试代码

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 两者性能与使用取舍⚡

  1. 底层差异

    • 数值比对:直接对整型数据运算,执行效率更高

    • 字符串比对:逐字符遍历匹配,性能略低。

  2. 使用建议

    • 纯数字大小 / 相等判断:优先使用 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 含数字,匹配失败

实际工程应用💼

  1. 校验用户传入的参数命名是否符合规范;

  2. 拦截非法格式的路径、网址、版本号;

  3. 对配置项内容做规则过滤,提升工程健壮性。

提示:正则语法属于通用技术,若需复杂规则,可自行拓展正则知识库。

五、if 语句综合总结与现存局限⚠️

5.1 语法体系复盘

  1. 一元判断defined(变量定义)、exist(文件)、command(命令),聚焦单元素状态;

  2. 二元判断 :区分数值比对字符串比对,按需选用,兼顾效率与兼容性;

  3. 正则匹配matches 赋能复杂格式校验,拓展 if 语句边界。

以上语法并非孤立存在,后续 CMake 学习中,列表操作、文件处理、版本迭代、策略配置 等模块,都会频繁嵌套 if 条件判断,它将贯穿整个工程构建流程。

5.2 CMake if 语句现存短板

  1. 代码冗余 :多层 if-else 嵌套会导致代码层级冗长,可读性下降;

  2. 场景受限 :在 Windows + Visual Studio 编译环境下,无法直接通过 if 区分 Debug/Release 模式,进而不能自动设置差异化调试路径;

  3. 嵌套能力弱 :复杂多分支逻辑下,原生 if 嵌套体验较差。

5.3 解决方案

CMake 后续提供表达式语句 ,可简化冗长的条件分支代码;而针对 VS 不同模式调试路径的问题,若无深入学习表达式语句,也可采用手动配置的方式规避,不影响常规工程使用。

六、写在最后📝

CMake if 条件判断是构建脚本的逻辑骨架,从基础的变量校验,到进阶的正则规则匹配,每一类语法都对应着真实的工程场景。

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