Xcode 13.4.1在CI/CD并行构建时共享缓存异常问题求助
当CI/CD系统的同一Mac代理上并行运行多个Xcode 13.4.1构建进程时,会因共享DerivedData/ModuleCache.noindex目录引发缓存损坏或签名不匹配错误,典型报错如下:
❌ fatal error: malformed or corrupted AST file: 'could not find file '.../Pods/Firebase/CoreOnly/Sources/module.modulemap' referenced by AST file '~Library/Developer/Xcode/DerivedData/ModuleCache.noindex/2FKA2K2BK8GI0/ObjectiveC-1KD62J152BYGO.pcm''
❌ fatal error: module file '~/Library/Developer/Xcode/DerivedData/ModuleCache.noindex/2FKA2K2BK8GI0/Foundation-A3SOD99KJ0S9.pcm' is out of date and needs to be rebuilt: signature mismatch
解决方案
1. 隔离每个构建的DerivedData目录
Xcode默认使用全局共享的~/Library/Developer/Xcode/DerivedData目录,并行构建时会出现读写冲突。通过指定独立的DerivedData路径可彻底隔离缓存:
在xcodebuild命令中添加参数:
xcodebuild -derivedDataPath ./Build/DerivedData-$(uuidgen)
利用uuidgen生成唯一目录名,确保每个构建进程的缓存空间完全独立,从根源避免缓存冲突。
2. 添加缓存异常的重试机制
针对缓存损坏导致的构建失败,添加自动重试逻辑:
- 捕获Xcode构建的非零退出码,过滤出缓存相关的错误信息
- 检测到错误后,等待60秒(给系统资源释放时间),清理当前构建的DerivedData目录后重启构建
- 设置重试次数上限(建议2-3次),避免无限循环
示例脚本片段:
MAX_RETRIES=3 RETRY_DELAY=60 for attempt in $(seq 1 $MAX_RETRIES); do DERIVED_DATA="./Build/DerivedData-$(uuidgen)" BUILD_OUTPUT=$(xcodebuild -derivedDataPath "$DERIVED_DATA" <其他构建参数> 2>&1) EXIT_CODE=$? if [ $EXIT_CODE -eq 0 ]; then echo "构建成功" exit 0 elif echo "$BUILD_OUTPUT" | grep -qE "malformed or corrupted AST file|signature mismatch"; then echo "缓存错误,等待$RETRY_DELAY秒后重试(第$attempt次)" sleep $RETRY_DELAY rm -rf "$DERIVED_DATA" else echo "非缓存类构建失败,退出" echo "$BUILD_OUTPUT" exit $EXIT_CODE fi done echo "已达最大重试次数,构建失败" exit $EXIT_CODE
3. 优化代理并行构建策略
根据代理的CPU、内存资源,限制同一Mac代理上同时运行的Xcode构建数量;或通过CI系统的队列调度机制,避免多个构建进程同时抢占缓存资源。
内容的提问来源于stack exchange,提问作者Mike Rosario

