Spec-Zone.ru › Kotlin 1.6

Разделение кода на платформах

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

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

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

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

Разделение кода на всех платформах

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

Code shared for all platforms

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

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

END_OF_DOCUMENT_MARKER

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

Часто требуется создать несколько нативных целей, которые могут потенциально повторно использовать много общей логики и 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 + JS + Native

  • JVM + Native

  • JS + Native

  • JVM + 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
Последнее изменение: 07 апреля 2022
Создание и публикация многоплатформенной библиотеки – учебник Подключение к платформа-специфичным API

© 2010–2022 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