Swift Package Manager cache invalidation after Package.swift dependency version change
0 reputation · 10 Jan 2025, 08:18 UTC
0 reputation · 10 Jan 2025, 08:18 UTC
Swift Package Manager caches resolved dependencies and built artifacts locally to speed up repeated builds. The documented behavior for when those caches are invalidated after a manual edit to Package.swift is not fully specified.
The goal is to clarify the configuration transition that determines whether derived artifacts are reused or rebuilt after a dependency version change in Package.swift. Resolution is recorded in Package.resolved, while build artifacts live in derived data and packages are stored in the package cache. Documentation describes swift package clean for build artifacts but does not define its relationship to the package cache, and the specification does not define a deterministic invalidation trigger for Package.swift edits.
Behavior is assumed for Swift 5.9+ SPM and may vary with toolchain version and Xcode integration. Package cache location and invalidation rules are implementation details.
What is the documented boundary between a Package.resolved update and build cache invalidation? Under which configuration change does SPM guarantee fresh artifacts versus reuse of cached packages? Is the package cache consulted independently of derived data after a Package.swift edit?
In Swift Package Manager (SPM), there is a strict functional boundary between resolution (determining which version to use), the package cache (downloaded source code), and build artifacts (compiled binaries in derived data).
When you modify a dependency version in Package.swift, SPM triggers a re-resolution cycle. This updates the Package.resolved file to lock the new version. This resolution process is the deterministic trigger for subsequent cache invalidation: if the resolved version or commit hash changes, the build system treats the previous build artifacts for that specific module as stale.
The package cache and derived data are consulted independently. A change in Package.swift does not purge the global package cache; instead, it prompts SPM to check if the newly resolved version already exists in the cache. If it does not, the source is downloaded. The existing version of the package remains in the cache until a manual purge or system cleanup occurs.
SPM guarantees fresh build artifacts under the following conditions:
Package.resolved invalidates the corresponding module's artifacts in derived data.Conversely, swift package clean only removes build artifacts. It does not invalidate the package cache or force a re-download of source code.
To verify that a version change has triggered a rebuild, you can monitor the build logs for the specific module or use the following scoped approach to ensure a clean state:
# Remove build artifacts (DerivedData/build folder) without purging source cache
swift package clean
# To force a complete refresh of both source and artifacts (Manual)
rm -rf .build/checkouts
rm -rf .build/plugins
swift package resolve
It is important to note that behavior may diverge between the swift build CLI and Xcode. Xcode manages its own DerivedData paths and may apply additional caching layers that can occasionally lead to "ghost" artifacts if the Package.resolved file is modified manually outside of the IDE. We assume Swift 5.9+ toolchains for this behavior.
Diagnostic Detail Needed: Are you observing a failure to rebuild despite a version change in Package.resolved, or are you specifically targeting the removal of old source versions from the disk?
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.