Xcode 11の再コンパイルが多すぎる


12

Xcode 11は、ローカルプライベート変数を変更したり、ローカルスコープの定数の値を変更したりした場合でも、プロジェクト全体を(ほぼ?)再コンパイルしています。予想どおり、クイックビルドで2つまたは3つの変更を取得できる場合がありますが、すぐにすべてを再コンパイルすることになります(時間がかかりすぎます)。

何が起こっているのでしょうか?Xcodeは何が変更されたかを判別できないのですか、なぜそれが他の多くのもの(他のモジュールでさえ)を再コンパイルするのですか?

どんなアドバイスでも大歓迎です、ありがとう!


2
私はアドバイスします:モジュール全体の最適化ではなく、増分ビルドでデバッグビルドを行っていることを確認してください。DerivedDataを終了して削除します。そして、Xcode 11.4にアップデートすると、コンパイルが非常に速くなるので、発生することすらありません。
マット

1
このスレッドは、あなたの質問に答えるかもしれません:stackoverflow.com/questions/25537614/...
Endanke

これは非常にプロジェクトに依存しているので、何が起こっているかについてビルドログを分析する必要があります。Xcode 11.2以降では、このような動作は見られませんが、非常に大きなプロジェクトがあります。どういうわけか、プロジェクトソースへのアクセスを提供しますか、そうでなければ、すべてのアドバイスは無意味ですか?
Asperi

レガシービルドシステムプロパティを確認します。サブモジュールを変更しない場合はオフにしてください
BrunoLoops

回答:


8

同じ問題があり、修正しました。二回。

インクリメンタルビルド(同じビルドマシン):

前:〜10分後:〜35秒

どうやって?

最初に私たちの経験から始めましょう。大規模なSwift / Obj-Cプロジェクトがあり、それが主な関心事でした。ビルド時間が遅く、新しい機能を実装するために新しいプロジェクトを作成する必要がありました(文字通り)。機能しない構文強調表示のボーナスポイント。

理論

これを本当に修正するには、ビルドシステムのしくみを本当に理解する必要があります。たとえば、次のコードスニペットを試してみましょう。

import FacebookSDK
import RxSwift
import PinLayout

これらのインポートをすべてファイルで使用するとします。また、このファイルは別のファイルに依存しています。これは別のライブラリに依存しており、さらに別のライブラリを使用しています。

したがって、ファイルをコンパイルするには、Xcodeは、あなたが言及したすべてのライブラリとそれに依存するすべてのファイルをコンパイルする必要があるため、「コア」ファイルの1つを変更すると、Xcodeは文字どおりプロジェクト全体を再構築する必要があります。

依存ツリー

Xcodeビルドはマルチスレッドですが、多くのシングルスレッドツリーで構成されています

したがって、すべての増分ビルドの最初のステップで、Xcodeはどのファイルを再コンパイルしてASTツリーをビルドする必要があるかを決定します。あなたは「として機能しているファイルに変更した場合、信頼性」として機能し、他のすべてのファイルので、他のファイルの「依存を」再コンパイルする必要があります。

カップリング

したがって、最初のアドバイスは、カップリング下げることです。プロジェクトパーツは互いに独立している必要があります。

Obj-C / Swiftブリッジ

Obj-C / Swiftブリッジを使用している場合、これらのツリーに問題があるため、Xcodeは通常より多くのフェーズを通過する必要があります。

パーフェクト・ワールド:

  1. Obj-Cコードをビルドする
  2. Swiftコードをビルドする

Swift / Obj-Cブリッジ

Obj-C / Swiftブリッジ:

  1. [繰り返し可能なステップ] Obj-Cコードをコンパイルするために必要なSwiftコードをビルドします。
  2. [繰り返し可能なステップ] Swiftコードのコンパイルに必要なObj-Cコードをビルドします
  3. 依存できないSwift&Obj-Cコードのみが残るまで、1と2を繰り返します。
  4. Obj-Cコードの作成
  5. Swiftコードをビルドする

Obj-C / Swiftブリッジ

したがって、ステップ1または2から何かを変更すると、基本的に問題が発生します。最善の解決策は、Obj-C / Swift Bridgeを最小化することです(そしてプロジェクトから削除します)。

Obj-C / Swiftブリッジがない場合、それはすばらしいことであり、次のステップに進むのに適しています。

Swift Package Manager

SwiftPMに移行する時間(または、少なくともCocoapodを適切に構成する時間)。

ことは、デフォルトのCocoapods構成を持つほとんどのフレームワークは、それらと一緒にあなたが必要としない多くのものをドラッグします。

これをテストするには、たとえば、PinLayoutのような依存関係が1つだけの空のプロジェクトを作成し、Cocoapods(デフォルト構成)とSwiftPMを使用してこのコードを記述してみます。

import PinLayout

final class TestViewController: UIViewController {

}

Spoiler:CocoapodsはPinLayout(UIKitを含む)のすべてのインポートをインポートし、SwiftPMはフレームワークをアトミックにインポートするため、SwiftPMはインポートしないため、このコードをコンパイルします。

ダーティハック

Xcodeビルドがマルチスレッドであることを覚えていますか?

まあ、プロジェクトを多数の独立した部分に分割し、それらのすべてを独立したフレームワークとしてプロジェクトにインポートできる場合は、それを悪用することができます。これはカップリングを低下させ、それが実際に使用した最初のソリューションでしたが、実際にはあまり効果的ではありませんでした。なぜなら、最初の方法と比較して、増分ビルド時間を約4〜5mにしか削減できなかったためです。


幸運、仲間。プロジェクトでカップリングをどのように下げたかについて、経験を共有してください。バイバイ!
x0 z1

3

ここには特効薬はありませんが、確認することがたくさんあります。

  • スキームで実際にデバッグ構成を使用していることを確認してくださいデバッグ構成を使用するXcodeスキーマエディター

  • マットのアドバイスに従って、インクリメンタルビルドとモジュール全体を確実に使用する方法については、以下を参照してください。また、デバッグビルドの最適化レベルがなしであることを確認してください。 インクリメンタルビルドを示すXcodeビルド設定

  • RxSwiftのような型推論の多いフレームワークを使用している場合は、明示的な型注釈を追加すると、ビルド時間が短縮されます。

  • プロジェクトが非常に大きい場合は、ソースファイルの論理グループをフレームワークにリファクタリングすることを検討できますが、これは、思いがけないほど大幅な変更になる可能性があります。

プロジェクトについてさらに具体的な情報を提供した場合に役立ちます。ライブラリを静的にリンクしていますか?フレームワークまたはアプリのターゲットですか?どのくらいのサイズで、どのバージョンを使用していますか?リンターやコード生成など、時々スキップできるカスタムビルドフェーズはありますか?

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.