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:
@@ -34,6 +34,17 @@ daoqi 仓库当前并存两条工作线:
|
||||
|
||||
---
|
||||
|
||||
## 依赖管理约定
|
||||
|
||||
新项目采用**纯 SPM + Vendor `.xcframework` 两层管理**,**禁止引入 CocoaPods**(详见 `docs/Development-Plan.md` ADR-006)。
|
||||
|
||||
- **首选 SPM**:开源 / 官方提供 Swift Package 的库(Sentry / ZIPFoundation / 七牛 `https://github.com/qiniu/objc-sdk` v8.9.x 等)
|
||||
- **Vendor `.xcframework` 手动**:所有闭源二进制(微信 / QQ / 高德 AMap / opencore-amr 等),按 Design §14.1「Vendor 接入标准流程」放 `Vendor/<SDKName>/` + Target → General → Frameworks 加入 + `Vendor/<SDKName>/README.md` 记录版本与来源
|
||||
- **禁止 CocoaPods**:项目内不放 `Podfile` / `Podfile.lock` / `Pods/` / `.xcworkspace`。工程入口固定为 `ylgamehall.xcodeproj`
|
||||
- **新增第三方依赖时**:按 SPM → Vendor 顺序尝试,PR 描述写明选型理由;若发现某 SDK 既无 SPM 又无 XCFramework,回到 ADR-006 决策框架重新评估
|
||||
|
||||
---
|
||||
|
||||
## Resources/ 目录约定
|
||||
|
||||
仓库根目录的 `Resources/` 是新外壳运行所需的**项目方提供资源**统一入库位置,由打包脚本在 Build Phase 引入,**不**直接放进 Xcode 工程内的 `ylgamehall/` 源码目录。
|
||||
|
||||
@@ -62,7 +62,7 @@ Contract Design Plan(本文档)
|
||||
| 微信 AppID(`wx586a9b321e56efb7`)+ Universal Links 配置 | 微信回调 | Phase 4 | 项目方 |
|
||||
| QQ OpenSDK `.framework` + AppID | QQ 分享 | Phase 4 | 项目方 |
|
||||
| 后台 `/wechat/login` 中转接口 | secret 不入 IPA 的前提 | Phase 4 | 后台团队 |
|
||||
| 高德地图 `APIKey` + SDK Pod | 定位 | Phase 5 | 已有 key `b0d4a8e3fcbbcc0dd96283b7df6a4494`,但需新建 Bundle ID 注册 |
|
||||
| 高德地图 `APIKey` + SDK XCFramework | 定位 | Phase 5 | 已有 key `b0d4a8e3fcbbcc0dd96283b7df6a4494`(但绑死 msext Bundle ID,需用新 Bundle ID 重新申请);SDK 走 Vendor 手动接入(ADR-006),下载页 https://lbs.amap.com/api/ios-location-sdk/download |
|
||||
| 七牛上传 token 颁发接口 | 录音上传 | Phase 3 | 后台团队 |
|
||||
| ~~极光 AppKey~~ | ~~用户统计~~ | **已决策暂不集成(ADR-005),未来启用时再协调** | — |
|
||||
| Sentry DSN | 崩溃监控 | Phase 9 | 项目方(需开通账号) |
|
||||
@@ -464,11 +464,11 @@ Contract Design Plan(本文档)
|
||||
|
||||
#### 前置
|
||||
- Phase 1 完成
|
||||
- ⏳ 高德 SDK(CocoaPods 接入,APIKey 已有但 Bundle ID 需重新注册)
|
||||
- ⏳ 高德 SDK XCFramework(Vendor 手动,ADR-006)+ 新 Bundle ID 重新申请 APIKey
|
||||
|
||||
#### 任务清单
|
||||
|
||||
- [ ] **5.1** 加 Podfile + 引入 `AMapLocation` 9.x
|
||||
- [ ] **5.1** 从 [高德官方下载页](https://lbs.amap.com/api/ios-location-sdk/download) 拉取最新 `AMapLocationKit.xcframework` + `AMapFoundationKit.xcframework`,放 `Vendor/AMap/`;Target → General → Embed Frameworks 加入;按 Design §14.1 Vendor 接入标准流程操作;`Vendor/AMap/README.md` 记录版本号 / 下载日期
|
||||
- [ ] **5.2** Info.plist 加 `NSLocationWhenInUseUsageDescription = "{gamehallname}需要访问您的位置以提供本地化服务"`
|
||||
- [ ] **5.3** `Source/SDK/AMap/AMapWrapper.swift`:启动期 `updatePrivacyShow` + `updatePrivacyAgree` + `apiKey` 设置
|
||||
- [ ] **5.4** `Source/Location/LocationService.swift`(actor)
|
||||
@@ -680,10 +680,10 @@ H5 调 `OpenurlTitleData` 打开弹层 WebView,弹层内 H5 用 `window.settin
|
||||
|
||||
| 集成方式 | SDK | 集成 Phase |
|
||||
|---------|-----|----------|
|
||||
| **SPM 优先** | ZIPFoundation / Sentry / 七牛 v8+ | Phase 1 / 9 / 3 |
|
||||
| **CocoaPods** | 高德 AMap | Phase 5 |
|
||||
| **Vendor `.framework`** | 微信 / QQ;闲聊 / Agora / **JAnalytics** 均暂不集成(Noop 占位) | Phase 4 |
|
||||
| **SPM 优先** | ZIPFoundation / Sentry / 七牛 v8.9.x(`https://github.com/qiniu/objc-sdk`) | Phase 1 / 9 / 3 |
|
||||
| **Vendor `.xcframework`** | 微信 / QQ / **高德 AMap**(ADR-006);闲聊 / Agora / JAnalytics 均暂不集成(Noop 占位) | Phase 4 / 5 |
|
||||
| **Vendor `.a`** | opencore-amr | Phase 3 |
|
||||
| ~~CocoaPods~~ | **不引入**(ADR-006,纯 SPM + Vendor 两层管理) | — |
|
||||
|
||||
每集成一个 SDK 立即提交一个独立 commit(CLAUDE.md "及时提交" 规则)。
|
||||
|
||||
@@ -792,7 +792,7 @@ H5 调 `OpenurlTitleData` 打开弹层 WebView,弹层内 H5 用 `window.settin
|
||||
- [ ] 4.12 远程图片分享
|
||||
|
||||
### Phase 5 定位
|
||||
- [ ] 5.1 AMap Pod
|
||||
- [ ] 5.1 AMap Vendor 接入(XCFramework)
|
||||
- [ ] 5.2 定位权限文案
|
||||
- [ ] 5.3 AMapWrapper 启动注册
|
||||
- [ ] 5.4 LocationService
|
||||
@@ -895,7 +895,31 @@ H5 调 `OpenurlTitleData` 打开弹层 WebView,弹层内 H5 用 `window.settin
|
||||
5. Info.plist 加 AppKey + 隐私授权文案
|
||||
- **复盘节点**:上线 3 个月后业务方根据数据需求决定是否启用
|
||||
|
||||
### ADR-006:纯 SPM + Vendor `.xcframework` 两层依赖管理,不引入 CocoaPods(2026-06-21)
|
||||
- **背景**:Design 原方案是"SPM 优先 + CocoaPods 兜底 + Vendor 手动"三层策略,CocoaPods 仅服务于高德 AMap 定位 SDK 一个依赖
|
||||
- **触发事件**:尝试 `pod init` 时,CocoaPods 1.15.2(Homebrew 上的最新版)自带的 `xcodeproj` gem 1.24.0 不识别 Xcode 26.5 默认的 `PBXFileSystemSynchronizedRootGroup`,pod init 直接抛 `unknown ISA` 异常
|
||||
- **调研结论**:
|
||||
- 七牛 SDK 已官方支持 SPM(`https://github.com/qiniu/objc-sdk`,v8.9.x),原计划的"七牛走 CocoaPods"完全无必要
|
||||
- 高德 AMap 定位 SDK 官方未提供 SPM(截至 2026-06),但提供 XCFramework 直接下载
|
||||
- CocoaPods 1.16+ 才支持新 ISA,但 Homebrew 未跟进;需绕道 Bundler + Gemfile / brew --HEAD / rbenv 自管 Ruby,均增加工具链复杂度
|
||||
- **决策**:依赖管理简化为**两层 — SPM 优先 + Vendor `.xcframework` 手动**,**完全不引入 CocoaPods**
|
||||
- SPM:ZIPFoundation / Sentry / Qiniu / WVJB JS(资源文件)
|
||||
- Vendor:微信 / QQ / **高德 AMap** / opencore-amr;闲聊 / Agora / JAnalytics 暂不集成(Noop 占位)
|
||||
- **理由**:
|
||||
- 项目实际只有高德 AMap 1 个 SDK 让 CocoaPods 必要;为 1 个依赖引入整套 Ruby + Bundler + CocoaPods + workspace 工具链 + Xcode 26 兼容性维护,性价比低
|
||||
- 闭源 SDK 本就是 Vendor 性质(微信 / QQ / 闲聊 / JAnalytics / opencore-amr),AMap 走同款流程不增加心智负担
|
||||
- 生态趋势:Google 已宣布 2026 Q2 后 iOS SDK 全部停止 CocoaPods 支持;CocoaPods 维护活跃度下降
|
||||
- 工程入口仍是 `.xcodeproj`(不需要 `.xcworkspace`),团队 / CI 配置不需要切换
|
||||
- **接入标准流程**(Vendor,写入 Design §14.1):
|
||||
1. 二进制放 `Vendor/<SDKName>/<SDKName>.xcframework`
|
||||
2. Target → General → Frameworks → `+`,动态库选 "Embed & Sign",静态库 "Do Not Embed"
|
||||
3. Library / Header Search Paths 用 `$(PROJECT_DIR)/Vendor/<SDKName>` 相对路径
|
||||
4. `Vendor/<SDKName>/README.md` 记录版本号 / 下载日期 / 官方更新页 URL
|
||||
5. 二进制入 git(项目规模可控,暂不强制 git-lfs)
|
||||
- **回滚条件**:未来某天出现 ≥ 3 个仅有 podspec 而无 SPM / XCFramework 的 SDK 必接需求时,重新评估是否引入 CocoaPods
|
||||
- **维护责任**:AMap 升级(年度级)→ 下载新 XCFramework 覆盖 `Vendor/AMap/` + 更新 README + 跑契约测试
|
||||
|
||||
---
|
||||
|
||||
文档完成日期:2026-06-21
|
||||
最后更新:2026-06-21(ADR-005 极光降级 + Resources/ 目录记录)
|
||||
最后更新:2026-06-21(ADR-006 纯 SPM + Vendor 策略 + ADR-005 极光降级 + Resources/ 目录记录)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user