Spec-Zone.ru › Kotlin 1.8

Обмен кодом между платформами

С помощью Kotlin Multiplatform вы можете обмениваться кодом, используя механизмы, предоставляемые Kotlin:

  • Обмен кодом между всеми платформами вашего проекта. Используйте его для обмена общей бизнес-логикой, которая применима ко всем платформам.

  • Обмен кодом между некоторыми платформами вашего проекта, но не со всеми. Вы можете повторно использовать большую часть кода на похожих платформах, используя иерархическую структуру. Вы можете использовать ярлыки для целей для общих комбинаций целей или создать иерархическую структуру вручную.

Если вам нужно получить доступ к платформно-специфичным API из общего кода, используйте механизм Kotlin ожидаемых и фактических объявлений.

Обмен кодом на всех платформах

Если у вас есть бизнес-логика, общая для всех платформ, вам не нужно писать одинаковый код для каждой платформы – просто поделитесь им в общем наборе исходных кодов.

Code shared for all platforms

Некоторые зависимости для наборов исходных кодов задаются по умолчанию. Вам не нужно указывать какие-либо 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, она включена по умолчанию. Подробнее см. Иерархическую структуру проекта.

Существует два способа создания иерархической структуры:

  • Использовать сокращения для целей, чтобы легко создать иерархическую структуру для общих комбинаций нативных целей.

  • Настроить иерархическую структуру вручную.

Узнайте больше о обмене кодом в библиотеках и использовании нативных библиотек в иерархической структуре.

Из-за известной проблемы, вы не сможете использовать возможности IDE, такие как автодополнение и подсветка кода, для общего нативного исходного набора в многоплатформенном проекте с поддержкой иерархической структуры, если ваш проект зависит от:

  • Многоплатформенных библиотек, которые не поддерживают иерархическую структуру.

  • Библиотеки сторонних производителей с нативным кодом, за исключением платформенных библиотек, поддерживаемых по умолчанию.

Эта проблема относится только к общему нативному исходному набору. IDE корректно будет поддерживать остальной код.

Узнайте, как решить эту проблему для аналогичных исходных наборов, таких как iosArm64 и iosX64.

Использование сокращений для целей

В типичном многоплатформенном проекте с двумя целями, связанными с iOS – iosArm64 и iosX64, иерархическая структура включает промежуточный исходный набор (iosMain), который используется нативными исходными наборами, специфичными для платформы.

Code shared for iOS targets

Плагин kotlin-multiplatform предоставляет сокращения для целей, для создания структур для общих комбинаций целей.

Сокращение для цели

Цели

ios

iosArm64, iosX64

watchos

watchosArm32, watchosArm64, watchosX64

tvos

tvosArm64, tvosX64

Все сокращения создают похожие иерархические структуры в коде. Например, сокращение 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, измените скрипт сборки следующим образом:

  1. Добавьте необходимую цель симулятора *SimulatorArm64.

  2. Свяжите цель симулятора с сокращением, используя зависимости исходных наборов (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)
        }
    }
}

Настройка иерархической структуры вручную

Чтобы создать иерархическую структуру вручную, добавьте промежуточный исходный набор, который содержит общий код для нескольких целей, и создайте структуру исходных наборов, включая промежуточный.

Hierarchical structure

Например, если вы хотите обмениваться кодом между нативными целями Linux, Windows и macOS – linuxX64M, mingwX64, и macosX64:

  1. Добавьте промежуточный исходный набор desktopMain, который содержит общую логику для этих целей.

  2. Укажите иерархию исходных наборов, используя отношение 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:

Library hierarchical structure

Исходный набор 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

  • Узнайте больше о иерархической структуре проекта

Последнее изменение: 10 января 2023
Публикация многоплатформенных библиотек Подключение к платформно-специфичным API

© 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API