Skip to content

system_judge - 系统判断宏

system_judge.h 定义了平台和架构检测的底层宏,是整个项目跨平台支持的基础。这个文件的设计原则很简单——只负责检测,不做任何决策,把判断结果以宏的形式暴露给上层使用。

操作系统检测

我们支持三个主流桌面操作系统,检测基于编译器预定义宏:

cpp
// Windows 平台检测(包括 32 位和 64 位)
#if defined(_WIN32) || defined(_WIN64)
#    define CFDESKTOP_OS_WINDOWS
#endif

// Linux 平台检测
#if defined(__linux__)
#    define CFDESKTOP_OS_LINUX
#endif
```text

Windows 的检测用了两个宏是因为 `_WIN32` 在 64 位 Windows 上也会被定义,而 `_WIN64` 只在 64 位上定义。用 `||` 连接可以覆盖所有情况。Linux 的 `__linux__` 则是所有类 Linux 系统通用的宏,如果你需要区分发行版,得在运行时检查 `/etc/os-release`。

## 架构检测

CPU 架构检测主要服务于性能优化和 SIMD 指令使用:

```cpp
// x86-64 (AMD64) 检测
#if defined(__x86_64__) || defined(_M_X64) || defined(__amd64__)
#    define CFDESKTOP_ARCH_X86_64
#endif

// ARM64 检测
#if defined(__aarch64__) || defined(_M_ARM64)
#    define CFDESKTOP_ARCH_ARM64
#endif

// ARM32 检测
#if defined(__arm__) || defined(_M_ARM)
#    define CFDESKTOP_ARCH_ARM32
#endif
```text

这里的 `__x86_64__` 和 `__aarch64__` 是 GCC/Clang 的约定,`_M_X64`、`_M_ARM64`、`_M_ARM` 是 MSVC 的约定。用多个宏检查是因为不同编译器的命名习惯不一样。

## 宏定义规则

每个宏定义都遵循相同的模式——检测到条件后定义一个不带值的标准宏:

```cpp
#if defined(<compiler_macro>)
#    define CFDESKTOP_<CATEGORY>_<NAME>
#endif
```text

不带值的设计是有意为之的。我们只需要知道"是不是这个平台",不需要传递额外信息。如果需要细分版本(比如 Windows 10 vs Windows 11),应该在运行时检测,而不是用编译时宏。

## 使用示例

```cpp
#include "base/macro/system_judge.h"

// 根据平台选择不同的实现
#if defined(CFDESKTOP_OS_WINDOWS)
    // Windows 实现
#elif defined(CFDESKTOP_OS_LINUX)
    // Linux 实现
#else
    #error "Unsupported platform"
#endif

// 根据架构选择优化路径
#if defined(CFDESKTOP_ARCH_X86_64)
    // 使用 AVX2 指令集
#elif defined(CFDESKTOP_ARCH_ARM64)
    // 使用 NEON 指令集
#endif
```bash

⚠️ 记得在 `#else` 或 `#elif` 分支加上 `#error`,避免在不支持的平台上静默编译通过,结果运行时出错。

## 编译器兼容性

这些宏在主流编译器上都能工作:

| 编译器 | 平台宏支持 | 架构宏支持 |
|--------|-----------|-----------|
| MSVC   | 完全支持  | 完全支持  |
| GCC    | 完全支持  | 完全支持  |
| Clang  | 完全支持  | 完全支持  |
| MinGW  | 完全支持  | 完全支持  |

如果你用了其他编译器(比如 Intel ICC),可能需要额外添加检测逻辑。

## 扩展新平台

添加新平台支持时,需要在两个地方修改代码:

```cpp
// 1. 在 system_judge.h 添加检测
#if defined(__NEW_OS__)
#    define CFDESKTOP_OS_NEW_OS
#endif

// 2. 在对应实现文件添加平台特定代码
#if defined(CFDESKTOP_OS_NEW_OS)
    // 新平台实现
#endif
```text

记得同步更新文档和测试,确保 CI 环境能在新平台上正常运行。

## 常见问题

为什么不用 C++20 的 `#ifdef`?因为 `std::is_constant_evaluated()` 只能判断是否在常量求值上下文,不能区分平台。

为什么不用 CMake 的 `CMAKE_SYSTEM_NAME`?因为那是构建系统的信息,不能直接在代码里用。我们用宏是为了在预处理阶段就知道平台,实现条件编译。

## 相关文档

- [macros - 宏定义系统](../macros.md)
- [基础工具类概述](../overview.md)

Built with VitePress