CMake流程控制
| 命令分类 | 核心命令 | 功能说明 | 典型使用场景 |
|---|---|---|---|
| 条件判断 | if(condition) ... elseif(...) ... else() ... endif() |
根据条件表达式的真假,选择性地执行代码块。 | 区分操作系统(如 Windows/Linux)、判断构建类型(Debug/Release)、控制可选组件的编译。 |
| 列表循环 | foreach() / endforeach() |
遍历列表中的元素或指定的数值范围,对每个元素执行循环体。 | 批量处理源文件、遍历依赖库列表、批量添加测试用例。 |
| 条件循环 | while() / endwhile() |
只要指定的条件表达式为真,就持续执行循环体。 | 循环计数、持续检查某个文件是否生成、复杂的迭代逻辑。 |
| 循环控制 | break() / continue() |
break 用于跳出整个循环;continue 用于跳过当前迭代,进入下一次循环。 |
在满足特定条件时提前终止遍历,或跳过不符合要求的元素。 |
| 函数/宏定义 | function() / macro() |
封装可复用的代码块。function 具有独立的变量作用域,macro 则是文本替换(无独立作用域)。 |
封装复杂的编译选项设置、自定义查找依赖的逻辑、代码复用。 |
一、IF条件判断
1.基本语法
| 结构 | 语法 | 说明 | 示例 |
|---|---|---|---|
| 基本if | if(condition) |
单一条件判断 | if(WIN32) |
| if-else | if(condition) ... else() |
二选一分支 | if(DEBUG) ... else() |
| if-elseif-else | if() ... elseif() ... else() |
多分支选择 | if(A) ... elseif(B) ... else() |
| 结束标记 | endif() |
必须的结束标记 | endif() |
2.条件类型
| 类别 | 语法 | 说明 | 示例 |
|---|---|---|---|
| 逻辑运算 | NOT condition |
逻辑非 | if(NOT WIN32) |
condition1 AND condition2 |
逻辑与 | if(UNIX AND NOT APPLE) |
|
condition1 OR condition2 |
逻辑或 | if(DEBUG OR TEST_MODE) |
|
| 字符串比较 | var STREQUAL "string" |
字符串相等 | if(TYPE STREQUAL "Debug") |
var STRLESS "string" |
字符串小于(字典序) | if(NAME STRLESS "zzz") |
|
var STRGREATER "string" |
字符串大于 | if(VER STRGREATER "1.0") |
|
var MATCHES "regex" |
正则匹配 | if(FILE MATCHES ".*\\.cpp$") |
|
| 数值比较 | var EQUAL number |
数值相等 | if(COUNT EQUAL 5) |
var LESS number |
小于 | if(AGE LESS 18) |
|
var GREATER number |
大于 | if(SIZE GREATER 1024) |
|
var LESS_EQUAL number |
小于等于 | if(N LESS_EQUAL 100) |
|
var GREATER_EQUAL number |
大于等于 | if(N GREATER_EQUAL 0) |
|
| 文件/目录 | EXISTS path |
文件或目录存在 | if(EXISTS "/tmp/file") |
IS_DIRECTORY path |
是否为目录 | if(IS_DIRECTORY "/usr") |
|
IS_SYMLINK path |
是否为符号链接 | if(IS_SYMLINK "/link") |
|
IS_ABSOLUTE path |
是否为绝对路径 | if(IS_ABSOLUTE "${PATH}") |
|
| 变量检查 | DEFINED var |
变量已定义 | if(DEFINED MY_VAR) |
var |
变量非空且非假值 | if(MY_VAR) |
|
| 目标检查 | TARGET name |
目标是否存在 | if(TARGET mylib) |
COMMAND name |
命令是否存在 | if(COMMAND add_test) |
3.布尔False类型
| 假值 | 说明 |
|---|---|
0 |
数字零 |
OFF |
关闭标志 |
NO |
否定标志 |
FALSE |
布尔假 |
N |
否定简写 |
IGNORE |
忽略标志 |
NOTFOUND |
未找到标志 |
"" |
空字符串 |
*-NOTFOUND |
任何以-NOTFOUND结尾的字符串 |
bash
# 判断是否为 Windows 系统
if(WIN32)
message(STATUS "当前系统为 Windows")
# 判断是否为 Linux 系统 (UNIX 且非 APPLE)
elseif(UNIX AND NOT APPLE)
message(STATUS "当前系统为 Linux")
else()
message(STATUS "其他操作系统")
endif()
message("CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}")
| 变量名 | 为 TRUE 的条件 | 说明 |
|---|---|---|
| WIN32 | Windows 系统 | 包括 32位 和 64位 Windows。注意:在 Cygwin 中也可能为真,需结合 CYGWIN 判断。 |
| APPLE | Apple 系统 | 包括 macOS (Darwin) 和 iOS。 |
| UNIX | 类 Unix 系统 | 包括 Linux, macOS, BSD, AIX, Solaris 等。注意:macOS 既是 APPLE 也是 UNIX。 |
| ANDROID | Android 系统 | 基于 Linux 内核,但通常单独处理。 |
| IOS | iOS 系统 | Apple 移动操作系统。 |
| MSVC | MSVC编译器 | 使用Microsoft Visual C++ |
| CMAKE_COMPILER_IS_GNUCXX | GCC编译器 | 使用GNU C++编译器 |
| CYGWIN | Cygwin 环境 | Windows 下的 POSIX 兼容层。 |
| MSYS | MSYS/MinGW 环境 | Windows 下的另一种 POSIX 兼容层。 |
| 具体系统名称可以读取变量CMAKE_SYSTEM_NAME |
| 操作系统 | CMAKE_SYSTEM_NAME 的值 | 备注 |
|---|---|---|
| Windows | "Windows" | |
| Linux | "Linux" | 各种发行版(Ubuntu, CentOS等)均为此值。 |
| macOS | "Darwin" | 注意:不是 "macOS" 或 "Apple"。 |
| iOS | "iOS" | |
| Android | "Android" | |
| FreeBSD | "FreeBSD" | |
| AIX | "AIX" | IBM Unix 系统。 |
| Solaris | "SunOS" | Oracle Solaris。 |
二、列表循环foreach
bash
# 定义一个list
set(TEST_FILES TestA.cpp TestB.cpp TestC.cpp)
# 遍历list
foreach(file_name IN LISTS TEST_FILES)
message(STATUS "file_name: ${file_name}")
endforeach()
# 从 1 遍历到 5,步长为 2
foreach(i RANGE 1 5 2)
message(STATUS "指定步长: ${i}")
endforeach()
# 从 1 遍历到 5,默认步长为 1
foreach(i RANGE 1 5)
message(STATUS "默认步长: ${i}")
endforeach()
三、条件循环while
bash
set(count 0)
while(count LESS 3)
message(STATUS "当前结果: ${count}")
math(EXPR count "${count} + 1")
endwhile()
四、循环控制break与continue
bash
# 跳过偶数
foreach(i RANGE 1 10)
math(EXPR temp "${i} % 2")
if(${temp} EQUAL 0)
message(STATUS "跳过偶数: ${i}")
continue()
endif()
# 输出奇数
message(STATUS "输出奇数: ${i}")
# 如果数字大于7,退出循环
if(${i} GREATER 7)
message(STATUS "数字 ${i} 大于7,循环结束!")
break()
endif()
endforeach()
五、函数与宏 (function / macro)
bash
function(my_func value)
set(name value)
message(STATUS "赋值 name -> ${value}")
endfunction()
my_func(张三)