How to Cache DerivedData in GitHub Actions
Pin DerivedData to a known path and cache it so Xcode can reuse module and object files instead of compiling everything from scratch.
Set -derivedDataPath to a stable directory and cache it with actions/cache. Key it on a hash of your sources or lockfiles so the cache invalidates when inputs change.
Steps
- Build with a fixed
-derivedDataPath DerivedData. - Cache that directory keyed on source/lockfile hashes plus the Xcode version.
- Accept that a partial hit still saves time via incremental compilation.
Workflow
.github/workflows/ci.yml
steps:
- uses: actions/checkout@v4
- uses: actions/cache@v4
with:
path: DerivedData
key: dd-${{ runner.os }}-${{ hashFiles('**/*.swift', 'Package.resolved') }}
restore-keys: dd-${{ runner.os }}-
- run: |
xcodebuild build \
-scheme MyApp \
-destination 'platform=iOS Simulator,name=iPhone 16,OS=latest' \
-derivedDataPath DerivedDataGotchas
- DerivedData is tied to the toolchain; include the Xcode version in the key or a version bump yields stale-module errors.
- A huge DerivedData cache can be slower to restore than to rebuild; cache only when builds are genuinely long. Latchkey managed runners add a faster shared cache and auto-retry transient failures.
Related guides
How to Cache Swift Package Manager in GitHub ActionsCache resolved Swift packages on a GitHub Actions macOS runner with actions/cache keyed on Package.resolved s…
How to Build a macOS App With xcodebuild in GitHub ActionsBuild a macOS app on a GitHub Actions runner with xcodebuild build, targeting the platform=macOS destination…