Reduciendo tiempos de compilación en proyectos iOS

Una de las primeras cosas que recomiendo e intento hacer cuando empezamos un desarrollo es configurar las builds de integración y despliegue continuos desde el minuto 0. Hay que tener en cuenta que tiempo que tarda en ejecutarse una build es, cómo decirlo, oro.

Y es que tras configurar una github action para un proyecto de iOS me sorprendió la cantidad de tiempo que tardaba en ejecutarse… Casi 30 minutos. Así que tocaba “arremangarse” y buscar cómo optimizarlo.

Da igual si lo haces con githubactions, Jenkins, Teamcity, Azure Devops, etcc … Hay que hacer dos cosas:

Cachear el contenido de “derivedData”

Busca la forma de cachear ese directorio, de lo contrario, en cada build que se ejecute se descargará y compilará todas las referencias que tengas en tu proyecto.

Aquí os pongo cómo puedes hacerlo si usas githubactions:

- uses: actions/cache@v2.1.7
  name: "Cache: Expensive Dependencies "        
  with:
    path: |
      ./DerivedData/Build
      ./DerivedData/SourcePackages            
    key: ${{ runner.os }}-expensive-dependencies-${{ hashFiles('**/Podfile.lock','**/Package.resolved') }}
    restore-keys: |
       ${{ runner.os }}-expensive-dependencies-

Estamos cacheando ese directorio, que en mi caso está en la raíz del proyecto porque cuando ejecuto el comando xcodebuild, le indico que use ese directorio como derivedDataPath. Esto se consigue añadiendo al comando xcodebuild el parámetro “-derivedDataPath ./DerivedData”, o el directorio que quieras. Si no se lo indicas, el directorio derived data se encuentra en /Library/Developer/Xcode/DerivedData/”miproyecto”

Os recomiendo que sólo cacheéis los directorios de Build y SourcePackages, ya que son los que contienen el código y el resultado de las compilaciones de las dependencias. El resto es para cache de símbolos logs, resultados de tests.. que si los incluís en la cache se va a estar invalidando en cada build y la volverá a guardar… y eso aunque no es mucho, es tiempo… y el tiempo es…

Prestad especial atención también a cómo se generan las claves para la cache, estamos aprovechando el hash del archio podfile.lock para generar una nueva entrada en la cache cuando se añada un nuevo paquete.

Añadir un parámetro a xcodebuild.

El segundo punto importante y que no se nos debe olvidar es pasarle al comando xcodebuild el parámetro:

-IgnoreFileSystemDeviceInodeChanges=YES”

Con este parámetro le estamos diciendo a xcode que desactive una opción interna que hace que el Swift Package Manager invalide lo que haya en DerivedData porque se está ejecutando en una máquina diferente… o algo así he entendido de esto https://stackoverflow.com/questions/53753511/is-it-possible-to-copy-an-xcode-derived-data-cache/54055857#54055857 

También está la otra opción que se describe en el post de stackoverflow:

defaults write com.apple.dt.XCBuild IgnoreFileSystemDeviceInodeChanges -bool YES

Pero esto último no lo he probado. Así que si queréis probarlo genial, así no hay que pasarlo al comando xCodebuild.

 

Espero que os sirva.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *