クラシルリワードにおけるXcodeCloudの実行時間削減対応まとめ(2025/04)
こんにちは。dely株式会社のiOSエンジニア uetyo です!
この記事では、2025年4月現在までに行ったクラシルリワードにおけるXcodeCloudの実行時間削減対応についてまとめます。
実行時間削減の経緯
クラシルリワードのiOSアプリ開発では、XcodeCloudを使ったCI/CD環境を構築しています。
プロジェクトはSwift Package Managerによるマルチモジュール構成で、各モジュールごとにテストターゲットも分割しています[1]。
XcodeCloudは実行環境としてIntel系のMacを使用していることが知られていますが、Apple Silicon系のMacに比べてビルド時間がかなり長くなる傾向があります。クラシルリワードにおいてもチームメンバーや機能開発の増加に伴い、XcodeCloudの実行時間が生産性に大きく影響を与えるようになってきました。
そこで、あらゆる方面からXcodeCloudの実行時間を削減するための対応を行いました。
対応内容
※ 一部の内容はクラシルリワードのプロジェクト構成に合わせて作成しているため、他のプロジェクトではそのまま利用できない場合があります。
1. 適切なキャッシュの利用設定
XcodeCloudのワークフロー設定を見直しました。
XcodeCloudのワークフロー設定では、利用するリポジトリの選択やXcode、MacOSのバージョン指定、クリーンビルドをするかどうかを設定できます。以下の画像のようにチェックを外すことで、クリーンビルドを利用しない(= キャッシュを利用する)ようにできます。
2. 無駄なビルドをスキップ
XcodeCloudのワークフローを実行するかどうかの条件も見直しました。
XcodeCloudをPRが作成された際に実行するためには「開始条件→プル要求の変更」を設定する必要があります。ただし、初期設定ではドキュメントの変更等の本来ビルドもテストも不要なものでもワークフローが実行されてしまいます。
そこで以下のように、実行する条件をカスタムルールによって細かく設定することで実行時間の削減が可能です。
クラシルリワードでは、実行する条件を「アプリターゲットのディレクトリ配下が変更された場合」「xcodeproj, xcworkspace配下が変更された場合」「SPMのマルチモジュール配下が変更された場合」に設定しています。
また、ビルドを自動でキャンセルする設定も忘れずに設定しておくと安心です。
3. ビルド時間の短縮
地道にビルド時間の削減も行いました。
ビルドシステムの最適化
Xcode16より利用できる "Explicitly Built Modules" という機能を有効にします。
WWDC24にて発表された新しいビルド機能で、モジュールのプリコンパイルを先に行っておくことで無駄なビルドを削減し、結果的にビルド時間も削減できるというものです。詳細については公式ドキュメント[3]や参考にした資料[4]を確認してください。
この対応によって、2分弱のビルド時間を削減することができました。
Task | Previous time | Explicity time | reduced time |
---|---|---|---|
SwiftCompile | 1311.9900 | 1215.2200 | 96.7700 |
SwiftEmitModule | 182.0170 | 169.0920 | 12.9250 |
CompileAssetCatalog | 139.8910 | 133.6330 | 6.2580 |
CompileC | 45.1475 | 40.0250 | 5.1225 |
ScanDependencies | 45.0315 | 42.5430 | 2.4885 |
Ld | 24.2650 | 22.3180 | 1.9470 |
SwiftDriver | 13.4345 | 13.1420 | 0.2925 |
CodeSign | 8.4605 | 4.7145 | 3.7460 |
RegisterExecutionPolicyException | 6.7245 | 5.8680 | 0.8565 |
GenerateAssetSymbols | 7.0685 | 2.1665 | 4.9020 |
Copy | 3.9320 | 3.5210 | 0.4110 |
WriteAuxiliaryFile | 3.0495 | 3.0930 | -0.0435 |
ProcessInfoPlistFile | 2.5405 | 3.0890 | -0.5485 |
Touch | 1.5655 | 1.0330 | 0.5325 |
CpResource | 1.4130 | 1.6890 | -0.2760 |
SwiftMergeGeneratedHeaders | 0.4970 | 0.4225 | 0.0745 |
SwiftDriver Compilation | 0.1875 | 0.2655 | -0.0780 |
SwiftDriver Compilation Requirements | 0.0705 | 0.0130 | 0.0575 |
Total | 1797.2900s | 1661.8500 | -135.4370s |
推論時間の削減
次に、コードの推論時間の削減も行いました。
他社でも実践されている型推論時間の削減方法を参考に、型推論に時間がかかる箇所を特定し、必要のない型推論を削減することでビルド時間の削減を行いました[5]。
Swift Package Manager の場合、Build Arguments に -Xfrontend -warn-long-expression-type-checking=100
を追加することで、型推論に100ms以上かかる場合に警告を出すことができます。これを利用して、型推論に時間がかかっている箇所を特定し、必要のない型推論を削減することでビルド時間の削減をしました。
例えば以下のように修正することで型推論の時間削減が可能です。
// 🤔
let data: SomeType = .init(
id: UUID()
)
// ✅ .init より実態を明示したほうが型推論が早い
let data = SomeType(
id: UUID()
)
一つひとつは微々たる変更ですが、数百カ所の変更を行うことで、数十秒のビルド時間を削減できました。
4. アーカイブ時間の短縮
テスト前のアーカイブ時間も削減しました。
以下のスクリプトを実行することで、成果物の容量が削減され、アーカイブ時間の削減に繋がりました。この対応により、CI時間を5分削減できました。
# ci_post_xcodebuild.sh
if [[ $CI_WORKFLOW = "Test" ]]; then
find "$CI_TEST_PRODUCTS_PATH/Binaries/0/Debug-iphonesimulator" \
-maxdepth 1 \
\( -type d -name "*.dSYM" -o \
-type f -name "*.o" -o \
-type d -name "*.bundle" -o \
-type f -name "*.a" \) \
-exec rm -rf {} +
fi
詳細は以下のリンクに記載されています。
5. 変更によって影響したテストのみ実行
テスト時間の削減も行いました。
テスト時に変更によって影響したモジュールのみをテストするようにスクリプトを作成しました。この対応により、CI時間を最大18分削減できました。
改善前 | 改善後 |
---|---|
![]() 全てのテストを実行 |
![]() 関連するモジュールのテストのみ実行 |
詳細は以下のリンクに記載されています。
まとめ
クラシルリワードにおけるXcodeCloudの実行時間削減対応についてまとめました。
XcodeCloudはBitriseやGitHubActionsに比べて実行時間あたりのコストが安いですが、利用されているマシンスペックが低いことや、スクリプト実行のタイミングが厳しく制限されているため、実行時間の削減が難しいという特徴があります。
こういった実行時間の削減方法が網羅的にまとめられている記事も少ないため、どなたかの参考になれば幸いです。
Discussion