Skip to content

Commit 27d0e97

Browse files
authored
Merge pull request #45 from mcpp-community/feat/macos-support
feat: macOS ARM64 support — LLVM default toolchain + CI
2 parents d146b55 + a2445f9 commit 27d0e97

13 files changed

Lines changed: 1785 additions & 11 deletions
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# std.compat 支持 + cxx_scan restat + 增量零重编 E2E
2+
3+
> 2026-05-15 — 收尾三个遗留项,一个 PR 完成
4+
5+
## 1. 三个任务
6+
7+
### 1.1 std.compat 模块支持
8+
9+
**现状**`import std.compat` 在语法层面被识别(`is_std_module()` 返回 true),会触发 std BMI 构建。但 `std.compat.cppm`(Clang)/ `bits/std_compat.cc`(GCC)从未被发现和编译,没有独立的 BMI 产出。
10+
11+
**Clang**`~/.mcpp/.../xim-x-llvm/20.1.7/share/libc++/v1/std.compat.cppm` 存在。需要 `--precompile` 编译为 `pcm.cache/std.compat.pcm` + `std.compat.o`
12+
**GCC**`bits/std_compat.cc` 在当前 xlings GCC 16.1.0 包中**不存在**。GCC 的 `import std.compat``bits/std.cc` 隐式覆盖(编译 `std.cc` 自动产出 `std.compat` 的 gcm)。因此 GCC **不需要额外处理**
13+
14+
**改动点**
15+
1. `Toolchain` 新增 `stdCompatSource`(可选路径)
16+
2. `clang.cppm::find_libcxx_std_module_source` → 同时查找 `std.compat.cppm` 路径
17+
3. `clang.cppm::enrich_toolchain` → 设置 `stdCompatSource`
18+
4. `stdmod.cppm` → 若 `stdCompatSource` 非空,额外编译 `std.compat.pcm` + `std.compat.o`
19+
5. `BuildPlan` 新增 `stdCompatBmiPath` + `stdCompatObjectPath`
20+
6. `ninja_backend.cppm` → 当 Clang + 有 std.compat 时,stage `std.compat.pcm``std.compat.o`
21+
7. `flags.cppm` → 若有 std.compat,加 `-fmodule-file=std.compat=<pcm>`
22+
8. E2E 测试:在 `38_llvm_modules.sh` 或新增测试中用 `import std.compat` 验证
23+
24+
**GCC 不变**:GCC 的 `import std.compat` 已经通过 `bits/std.cc` 的隐式 gcm 工作,无需额外构建。
25+
26+
### 1.2 cxx_scan restat(P2 重新实现)
27+
28+
**之前失败原因**:经调查,CI 失败是 GitHub Actions 缓存 fallback restore(`restore-keys` 匹配到旧 commit 的 `target/`),导致 gtest `.o` 是旧的但 ninja 认为 up-to-date。与 restat 无关 — PR #35 第二次运行(无任何代码改动)就成功了。
29+
30+
**方案**:重新实现 backup-compare-restore + `restat = 1`,与 `cxx_module` 的 BMI 保留模式完全一致。
31+
32+
**改动点**`ninja_backend.cppm``cxx_scan` rule。
33+
34+
### 1.3 增量零重编 E2E
35+
36+
**改动点**:增强 `tests/e2e/39_llvm_incremental.sh`,新增一个验证步骤:
37+
- touch `greet.cppm` 但不改内容
38+
- rebuild with verbose
39+
- 验证 SCAN 跑了但 MOD/OBJ 没跑(restat 截断了级联)
40+
41+
## 2. 实施计划
42+
43+
所有改动在一个 PR 中,按以下顺序实施。
44+
45+
### Step 1:std.compat — 工具链层
46+
- `model.cppm``Toolchain``stdCompatSource` 字段
47+
- `clang.cppm``find_libcxx_std_compat_source()` + `enrich_toolchain` 填充
48+
- `clang.cppm``std_compat_build_commands()` — 两步编译(同 std)
49+
- `clang.cppm``std_compat_bmi_path()` / `staged_std_compat_bmi_path()`
50+
51+
### Step 2:std.compat — 构建管线层
52+
- `plan.cppm``BuildPlan``stdCompatBmiPath` + `stdCompatObjectPath`
53+
- `stdmod.cppm`:若 `tc.stdCompatSource` 非空,额外编译
54+
- `cli.cppm``prepare_build` 中把 `StdModule` 的 compat 路径传入 plan
55+
- `ninja_backend.cppm`:stage `std.compat.pcm` + `std.compat.o`(cp_bmi 边)
56+
- `flags.cppm`:Clang 时加 `-fmodule-file=std.compat=<staged_pcm>`
57+
58+
### Step 3:cxx_scan restat
59+
- `ninja_backend.cppm`:backup-compare-restore + `restat = 1`
60+
61+
### Step 4:E2E 测试
62+
- 新增 `tests/e2e/41_llvm_std_compat.sh``import std.compat` + C 函数使用
63+
- 增强 `tests/e2e/39_llvm_incremental.sh`:touch 零重编验证
64+
65+
## 3. 不做的事
66+
67+
- GCC std.compat 额外构建 — GCC 的 `bits/std.cc` 隐式覆盖
68+
- 改 E2E 04_incremental.sh(GCC) — 已有且工作正常
69+
- macOS / Windows — 远期
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# MCPP 跨平台 Clang/LLVM 支持分析报告
2+
3+
> 2026-05-16 — Linux Clang 平权现状 + 跨平台设计路线
4+
5+
## 一、Linux Clang 已达 GCC 平权
6+
7+
通过 PR #34 (Clang module pipeline parity) 到 `c7c1c3e` (std.compat + restat),12 个核心 Blocker 已全部解决:
8+
9+
| 能力 | GCC | Clang | 状态 |
10+
|---|---|---|---|
11+
| 工具链检测 & 安装 | `gcc@16` | `llvm@20` | ✅ 对等 |
12+
| 非模块 C/C++ 编译 ||| ✅ 对等 |
13+
| `import std` | `bits/std.cc``gcm.cache/std.gcm` | `std.cppm``pcm.cache/std.pcm` | ✅ 对等 |
14+
| `import std.compat` | GCC 隐式覆盖 | `std.compat.cppm``pcm.cache/std.compat.pcm` | ✅ 对等 |
15+
| 多模块项目 (dyndep) | `-fdeps-format=p1689r5` | 同一 flag (去掉 `-fmodules`) | ✅ 对等 |
16+
| BMI 缓存 (跨项目) | `gcm.cache/*.gcm` | `pcm.cache/*.pcm` | ✅ 对等 |
17+
| 增量重编 || ✅ + restat | ✅ 对等 |
18+
| Fingerprint 隔离 || ✅ (独立 fingerprint) | ✅ 对等 |
19+
| E2E 测试覆盖 | 6+ 个 | 6 个 (36-41) | ✅ 对等 |
20+
21+
核心抽象层 `BmiTraits` (`model.cppm:46-56`) 是平权的关键。
22+
23+
## 二、跨平台差距分析
24+
25+
### 2.1 macOS (Apple Clang) — 难度:中等
26+
27+
**可复用**:BmiTraits、clang.cppm 检测 (已识别 `apple clang version`)、P1689 扫描、两步编译
28+
29+
**Blocker (6 个)**
30+
31+
| # | 问题 | 说明 |
32+
|---|---|---|
33+
| M1 | Apple Clang 版本差异 | Apple Clang 版本号与 upstream 不同 |
34+
| M2 | libc++ 模块源码路径 | macOS 的 libc++ 在 Xcode SDK 内 |
35+
| M3 | Sysroot 发现 | 需要 `xcrun --show-sdk-path` |
36+
| M4 | 链接器差异 | macOS 用 `ld64`/`ld_prime``-rpath` 语法不同 |
37+
| M5 | 运行时库 | macOS 自带 libc++,不需要额外 rpath |
38+
| M6 | xlings 包管理 | macOS 上包名/路径适配 |
39+
40+
### 2.2 Windows (MSVC) — 难度:高
41+
42+
**Blocker (10+ 个)**:全新编译器族 (`.ifc`)、编译命令语法 (`/std:c++latest`)、P1689 (`/scanDependencies`)、路径分隔符、Ninja shell 可移植性、VS 环境发现 (`vswhere`)、链接器差异等。
43+
44+
### 2.3 Windows (Clang-cl) — 难度:中高
45+
46+
相比 MSVC 稍简单,可作为 Windows 支持第一步。
47+
48+
## 三、架构设计
49+
50+
### 3.1 分层架构
51+
52+
```
53+
┌─────────────────────────────────────────────┐
54+
│ mcpp CLI / Build Pipeline │ ← 平台无关
55+
├─────────────────────────────────────────────┤
56+
│ BmiTraits + CompilerProfile │ ← 编译器抽象 (已有)
57+
├──────────┬──────────┬──────────┬────────────┤
58+
│ gcc.cppm │clang.cppm│ msvc.cppm│apple_clang │ ← 编译器实现
59+
├──────────┴──────────┴──────────┴────────────┤
60+
│ PlatformTraits (新增) │ ← 平台抽象
61+
├──────────┬──────────┬───────────────────────┤
62+
│ linux │ macos │ windows │ ← 平台实现
63+
├──────────┴──────────┴───────────────────────┤
64+
│ xlings / Registry │ ← 包管理
65+
└─────────────────────────────────────────────┘
66+
```
67+
68+
### 3.2 建议新增 PlatformTraits
69+
70+
```cpp
71+
struct PlatformTraits {
72+
std::string_view os; // "linux" | "macos" | "windows"
73+
std::string_view exeExt; // "" | ".exe"
74+
std::string_view staticLibExt; // ".a" | ".lib"
75+
std::string_view sharedLibExt; // ".so" | ".dylib" | ".dll"
76+
std::string_view copyCmd; // "cp -p" | "copy"
77+
std::string_view cmpCmd; // "cmp -s" | "fc /b"
78+
std::string_view rmCmd; // "rm -f" | "del /f"
79+
};
80+
```
81+
82+
### 3.3 实施路线
83+
84+
```
85+
Phase 1 (已完成): Linux GCC + Linux Clang 平权
86+
87+
Phase 2: macOS Apple Clang (复用 clang.cppm, Unix-like)
88+
89+
Phase 3: Windows Clang-cl (新增 PlatformTraits, Ninja shell 可移植化)
90+
91+
Phase 4: Windows MSVC (新增 msvc.cppm, .ifc, vswhere)
92+
```
93+
94+
## 四、关键决策
95+
96+
1. **macOS**: 复用 `clang.cppm`,内部 `is_apple_clang()` 分支
97+
2. **Windows 首选**: 先 Clang-cl (复用 `.pcm`),后 MSVC
98+
3. **Ninja shell 可移植**: backup-compare-restore 抽取为 `mcpp internal bmi-guard` 子命令
99+
4. **xlings 跨平台**: `publisher.cppm` 已有三平台支持,包管理层基本就绪

0 commit comments

Comments
 (0)