我日常用的是一台 16GB 的 MacBook Air。写 Swift 没问题,一点 ⌘B 全量编译,风扇立刻拉满,SourceKit 和编译器抢同一块磁盘,光标能卡半秒——这时候继续改代码基本不现实。换顶配笔电当然行,但我更需要的是:编译别占着我唯一这台机器。
试了一圈之后,能长期用下来的组合很简单:轻薄本只改代码、推 Git;租一台云端 Mac mini M4,专门跑 xcodebuild。不是把 Xcode 整桌面挂到 VNC 里(我试过,跨洋延迟下比本地还难受),而是让远端当一台始终开着的构建机。
先确认:你卡的是编译,不是索引
Activity Monitor 里如果 swift-frontend、ld 或 XCBBuildService 顶满 CPU,就是构建在吃机器;如果是 SourceKitService 常驻高 CPU,换远程构建帮助有限,得先查 Derived Data 是否膨胀、是否误把 build/ 提交进仓库。我有一次以为要上大内存,清掉 40GB 的陈旧 Derived Data 之后本地增量编译就回来了——远程构建解决的是「重活别在笔电上跑」,不是万能药。
Clean Build 后半段变慢,还常见热节流:前三分钟还行,后面芯片降频,你会以为项目「又变大了」。把这类任务挪到机房的 M4,至少风扇和热量不跟你抢桌子。
我怎么分工
- 本地: 改源码、
git commit、看 MR diff、偶尔单文件 Preview。不在本地跑全量⌘U。 - 云端 M4:
xcodebuild build、test、archive、exportArchive。证书和 match 也只在这台机的钥匙串里。 - 真机调试: 设备在身边就插本机;否则在构建机上跑,我很少为了日常调试开 VNC。
Xcode 没有官方的「远程编译」按钮。能接受这一点,后面就好办。
落地:从一台云 Mac 到能编过
1. 版本对齐。 本地和远端各跑一遍 xcodebuild -version,大版本必须一致。我吃过一次云端还是 Xcode 15、本地 16 的亏,Swift 语法直接编不过。
2. 仓库只走 Git。 构建机上 git clone 同一 remote;子模块用 deploy key。别 rsync 整个工程目录——容易把 .git 状态搞乱。
3. Derived Data 固定在远端,别往回同步。 我设成 /Users/builder/Cache/DerivedData,构建脚本里带 -derivedDataPath。千万别把笔记本上的 Derived Data rsync 上去,体积大、路径还带机器特征,索引会锁死。Apple 文档里也提到构建阶段会大量写中间产物(见 Building your app);缓存留在构建机才是正路。
4. 一条命令触发远端编译。 我在项目根放了 Makefile,日常就敲这个:
REMOTE := builder@your-m4.host REPO := MyApp SCHEME := MyApp build-remote: git push origin HEAD ssh $(REMOTE) 'cd ~/workspace/$(REPO) && \ git pull --ff-only && \ xcodebuild -scheme $(SCHEME) -configuration Debug \ -derivedDataPath ~/Cache/DerivedData build'
失败时日志在 SSH 终端里,本地改完再 push、再 make build-remote。命令行参数不熟可以对照 TN2339。
5. 测一次是否真的省事。 同一个 commit:本地 Air 全量编一遍记时间,远端编一遍。我那次远端快了大概 2.5 倍,之后本地默认不再 Clean Build。
VNC 我只在这些时候开
导入 p12、在钥匙串里点允许、Archive 向导里某个只有 GUI 的勾选项——开 VNC 处理完就关。别在 VNC 里写一天 Swift,那等于花云主机钱买卡顿。跨洋链路更明显:SSH 跑构建完全够用,屏幕共享只是偶尔的工具。
三个人以上:同一台 M4 兼 CI
个人用 SSH 够了。团队可以把这台机注册成 GitHub self-hosted runner(官方说明),白天你手动 SSH 编,夜间 push 走同一套 Derived Data 缓存。我们后来把 Release 和 match 也固定在这台上,避免托管 macOS runner 每次冷启动。具体怎么拆 signing job,可以参考这篇 自建 runner 笔记。
我踩过的坑
- 同步了 Derived Data。 rsync 跑了一晚上,第二天两端索引都异常。只同步 Git 里的东西。
- 忘了提交
Package.resolved。 远端 resolve 出另一版依赖,本地能过、远端挂。 - 在 VNC 里日常开发。 延迟 + 压缩画质,改 UI 比本地更痛苦。Preview 仍放本机小范围用,整屏验收用真机或构建机截图。
- 构建机磁盘 512GB 塞满 SPM + 多分支。
df -h常年黄区时该升盘或清 Archives,别硬扛。磁盘水位我们另写过一篇 长周期占用。
机器怎么选(只谈编译)
我现在的构建机是 M4、24GB、512GB:24GB 是为了 xcodebuild test 时别 swap;512GB 单仓够用。monorepo 或多个 Xcode 版本并存再考虑 1TB。要上 App Store Connect API、企业代理白名单,我会要固定出口 IP,不然今天能上传明天被拒,排查很耗时间(一机一 IP 那篇讲的就是这个)。
没上云之前我也考虑过别的
买 14 寸 MBP: 编译快,但编译时你还是不能流畅写代码,且没法挂着跑夜间全量测试。Xcode Cloud: PR 检查很省心;我们自己的 match、Fastlane 和固定钥匙串仍要自建机,Cloud 和云 Mac 可以并存。黑苹果 VM: 发版风险我不愿意扛。
如果你只有 Windows 笔电,思路一样:Windows 写代码,云 Mac 跑一切 xcodebuild,可以看 Windows + 云 Mac 那篇。亚太编辑、北美节点编的话,Release 和公证还有额外坑,见 公证/Release 流水线。
还会被问到的几句
能在本地 Xcode 点 Run、编译在远端吗? 不能,除非你愿意整台 Xcode 在 VNC 里。我习惯远端 build-for-testing,本地只看 .xcresult 或日志。
SSH 跨太平洋延迟要紧吗? 不要紧。编译在远端跑,你只等日志流;我这边 RTT 200ms 左右,可接受。要紧的是别用 VNC 写代码。
安全: 分发证书别进个人笔电钥匙串;构建机 SSH 只开密钥;runner 别接不可信 fork 的 PR workflow。