Gradle и плагин Kotlin Multiplatform

Минимальный build-скрипт, который превращает обычный модуль в мультиплатформенный.

Плагин kotlin("multiplatform") — Gradle-плагин, добавляющий блок kotlin { } с объявлением целей компиляции и иерархии исходных наборов.

С чего начинается KMP-модуль

KMP-проект — это обычный Gradle-проект, в котором общий модуль подключает специальный плагин. Конфигурация пишется на Kotlin DSL (build.gradle.kts). Объявляем плагины и цели:

plugins {
    kotlin("multiplatform") version "2.0.0"
    id("com.android.library") version "8.5.0"
}

kotlin {
    androidTarget()
    iosX64()
    iosArm64()
    iosSimulatorArm64()

    sourceSets {
        commonMain.dependencies {
            // общие зависимости
        }
        androidMain.dependencies {
            // только Android
        }
        iosMain.dependencies {
            // только iOS
        }
    }
}

Три iOS-цели — это не прихоть: iosArm64 для физического устройства, iosX64 для симулятора на Intel-Mac, iosSimulatorArm64 для симулятора на Apple Silicon. Современный шаблон объединяет их общим iosMain автоматически.

Зависимости по наборам

Ключевая особенность — зависимости объявляются на уровне source set, а не всего модуля. Библиотека, нужная всем (например, корутины), идёт в commonMain. Платформенная (например, OkHttp-движок Ktor) — в androidMain. Так вы держите общий код чистым.

Версионный каталог

Версии библиотек удобно держать в одном месте — gradle/libs.versions.toml:

[versions]
kotlin = "2.0.0"
ktor = "2.3.12"

[libraries]
ktor-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }

Как работает под капотом

Плагин регистрирует для каждой цели набор Gradle-задач: компиляция, сборка артефакта, тесты. Для iOS он умеет собирать .framework и генерировать задачу, которую вызывает Xcode. Все цели делят один граф зависимостей, но разрешают его независимо: версия библиотеки для Android и для iOS может физически различаться (разные артефакты под разные платформы публикуются с общими координатами). Gradle сам подбирает нужный вариант через метаданные Kotlin Multiplatform.

Частые ошибки

Самая частая — забыть цель симулятора под архитектуру своего Mac, после чего «приложение не запускается на симуляторе». На Apple Silicon обязателен iosSimulatorArm64. Вторая — класть зависимость в commonMain, когда у неё нет мультиплатформенного артефакта (она только JVM): сборка Android пройдёт, iOS — упадёт на этапе разрешения зависимостей. Проверяйте, что библиотека действительно мультиплатформенная.

Итоги

  • Плагин kotlin("multiplatform") добавляет блок kotlin { } с целями.
  • iOS — это три цели: устройство и два варианта симулятора.
  • Зависимости объявляются по source set'ам, не на весь модуль.
  • В commonMain — только мультиплатформенные библиотеки.
Проверьте себя
1. На каком уровне в KMP объявляются зависимости?
AТолько глобально на весь проект
BНа уровне отдельного source set (commonMain, androidMain, iosMain)
CТолько в settings.gradle
DВ манифесте Android
2. Зачем нужна цель iosSimulatorArm64?
AДля серверного Kotlin
BДля запуска на симуляторе iOS на Apple Silicon
CДля веб-сборки
DЭто устаревшая цель