Back to Blog
·1 min read

Debug 能过、Release 编不过:同一份代码,两种编译模式,看到的是两个…

Debug 能过、Release 编不过:同一份代码,两种编译模式,看到的是两个世界。 最近一次归档前的 Release 编译挂了 4 个错误,集中在 1 个文件里,而日常 Deb

Debug 能过、Release 编不过:同一份代码,两种编译模式,看到的是两个世界。

最近一次归档前的 Release 编译挂了 4 个错误,集中在 1 个文件里,而日常 Debug 构建一直是绿的。错误类型很典型:

1. 跨文件的 extension 访问 private 成员 2. 从 nonisolated 上下文里碰到 @MainActor / actor 隔离的东西 3. 某个文件靠"别的文件已经 import 了"才碰巧能用的符号 4. 放在 extension 文件里的符号,可见性比使用方以为的更窄

为什么一直没被发现:Debug 默认走增量编译,逐文件处理,依赖别处已经解析好的状态,宽松得多;Release 是整模块编译,所有文件放在一起重新做完整的名称解析和并发检查。日常开发只跑 Debug,"CI 全绿"就等于"Release 路径从没被编译过"。这些错误不是新写的,是早就潜伏着,只是一直没有人让编译器用严格模式看一遍。

修的顺序比修的内容更重要:

  • 先复现:用 Release 配置把错误完整列出来,不要凭 Debug 的印象改。
  • 再按因果顺序处理:先补每个文件自己的 import,再理顺访问级别(真需要跨文件就放宽到 internal,而不是靠碰巧),最后处理 actor 隔离标注。隔离问题经常是前两类的下游,顺序反了会反复冒出新错误。
  • 每改一轮都用 Release 重新编译验证,而不是回到 Debug 看一眼就算过。
  • 最后把"Release 编译一遍"放到归档之前的固定步骤里,别等到打包那一刻才第一次见它。

一分钟自测:现在对你的工程跑一次 xcodebuild -configuration Release build(不要 archive,只编译)。如果你这个月从没跑过它,先别相信"全绿"。

#build-log

Written by

Peter Zhang

Building local-first Mac & iOS productivity apps at Obelisk Club.