Spec-Zone.ru › Kotlin 1.4

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

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

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

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

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

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

Code shared for all platforms

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

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

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

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

Например, в типичном проекте multiplatform, нацеленном на iOS, есть две целевые платформы, связанные с iOS: одна для устройств iOS ARM64, другая для симулятора x64. У них есть отдельные наборы исходных файлов, специфичные для платформы, но на практике редко возникает необходимость в различном коде для устройства и симулятора, и их зависимости во многом одинаковы. Таким образом, код, специфичный для iOS, можно обмениваться между ними.

Очевидно, в этой настройке желательно иметь общий набор исходных файлов для двух целевых платформ iOS, с кодом Kotlin/Native, который по-прежнему может напрямую вызывать любой из API, общий как для устройства iOS, так и для симулятора.

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

Для включения поддержки иерархической структуры добавьте следующий флаг в ваш gradle.properties.

kotlin.mpp.enableGranularSourceSetsMetadata=true

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

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

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

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

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

Code shared for iOS targets

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

Сокращение для целейЦелевые платформы
ios iosArm64, iosX64
watchos watchosArm32, watchosArm64, watchosX86
tvos tvosArm64, tvosX64

Все сокращения создают аналогичные иерархические структуры в коде. Например, сокращение ios создает следующую иерархическую структуру:

kotlin {
    sourceSets{
        iosMain {
            dependsOn(commonMain)
            iosX64Main.dependsOn(it)
            iosArm64Main.dependsOn(it)
        }
    }
}
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)
        }
    }
}

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

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

Hierarchical structure

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

  1. Добавьте промежуточный набор исходных файлов desktopMain, который содержит общую логику для этих платформ.
  2. Укажите иерархию наборов исходных файлов с помощью dependsOn связи.
kotlin {
    sourceSets {
        desktopMain {
            dependsOn(commonMain)
        }
        linuxX64Main {
            dependsOn(desktopMain)
        }
        mingwX64Main {
            dependsOn(desktopMain)
        }
        macosX64Main {
            dependsOn(desktopMain)
        }
    }
}

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)
        }
    }
}

Вы можете иметь общий набор исходных файлов для следующих комбинаций целевых платформ:

  • JVM + JS + Native
  • JVM + Native
  • JS + Native
  • JVM + JS
  • Native

В настоящее время мы не поддерживаем совместное использование набора исходных файлов для этих комбинаций:

  • Несколько целевых платформ 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, в наборах исходных файлов, общих для нескольких целевых нативных платформ. Это помогает обмениваться большем нативным кодом, не ограничиваясь зависимостями, специфичными для платформы.

Дополнительные шаги не требуются — все выполняется автоматически. IntelliJ IDEA поможет вам обнаружить общие декларации, которые можно использовать в общем коде.

Однако, обратите внимание на некоторые ограничения:

  • Этот подход работает только для нативного набора исходных файлов, который совместно используется между наборами исходных файлов, специфичными для платформы. Он не работает для нативных наборов исходных файлов, общих на более высоких уровнях иерархии набора исходных файлов.
    Например, если у вас nativeDarwinMain является родителем watchosMain и iosMain, где iosMain имеет двух потомков — iosArm64Main и iosX64Main, вы можете использовать платформозависимые библиотеки только для iosMain, но не для nativeDarwinMain.
  • Он работает только для библиотек межплатформенного взаимодействия, поставляемых с Kotlin/Native.

Чтобы включить использование платформозависимых библиотек в общих наборах исходных файлов, добавьте следующее в свой gradle.properties:

kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false

Узнайте больше о технических деталях.

© 2010–2020 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/reference/mpp-share-on-platforms.html

Spec-Zone.ru

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