cmake中用if(win32)/if(unix)/if(apple)可直接判断系统,win32匹配所有windows(不含cygwin),unix匹配linux/macos/freebsd等,apple专指macos且隐含unix;三者非严格互斥,推荐用elseif确保逻辑安全;路径统一用/,后缀由cmake自动处理,rpath需按平台显式配置。

怎么用 if(WIN32)/if(UNIX)/if(APPLE) 判断系统
直接用 CMake 内置变量是最简单、最可靠的方式,不需要自己解析 CMAKE_SYSTEM_NAME 或环境变量。这些判断在 configure 阶段就完成,不依赖运行时。
-
if(WIN32)匹配所有 Windows(含 MSVC/MinGW/Clang-CL),但不匹配 Cygwin; -
if(UNIX)匹配 Linux、macOS、FreeBSD 等所有 Unix-like 系统,范围比if(APPLE)大; -
if(APPLE)专用于 macOS(CMAKE_SYSTEM_NAME是 Darwin),它隐含UNIX,但不能反过来推; - 三者互斥性不强——比如
if(APPLE)和if(UNIX)可能同时为真,所以嵌套或用elseif更安全。
链接库和编译定义怎么按平台写
不同系统需要不同的链接项和预定义宏,硬写死会导致 Linux 下链接失败或 Windows 下找不到头文件。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- Windows 下常用
ws2_32(网络)、user32(GUI)、advapi32(安全)等库,Linux/macOS 一般用pthread、dl; - 用
target_link_libraries(myapp PRIVATE ...)而不是全局link_libraries(),避免污染其他 target; - 宏定义推荐用
add_compile_definitions(),而不是add_definitions()(后者已过时); - 示例:
if(WIN32)
target_link_libraries(myapp PRIVATE ws2_32 user32)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS UNICODE)
elseif(UNIX)
target_link_libraries(myapp PRIVATE pthread dl)
if(APPLE)
find_library(COREFOUNDATION CoreFoundation)
target_link_libraries(myapp PRIVATE ${COREFOUNDATION})
endif()
endif()
路径分隔符和文件后缀要不要手动处理
不用。CMake 内部自动转换路径分隔符,硬编码 "\\" 或拼接 "${CMAKE_CURRENT_SOURCE_DIR}\config" 是典型反模式。
- 一律用正斜杠
/:如include_directories(${CMAKE_SOURCE_DIR}/include); - 库/可执行文件后缀由 CMake 自动决定:
CMAKE_STATIC_LIBRARY_SUFFIX、CMAKE_SHARED_LIBRARY_SUFFIX等变量已有默认值,除非你要强制覆盖(比如打包时要求 .dll 而非 .so); - 真正要留意的是动态库的运行时路径(RPATH):Linux 用
$ORIGIN,macOS 用@loader_path,Windows 不需要——这部分必须显式配置,否则程序启动时报“找不到 DLL”或“dylib not found”。
为什么 CMAKE_SYSTEM_NAME 比 WIN32 更难用但有时必须用
因为 WIN32 无法区分 Windows Desktop 和 Windows Store/UWP,UNIX 无法区分 Linux 和 FreeBSD,而某些底层 API(如 sendfile、epoll vs kqueue)只存在于特定子系统。
- 当项目需支持 Android 或嵌入式(如 QNX、Emscripten),
CMAKE_SYSTEM_NAME是唯一选择; - 示例:
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")可以精准启用epoll支持,而if(UNIX)会误判 macOS; - 注意:
CMAKE_SYSTEM_NAME在交叉编译时反映的是目标平台,不是宿主平台——这点容易被忽略,尤其在用 Docker 构建 ARM Linux 时。
add_subdirectory() 之后——那样子目录里的 CMakeLists.txt 就看不到父级的判断结果了。变量作用域和执行顺序得盯紧。










