Electron 中使用 SwiftPM 构建跨平台 TRTC Native Addon

背景 Electron 的优势在于 UI 开发效率高,但在实现 RTC、视频前处理、美颜和虚拟背景等能力时,往往会触及 Web SDK 的边界。 TRTC 是腾讯云实时音视频 SDK,适合做采集、推流、拉流、前处理和视频渲染这条主链路。它和浏览器里的 Web SDK 不是一回事:Web SDK 更轻,TRTC Native SDK 则给了更完整的原生能力。 SwiftPM 是 Swift Package Manager,也就是 Swift 的包管理和构建工具。它不只是“装依赖”,还负责描述 target、平台条件、二进制产物和构建关系,所以很适合拿来组织 Swift、C、C++ 和 Objective-C++ 混合工程。 以 TRTC 为例,如果 Web SDK 不支持发送前的视频处理,主链路就无法只依靠 <video>、Canvas、WebGL 或 WebGPU,而需要接入 TRTC Native SDK。 本文整理了一套可落地的方案:用 SwiftPM 管理混合代码,构建 Node Addon;Electron 负责 UI 和布局,TRTC Native SDK 负责采集、前处理、编解码和视频渲染。 目标不是强行让所有平台共用完全相同的原生代码,而是统一 JS API 和包管理结构,并在平台适配层分别接入 macOS 与 Windows SDK。 为什么 addon 用 Swift 这篇方案里,addon 选择 Swift 不是为了绕开 C++,而是因为它刚好处在一个很合适的中间层:上面要接 Electron 和 Node-API,下面要接平台 SDK、窗口句柄和 TRTC。 ...

August 8, 2026

腾讯体育 Vibe Coding 实践:基于 Claude Code 的团队 AI 工作流框架落地

一、背景:团队在 AI 辅助开发中的痛点 随着 Claude Code / CodeBuddy 等 AI 编程助手的普及,腾讯体育团队在日常开发中逐渐积累了大量与 AI 协作的经验。但在推广过程中,我们发现了几个反复出现的问题: 1. 重复解释团队上下文 每位同学使用 AI 时,都需要反复告诉它:“我们的路由怎么跳转”、“我们的架构层级是什么”、“Commit 格式应该怎么写”。这些团队共有的知识,每次都要重新解释。 2. 有效方案无法沉淀复用 某位同学花了一下午和 Claude 反复沟通,终于摸索出某类问题的可靠解决方案。但下一位同学面对同样的问题时,却不得不从头再来——AI 不会记住上一位同学的探索成果。 3. 规范依赖自觉,缺乏确定性保障 可以把规范写进 Prompt,但 Agent 是否遵守取决于模型"自律"。关键的验证步骤(如编译检查、commit 格式)需要确定性的工具触发,而不是靠模型"记得做"。 4. 社区能力与企业场景之间存在鸿沟 Claude Code 社区(如 OMC/oh-my-claudecode)提供了优秀的多 Agent 编排、自动规划等能力,但它不了解我们团队的 tRPC/DDD 架构约定、日志规范、代码评审流程等企业特定知识。 二、核心思路:“AI 时代的业务组件” OSC(oh-sports-claudecode)的核心设计理念是: 一个同学与大模型反复沟通,最终沉淀出某类问题的解决方案(知识库 + Skill);下一个同学直接复用,无需再次摸索,AI 开箱即用地理解我们的业务上下文。 这与"业务组件"的思想完全一致——只是这里的"组件"不是 UI 组件或函数库,而是 AI 可消费的知识与工作流。 传统组件: 团队共享代码 → 减少重复实现 AI 业务组件:团队共享知识 → 减少重复沟通 基于这个思路,OSC 在 oh-my-claudecode (OMC) 开源框架之上,构建了一套适合腾讯体育团队的 AI 工作流体系。 三、架构设计:三层体系 OSC 采用 知识层 → Workflow 层 → 工具层 的三层架构,每一层职责清晰、可独立演进。 ...

June 4, 2026

编译优化

大型 iOS 工程的编译耗时往往是研发效能最突出的瓶颈之一。以抖音、今日头条、美团为代表的一线团队,工程代码量通常在数百万到千万行级,本地全量编译耗时 10 分钟以上、CI 上半小时起步已是常态。编译等待不仅直接压缩研发时间,还会打断心流、降低人均产出。 本系列文章从 iOS 编译系统的原理出发,结合社区最新实践(Xcode 16/17 Explicit Modules、rules_xcodeproj、seer-optimize、cocoapods-hmap-prebuilt、Rugby 等),系统性介绍编译优化的各类手段与背后的原理。 编译流程概述 理解iOS编译原理是编译优化的前提。一次典型的 iOS 编译流程可以划分为以下阶段: flowchart TD A[Parse Podfile / 生成工程] --> B[Pod Install / 依赖解析] B --> C[Xcode Build System 调度] C --> D[Dependency Scan / 模块依赖扫描] D --> E[Swift/Clang 前端编译] E --> F[生成 .o / .swiftmodule / .pcm] F --> G[链接 ld64 / ld-prime / lld] G --> H[签名 / 打包 / 资源处理] H --> I[产出 .app / .ipa] 阶段 主要工作 常见瓶颈 依赖管理 Pod Install、SPM 解析 Source 更新慢、Specification 解析重复、沙盒拷贝 工程生成 生成 Pods.xcodeproj、xcconfig、hmap Target 数量多、pbxproj 膨胀 构建调度 Build System 解析任务图、并行调度 依赖粒度过粗、并行度不足 模块扫描 Clang/Swift 依赖扫描 隐式模块重复编译 源码编译 Swift/Clang 前端、类型检查、SIL/IR 生成 类型推导爆炸、WMO 关闭、PCH 失效 链接 符号解析、LTO、dead-strip 链接参数过长、ThinLTO 串行 收尾 签名、资源拷贝、dSYM 串行脚本阻塞 优化思路全景 编译优化的核心思路只有三条:减少需要做的工作、让必须做的工作更快、让做过的工作可复用。所有社区实践都可以归入这三类。 ...

May 27, 2026

编译优化-二进制化实现原理

本文结合 cocoapods-bin(社区最成熟的二进制化插件)拆解"Pod 二进制化"背后的工程机制:集成时如何透明替换 spec、打包时如何还原 Xcode 产物、调试时如何跳回源码。文末给出"自研一套二进制系统"的落地 checklist。 想先了解二进制化的整体背景、坑点和适用场景,可以先看 编译优化-二进制化;想了解 pod install 阶段本身的优化(HMap、并发下载等)见 编译优化-CocoaPods优化。 总体架构 一套完整的 Pod 二进制化系统由三层组成: flowchart TB subgraph CI[打包 CI] A1[源码 podspec] --> A2[壳工程 pod install] A2 --> A3[xcodebuild 双 SDK 编译] A3 --> A4[lipo / create-xcframework] A4 --> A5[上传 OSS] A5 --> A6[生成 binary podspec] A6 --> A7[push 到二进制仓] end subgraph Dev[开发机 pod install] B1[Podfile 声明 plugin] --> B2[Resolver/LazySpecification Hook] B2 --> B3{二进制仓是否有该版本?} B3 -- 是 --> B4[替换为 binary spec] B3 -- 否 --> B5[回退源码 spec] B4 --> B6[pod download zip] B5 --> B6 B6 --> B7[Xcode 链接] end subgraph Debug[调试] C1[dwarfdump 读取DW_AT_comp_dir] --> C2[下载源码] C2 --> C3[软链到 DWARF 路径] C3 --> C4[LLDB 自动跳转源码] end A7 --> B3 A3 -.DWARF 路径信息.-> C1 关键设计点: ...

May 8, 2026

编译优化-编译缓存

“已经编译过的东西不再编译一遍”——这是编译优化的基础原理。Xcode 的增量编译、CocoaPods 的二进制缓存、Bazel 的 Action Cache 都是不同层次的编译缓存。本文聚焦 ccache、Clang/Swift module cache、远程缓存等通用方案的原理与 iOS 落地。 缓存分层 缓存按命中粒度可以分为三个层次: flowchart TD A[编译缓存] --> B[编译器内部缓存PCH/PCM/module cache] A --> C[Action 级缓存ccache/sccache] A --> D[产物级缓存framework/xcframework] B --> B1[进程内复用模块] C --> C1[按 .o 粒度缓存] D --> D1[按 Pod/module 缓存] 层次 粒度 代表 命中率 编译器内部 frontend 解析结果 Clang ModuleCache、Swift Module Cache 高(本地) Action 源文件 → 目标文件 ccache、sccache、Bazel 中(取决于参数稳定性) 产物 整个 Pod 或 module cocoapods-bin、Rugby 高(版本号稳定) Clang Module Cache 原理 Clang 的 @import / @_exported import 会把外部模块预编译成 .pcm,缓存到 ModuleCachePath: ...

May 8, 2026

编译优化-观测

“无法度量就无法优化”。在开始任何编译优化动作之前,必须先建立一套可重复、可对比的观测手段,否则改动的真实收益无从谈起。本文介绍 iOS 编译耗时观测的主要工具链和原理。 观测目标分层 不同层次的观测工具回答不同的问题: flowchart TD A[编译耗时观测] --> B[整体耗时] A --> C[阶段耗时] A --> D[任务级耗时] A --> E[函数/表达式级] B --> B1[xcodebuild 总耗时] C --> C1[Build Timing Summary] C --> C2[Pod Install 阶段计时] D --> D1[Build Timeline] D --> D2[XCLogParser] E --> E1[-debug-time-compilation] E --> E2[-warn-long-expression] 观测层次 典型问题 工具 整体 一次构建花了多久? time xcodebuild、MetricKit 阶段 哪个阶段最慢? -showBuildTimingSummary、Build Timing Summary 任务 哪个文件/目标最慢? Xcode Build Timeline、XCLogParser 函数级 哪个函数/表达式让前端卡住? -debug-time-function-bodies、-warn-long-expression-type-checking 整体耗时 xcodebuild 命令行计时 最简单也最稳定的方式是直接给 xcodebuild 加 time: ...

May 5, 2026

编译优化-Explicit Modules

Apple 从 Xcode 15 开始在 Swift 上引入 Explicit Modules,Xcode 16 在 C/C++/Objective-C 上全面铺开,Xcode 17 进一步默认启用并与细粒度依赖追踪结合。这是近五年 Apple 构建系统最重要的一次变革,直接影响到大部分项目的编译模型。 模块(Module)基础 为什么需要模块 C 家族语言的 #include 机制有两个致命问题: 文本替换:头文件是纯文本替换,每个源文件都要重新解析一遍所有包含的头文件 宏污染:先引入的头文件宏会影响后续头文件的行为,没有隔离 Clang 在 2012 年引入 Clang Modules,用一个预编译的二进制模块(.pcm)替代文本包含,同一 module 在一次构建里只解析一次。Swift 的 .swiftmodule 从设计之初就是模块化的。 flowchart LR A["源文件"] -->|"include 头文件"| B["Foundation.h 文本"]; B --> C["每次都重新解析"]; D["源文件"] -->|"@import Foundation"| E["Foundation.pcm 预编译"]; E --> F["一次解析,多次复用"]; 模块的组成 类型 载体 描述 Clang Module .pcm C/OC 模块的序列化 AST Swift Module .swiftmodule Swift 模块的接口 + SIL Swift Interface .swiftinterface 可被不同 Swift 版本解析的文本接口 Module Map module.modulemap 描述哪些头文件构成某个 module Implicit Modules 的问题 原理 在 Xcode 16 之前,Clang Modules 以 隐式 方式工作: ...

May 5, 2026

编译优化-链接优化

链接是 iOS 编译的最后一个阶段,也是大型工程里经常被忽略的瓶颈。Apple 在 WWDC22 的 “Link fast: Improve build and launch times” 演讲中公开:Xcode 14 新的 ld-prime 链接器比 ld64 快 2 倍。随着 Xcode 17、ThinLTO、Mergeable Libraries 等改进,链接优化已经成为编译加速的重要一环。 链接器的职责 链接器把多个 .o 合并成最终可执行文件或库: flowchart TD A[若干 .o] --> L[链接器] B[静态库 .a] --> L C[动态库 .dylib / framework] --> L L --> D[符号解析] D --> E[dead_strip] E --> F[ObjC runtime fix-up] F --> G[生成 LC_* 加载命令] G --> H[写入 Mach-O] 关键任务: 符号解析:所有 undefined symbol 必须在某个 .o / .a / .dylib 里找到 重定位:把符号引用的偏移写入正确位置 Dead Strip:去掉未被使用的代码/数据 ObjC 元数据修复:把分散的类、分类信息合并成 ObjC runtime 能识别的结构 生成 Mach-O:写 Load Commands、__LINKEDIT 等段 链接器对比 ld64(经典) ld64 是 Apple 长期使用的经典链接器,源代码在 apple-oss-distributions/ld64。单线程为主,在大工程上明显偏慢。 ...

May 2, 2026

编译优化-头文件与HMap

对以 Objective-C 为主或混编的 iOS 大型工程,头文件查找是一个被严重低估的编译开销点。美团的统计显示,400+ Pod 组件的工程会产生近 5 万个头文件,导致海量的 IO 操作和编译参数膨胀。Header Map(HMap)技术能把头文件查找从 O(n) 的目录扫描退化为 O(1) 的哈希查表。 头文件查找的代价 Clang 的查找流程 当 Clang 遇到 #import <AFNetworking/AFNetworking.h> 时: flowchart TD A[遇到 #import] --> B{是否系统头?} B -- 是 --> C[SYSTEM_HEADER_SEARCH_PATHS] B -- 否 --> D[USER_HEADER_SEARCH_PATHS] C --> E[按顺序遍历 HEADER_SEARCH_PATHS] D --> E E --> F{路径下有吗?} F -- 否 --> G[下一个路径] G --> E F -- 是 --> H[stat + open] H --> I[解析头文件] 每一次查找都要对所有 HEADER_SEARCH_PATHS 执行 stat(2) 系统调用,当路径数量达到数千时,光 stat 就是显著开销。 ...

May 2, 2026

编译优化-二进制化

二进制化是大型 iOS 工程编译加速的"银弹":把组件从源码编译改成预编译产物链接,在本地无需再跑 Swift/Clang 前端,直接链接已有的 .a / .framework / .xcframework。美团在 cocoapods-hmap-prebuilt 之外,还通过二进制化把整体编译速度提升 50%+。本文系统介绍二进制化的原理、实现方式与工具链。 为什么能加速 典型项目的编译时间分布(抖音量级): pie title 冷编译耗时占比 "业务代码编译" : 25 "第三方依赖编译" : 50 "链接" : 15 "其他" : 10 超过一半的时间都花在编译 “不会改” 的依赖上。把依赖预编译成二进制,本地只需要链接,这部分耗时直接归零。再配合远程缓存,第一次拉代码的同学也能命中他人产物。 二进制产物形态 静态库(.a) 最传统的形态: libSDWebImage.a SDWebImage/Headers/ ├── SDWebImage.h └── ... 特点: 最小体积,Mach-O 里没有 LC_SEGMENT_64 / LC_LOAD_DYLIB 负担 启动最快,无 dyld 成本 静态链接时整合到主可执行 不支持资源文件(需要单独管理 bundle) Framework(.framework) Apple 推荐的打包形态: SDWebImage.framework/ ├── SDWebImage # 二进制(静态或动态) ├── Headers/ # 公开头文件 ├── Modules/ # modulemap、swiftmodule │ ├── module.modulemap │ └── SDWebImage.swiftmodule/ │ ├── arm64-apple-ios.swiftmodule │ └── arm64-apple-ios.swiftinterface └── Info.plist 通过 Mach-O Type 设置决定内部是静态还是动态库: ...

May 2, 2026