Tuvimos el mismo problema y lo solucionamos. Dos veces.
Construcción incremental (misma máquina de construcción):
antes: ~ 10m después: ~ 35s
¿CÓMO?
Comencemos con nuestra experiencia primero. Teníamos un proyecto masivo Swift / Obj-C y esa era la principal preocupación: los tiempos de construcción eran lentos y había que crear un nuevo proyecto para implementar una nueva característica (literalmente). Puntos de bonificación por resaltado de sintaxis que nunca funciona.
Teoría
Para solucionar esto realmente, debe comprender realmente cómo funciona el sistema de compilación. Por ejemplo, intentemos este fragmento de código:
import FacebookSDK
import RxSwift
import PinLayout
e imagine que usa todas estas importaciones en su archivo. Y también este archivo depende de otro archivo, que depende de otras bibliotecas, que a su vez usa otras bibliotecas, etc.
Entonces, para compilar su archivo, Xcode tiene que compilar cada biblioteca que mencionó y cada archivo del que depende, por lo que si cambia uno de los archivos "centrales", Xcode tiene que reconstruir literalmente todo el proyecto.
La construcción de Xcode es multiproceso , pero consta de muchos árboles de subproceso único .
Entonces, en el primer paso de cada compilación incremental, Xcode decide qué archivos deben volver a compilarse y crea un árbol AST . Si cambia un archivo que actúa como " confiable " en otros archivos, entonces todos los demás archivos que actúan como " dependientes " tienen que volver a compilarse.
Entonces, el primer consejo es reducir el acoplamiento . Las partes de su proyecto deben ser independientes entre sí.
Obj-C / Puente Swift
Problema con esos árboles si está utilizando un puente Obj-C / Swift, Xcode tiene que pasar por más fases de lo habitual:
Mundo perfecto:
- Construye código Obj-C
- Construir código Swift
Obj-C / Puente Swift:
- [PASO REPETIBLE] Cree el código Swift, que es necesario para compilar el código Obj-C
- [PASO REPETIBLE] Compila el código Obj-C, que es necesario para compilar el código Swift
- Repita 1 y 2 hasta que solo le quede un código Swift y Obj-C no confiable
- Construir código Obj-C
- Construir código Swift
Entonces, si cambia algo del paso 1 o 2, básicamente está en problemas. La mejor solución es minimizar Obj-C / Swift Bridge (y eliminarlo de su proyecto).
Si no tiene un puente Obj-C / Swift, es increíble y puede continuar con el siguiente paso:
Swift Package Manager
Es hora de pasar a SwiftPM (o al menos configurar mejor sus Cocoapods).
La cuestión es que la mayoría de los marcos con configuración predeterminada de Cocoapods arrastran consigo muchas cosas que no necesita.
Para probar esto, cree un proyecto vacío con una sola dependencia como PinLayout, por ejemplo, e intente escribir este código con Cocoapods (configuración predeterminada) y SwiftPM.
import PinLayout
final class TestViewController: UIViewController {
}
Spoiler: Cocoapods compilará este código, porque Cocoapods importará CADA IMPORTACIÓN de PinLayout (incluido UIKit) y SwiftPM no porque SwiftPM importa marcos atómicamente.
Truco sucio
¿Recuerdas que la construcción de Xcode es multihilo?
Bueno, puede abusar de él si puede dividir su proyecto en muchas partes independientes e importarlas todas como marcos independientes para su proyecto. Reduce el acoplamiento y esa fue en realidad la primera solución que usamos, pero de hecho no fue muy efectiva, porque solo pudimos reducir el tiempo de construcción incremental a ~ 4-5m, lo cual no es NADA en comparación con el primer método.