截至 2026 年 9 月 14 日,macOS 27 已正式发布;Apple 将它定义为通用 Rosetta 支持的最后一个 macOS 大版本。症状是:主应用已经显示 Universal,但 CI 中的代码生成器仍以 x86_64 运行。最快解法是:不要等待后续支持完全退出,立即在隔离的 Apple Silicon 节点上盘点依赖,完成原生 arm64 构建、测试、签名和重启复测;仍需交付 Intel 版本时,再单独保留兼容流水线。(apple.com)
谁该看这篇:
如果你维护含原生库、插件或命令行工具的 macOS 应用,需要确认完整进程依赖链是否支持 arm64,这份清单适合你。
如果你负责远程 Mac CI、发布签名或多架构交付,也可以用它判断当前节点应当通过、限期整改,还是阻断上线。
最后更新于 2026 年 9 月 20 日,结论核实自 Apple Developer News、macOS 27 发布记录、Rosetta 文档、macOS Release Notes 与 Xcode Build Settings Reference。
先划清验收边界
macOS 27 仍处于 Intel 应用迁移窗口内。Apple 的支持文档说明,Apple Silicon Mac 在 macOS 27 或更早版本仍可运行依赖 Rosetta 的 Intel 应用;但 Apple Developer News 已明确提示,macOS 27 是面向普通 Intel 应用的最终支持阶段,后续 macOS 大版本不再为普通应用提供同等的转译路径。(support.apple.com)
因此,你不能把“当前构建能通过”当作迁移完成。验收对象至少包括:
- 主应用与 App Extension;
- Framework、动态库、静态库和 XCFramework;
- 插件、加载器、SDK 和闭源辅助程序;
- Shell、代码生成器、包管理器和自定义 Build Phase;
- Runner 服务、缓存、签名、公证和发布脚本;
- 重启后仍能恢复的后台任务与构建服务。
| 状态 | 代表含义 | 对生产主线的判断 | 对 Intel 兼容线的判断 |
|---|---|---|---|
纯 arm64 | 只能在 Apple Silicon 上原生执行 | ✅ 可作为原生主线候选 | ❌ 无法直接服务 Intel Mac |
纯 x86_64 | 依赖 Intel 架构或转译环境 | ❌ 不应继续作为默认工具链 | ✅ 可放入隔离兼容任务 |
| Universal Binary | 同时包含多个架构切片 | ✅ 需继续检查实际启动路径 | ✅ 通常可覆盖两类硬件 |
| 主程序 Universal、依赖混杂 | 外层入口支持多架构,内部组件仍可能是 Intel-only | ⚠️ 必须逐项验证 | ⚠️ 不能仅凭 Finder 信息判定 |
ARCHS 设置决定目标构建哪些架构;当指定多个架构时,才会生成 Universal Binary。也就是说,Universal Binary 只说明某个目标包含多个切片,不等于整个应用依赖链都已经原生化。([developer.apple.com](https://developer.apple.com/documentation/xcode/build-settings-reference?changes=_1&utm_source=openai))
盘点二进制与隐藏依赖
查找项目中的 x86_64 文件
先在全新克隆的工作目录中建立资产清单,不要直接依赖开发者电脑上已经安装的工具。对应用、Framework、插件、命令行工具和构建产物逐项执行:
file /path/to/binary
lipo -info /path/to/binary
file 用于初步识别 Mach-O 文件的架构,lipo -info 用于确认实际包含哪些切片。重点不是找出一个 Intel 文件,而是记录它由谁调用、在什么阶段调用,以及是否会进入最终用户环境。
建议清单至少包含以下字段:
组件名称
文件路径
来源仓库或供应方
调用阶段
实际架构
是否可从源码重建
替换责任人
阻塞级别
退出条件
不要只扫描 .app 主目录。以下路径经常藏有迁移遗漏:
.app/Contents/Frameworks/
.app/Contents/PlugIns/
.app/Contents/XPCServices/
.app/Contents/Helpers/
~/Library/Application Support/
自定义工具链目录
Runner 工作目录
Apple 也特别提醒,Intel 插件和加载器可能不会完整出现在系统兼容性列表中,常见位置包括音频插件、打印组件、Quick Look、Spotlight 扩展和其他系统级插件目录。(developer.apple.com)
每个依赖只能归入以下 4 类之一:
- 可升级:供应方已有
arm64或 Universal 版本; - 可重建:源码可用,能够在 Apple Silicon 节点重新编译;
- 可替换:现有组件不可迁移,但业务存在替代实现;
- 暂时阻断:只能运行
x86_64,且没有明确修复路径。
Universal Binary 不是免检通行证
Universal Binary 解决的是文件中是否存在多个架构切片,不会自动解决以下问题:
- 应用启动后加载的插件仍是纯
x86_64; - 子进程由脚本硬编码到 Intel 路径;
- 动态库搜索路径指向旧目录;
- JIT、底层指令集或汇编代码只适用于 Intel;
- 构建工具本身通过 Rosetta 启动;
- 签名或公证阶段调用了 Intel-only 辅助工具。
arm64 指令;如果程序只有 x86_64,系统才会转入翻译路径。对于同时包含 arm64 与 x86_64 的程序,用户还可能手动选择以 Rosetta 启动,以兼容旧插件。([developer.apple.com](https://developer.apple.com/documentation/apple-silicon/about-the-rosetta-translation-environment?changes=_7&utm_source=openai))
所以,验收记录不能只写“应用类型:Universal”。你还需要记录启动时的实际架构、子进程架构、插件加载结果和测试产物位置。
检查 CI 工具链的实际执行架构
本地终端通过,并不代表远程 Runner 通过。最常见的误判是:开发者账户的 PATH 指向新版原生工具,而 CI 服务账户仍调用旧版 Intel 工具;或者交互式 SSH 会话加载了新的 Shell 配置,后台服务却继续使用历史环境变量。
在交互式终端、SSH 会话和 CI 任务中分别采集:
uname -m
arch
which xcodebuild
which swift
which ruby
which python3
which node
ps -axo pid,comm
然后检查以下对象:
- 编译器包装脚本是否写死
arch -x86_64; - Homebrew 或其他包管理器路径是否混用了 Intel 目录;
- Ruby、Python、Node.js 的插件或原生扩展是否只提供
x86_64; - 自定义 Build Phase 是否调用预编译代码生成器;
- Shell 脚本是否根据
uname拼接了旧路径; - Runner 启动服务是否使用与人工 SSH 不同的用户和环境。
对于远程 Mac CI,建议把原生节点作为独立标签,例如:
macos-27-arm64-native
同时保留一个职责单一的兼容标签:
macos-intel-compat
兼容标签只处理仍需交付 Intel 产物或复现旧环境的任务,不能继续承载所有生产构建。
清空缓存后复测构建链
缓存是迁移验收中最容易制造假象的环节。旧缓存可能包含 Intel 编译产物、旧版 SwiftPM 二进制、错误架构的派生数据,导致本应失败的节点继续通过;反过来,清缓存后才暴露真正的架构缺口。
你至少要执行一次以下流程:
- 新建或清空可再生构建缓存;
- 使用全新 Git 克隆,不复用旧工作目录;
- 删除 DerivedData、包管理器缓存和自定义下载目录;
- 在独立 Apple Silicon 节点重新安装依赖;
- 运行完整构建、单元测试和集成测试;
- 检查每个关键产物的
file与lipo -info输出; - 保存构建日志、依赖版本和节点架构信息。
macOS 主版本
Xcode 版本
目标架构
依赖锁定文件
工具链版本
如果同一提交在旧节点成功、清缓存后的原生节点失败,优先判定为迁移未完成,而不是把失败归因于“新节点不稳定”。
分离原生测试与转译测试
Intel 应用在 macOS 27 上的兼容边界
在 macOS 27 的迁移窗口内,Apple Silicon Mac 仍可以通过 Rosetta 运行需要转译的 Intel 应用;但这条路径只能作为兼容性或回退验证,不能替代原生 arm64 验收。Apple 也要求开发者重新评估过去依赖 Rosetta 的兼容性问题,并关注升级后 Rosetta 是否仍按预期存在。(support.apple.com)
测试应拆成两组:
原生主线:
- 以
arm64启动主应用; - 执行单元测试与集成测试;
- 加载所有关键插件与扩展;
- 执行代码生成、资源处理和打包;
- 完成签名、公证和发布前校验;
- 重启节点后重新执行关键任务。
- 使用明确的
x86_64或 Universal 目标; - 验证 Intel Mac 用户所需功能;
- 验证旧插件、旧 SDK 或闭源工具;
- 记录哪些任务仍必须保留;
- 设定负责人和停用条件。
验证签名、发布与重启恢复
迁移成功但发布失败,通常不是编译问题,而是签名链仍依赖旧环境。你需要在独立节点核对:
- 签名身份是否由正确的 CI 用户访问;
- Keychain 是否在非交互式会话中可用;
codesign检查的是否为最终导出产物;- 公证上传工具是否由原生工具链执行;
- 安装包脚本是否默认使用
arm64; - 发布后启动的 Helper、XPC 服务和插件是否包含正确切片。
hostArchitecture 的安装包可能默认使用 arm64,因此安装前后脚本和旧版安装插件都需要重新审计。([developer.apple.com](https://developer.apple.com/documentation/macos-release-notes/macos-27-release-notes?changes=latest_minor&utm_source=openai))
重启复测不能省略。远程节点上的 GUI 登录、Keychain 解锁、Runner 服务、定时任务和后台代理,可能只在人工登录后正常。至少记录:
重启前构建结果
重启后 Runner 状态
SSH 是否可用
签名身份是否可访问
首次构建是否重新下载依赖
后台任务是否自动恢复
最终产物架构与签名状态
用清单给出上线结论
下面的清单适合在发布评审中逐项勾选。没有证据入口的项目,不应直接标记为通过。
- [ ] 已在独立 Apple Silicon 节点建立全新工作目录;
- [ ] 已扫描主应用、Framework、插件、XPC、Helper 和命令行工具;
- [ ] 每个
x86_64文件都有来源、调用位置和责任人; - [ ] 已区分纯
arm64、纯x86_64与 Universal Binary; - [ ] 已检查代码生成器、包管理器和自定义 Build Phase;
- [ ] SSH、CI 服务账户和交互式终端使用同一套预期工具链;
- [ ] 已清空 DerivedData、依赖缓存和可再生构建缓存;
- [ ] 全新克隆后能够完成原生
arm64构建; - [ ] 单元测试、集成测试和关键业务任务均以原生路径执行;
- [ ] 已单独验证 Intel 兼容线,不再用转译路径冒充原生通过;
- [ ] 签名、公证、安装包脚本和发布工具完成原生复测;
- [ ] 重启节点后 Runner、Keychain 和定时任务能够恢复;
- [ ] 已保存构建日志、架构输出、测试产物和签名证据;
- [ ] 已定义 Rosetta 路径的停用日期或触发条件;
- [ ] 仍需支持 Intel 用户时,已将兼容任务与生产主线隔离。
- 通过:原生主线完成构建、测试、签名和重启复测,阻塞项为 0;
- 限期整改:只剩可替换或已有明确修复责任人的依赖,兼容线暂时保留;
- 阻断上线:生产构建仍依赖 Rosetta、旧缓存、Intel-only 工具,或重启后无法恢复。
从 Rosetta 默认路径退出
你当前的 Intel Mac、旧虚拟机或长期保留的转译环境,最大问题不是今天不能构建,而是它们会持续掩盖 3 类风险:看不到纯 arm64 节点上的依赖缺口,无法确认 CI 服务账户是否调用原生工具,也很难验证重启后的签名和后台任务恢复。
因此,更稳妥的做法不是立即删除所有 Intel 兼容任务,而是先使用一台隔离的 Apple Silicon 远程 Mac,复制同一条流水线,完成原生构建、测试、签名和重启复测;通过后把它设为生产候选主线,同时让 Intel 兼容节点只承担明确的旧版本交付。这样使用 MACGPU 的远程 Mac,不是为了绕过迁移问题,而是为了在不购买新 Mac、也不影响现有发布节奏的情况下,获得一个可重复的原生验收环境。