Структура проекта KMP: commonMain, androidMain, iosMain
Разберитесь в иерархии наборов исходного кода и в совместном использовании кода между целевыми платформами.
«Структура проекта KMP: commonMain, androidMain, iosMain» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.
Что такое KMP?
Kotlin Multiplatform (KMP) позволяет писать общий код на Kotlin, который компилируется для JVM, Android, iOS (с помощью Kotlin/Native) и JS. Платформенный код находится в отдельных наборах исходного кода.
// Typical KMP module structure:
// shared/
// src/
// commonMain/kotlin/ <- shared code
// androidMain/kotlin/ <- Android-only
// iosMain/kotlin/ <- iOS-only
// commonTest/kotlin/ <- shared tests
fun main() { println("KMP: one codebase, many targets") }Иерархия наборов исходного кода
Наборы исходного кода образуют иерархию. commonMain является корневым набором; androidMain и iosMain зависят от него. Код из commonMain виден всем целевым платформам.
// build.gradle.kts (Kotlin DSL)
kotlin {
androidTarget()
iosX64()
iosArm64()
iosSimulatorArm64()
sourceSets {
val commonMain by getting {
dependencies { /* shared deps */ }
}
val androidMain by getting
val iosMain by getting
}
}commonMain: общая логика
Размещайте бизнес-логику, доменные модели, репозитории и сценарии использования в commonMain. Этот код компилируется для всех целевых платформ.
// commonMain/kotlin/com/example/domain/User.kt
data class User(val id: String, val name: String, val email: String)
// commonMain/kotlin/com/example/repository/UserRepository.kt
interface UserRepository {
suspend fun getUser(id: String): User?
suspend fun saveUser(user: User)
}androidMain: специфика Android
androidMain может использовать классы Android SDK. Типичное применение: платформенные реализации объявлений expect/actual.
// androidMain/kotlin/com/example/platform/PlatformLogger.kt
import android.util.Log
class AndroidLogger : Logger {
override fun log(msg: String) = Log.d("App", msg)
}
// androidMain/kotlin/com/example/di/PlatformModule.kt
// Koin or Hilt module that binds AndroidLogger to LoggeriosMain: специфика iOS
iosMain получает доступ к фреймворкам Apple через взаимодействие Kotlin/Native. Используйте его для реализаций API expect/actual на iOS.
// iosMain/kotlin/com/example/platform/PlatformLogger.kt
import platform.Foundation.NSLog
class IosLogger : Logger {
override fun log(msg: String) = NSLog(msg)
}
// iOS uses Kotlin/Native runtime; no JVM hereКонфигурация Gradle для целей iOS
Для iOS обычно объявляют три цели: x64 (эмулятор на процессоре Intel), arm64 (устройство) и simulatorArm64 (эмулятор на Apple Silicon).
// build.gradle.kts
kotlin {
iosX64()
iosArm64()
iosSimulatorArm64()
sourceSets {
val iosMain by creating {
dependsOn(commonMain.get())
}
val iosX64Main by getting { dependsOn(iosMain) }
val iosArm64Main by getting { dependsOn(iosMain) }
val iosSimulatorArm64Main by getting { dependsOn(iosMain) }
}
}Общие зависимости в commonMain
Добавляйте общие зависимости (Ktor, SQLDelight, kotlinx.serialization, Koin) в commonMain. Платформенные драйверы размещайте в наборах исходного кода соответствующих платформ.
// commonMain dependencies example:
// implementation("io.ktor:ktor-client-core:2.3.0")
// implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
// implementation("io.insert-koin:koin-core:3.4.0")
// androidMain:
// implementation("io.ktor:ktor-client-okhttp:2.3.0")
// iosMain:
// implementation("io.ktor:ktor-client-darwin:2.3.0")commonTest: общие тесты
Тесты в commonTest запускаются на всех целевых платформах. Используйте библиотеку тестирования Kotlin и пишите независимые от платформы модульные тесты для общей бизнес-логики.
// commonTest/kotlin/UserRepositoryTest.kt
import kotlin.test.Test
import kotlin.test.assertEquals
class UserRepositoryTest {
@Test
fun testUserCreation() {
val user = User("1", "Alice", "alice@example.com")
assertEquals("Alice", user.name)
}
}Промежуточные наборы исходного кода
Можно создавать промежуточные наборы исходного кода, общие для подмножества целевых платформ, например nativeMain для всех нативных платформ или appleMain для iOS и macOS.
// Create appleMain shared between iOS and macOS:
sourceSets {
val appleMain by creating { dependsOn(commonMain.get()) }
val iosMain by getting { dependsOn(appleMain) }
val macosMain by getting { dependsOn(appleMain) }
}Структура файлов проекта
Типичная структура каталогов общего модуля KMP, которая помогает чётко разделить зоны ответственности.
// shared/
// build.gradle.kts
// src/
// commonMain/kotlin/
// domain/ User.kt, Post.kt
// repository/ UserRepository.kt
// usecase/ GetUserUseCase.kt
// androidMain/kotlin/
// repository/ RoomUserRepository.kt
// iosMain/kotlin/
// repository/ CoreDataUserRepository.kt
// commonTest/kotlin/ GetUserUseCaseTest.ktИнтеграция CocoaPods / SPM
Плагин KMP для Gradle создаёт XCFramework (или модуль CocoaPods), который добавляется в проект Xcode и предоставляет общий код Kotlin как нативный фреймворк.
// build.gradle.kts for CocoaPods:
kotlin {
cocoapods {
name = "Shared"
version = "1.0"
ios.deploymentTarget = "14.0"
framework { baseName = "Shared" }
}
}
// Run: ./gradlew :shared:podPublishReleaseXCFrameworkБыстрая проверка
Где в проекте KMP следует размещать общую бизнес-логику (доменные модели и сценарии использования)?
Итоги
commonMain содержит общую логику (доменный слой, репозитории и сценарии использования). androidMain/iosMain содержат платформенные реализации. commonTest запускает тесты на всех целевых платформах. Зависимости разделяются: общие API находятся в commonMain, а платформенные драйверы — в наборах исходного кода платформ.
Часто задаваемые вопросы
Урок «Структура проекта KMP: commonMain, androidMain, iosMain» бесплатный?
Да — полный текст урока «Структура проекта KMP: commonMain, androidMain, iosMain» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.
Чему я научусь в уроке «Структура проекта KMP: commonMain, androidMain, iosMain»?
Разберитесь в иерархии наборов исходного кода и в совместном использовании кода между целевыми платформами. Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Kotlin Academy?
Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Структура проекта KMP: commonMain, androidMain, iosMain»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Kotlin Academy?
Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Структура проекта KMP: commonMain, androidMain, iosMain
- Механизм expect/actual для API платформ
- Общие слои репозитория и вариантов использования
- Внедрение зависимостей в KMP с Koin