Guía

Compila la app de iOS de un proyecto Kotlin Multiplatform sin Mac

Con Kotlin Multiplatform, casi toda tu app vive en código Kotlin compartido. Puedes escribirlo en Windows o Linux. El framework de iOS y la app de Xcode siguen necesitando macOS. Lo probamos el 19 de octubre de 2026 con la plantilla KMP oficial de JetBrains. Abajo está lo que funcionó, y una trampa.

Qué funciona en Windows y Linux

La documentación de Kotlin dice que puedes trabajar en el código compartido y en todas las plataformas salvo iOS desde cualquier sistema. Lo comprobamos con KMP-App-Template, la plantilla oficial del equipo de Kotlin en GitHub. Es una app de Compose Multiplatform para Android, iOS, escritorio y web. En runners de Windows y Ubuntu, esto funcionó:

./gradlew :shared:compileKotlinJvm :androidApp:assembleDebug

El código compartido compiló para la JVM y la app de Android se generó. Puedes ejecutar los tests de Android, escritorio y JVM de la misma forma. Escribe ahí tu lógica de negocio y tu UI de Compose, y compruébala en Android.

La trampa: una build en verde sin framework de iOS

Después pedimos el framework de iOS a los runners de Windows y Ubuntu. Gradle compiló el Kotlin para iOS y luego se saltó el paso de enlazado. Aun así informó de éxito:

> Task :shared:compileKotlinIosSimulatorArm64
> Task :shared:linkDebugFrameworkIosSimulatorArm64 SKIPPED
BUILD SUCCESSFUL in 27s

No salió ningún framework. La página de plataformas compatibles de Kotlin explica por qué. Linux y Windows pueden crear bibliotecas de Kotlin para destinos de Apple. Pero los binarios finales para Apple no se pueden compilar ahí. El paso de configuración también avisó de que los tests del simulador de iOS necesitan macOS.

Qué necesita macOS

  • Enlazar el framework. La app de iOS importa tu código compartido como un framework, y solo un Mac puede enlazarlo.
  • El proyecto iosApp. Es un proyecto normal de Xcode. Su fase de build llama a Gradle para incrustar el framework.
  • Los tests de iOS y el simulador. Los dos necesitan Xcode.
  • CocoaPods y otro cinterop. La documentación de Kotlin dice que necesitan un host con macOS incluso para bibliotecas.

Los comandos en el Mac

Un Mac de MacRun viene con Xcode 27.1 y Xcode 26.6. No trae JDK, así que instala uno primero. Nosotros usamos Zulu JDK 21. La guía rápida de Kotlin dice que abras Xcode una vez antes de tu primera build, para que termine su configuración. Después clona tu repo y enlaza el framework del simulador:

./gradlew :shared:linkDebugFrameworkIosSimulatorArm64

Luego compila el proyecto iosApp para el simulador. Estas opciones son las del propio archivo de CI de la plantilla. CODE_SIGNING_ALLOWED=NO se salta la firma, que una build para el simulador no necesita.

cd iosApp
xcodebuild -project iosApp.xcodeproj -scheme iosApp \
  -configuration Debug -sdk iphonesimulator -arch arm64 \
  -derivedDataPath build CODE_SIGNING_ALLOWED=NO build

Mantén -arch arm64. En nuestro primer intento usamos un destino genérico de simulador. Xcode pidió entonces a Gradle también una versión para simulador Intel, y la build falló:

Xcode requested target architectures that are not configured in your Gradle build: ios_x64.

La plantilla solo define iosArm64 e iosSimulatorArm64. Poner a la vez -destination y -arch también falló. Xcode dijo que el destino ya implica la arquitectura.

Para abrir la app, arranca un simulador e instala la build. Usa tu propio bundle ID. En MacRun, el runtime de iOS 27.1 trae el dispositivo iPhone Duo.

xcrun simctl list devices available
xcrun simctl boot "iPhone Duo"
xcrun simctl install booted "build/Build/Products/Debug-iphonesimulator/KMP App.app"
xcrun simctl launch booted com.jetbrains.kmpapp.KMP-App-Template

También puedes abrir iosApp.xcodeproj en Xcode con la pantalla compartida. Elige tu equipo y pulsa Run. Desde Windows, consulta Xcode desde Windows para la pantalla remota.

El workflow que ejecutamos en GitHub Actions

Este es el job de macOS de nuestra prueba. Fija la plantilla a un commit, así que puedes ejecutarlo tal cual. En tu propio repo, haz checkout de tu código en su lugar.

name: kmp-ios
on: workflow_dispatch
env:
  TEMPLATE_SHA: 6b6d09e4f3f5e845116422d59b658791ed6149c6
jobs:
  macos:
    runs-on: macos-26
    steps:
      - uses: actions/checkout@v4
        with:
          repository: Kotlin/KMP-App-Template
          ref: ${{ env.TEMPLATE_SHA }}
      - uses: actions/setup-java@v4
        with:
          distribution: zulu
          java-version: 21
      - run: xcodebuild -version && sw_vers && java -version
      - name: Link the iOS simulator framework
        run: time ./gradlew :shared:linkDebugFrameworkIosSimulatorArm64
      - name: Build the iosApp for the Simulator
        run: |
          time xcodebuild -project iosApp.xcodeproj -scheme iosApp \
            -configuration Debug -sdk iphonesimulator -arch arm64 \
            -derivedDataPath build CODE_SIGNING_ALLOWED=NO build
        working-directory: iosApp
      - name: Install and launch in the Simulator
        run: |
          APP=$(ls -d build/Build/Products/Debug-iphonesimulator/*.app | head -1)
          UDID=$(xcrun simctl list devices available -j | python3 -c "import json,sys; d=json.load(sys.stdin)['devices']; print(next(x['udid'] for k,v in d.items() if 'iOS' in k for x in v if x['name'].startswith('iPhone')))")
          xcrun simctl boot "$UDID"
          xcrun simctl bootstatus "$UDID"
          xcrun simctl install booted "$APP"
          xcrun simctl launch booted com.jetbrains.kmpapp.KMP-App-Template
          sleep 10
          xcrun simctl io booted screenshot shot.png && ls -la shot.png
        working-directory: iosApp

El job tardó 6 minutos y 35 segundos. El enlazado con Gradle tardó 4 minutos y 7 segundos en un runner en frío, sobre todo para descargar la toolchain de Kotlin/Native. El paso de xcodebuild tardó 26 segundos. Estas líneas salen del log:

Xcode 26.6
Build version 17F113
openjdk version "21.0.12" 2026-07-21 LTS
BUILD SUCCESSFUL in 4m 4s
263M	shared/build/bin/iosSimulatorArm64/debugFramework/Shared.framework
** BUILD SUCCEEDED **
 59M	build/Build/Products/Debug-iphonesimulator/KMP App.app
com.jetbrains.kmpapp.KMP-App-Template: 26325

La última línea es la app funcionando en el simulador. Nuestra ejecución usó Xcode 26.6, porque la imagen de GitHub no tiene Xcode 27. En un Mac de MacRun puedes igualarlo con sudo xcode-select -s /Applications/Xcode.app, que ahí es Xcode 26.6.

Publicar en TestFlight

La build release se hace en el proyecto iosApp, como en cualquier app de iOS. Elige tu equipo en Xcode, archiva y sube a App Store Connect. Nuestra guía de publicación explica la firma, las claves de API y la revisión. No probamos esos pasos, porque nuestro runner no tenía cuenta de Apple. Para un iPhone real, instala desde TestFlight. Un Mac remoto no ve un teléfono conectado a tu PC.

Quién no debería alquilar un Mac para esto

Si solo necesitas una build que demuestre que iOS sigue compilando, usa CI. El workflow de arriba funciona en un runner de macOS de GitHub Actions y se cobra por minuto. Las cuentas personales de Codemagic incluyen 500 minutos gratis de build en macOS al mes. Si trabajas en iOS todos los días, un Mac propio puede salir más barato en un año.

Alquila un Mac cuando necesites ver la app de iOS. Es decir, la UI de Compose en una pantalla real de iOS, un fallo en Xcode o un problema de firma. Un pase de un día de MacRun cuesta $15 por un Mac mini M6 dedicado, y una semana cuesta $59. Pagas una sola vez y no se renueva nada. El Mac se borra al final, así que sube antes tu trabajo a git.

Preguntas frecuentes

¿Puedo compilar la app de iOS de un proyecto Kotlin Multiplatform en Windows?

+

No. La documentación de Kotlin dice que los binarios finales para Apple no se pueden compilar en Linux ni en Windows. El código compartido y los destinos Android y JVM compilan bien ahí. El framework de iOS y la app de Xcode necesitan un Mac.

¿Por qué Gradle dice BUILD SUCCESSFUL para iOS en Windows?

+

En Linux y Windows, Gradle se salta las tareas de enlazado de Apple en vez de fallar. En nuestra prueba, linkDebugFrameworkIosSimulatorArm64 mostró SKIPPED y Gradle aun así informó de éxito. No se generó ningún framework.

¿Puedo escribir UI de Compose Multiplatform en Windows?

+

Sí. En nuestra prueba, el código compartido de la plantilla compiló para la JVM y su app de Android se generó en Windows. Solo necesitas un Mac para compilar y ejecutar la UI en iOS.

¿Cómo se arregla "Xcode Requested Architecture Not Configured in Gradle"?

+

Compila para una sola arquitectura. Pasamos -sdk iphonesimulator -arch arm64 a xcodebuild, como hace el propio CI de la plantilla KMP. Un destino genérico de simulador pedía también x86_64, que la plantilla no define.

¿Cuánto tarda una build de Kotlin Multiplatform para iOS?

+

En el runner macos-26 de GitHub, enlazar el framework del simulador de la plantilla tardó unos 4 minutos en un runner en frío. Después, la build de iosApp en Xcode tardó 26 segundos.

¿Hay un JDK instalado en un Mac de MacRun?

+

No. Están instalados Xcode 27.1, Xcode 26.6 y el simulador de iOS 27.1. Tienes acceso admin y Homebrew, así que instalas el JDK y todo lo que necesites.

Guías relacionadas