docs:依赖管理改为纯 SPM + Vendor,移除 CocoaPods(ADR-006)

调研发现 Qiniu SDK 已官方支持 SPM(https://github.com/qiniu/objc-sdk
v8.9.x),AMap 仍仅支持 CocoaPods 或手动 XCFramework;CocoaPods 1.15.2
不兼容 Xcode 26 的 PBXFileSystemSynchronizedRootGroup,需绕道 Bundler
才能升到 1.16+。综合性价比决定不引入 CocoaPods 工具链,所有闭源 SDK
(含 AMap)统一走 Vendor .xcframework 手动接入。

- Design §14.1 三层策略改写为两层(SPM + Vendor),新增 Vendor 接入
  标准流程 6 步法
- Design §14.2 AMap 接入方式从 CocoaPods 改为 Vendor,Qiniu 标注 SPM
  URL 与版本
- Plan §2.3 / §5 Phase 5.1 / §6.1 / §8 同步 AMap Vendor 化
- Plan 新增 ADR-006 完整决策记录
- CLAUDE.md 新增「依赖管理约定」节,禁止引入 CocoaPods
This commit is contained in:
joywayer
2026-06-21 21:46:19 +08:00
parent 2a3d985dd7
commit 17a8b96cf8
3 changed files with 74 additions and 21 deletions
+31 -13
View File
@@ -54,7 +54,7 @@
| H5 桥 | 自研 Swift 桥(实现 WebViewJavascriptBridge 的 JS 端协议作为契约边界)+ 弹层注入 `window.settings.*` polyfill |
| 网络 | **URLSession + async/await + Codable**,自研 HTTPClient,Endpoint 协议化 |
| 持久化 | UserDefaults + FileManager;**不引入 CoreData/SQLite** |
| 依赖管理 | **SPM 优先**,微信/QQ/声网/高德等无 SPM 的用 CocoaPods |
| 依赖管理 | **SPM + Vendor `.xcframework` 手动**(完全不引入 CocoaPods 工具链);开源 / 官方 SPM 走 SPM,闭源二进制无 SPM 的走 Vendor 手动 |
| 架构 | **Modular Clean Architecture** + **Coordinator 路由** |
| 监控 | **默认接入 Sentry**(崩溃 + 性能 + breadcrumb);提供编译开关 `SENTRY_ENABLED` 作为关闭逃生口 |
| 包名 / Target | 与现 `msext` 解耦,新名 `Daoqi`(支持企业签 / 超签 / TF 同包并存) |
@@ -2078,22 +2078,40 @@ done
## 14. 第三方 SDK 集成清单
### 14.1 依赖管理策略:SPM 优先 + CocoaPods 兜底 + Vendor 手动
### 14.1 依赖管理策略:SPM 优先 + Vendor `.xcframework` 手动
新项目采用**层混合策略**,按优先级从高到低:
新项目采用**层混合策略**,**完全不引入 CocoaPods 工具链**:
1. **首选 SPM** —— Apple 官方,Xcode 原生集成,无第三方工具依赖,无衍生工程文件污染,新人 clone 即用。适用于:Sentry、ZIPFoundation、Agora 4.x、七牛 v8+ 等**已发布官方 Swift Package** 的库
2. **CocoaPods 兜底** —— 用于"有 podspec 但暂无 SPM 包"的 SDK,主要是高德定位、部分 Agora 旧版兼容场景。Podfile 仅写必须的 Pod,不引入大规模 transitive 依赖
3. **Vendor 手动** —— `Vendor/` 目录直接放闭源 `.framework` / `.a`,xcconfig 配置 link flag。适用于:微信 OpenSDK、QQ OpenSDK、闲聊 SDK(暂不集成)、JAnalytics(暂不集成)、opencore-amr 等**官方不提供 SPM / Pod 的私有 framework**
1. **首选 SPM** —— Apple 官方,Xcode 原生集成,无第三方工具依赖,无衍生工程文件污染,新人 clone 即用。适用于:Sentry、ZIPFoundation、七牛 v8.9+ 等**已发布官方 Swift Package** 的库
2. **Vendor 手动** —— `Vendor/` 目录直接放闭源 `.xcframework` / `.framework` / `.a`,target Build Phase 加入 `Link Binary With Libraries` + `Embed Frameworks`(动态库需要)。适用于:微信 OpenSDK、QQ OpenSDK、AMap 高德定位、opencore-amr 等**官方不提供 Swift Package** 的二进制
#### 为什么不引入 CocoaPods
ADR-006 决策记录(见 `docs/Development-Plan.md` §9)详细背景。简短理由:
- **唯一会触发 Pods 的 SDK 是 AMap 高德定位**(其它 SDK 要么 SPM,要么本就是 Vendor 手动);为 1 个 SDK 引入完整 Ruby + Bundler + CocoaPods 工具链性价比低
- **Xcode 26 与 CocoaPods 的兼容性问题**:Xcode 26 默认 `PBXFileSystemSynchronizedRootGroup`,Homebrew 的 CocoaPods 1.15.2 自带 `xcodeproj` gem 1.24.0 不识别,需绕道 Bundler + Gemfile 锁定 1.16+
- **生态趋势**:Google 已宣布 2026 Q2 后停止 iOS SDK 的 CocoaPods 支持,Firebase / GoogleMaps 转 SPM
- **AMap 手动接入成本可控**:闭源 XCFramework 升级频率年度级,每次 30 分钟手动操作,对比 CocoaPods 工具链长期维护更低成本
#### 为什么不选纯 SPM
微信 / QQ / 闲聊 / JAnalytics 等闭源 SDK 官方至今(2026)未提供 Swift Package,强行纯 SPM 化需要自己包一层私有 Package,维护成本反而上升。
#### 为什么不选纯 CocoaPods
Sentry / ZIPFoundation 等纯 Swift 包走 Pods 需绕一道 podspec,失去 SPM 的"Xcode 原生 resolve、增量缓存、零 Ruby 依赖"优势;且 CI 上每次 `pod install` 都拉远端,慢且不稳定。
微信 / QQ / 闲聊 / JAnalytics / AMap 等闭源 SDK 官方至今(2026)未提供 Swift Package,强行纯 SPM 化需要自己包一层私有 Wrapper Package,维护成本反而上升。
#### 决策方法
新增第三方依赖时,**按 SPM → Pods → Vendor 顺序尝试**,前一项无法满足才退到下一项。任何团队成员改变接入方式(如把某 SDK 从 SPM 迁到 Pods)需要在 PR 描述里写明降级理由。
新增第三方依赖时,**按 SPM → Vendor 顺序尝试**,前一项无法满足才退到下一项。任何团队成员把已 SPM 化的 SDK 改成 Vendor,需在 PR 描述里写明理由。**禁止引入 CocoaPods**(违反 ADR-006)。
#### Vendor 接入标准流程
闭源 SDK Vendor 化按以下顺序操作,保持工程一致性:
1. SDK 二进制放 `Vendor/<SDKName>/<SDKName>.xcframework`(动态库)或 `Vendor/<SDKName>/lib<name>.a` + 头文件目录(静态库)
2. Xcode → Target → General → Frameworks, Libraries, and Embedded Content → `+` 加入,动态库选 "Embed & Sign",静态库选 "Do Not Embed"
3. 静态库 `Library Search Paths` / 头文件 `Header Search Paths` 写到 `$(PROJECT_DIR)/Vendor/<SDKName>` 相对路径,**不写绝对路径**
4. 新增 module bridging header(若是 Swift 调 OC SDK)
5. `Vendor/<SDKName>/README.md` 写明版本号 / 下载日期 / 官方更新页 URL
6. SDK 二进制入 git(配合 git-lfs 处理大文件;当前项目不强制 lfs,因为 SDK 体积可控)
### 14.2 SDK 详细清单
@@ -2103,8 +2121,8 @@ Sentry / ZIPFoundation 等纯 Swift 包走 Pods 需绕一道 podspec,失去 SPM
| QQShare | Vendor | latest | ✅ 启用,启动注册 |
| **Xianliao** | — | — | ⏸️ **暂不集成**(`ShareCenter.xianliao = NoopSharePlatform`,§8.2)。当 H5 调 `friendsShare...({sharetype:"3"})` 时,Noop 立即回 `sharesuccess`,业务流不中断。启用时把 Vendor `.framework` 放入 + 把 `NoopSharePlatform` 换为 `XianliaoShare` |
| **Agora RTC** | — | — | ⏸️ **暂不集成**(`VideoRoom = NoopVideoRoom`,§8.3)。子游戏视频房间 3 个 handler 当前 stub 实现。启用时按 §8.3 末尾的 4 步说明切换 |
| AMap Location | CocoaPods(官方暂无 SPM) | 2.9+ | ✅ 启用,启动注册 |
| Qiniu SDK | **SPM**(官方 v8+ 支持 Swift Package) | latest | ✅ 启用,录音上传时初始化 |
| AMap Location | Vendor `.xcframework`(官方暂无 SPM,ADR-006 决策不引 CocoaPods) | latest 2.x | ✅ 启用,启动注册;下载页 `https://lbs.amap.com/api/ios-location-sdk/download` |
| Qiniu SDK | **SPM** `https://github.com/qiniu/objc-sdk` | **8.9.x** | ✅ 启用,录音上传时初始化;import `QiniuSDK` |
| opencore-amr | 静态 `.a`(直接接入 — H5 端通过此库收发的 AMR 音频是契约边界) | 2014 版本 | ✅ 启用 |
| ZIPFoundation | **SPM** | latest | ✅ 启用 |
| Sentry-Cocoa | **SPM**(默认 ON,编译开关 `SENTRY_ENABLED` 提供逃生口) | latest | ✅ 启用,启动并发注册 |
@@ -2183,7 +2201,7 @@ Sentry / ZIPFoundation 等纯 Swift 包走 Pods 需绕一道 podspec,失去 SPM
- 本项目独立目录(`/Daoqi/`),不与 `/msext/` 共用任何文件
- `gamehall.zip` 直接复用现网产物,放进 `Resources/`
- `Vendor/` 下的 SDK 二进制可以直接从 `msext/Pods/` / `msext/Frameworks/` 拷贝
- `Vendor/` 下的 SDK 二进制可参照 msext 的 `Pods/` / `Frameworks/` 找到对应版本,但**不要走 CocoaPods 流程**(ADR-006);从官方下载页或 msext 仓库直接拷贝 `.xcframework` / `.framework` / `.a``Vendor/`
- 渠道配置脚本可与现 `msext` 共享同一 Jenkins job 参数表
- 灰度期间旧 msext 外壳保持线上不动(避免双线推送);新外壳全量切流稳定后再评估是否归档 msext target