Обмен кодом между платформами
С помощью Kotlin Multiplatform вы можете обмениваться кодом, используя механизмы, предоставляемые Kotlin:
Обмен кодом между всеми платформами вашего проекта. Используйте его для обмена общей бизнес-логикой, которая применима ко всем платформам.
Обмен кодом между некоторыми платформами вашего проекта, но не со всеми. Вы можете повторно использовать большую часть кода на похожих платформах, используя иерархическую структуру. Вы можете использовать ярлыки для целей для общих комбинаций целей или создать иерархическую структуру вручную.
Если вам нужно получить доступ к платформно-специфичным API из общего кода, используйте механизм Kotlin ожидаемых и фактических объявлений.
Обмен кодом на всех платформах
Если у вас есть бизнес-логика, общая для всех платформ, вам не нужно писать одинаковый код для каждой платформы – просто поделитесь им в общем наборе исходных кодов.

Некоторые зависимости для наборов исходных кодов задаются по умолчанию. Вам не нужно указывать какие-либо dependsOn связи вручную:
Для всех наборов исходных кодов, специфичных для платформы, которые зависят от общего набора исходных кодов, таких как
jvmMain,macosX64Main, и другие.Между наборами исходных кодов
mainиtestконкретной цели, такой какandroidMainиandroidTest.
Если вам нужно получить доступ к платформно-специфичным API из общего кода, используйте механизм Kotlin ожидаемых и фактических объявлений.
Обмен кодом на похожих платформах
Часто требуется создать несколько нативных целей, которые потенциально могут повторно использовать много общей логики и API сторонних библиотек.
Например, в типичном многоплатформенном проекте, нацеленном на iOS, есть две цели, связанные с iOS: одна для устройств iOS ARM64, другая для симулятора x64. У них есть отдельные нативные исходные наборы, но на практике редко возникает необходимость в разном коде для устройства и симулятора, и их зависимости очень похожи. Поэтому код, специфичный для iOS, можно использовать совместно.
Очевидно, в такой настройке желательно иметь общий исходный набор для двух целей iOS с кодом Kotlin/Native, который всё ещё может напрямую вызывать любой API, общий как для устройства iOS, так и для симулятора.
В этом случае вы можете обмениваться кодом между нативными целями в своём проекте, используя иерархическую структуру. Начиная с Kotlin 1.6.20, она включена по умолчанию. Подробнее см. Иерархическую структуру проекта.
Существует два способа создания иерархической структуры:
Использовать сокращения для целей, чтобы легко создать иерархическую структуру для общих комбинаций нативных целей.
Узнайте больше о обмене кодом в библиотеках и использовании нативных библиотек в иерархической структуре.
Использование сокращений для целей
В типичном многоплатформенном проекте с двумя целями, связанными с iOS – iosArm64 и iosX64, иерархическая структура включает промежуточный исходный набор (iosMain), который используется нативными исходными наборами, специфичными для платформы.

Плагин kotlin-multiplatform предоставляет сокращения для целей, для создания структур для общих комбинаций целей.
Сокращение для цели |
Цели |
|---|---|
|
|
|
|
|
|
Все сокращения создают похожие иерархические структуры в коде. Например, сокращение ios создаёт следующую иерархическую структуру:
kotlin {
sourceSets{
val commonMain by sourceSets.getting
val iosX64Main by sourceSets.getting
val iosArm64Main by sourceSets.getting
val iosMain by sourceSets.creating {
dependsOn(commonMain)
iosX64Main.dependsOn(this)
iosArm64Main.dependsOn(this)
}
}
}
kotlin {
sourceSets{
iosMain {
dependsOn(commonMain)
iosX64Main.dependsOn(it)
iosArm64Main.dependsOn(it)
}
}
}
Сокращения для целей и симуляторы ARM64 (Apple Silicon)
Сокращения для целей ios, watchos, и tvos не включают цели симулятора для платформ ARM64 (Apple Silicon): iosSimulatorArm64, watchosSimulatorArm64, и tvosSimulatorArm64. Если вы используете сокращения для целей и хотите скомпилировать проект для симулятора Apple Silicon, измените скрипт сборки следующим образом:
Добавьте необходимую цель симулятора
*SimulatorArm64.Свяжите цель симулятора с сокращением, используя зависимости исходных наборов (
dependsOn).
kotlin {
ios()
// Add the ARM64 simulator target
iosSimulatorArm64()
val iosMain by sourceSets.getting
val iosTest by sourceSets.getting
val iosSimulatorArm64Main by sourceSets.getting
val iosSimulatorArm64Test by sourceSets.getting
// Set up dependencies between the source sets
iosSimulatorArm64Main.dependsOn(iosMain)
iosSimulatorArm64Test.dependsOn(iosTest)
}
kotlin {
ios()
// Add the ARM64 simulator target
iosSimulatorArm64()
// Set up dependencies between the source sets
sourceSets {
// ...
iosSimulatorArm64Main {
dependsOn(iosMain)
}
iosSimulatorArm64Test {
dependsOn(iosTest)
}
}
}
Настройка иерархической структуры вручную
Чтобы создать иерархическую структуру вручную, добавьте промежуточный исходный набор, который содержит общий код для нескольких целей, и создайте структуру исходных наборов, включая промежуточный.

Например, если вы хотите обмениваться кодом между нативными целями Linux, Windows и macOS – linuxX64M, mingwX64, и macosX64:
Добавьте промежуточный исходный набор
desktopMain, который содержит общую логику для этих целей.Укажите иерархию исходных наборов, используя отношение
dependsOn.
kotlin{
sourceSets {
val desktopMain by creating {
dependsOn(commonMain)
}
val linuxX64Main by getting {
dependsOn(desktopMain)
}
val mingwX64Main by getting {
dependsOn(desktopMain)
}
val macosX64Main by getting {
dependsOn(desktopMain)
}
}
}
kotlin {
sourceSets {
desktopMain {
dependsOn(commonMain)
}
linuxX64Main {
dependsOn(desktopMain)
}
mingwX64Main {
dependsOn(desktopMain)
}
macosX64Main {
dependsOn(desktopMain)
}
}
}
Вы можете иметь общий исходный набор для следующих комбинаций целей:
JVM или Android + JS + Native
JVM или Android + Native
JS + Native
JVM или Android + JS
Native
Kotlin в настоящее время не поддерживает общий исходный набор для следующих комбинаций:
Несколько целей JVM
JVM + Android цели
Несколько целей JS
Если вам нужно получить доступ к платформам-специфичным API из общего нативного исходного набора, IntelliJ IDEA поможет вам определить общие объявления, которые можно использовать в общем нативном коде. В других случаях используйте механизм Kotlin для ожидаемых и фактических объявлений.
Обмен кодом в библиотеках
Благодаря иерархической структуре проекта, библиотеки также могут предоставлять общий API для подмножества целей. Когда библиотека опубликована, API её промежуточных исходных наборов включён в артефакты библиотеки вместе с информацией о структуре проекта. Когда вы используете эту библиотеку, промежуточные исходные наборы вашего проекта получают доступ только к тем API библиотеки, которые доступны для каждой цели.
Например, рассмотрите следующую иерархию исходных наборов из репозитория kotlinx.coroutines:

Исходный набор concurrent объявляет функцию runBlocking и компилируется для JVM и нативных целей. После того, как библиотека kotlinx.coroutines обновлена и опубликована с иерархической структурой проекта, вы можете зависеть от неё и вызывать runBlocking из исходного набора, который общий для JVM и нативных целей, поскольку он соответствует «подписи целей» исходного набора библиотеки concurrent.
Использование нативных библиотек в иерархической структуре
Вы можете использовать платформенно-зависимые библиотеки, такие как Foundation, UIKit, и POSIX в исходных наборах, общих для нескольких нативных целей. Это помогает обмениваться нативным кодом, не ограничиваясь платформенно-специфическими зависимостями.
Начиная с Kotlin 1.6.20, использование платформенно-зависимых библиотек доступно в общих исходных наборах по умолчанию. Не требуется никаких дополнительных шагов – IntelliJ IDEA поможет вам определить общие объявления, которые можно использовать в общем коде. Подробнее см. Иерархическая структура проекта.
В дополнение к платформенным библиотекам, поставляемым с Kotlin/Native, этот подход также может обрабатывать настраиваемые cinterop библиотеки, делая их доступными в общих исходных наборах. Для включения этой поддержки укажите дополнительный ключ kotlin.mpp.enableCInteropCommonization:
kotlin.mpp.enableCInteropCommonization=true
Что дальше?
Посмотрите примеры совместного использования кода с помощью механизма Kotlin объявлений expect и actual
Узнайте больше о иерархической структуре проекта
© 2010–2023 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/multiplatform-share-on-platforms.html