What changed
The Copy Module Map script phase that ModuleMapMapper appends to framework targets now copies with cp -f instead of plain cp.
Why / root cause
With Xcode compilation caching enabled (COMPILATION_CACHE_ENABLE_CACHING=YES), build outputs are materialized from the CAS as read-only files. Plain cp refuses to overwrite a read-only destination, so the phase failed with:
cp: .../Build/Products/Debug-iphonesimulator/_AtomicsShims.framework/Modules/module.modulemap: Permission denied
Command PhaseScriptExecution failed with a nonzero exit code
Any generated project with SPM dependencies that carry custom module maps (Objective-C packages, swift-atomics’ shims, etc.) cannot build under xcode-cache today; the same build succeeds with caching disabled, which is what isolated this phase. cp -f removes the unwritable destination and recreates it, which is the intended semantics of this copy.
Impact
Unblocks Xcode compilation cache adoption for generated projects with module-map-carrying SPM dependencies. No behavior change for non-cached builds.
Validation
- Found and reproduced on a staging runner benchmarking the Mastodon fixture: build green with caching off, red with caching on, green again with the copy patched to
cp -f.
TuistGenerator builds via SwiftPM; swiftformat clean; the mapper unit test’s expected script updated to match.
🤖 Generated with Claude Code