CMake流程控制

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