快取原理與命中條件對照表
Derived Data 匯聚索引、模組快取、中間產物與建置資料庫;能否「增量命中」取決於輸入指紋是否一致:原始碼與資源雜湊、編譯旗標、SWIFT_VERSION、SDK、簽章設定與部分環境變數。CI 上常見未命中原因,是快取鍵只綁了分支名稱,卻漏了 Xcode.app 版本或 Command Line Tools 路徑。
| 輸入維度 | 命中影響 | 建議納入快取鍵/紀錄 |
|---|---|---|
| Xcode/CLT 版本 | 高 | xcodebuild -version 與 xcode-select -p 輸出 |
| Podfile.lock/Package.resolved | 高 | 鎖檔雜湊;多套件時分開 SPM 與 CocoaPods 目錄 |
| Build configuration | 中~高 | Debug/Release、自定 xcconfig 路徑 |
| Provisioning/entitlements | 中 | profile UUID 或檔案雜湊變更時預期失效 |
-derivedDataPath 變更 | 致命 | 固定絕對路徑;勿在 job 內隨機臨時目錄 |
# 建議在 CI 開頭記錄工具鏈指紋(寫入 artifact 便於對照未命中) xcodebuild -version xcode-select -p xcrun swift --version
遠端節點預熱與清理策略
共享遠端 Mac上,節點穩定性與磁碟碎片化的平衡點在「預熱足夠、但不囤積過期專案」。預熱目標是讓下一次 job 直接命中模組與 Swift 增量狀態;清理則在水位觸線時回收最舊的 Derived Data 子目錄或整包刪除指定前綴。
- 固定路徑:
DERIVED_DATA="$CI_WORKSPACE/.derivedData";SPM:-clonedSourcePackagesDirPath "$CI_WORKSPACE/.spm",兩者一併掛載快取卷。 - 預熱建置:在 main 合併後跑一次
xcodebuild build(與正式相同 scheme/configuration),或夜間 cron 針對熱門分支執行。 - 清理觸發:可用空間 < 20 GB(中大型專案建議 30 GB)→ 刪除超過 14 天未存取的 Derived Data 子目錄;仍不足再全清該 repo 前綴。
- 索引開銷:純編譯驗證可設
COMPILER_INDEX_STORE_ENABLE=NO降低 I/O(依團隊是否依賴索引產物決定)。
# xcodebuild 示例:固定 Derived Data 與 SPM 目錄(請替換 SCHEME / WORKSPACE) export COMPILER_INDEX_STORE_ENABLE=NO xcodebuild -workspace Your.xcworkspace -scheme YourScheme -configuration Release \ -derivedDataPath "$CI_WORKSPACE/.derivedData" \ -clonedSourcePackagesDirPath "$CI_WORKSPACE/.spm" \ build CODE_SIGNING_ALLOWED=NO # 磁碟抽檢(可用於 pre-hook) df -h "$CI_WORKSPACE" du -sh "$CI_WORKSPACE/.derivedData" 2>/dev/null || true
與 clean build 的參數取捨
「每次 CI 都 clean」能排除狀態污染,但會犧牲建置加速與快取投資報酬率。實務上可用決策矩陣:僅在必要維度觸發完整清理,其餘依賴固定 derivedDataPath 的增量路徑。
| 情境 | 建議動作 | 備註 |
|---|---|---|
| 日常 PR/feature 分支 | 不 clean | 保留模組快取;失敗再單次 clean 重跑 |
| Xcode 大版本升級當日 | xcodebuild clean 或刪除該專案 Derived Data | 避免混用舊索引 |
| 簽章、entitlements、Capabilities 變更 | clean 或刪除對應 Build 子目錄 | 降低「看似成功、實則過期產物」風險 |
| 快取損壞(連結器/module map 詭異錯誤) | 一次 clean + 重建 | 並檢查是否並行 job 寫入同一路徑 |
若多個 job 共用同一台機器,務必以專案+分支或 pipeline ID隔離 derivedDataPath,否則並行寫入會同時傷害CI/CD正確性與快取命中率。
失敗回退與磁碟水位閾值 FAQ
第一輪保留增量;若錯誤訊息符合「stale/module map/derived data」類關鍵字,第二輪自動加上 xcodebuild clean build 或刪除 $DERIVED_DATA/ModuleCache.noindex 後再建置。第三輪仍失敗應改人工介入,避免無限重試占滿節點。
除絕對閾值外,建議監控可用比例:若根卷或工作區卷 可用 < 15% 且絕對值低於上述 GB 門檻,優先清 Derived Data 與過期 .spm,再通知維運扩容或分流 job。
檢查是否混用 xcodebuild 與 Xcode GUI 不同使用者、或 sudo 造成所有者不一致;另確認沒有腳本每次產生不同 OTHER_SWIFT_FLAGS 時間戳。可對照本站 Submodule/LFS 與遠端 Mac CI 決策矩陣,排除拉取階段造成的偽增量。
總結與站內導覽
總結:2026 年在遠端 Mac跑 iOS CI,要把Xcode 編譯快取當成「指紋對齊的狀態機」——工具鏈、鎖檔、Derived Data 路徑與並行隔離缺一不可;用預熱換冷啟動時間,用磁碟水位閾值與失敗回退換節點穩定性;clean build 則留在升級、簽章與疑難排解場景。若你需要專用 Apple Silicon 作為長期快取載體,歡迎免登入瀏覽 查看方案定價、前往購買頁選擇套餐,或至 說明中心查閱連線與環境建議;亦可回到 技術部落格 延伸閱讀 Git/依賴加速主題。