AskCleanAskClean问净

如何安全清理 Swift Package Manager 缓存

AskClean 团队 · 更新于 2026-07-31

单个项目的构建产物先用 swift package clean;需要重置该包完整的构建缓存时用 reset;只有共享仓库缓存本身过大或损坏时,才用 swift package purge-cache。Package.swift 和 Package.resolved 定义了依赖,不属于应该随手删除的缓存。

Swift 包依赖图中,正在使用的包与重复缓存层被清晰分开
先清当前项目的构建产物,只有确认共享下载缓存有问题时才扩大范围。

SwiftPM 缓存不止一层

Swift Package Manager 会在不同范围保存不同类型的可再生数据。命令行包通常有一个 .build 目录,里面包括依赖检出、仓库数据、构建产物和工作区状态。SwiftPM 还维护共享仓库缓存,让多个项目不必反复从网络下载同一份依赖。

Xcode 又增加了一层。App 使用 Swift Package 时,包的检出与构建产物通常跟随项目的 DerivedData。因此,同一个依赖如果只在 Xcode 内出问题,处理方法可能与直接运行 swift build 不同。

最安全的原则是:只清理足以解释当前问题的最小范围。一次构建失败,不等于要抹掉全局缓存。项目级清理恢复更快,更可能在离线状态下完成,也不会拖慢其他仓库。

三个 SwiftPM 命令,作用范围完全不同

SwiftPM 官方文档把三个命令的职责分得很清楚。swift package clean 删除当前包的构建产物。遇到旧编译结果、莫名其妙的链接问题,或只想回收某一个仓库的空间时,应先用它。

swift package reset 会重置当前包完整的缓存与构建目录。它比 clean 更彻底,可能让该包的依赖和工作区状态重新准备。只有 clean 没解决本地包工作区损坏或不一致时,才需要升级到 reset。

swift package purge-cache 清理的是 SwiftPM 全局共享的仓库缓存。之后多个项目都可能重新联网获取依赖,首次解析与构建也会变慢。它适合处理确实异常膨胀或损坏的共享缓存,不适合变成每次构建前的固定仪式。

  1. 先提交或暂存源代码改动,确认 Package.swift 和 Package.resolved 仍在项目应有的位置。
  2. 进入包根目录,运行 swift package clean,再重试原来的构建。
  3. 如果包级工作区仍然不一致,运行 swift package reset,然后重新解析和构建。
  4. 只有确认共享仓库缓存过大或损坏时,才运行 swift package purge-cache。
  5. 在清理 Xcode DerivedData 前,先核对依赖图和命令行构建是否已经恢复。

命令是否可用取决于当前安装的 Swift 工具链。先运行 swift package --help,确认这台 Mac 支持哪些子命令。

不要把 Package.resolved 当缓存删

Package.resolved 记录的是依赖解析结果,不是下载缓存。对 App 项目来说,把它纳入版本控制,可以让团队成员和 CI 使用一致的依赖版本。删除后,下一次解析可能选中 Package.swift 允许范围内的其他版本。

当你明确想重新解析全部依赖时,删除它可以是一项有意识的排查动作,但这已经改变了实验变量。如果目标只是腾空间或重建产物,就应该保留 Package.resolved,避免一次清缓存悄悄变成依赖升级。

Package.swift 更是源代码,任何缓存清理都不应该删除或随意修改它。同理,Sources、Tests、插件和本地路径依赖也是项目内容。生成的 .build 可以再生,作者写下的文件却未必能够恢复。

清理 Xcode 项目使用的 Swift Package

如果依赖由 Xcode 项目使用,可以先尝试 File > Packages > Reset Package Caches;随后用 File > Packages > Resolve Package Versions,按项目与解析文件重新恢复依赖图。不同 Xcode 版本的菜单名称可能略有差异。

如果问题出在该项目编译后的包产物,删除对应项目的 DerivedData 即可。可以通过 Xcode Settings > Locations 打开位置,再在访达中只处理那一个项目文件夹。下次构建会重新编译 App 和包,并重建索引。

只有一个项目受影响时,不要顺手清空整个 DerivedData 根目录。保留每天活跃项目的热缓存,可以少付很多编译时间。如果 Mac 上装有多套 Xcode,重新解析前先启动真正要使用的版本,让正确的工具链和平台支持参与构建。

先诊断,再清缓存

为了磁盘空间,应该先测量各仓库的 .build 与共享缓存,而不是凭感觉。搜索废弃项目里的 .build,经常比抹掉仍在为活跃项目加速的全局缓存更划算。

为了构建故障,则要先保存原始错误。认证失败、Git 服务不可用、Package manifest 无效、工具链不兼容、校验和变化,都不会因为删掉下载文件而自动修好。过早清缓存还可能抹掉线索,并额外引入一次网络失败。

清理后,用 swift package show-dependencies 或 Xcode 的包依赖图核对解析结果,并运行真正相关的测试。依赖能成功下载,不代表它就与当前工具链、平台或部署目标兼容。

开发机与 CI 应采用不同策略

开发机适合选择性清理:仓库长期不再使用时删掉本地构建产物,只要全局仓库缓存仍在节省下载时间就不必动它。CI 则不同,临时 Runner 可以每次从干净环境开始;长期 Runner 需要明确的体积预算,缓存键还应包含 Swift 工具链与依赖解析状态。

不要在每次构建前运行 purge-cache。那会放弃复用、增加网络依赖,并让限流或上游故障更难受。只有测量显示异常增长、确认缓存完整性有问题,或长期 CI 节点到了受控维护窗口时,才值得清理全局缓存。

故障记录里也要写清范围。「清过 SwiftPM 缓存」含糊不清;「在仓库 A 运行 swift package clean」和「清空全局仓库缓存」的影响面与恢复成本完全不同。

用 AskClean 找到周边的开发者存储

AskClean 可以盘点 SwiftPM 周围的大型开发者存储,包括各项目 Xcode DerivedData、仓库构建产物、npm 等已声明的包缓存、模拟器数据和无法归类的大文件夹,并说明每项是否可重建。

SwiftPM 自身仍应以官方 Swift 命令定义的作用范围为准。AskClean 适合告诉你真正占空间的是哪一类,而不是把精确的包管理操作变成一次解释不清的批量删除。

SwiftPM 命令作用范围

按问题范围与恢复成本选命令,不要默认选择最激进的那个。

操作作用范围预期后果
swift package clean当前包的构建产物下次构建时重新编译。
swift package reset当前包的缓存与构建目录包级本地状态需要重新准备。
swift package purge-cache全局 SwiftPM 仓库缓存多个项目之后可能需要联网重新获取依赖。
删除 Package.resolved依赖解析状态下次可能解析出其他允许版本;这不是普通缓存清理。

常见问题

swift package clean 会删除什么?

它删除当前包的构建产物,不会删除 Package.swift,也不会主动升级依赖要求。下一次构建会重新生成这些内容。

reset 和 purge-cache 有什么区别?

reset 针对当前包的完整缓存和构建目录;purge-cache 针对 SwiftPM 全局共享的仓库缓存。后者会影响多个项目之后的依赖获取。

应该删除 Package.resolved 吗?

普通清理不应该删。它记录已经解析的依赖版本,删除后下次可能选中其他允许版本。只有明确需要重新解析依赖时,才把它作为有意识的操作。

为什么运行 clean 后,Swift Package 还是占很多空间?

剩余内容可能是依赖检出、全局仓库缓存,或者属于 Xcode DerivedData,而不是命令行包的构建产物。先测量每一层,再决定用 reset、purge-cache 还是清理特定项目 DerivedData。

参考来源

继续清理开发者缓存