目录
[2.3.文件 / 路径判断](#2.3.文件 / 路径判断)
[2.4. 目标 / 组件判断](#2.4. 目标 / 组件判断)
[2.5. 系统与编译器判断](#2.5. 系统与编译器判断)
[2.6.逻辑组合(与 / 或 / 非)](#2.6.逻辑组合(与 / 或 / 非))
1.简介
CMake 的条件判断是通过 if()
/elseif()
/else()
/endif()
结构实现流程控制的核心,常用于根据环境、配置、依赖等动态调整构建逻辑。
基本语法:
cpp
if(<条件>)
# 条件为真时执行
elseif(<另一条件>) # 可选,可多个
# 另一条件为真时执行
else() # 可选
# 所有条件为假时执行
endif() # 必须闭合(推荐加注释:endif(<条件>) 增强可读性)
如果是基本表达式,条件(expression)有以下三种情况:常量、变量、字符串
- 如果是
1
,ON
,YES
,TRUE
,Y
,非零值
,非空字符串
时,条件判断返回True
- 如果是
0
,OFF
,NO
,FALSE
,N
,IGNORE
,NOTFOUND
,空字符串
时,条件判断返回False
2.核心判断类型及示例
2.1.变量相关判断
1)if(<var>)
:变量存在且值为 "真"(1
/ON
/YES
/TRUE
/Y
,不区分大小写)。
cpp
set(ENABLE_FEATURE ON)
if(ENABLE_FEATURE) # 成立
message("Feature enabled")
endif()
2)if(NOT <var>)
:变量不存在或值为 "假"(0
/OFF
/NO
/FALSE
/N
/ 空值)。
3)if(DEFINED <var>)
:仅判断变量是否被定义(无论值是否为空)。
cpp
set(EMPTY_VAR "")
if(DEFINED EMPTY_VAR) # 成立(变量已定义)
message("变量已定义")
endif()
4)字符串比较 :STREQUAL
(全等,区分大小写)、STRLESS
(小于)、STRGREATER
(大于)。
if(string1 STREQUAL string2)
:字符串相等(区分大小写)。
if(string1 MATCHES regex)
:正则匹配。
cpp
# 1
if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") # 字符串完全匹配, 编译Debug版本
...
endif()
# 2
set(OS_TYPE "Linux")
if(OS_TYPE STREQUAL "macOS") # 注意大小写
message("macOS detected") # 不会执行(L != l)
endif()
2.2.数值判断
支持整数比较,使用 EQUAL
(等于)、LESS
(小于)、GREATER
(大于)、LESS_EQUAL
(小于等于)、GREATER_EQUAL
(大于等于):
cpp
set(NUM 5)
if(NUM GREATER 3) # 成立(5 > 3)
message(STATUS "NUM 大于 3")
endif()
2.3.文件 / 路径判断
if(EXISTS <路径>)
:路径存在(文件或目录均可)。
cpp
if(EXISTS "src/main.cpp") # 若文件存在则成立
message(STATUS "找到源文件")
endif()
if(IS_DIRECTORY <路径>)
:路径为目录则成立。
cpp
if(IS_DIRECTORY "include") # 若 include 是目录则成立
message(STATUS "找到 include 目录")
endif()
-
if(IS_FILE <路径>)
:路径为文件则成立(CMake 3.14+ 支持)。 -
if(IS_SYMLINK file-name) : 判断是不是软链接, 此处的
file-name
必须是绝对路径 -
if(IS_ABSOLUTE path) : 判断是不是绝对路径
2.4. 目标 / 组件判断
if(TARGET <目标名>)
:检查是否存在指定名称的构建目标(如通过add_executable
/add_library
定义的目标)。
cpp
add_executable(my_app main.cpp)
if(TARGET my_app) # 成立(目标存在)
message(STATUS "目标 my_app 已定义")
endif()
if(<包名>_FOUND)
:检查通过find_package()
查找的包是否成功(通常包会定义<包名>_FOUND
变量)。
cpp
find_package(OpenSSL)
if(OpenSSL_FOUND) # 找到 OpenSSL 则成立
message(STATUS "OpenSSL 已找到")
endif()
2.5. 系统与编译器判断
条件 | 含义 |
---|---|
if(WIN32) |
Windows 系统(含 32/64 位) |
if(UNIX) |
类 Unix 系统(Linux/macOS 等) |
if(APPLE) |
macOS/iOS 系统 |
if(CMAKE_SYSTEM_NAME STREQUAL "Linux") |
精确匹配 Linux 系统 |
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") |
编译器为 GCC |
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") |
编译器为 Clang(含 AppleClang) |
cpp
if(WIN32)
message(STATUS "当前系统:Windows")
elseif(APPLE)
message(STATUS "当前系统:macOS")
elseif(UNIX)
message(STATUS "当前系统:Linux 或其他类 Unix 系统")
endif()
2.6.逻辑组合(与 / 或 / 非)
if(<条件1> AND <条件2>)
:两个条件都为真则成立。if(<条件1> OR <条件2>)
:至少一个条件为真则成立。if(NOT <条件>)
:条件为假则成立(前面已提)。
cpp
set(A 1)
set(B 0)
if(A AND NOT B) # 成立(A 为真,B 为假)
message(STATUS "条件成立")
endif()
2.7.括号分组(优先级控制)
用 ()
调整逻辑优先级:
cpp
if((A OR B) AND C) # 先判断 A 或 B,再与 C 组合
...
endif()
2.8.判断某个元素是否在列表中
CMake版本要求 > 3.3
cpp
if(<variable|string> IN_LIST <variable>)
3.常见实用场景
1.根据构建类型(Debug/Release)配置:
cpp
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-DDEBUG_MODE) # Debug 模式定义宏
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0") # 关闭优化
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") # Release 模式开优化
endif()
2.条件添加源文件 / 宏:
cpp
add_executable(myapp main.cpp)
if(ENABLE_FEATURE_X) # 若启用 Feature X,添加对应源文件
target_sources(myapp PRIVATE feature_x.cpp)
target_compile_definitions(myapp PRIVATE ENABLE_X)
endif()
3.检查 CMake 版本是否满足要求:
cpp
cmake_minimum_required(VERSION 3.10) # 最低版本要求
if(CMAKE_VERSION VERSION_LESS "3.18") # 低于 3.18 时提示
message(WARNING "CMake 版本过低,部分功能可能受限")
endif()
4.根据用户选项(option()
)开启/关闭功能
cpp
option(ENABLE_FOO "Enable feature FOO" ON)
option(ENABLE_BAR "Enable feature BAR (requires FOO)" OFF)
if(ENABLE_BAR AND NOT ENABLE_FOO)
message(FATAL_ERROR "ENABLE_BAR requires ENABLE_FOO to be ON")
endif()
if(ENABLE_FOO)
target_compile_definitions(my_app PRIVATE HAVE_FOO)
if(ENABLE_BAR)
target_compile_definitions(my_app PRIVATE HAVE_BAR)
endif()
endif()
更多内容可参考:CMake指令:option_cmake option-CSDN博客
5.依赖项检查(如 find_package()
结果)
cpp
find_package(Protobuf 3.14 QUIET) # 优先找 3.14+
if(NOT Protobuf_FOUND)
find_package(Protobuf 3.0 REQUIRED) # 找不到则降级到 3.0+
endif()
target_link_libraries(my_app PRIVATE ${Protobuf_LIBRARIES})
更多内容可参考:CMake指令:find_package_cmake find package-CSDN博客
4.注意事项
1.变量引用无需 ${}
:if(MY_VAR)
直接用变量名,而非 if(${MY_VAR})
(后者会解析为变量值,易出错)。
2.空变量视为假 :未定义的变量或值为空时,if(<var>)
结果为假。
3.字符串比较大小写敏感 :STREQUAL
严格区分大小写,如需忽略可先统一大小写(如 string(TOLOWER ${A} A_LOW)
)。
4.路径用绝对路径更可靠 :结合 CMAKE_SOURCE_DIR
(源码根目录)等内置变量:
cpp
if(EXISTS "${CMAKE_SOURCE_DIR}/third_party") # 绝对路径检查
...
endif()
相关链接
- CMake 官网 CMake - Upgrade Your Software Build System
- CMake 官方文档:CMake Tutorial --- CMake 4.1.0-rc1 Documentation
- CMake 源码:https://github.com/Kitware/CMake
- CMake 源码:Sign in · GitLab