Xcode 11 rekompiluje (prawie?) Cały mój projekt, nawet jeśli po prostu zmienię lokalną zmienną prywatną lub zmienię wartość stałej w lokalnym zasięgu, czasem nawet w lokalnym lokalnym zakresie funkcji. Czasami mogę uzyskać 2 lub 3 zmiany z szybkimi kompilacjami zgodnie z oczekiwaniami, ale wkrótce postanawia ponownie wszystko skompilować (co zajmuje zbyt dużo czasu).
Jakieś pomysły, co się dzieje? Czy Xcode nie jest w stanie określić, co się zmieniło, dlaczego rekompiluje tyle innych rzeczy (nawet innych modułów).
Wszelkie porady są mile widziane, dziękuję!
Odpowiedzi:
Mieliśmy ten sam problem i naprawiliśmy go. Dwa razy.
Kompilacja przyrostowa (ta sama maszyna do kompilacji):
przed: ~ 10 m po: ~ 35s
W JAKI SPOSÓB?
Zacznijmy od naszego doświadczenia. Mieliśmy ogromny projekt Swift / Obj-C i to był główny problem: czasy kompilacji były powolne i trzeba było stworzyć nowy projekt, aby wdrożyć nową funkcję (dosłownie). Punkty bonusowe za niedziałające podświetlanie składni.
Teoria
Aby naprawdę to naprawić, musisz naprawdę zrozumieć, jak działa system kompilacji. Na przykład spróbujmy tego fragmentu kodu:
i wyobraź sobie, że używasz wszystkich tych importów w swoim pliku. A także ten plik zależy od innego pliku, który zależy od innych bibliotek, które z kolei korzystają z innych bibliotek itp.
Aby skompilować plik, Xcode musi skompilować każdą wymienioną bibliotekę i każdy plik , od którego zależy, więc jeśli zmienisz jeden z „podstawowych” plików, Xcode musi odbudować dosłownie cały projekt.
Kompilacja Xcode jest wielowątkowa , ale składa się z wielu jednowątkowych drzew .
Tak więc na pierwszym etapie każdej przyrostowej kompilacji Xcode decyduje, które pliki należy ponownie skompilować i buduje drzewo AST . Jeśli zmienisz plik, który działa jako „ niezawodny ” w stosunku do innych plików, więc każdy inny plik, który działa jako „ zależny ”, musi zostać ponownie skompilowany.
Pierwszą radą jest więc obniżenie sprzęgła . Części twojego projektu muszą być od siebie niezależne.
Most Obj-C / Swift
Problem z tymi drzewami, jeśli używasz mostu Obj-C / Swift, Xcode musi przejść więcej faz niż zwykle:
Doskonały świat:
Most Obj-C / Swift:
Więc jeśli zmienisz coś od kroku 1 lub 2, zasadniczo masz kłopoty. Najlepszym rozwiązaniem jest zminimalizowanie Obj-C / Swift Bridge (i usunięcie go z projektu).
Jeśli nie masz mostu Obj-C / Swift, to jest niesamowite i możesz przejść do następnego kroku:
Menedżer pakietów szybkich
Czas przejść do SwiftPM (lub przynajmniej lepiej skonfigurować Cocoapody).
Rzecz w tym, że większość frameworków z domyślną konfiguracją Cocoapods przeciąga wraz z sobą wiele rzeczy, których nie potrzebujesz.
Aby to przetestować, utwórz pusty projekt z tylko jedną zależnością, na przykład PinLayout, i spróbuj napisać ten kod za pomocą Cocoapods (konfiguracja domyślna) i SwiftPM.
Spoiler: Cocoapods skompilują ten kod, ponieważ Cocoapods zaimportują KAŻDY IMPORT PinLayout (w tym UIKit), a SwiftPM nie, ponieważ SwiftPM importuje struktury atomowo.
Brudny hack
Czy pamiętasz, że Xcode jest wielowątkowy?
Cóż, możesz go nadużyć, jeśli jesteś w stanie podzielić swój projekt na wiele niezależnych elementów i zaimportować je wszystkie jako niezależne ramy do projektu. Zmniejsza to sprzężenie i było to właściwie pierwsze zastosowane przez nas rozwiązanie, ale w rzeczywistości nie było bardzo skuteczne, ponieważ mogliśmy jedynie skrócić czas kompilacji do ~ 4-5 m, co nie jest NIC w porównaniu z pierwszą metodą.
źródło
Nie ma tutaj złotej kuli, ale mnóstwo rzeczy do sprawdzenia:
Upewnij się, że faktycznie używasz konfiguracji debugowania w swoim schemacie
Zobacz poniżej, jak upewnić się, że używasz przyrostowych kompilacji w porównaniu do całego modułu zgodnie z poradami Matta. Upewnij się również, że Twój poziom optymalizacji kompilacji debugowania jest zerowy.
Jeśli używasz ciężkich struktur wnioskowania typu, takich jak RxSwift, dodanie wyraźnych adnotacji typu może przyspieszyć czas kompilacji.
Jeśli projekt jest bardzo duży, możesz rozważyć przekształcenie logicznych grup plików źródłowych w ramy, ale może to być zbyt drastyczna zmiana, niż wolisz
Może to pomóc, jeśli podasz więcej szczegółów na temat projektu: czy statycznie łączysz jakieś biblioteki? Czy jest to docelowy framework lub aplikacja? Jak dużej i jakiej szybkiej wersji używasz? Czy masz jakieś niestandardowe fazy kompilacji, takie jak kłaczki lub generowanie kodu, które można czasem pomijać?
źródło