DEV Community

Cover image for Xcodebuild y fastlane: compilar apps iOS y Mac sin abrir Xcode
lu1tr0n
lu1tr0n

Posted on • Originally published at elsolitario.org

Xcodebuild y fastlane: compilar apps iOS y Mac sin abrir Xcode

Compilar, firmar y publicar una app de iOS o macOS suele significar abrir Xcode, esperar a que indexe el proyecto y navegar por decenas de menús. Pero la interfaz gráfica no es el único camino: Apple expone toda esa cadena (build, firma, notarización y subida a App Store Connect) a través de herramientas de línea de comandos que se pueden encadenar sin tocar el editor.

Un desarrollador independiente documentó recientemente su flujo completo para compilar apps sin Xcode, usando solo la terminal, un editor de texto y unos cuantos scripts. El resultado es un pipeline reproducible que cualquier equipo puede adaptar para su propio proyecto.

TL;DR

  • xcodebuild es la herramienta CLI de Apple para compilar, archivar y exportar apps sin abrir Xcode.app.- xcrun notarytool reemplazó a altool en 2023 como único método soportado para notarizar builds de macOS e iOS.- fastlane, creado por Felix Krause en 2014, automatiza firma de código y subida a App Store Connect con un solo Fastfile.- El archivo project.pbxproj se puede generar con Swift Package Manager o XcodeGen sin editarlo a mano en la GUI.- GitHub Actions ofrece runners macOS con Xcode preinstalado para correr xcodebuild en integración continua.- sourcekit-lsp habilita autocompletado y navegación de código Swift en editores como VS Code o Neovim, sin Xcode.- La notarización exige una cuenta de Apple Developer Program activa y una contraseña específica de aplicación.

El problema con la interfaz gráfica de Xcode

Cualquiera que haya trabajado en un equipo de iOS conoce los síntomas: Xcode indexando el proyecto durante minutos cada vez que se cambia de rama, el archivo project.pbxproj generando conflictos de merge ilegibles porque es un plist con identificadores UUID, y builds que fallan de forma distinta en cada máquina según la versión de Xcode instalada localmente.

Ninguno de esos problemas es exclusivo de la GUI: son consecuencia de tratar el build como un proceso manual en lugar de uno declarativo y scripteable. La alternativa, compilar apps sin Xcode desde la terminal, no elimina Xcode como dependencia (el toolchain sigue siendo necesario), pero sí elimina la dependencia de la aplicación gráfica como paso obligatorio del flujo de trabajo diario.

Contexto e historia: dos décadas de herramientas de línea de comandos

xcodebuild no es nuevo: forma parte de las Xcode Command Line Tools desde hace más de veinte años y es la misma herramienta que usa Xcode.app internamente cada vez que alguien pulsa el botón de Run o Archive en la interfaz. Lo que cambió con los años fue el ecosistema alrededor: en 2014 Felix Krause publicó fastlane, un conjunto de herramientas en Ruby para automatizar capturas de pantalla, firma de código y publicación en las tiendas de Apple y Google. Twitter adquirió fastlane junto con Fabric en 2015, y Google terminó heredando el proyecto cuando compró el negocio de Fabric a Twitter en enero de 2017, manteniéndolo como código abierto desde entonces.

En paralelo, Apple fue endureciendo los requisitos de seguridad: la notarización de apps de macOS se volvió obligatoria fuera de la Mac App Store, primero opcional y luego forzada por Gatekeeper. Durante años el envío se hizo con altool, hasta que Apple lo retiró en 2023 en favor de xcrun notarytool, introducido con Xcode 13 y con una API más moderna basada en JSON.
xcodebuild compila, archiva y exporta sin necesidad de abrir la interfaz de Xcode.

Detalles técnicos: el pipeline para compilar apps sin Xcode

xcodebuild: compilar y archivar desde la terminal

El primer bloque del pipeline es xcodebuild, que acepta un esquema (-scheme), una configuración (-configuration) y un destino de archivo. Para un proyecto simple basado en Swift Package Manager, ni siquiera hace falta un .xcodeproj: swift build compila el paquete directamente.

swift package init --type executable --name ClimaCLI
swift build -c release
.build/release/ClimaCLI
Enter fullscreen mode Exit fullscreen mode

Este ejemplo crea un ejecutable Swift desde cero y lo compila en modo release usando solo el compilador, sin ningún archivo de proyecto de Xcode de por medio. Para una app real de iOS o macOS con recursos, entitlements y firma, el paso equivalente es un archive con xcodebuild:

xcodebuild archive \
  -scheme ClimaApp \
  -configuration Release \
  -archivePath build/ClimaApp.xcarchive

xcodebuild -exportArchive \
  -archivePath build/ClimaApp.xcarchive \
  -exportOptionsPlist ExportOptions.plist \
  -exportPath build/export
Enter fullscreen mode Exit fullscreen mode

El primer comando genera el .xcarchive con el binario compilado y firmado según el perfil de aprovisionamiento configurado en el proyecto. El segundo lo exporta como .ipa (iOS) o .app (macOS) usando las opciones declaradas en ExportOptions.plist, donde la clave method define si el destino es app-store, developer-id o ad-hoc.

Notarización con xcrun notarytool

Para apps de macOS distribuidas fuera de la App Store, el binario exportado debe pasar por notarización antes de que Gatekeeper lo deje ejecutar sin advertencias. El comando clave es xcrun notarytool submit, que envía un .zip o .pkg a los servidores de Apple y espera el veredicto:

xcrun notarytool submit build/export/ClimaApp.zip \
  --keychain-profile "AC_PROFILE" \
  --wait

xcrun stapler staple build/export/ClimaApp.app
Enter fullscreen mode Exit fullscreen mode

--wait hace que el comando no retorne hasta que Apple resuelva el envío (aprobado o rechazado), y stapler staple adjunta el ticket de notarización directamente al binario para que funcione incluso sin conexión a internet en el equipo del usuario final.

fastlane: orquestando todo el flujo

Encadenar manualmente xcodebuild, notarytool y la subida a App Store Connect funciona, pero se vuelve tedioso en un pipeline de CI con múltiples esquemas y entornos. fastlane resuelve esto con un Fastfile declarativo que envuelve internamente los mismos comandos de xcodebuild, más pasos adicionales como incrementar el número de build o subir capturas de pantalla.
HerramientaCuándo usarlaVentajaLimitaciónxcodebuildBuild o archive puntual desde un script propioViene incluido con las Command Line Tools, sin dependencias externasSintaxis verbosa para flujos con firma y notarización completosfastlanePipelines completos de CI/CD con firma, capturas y subida a las tiendasUn Fastfile declarativo reemplaza decenas de comandos xcodebuildRequiere Ruby y mantener plugins actualizadosXcodeGen / TuistGenerar el .xcodeproj a partir de YAML o Swift, sin editar project.pbxprojElimina los conflictos de merge en el archivo de proyectoCurva de aprendizaje al migrar un proyecto existenteGitHub Actions (runner macOS)Ejecutar el pipeline completo sin una Mac local dedicadaXcode y el SDK ya vienen preinstalados en la imagenLos minutos de runner macOS son más caros que los de Linux

💡 Tip: Guardá las credenciales de notarización una sola vez con notarytool store-credentials: quedan en el keychain local y no hace falta repetir el usuario ni la contraseña específica de aplicación en cada build.

Cómo compilar apps sin Xcode paso a paso

El primer requisito, aunque suene contradictorio, es tener instaladas las Xcode Command Line Tools. Eso se resuelve con un solo comando, sin abrir la aplicación:

xcode-select --install
Enter fullscreen mode Exit fullscreen mode

Con las herramientas instaladas, el siguiente paso es registrar las credenciales de notarización una única vez:

xcrun notarytool store-credentials "AC_PROFILE" \
  --apple-id "dev@ejemplo.com" \
  --team-id "AB12CD34EF" \
  --password "app-specific-password"
Enter fullscreen mode Exit fullscreen mode

A partir de ahí, el ciclo diario para compilar apps sin Xcode se reduce a tres pasos: archive, export y notarize, tal como se mostró en la sección anterior. Para un proyecto en Swift Package Manager, XcodeGen puede generar el .xcodeproj necesario a partir de un archivo project.yml versionado en el repositorio, así que ni siquiera ese archivo requiere edición manual en la GUI.
Un runner macOS en CI reemplaza a la Mac local para compilar y notarizar.

flowchart TD
    A["Codigo fuente Swift"] --> B["xcodebuild archive"]
    B --> C["Exportar .ipa o .app"]
    C --> D["xcrun notarytool submit"]
    D --> E["Apple notariza el binario"]
    E --> F["xcrun stapler staple"]
    F --> G["Subida a App Store Connect"]
Enter fullscreen mode Exit fullscreen mode

Para verificar que un build quedó correctamente notarizado antes de distribuirlo, el comando xcrun stapler validate build/export/ClimaApp.app confirma si el ticket quedó grapado al binario, y xcrun notarytool info <submission-id> --keychain-profile "AC_PROFILE" permite consultar el estado exacto de un envío específico sin depender de la interfaz de Organizer en Xcode.

⚠️ Ojo: Notarizar requiere una cuenta de Apple Developer Program activa (99 USD al año) y una contraseña específica de aplicación generada en appleid.apple.com: la contraseña normal del Apple ID no funciona con notarytool.

Impacto y análisis

El beneficio más inmediato de compilar apps sin Xcode es que el proceso se vuelve reproducible: el mismo comando que corre en la laptop de un desarrollador puede correr, sin cambios, en un runner de GitHub Actions o en cualquier otro sistema de integración continua. Eso reduce la clase de errores conocida como "en mi máquina funciona", porque el build ya no depende de configuraciones invisibles guardadas en las preferencias de la app.

También cambia la forma de resolver conflictos de equipo. Si el proyecto se genera con XcodeGen o Tuist a partir de un archivo de texto plano, dos desarrolladores que agregan archivos nuevos en ramas distintas ya no generan un conflicto binario en project.pbxproj: el archivo de proyecto se regenera automáticamente antes de compilar.

El trade-off honesto es que este flujo no reemplaza completamente a Xcode.app. El debugger visual, el editor de Interface Builder para Storyboards y el profiler de Instruments siguen siendo más cómodos, y en algunos casos únicos, desde la interfaz gráfica. Para depuración en terminal existe lldb, pero inspeccionar la jerarquía de vistas de una app en ejecución sin el View Debugger de Xcode es notablemente más lento. La recomendación práctica no es abandonar Xcode.app por completo, sino usarlo solo para lo que la terminal no resuelve bien, y automatizar todo lo demás.

Qué sigue

La tendencia en el ecosistema Swift apunta a reducir más la dependencia de la GUI. Swift Package Manager se consolidó como el gestor de dependencias por defecto en lugar de CocoaPods o Carthage, y sourcekit-lsp, el servidor de Language Server Protocol de Apple, ya permite autocompletado y navegación de código Swift en editores como VS Code, Neovim o Zed sin instalar Xcode.app en absoluto para esa parte del flujo. Apple también mantiene Xcode Cloud como alternativa gestionada a un pipeline de fastlane casero, aunque con menos control granular sobre cada paso.

📖 Resumen en Telegram: Ver resumen

Preguntas frecuentes

¿Necesito Xcode instalado aunque no abra la aplicación?

Sí. xcodebuild forma parte de las Command Line Tools que Apple distribuye junto con Xcode y se instalan con xcode-select --install o descargando Xcode desde el App Store. Lo que se evita es abrir el .app en sí, no el toolchain completo.

¿Puedo compilar una app de iOS en Linux o Windows?

No completamente. El SDK de iOS y el linker de Apple solo corren sobre macOS. Swift en Linux compila el lenguaje, pero no puede generar binarios firmados para iOS. Linux y Windows sirven para escribir código con sourcekit-lsp, no para el build final.

¿Qué reemplazó a altool ahora que Apple lo retiró?

xcrun notarytool, disponible desde Xcode 13, es el único método soportado para enviar builds a notarización desde 2023.

¿fastlane sustituye a xcodebuild?

No, lo envuelve. Internamente fastlane sigue llamando a xcodebuild y a las herramientas de firma de Apple; su valor es declarar el flujo completo en un Fastfile en lugar de encadenar comandos sueltos a mano.

¿Cómo verifico que un build quedó notarizado antes de distribuirlo?

Con xcrun stapler validate ruta/a/TuApp.app, que confirma si el ticket de notarización quedó grapado al binario, o con xcrun notarytool info <id> --keychain-profile "AC_PROFILE" para consultar el estado de un envío específico.

¿Este flujo sirve igual para apps de macOS y de iOS?

Sí, xcodebuild y notarytool trabajan igual para ambas plataformas. La diferencia está en el método de exportación configurado en ExportOptions.plist y en que las apps de macOS distribuidas fuera de la App Store necesitan notarización obligatoria, mientras que las de iOS se validan al subirlas a App Store Connect.

Referencias

📱 ¿Te gusta este contenido? Únete a nuestro canal de Telegram @programacion donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.

Top comments (0)