アーカイブ作成や自動テストを長期間担うクラウドMacでは、障害の原因がコードにあるとは限りません。XcodeはDerivedData、アーカイブ、デバイスサポートファイル、シミュレータデータを継続的に書き込みます。ディスク容量が限界に近づくと、コンパイラが本質とは関係のない書き込みエラーを返したり、署名処理で不完全な成果物しか残らなかったりすることがあります。確実な対策は、定期的にすべてのディレクトリを空にすることではありません。まず使用量を数値化し、ビルドの容量ゲートを設けたうえで、復元しやすいデータから段階的に整理します。
まずディスク使用量の基準値を把握する
最初にシステムの空き容量を記録し、続いて開発関連ディレクトリを確認します。dfはファイルシステムにあとどれだけ書き込めるかを示し、duは容量を消費している場所を特定するために使います。両者を相互に代用することはできません。
df -Pk /
for path in \
"$HOME/Library/Developer/Xcode/DerivedData" \
"$HOME/Library/Developer/Xcode/Archives" \
"$HOME/Library/Developer/CoreSimulator" \
"$HOME/Library/Developer/Xcode/iOS DeviceSupport"
do
if [ -e "$path" ]; then
du -sk "$path"
fi
done
クリーンビルドの直前、アーカイブ完了後、テスト終了後の3回に分けて計測することを推奨します。この3つの値から、1回のジョブで増加する容量を把握でき、通常のピークを容量リークと誤認することも防げます。DerivedData内で特に大きいディレクトリをさらに調べるには、次を実行します。
du -sk "$HOME/Library/Developer/Xcode/DerivedData"/* 2>/dev/null \
| sort -nr \
| head -20
APFSで表示される空き容量は、パージ可能なデータの影響を受ける場合があります。ビルドの容量ゲートでは
dfが示す空きブロックを参照し、ディレクトリの見かけ上のサイズだけでジョブを完了できると判断しないでください。
ビルドに明確な容量ゲートを設ける
容量のしきい値は経験則で固定せず、実測したピーク値から決めます。まずは30GBを基準にし、アーカイブ処理全体を通じた最小空き容量を記録してください。数回安定して実行できたら、しきい値をピーク増加量の1.5倍に調整し、さらにエクスポート成果物に必要な容量を加えます。
次のスクリプトはパイプラインの先頭に配置できます。容量が不足している場合はステータスコード75で終了させ、失敗する可能性が高いビルドを開始するのではなく、スケジューラ側で一時的に実行不可のジョブとして扱えるようにします。
#!/bin/zsh
set -euo pipefail
minimum_kb=$((30 * 1024 * 1024))
available_kb=$(df -Pk / | awk 'NR == 2 {print $4}')
if (( available_kb < minimum_kb )); then
printf 'Insufficient disk capacity: %s KB available
' "$available_kb"
exit 75
fi
printf 'Disk capacity check passed: %s KB available
' "$available_kb"
しきい値はノードごとに保存してください。Xcodeのバージョン、シミュレータの組み合わせ、プロジェクト規模によってピーク値は異なります。小規模プロジェクトの測定結果を、そのまま大規模ワークスペースの根拠にしてはいけません。
ビルドごとに独立したディレクトリを使用する
デフォルトのDerivedDataを共有する問題は、容量だけではありません。各ディレクトリがどのジョブに属するのか判別できなくなります。ワークスペースごとに独立したパスを指定すれば、ジョブ終了後に対象だけを正確に削除でき、実行中のほかのビルドにも影響しません。
job_root="$HOME/build-jobs/$BUILD_ID"
derived_data="$job_root/DerivedData"
archive_path="$job_root/artifacts/App.xcarchive"
mkdir -p "$job_root/artifacts"
xcodebuild \
-workspace App.xcworkspace \
-scheme App \
-configuration Release \
-derivedDataPath "$derived_data" \
-archivePath "$archive_path" \
archive
BUILD_IDはジョブ管理システムから受け取り、使用できる文字を英字、数字、ピリオド、アンダースコア、ハイフンに制限します。削除前には対象パスがbuild-jobs配下にあることも検証し、空の変数によってホームディレクトリまで削除対象が広がらないようにしてください。
復元しやすいデータから段階的に整理する
整理は再生成できるデータから始め、最後に人による確認が必要なアーカイブを扱います。
| レベル | データ | 推奨する処理 | 主な注意点 |
|---|---|---|---|
| 1 | 完了済みジョブのDerivedData | ジョブディレクトリ単位で削除 | ビルドプロセスが使用中でないことを確認 |
| 2 | 使用不能なシミュレータ情報 | simctlで整理 |
Devicesディレクトリを直接削除しない |
| 3 | 古いデバイスサポートファイル | 実際のテスト対象バージョンに照らして確認 | デバッグに必要なOSバージョンを残す |
| 4 | xcarchiveとdSYM | 人が確認してから別の場所へ移動 | リリース済みバージョンの追跡可能性を維持 |
使用不能になったシミュレータは、システムツールで削除します。
xcrun simctl delete unavailable
CoreSimulator/Devicesを直接空にしないでください。ファイルディレクトリとシミュレータサービスの状態が一致しなくなると、その後のデバイス作成や起動で、さらに原因を特定しにくい問題が発生します。アーカイブディレクトリも、「一定日数を超えた」という理由だけで削除すべきではありません。xcarchiveには、リリース済みバージョンに対応するdSYMが保存されている可能性があります。バージョン、ビルド番号、移動先を先に記録し、その後でローカルコピーを削除するのが正しい手順です。
自動整理で避けるべき3つの落とし穴
第一に、ビルド中は共有ディレクトリを整理しないでください。古く見えるファイルであっても、コンパイラがインデックスや中間成果物を介して参照している可能性があります。整理ジョブではノード単位のロックを取得するか、完了済みと明示された独立作業ディレクトリだけを対象にします。
第二に、「削除が成功した」ことと「容量が解放された」ことを同一視しないでください。削除後にdf -Pk /を再実行し、空きブロックが実際に増えたことを確認します。変化がなければ削除コマンドを繰り返すのではなく、プロセスによって開かれたままのファイルがないか調べてください。
第三に、アーカイブの重要性をスクリプトだけで判断させないでください。無人ジョブの役割は候補の列挙までです。たとえば、ディレクトリサイズ、最終更新日時、関連するビルド番号を出力します。別の場所へ移すか削除するかは、リリース記録に基づいて判断します。
再現可能なビルドで最終確認する
整理が完了したら、少なくとも1回は本番ジョブと同じ条件でアーカイブを実行します。検証時には、開始時の空き容量、最小空き容量、終了時の空き容量、アーカイブパス、終了ステータスを記録し、.xcarchiveが完全に生成されていることを確認してください。ノードでシミュレータテストも実行する場合は、テストマトリクスで保持対象となっている各バージョンを1回ずつ起動し、デバイスを正常に作成、起動、終了できることも確認します。
最終チェック項目は簡潔で構いません。ビルド前の容量ゲートを通過していること、ジョブが独立したDerivedDataを使用していること、終了後にコンパイルプロセスが残っていないこと、アーカイブとdSYMが記録済みであること、simctl listに異常なデバイスがないこと、残りのディスク容量が次回ジョブのしきい値を上回っていることを確認します。これらの条件をすべて満たして初めて、整理作業が完結したと判断できます。
よくある質問
Xcodeのビルド前に最低どれだけの空き容量が必要ですか?
一律の正解はありません。まず30GBを下限にし、完全なアーカイブで記録した最大使用量に合わせて調整します。大規模な複数モジュール構成では最大値の1.5倍以上が目安です。
DerivedData全体を削除しても安全ですか?
実行中のビルドが参照していなければ削除できます。ただし、ワークスペースごとにDerivedDataPathを分け、完了済みジョブの領域だけを削除する方が安全です。
自動整理の対象にしてはいけないXcodeデータは何ですか?
処理中のアーカイブ、未退避のxcarchive、公開済みビルドに対応するdSYM、稼働中のテスト構成で使うシミュレータ端末は自動削除から除外します。
再現可能な環境を同じクラウドMacに保持する
固定のモデル、リージョン、契約期間を選び、完全なmacOSグラフィカルインターフェースとコマンドラインで開発や自動化タスクを実行できます。