Руководство по совместимости Kotlin Multiplatform
В этом руководстве приводится краткий обзор несовместимых изменений, с которыми вы можете столкнуться при разработке проектов с Kotlin Multiplatform.
Текущая стабильная версия Kotlin — 2.4.20. Учитывайте цикл устаревания конкретного изменения применительно к версии Kotlin в ваших проектах, например:
При обновлении с Kotlin 1.7.0 до Kotlin 1.9.0 проверьте несовместимые изменения, вступившие в силу как в Kotlin 1.9.0, так и в Kotlin 1.7.0−1.8.22.
При обновлении с Kotlin 1.9.0 до Kotlin 2.0.0 проверьте несовместимые изменения, вступившие в силу как в Kotlin 2.0.0, так и в Kotlin 1.9.0−1.9.25.
Совместимость версий
При настройке проекта проверьте совместимость конкретной версии плагина Kotlin Multiplatform Gradle (она совпадает с версией Kotlin в вашем проекте) с версиями Gradle, Xcode и Android Gradle Plugin:
Версия плагина Kotlin Multiplatform |
Gradle |
Android Gradle Plugin |
Xcode |
|---|---|---|---|
2.4.20 |
7.6.3–9.7.0 |
8.5.2–9.3.1 |
26.4 |
2.4.0-2.4.10 |
7.6.3–9.5.0 |
8.5.2–9.1.0 |
26.4 |
2.3.20–2.3.21 |
7.6.3–9.3.0 |
8.2.2–9.0.0 |
26.0 |
2.3.10 |
7.6.3–9.0.0 |
8.2.2–9.0.0 |
26.0 |
2.3.0 |
7.6.3–9.0.0 |
8.2.2–8.13.0 |
26.0 |
2.2.21 |
7.6.3–8.14 |
7.3.1–8.11.1 |
26.0 |
2.2.20 |
7.6.3–8.14 |
7.3.1–8.11.1 |
16.4 |
2.2.0–2.2.10 |
7.6.3–8.14 |
7.3.1–8.10.0 |
16.3 |
2.1.21 |
7.6.3–8.12.1 |
7.3.1–8.7.2 |
16.3 |
2.1.20 |
7.6.3–8.11 |
7.4.2–8.7.2 |
16.0 |
2.1.0–2.1.10 |
7.6.3-8.10* |
7.4.2–8.7.2 |
16.0 |
2.0.21 |
7.5-8.8* |
7.4.2–8.5 |
16.0 |
2.0.20 |
7.5-8.8* |
7.4.2–8.5 |
15.3 |
2.0.0 |
7.5-8.5 |
7.4.2–8.3 |
15.3 |
1.9.20 |
7.5-8.1.1 |
7.4.2–8.2 |
15.0 |
Kotlin 2.0.0 и более поздние версии
В этом разделе описаны несовместимые изменения, которые завершают цикл устаревания и вступают в силу в Kotlin 2.0.0–2.4.20.
Переход на плагин Google для целевых платформ Android
Что изменилось?
До Kotlin 2.3.0 мы предоставляли поддержку целевой платформы Android с помощью плагинов com.android.application и com.android.library. Это было временное решение на период разработки командой Android в Google отдельного плагина, предназначенного для Kotlin Multiplatform.
Изначально мы использовали блок android, но позднее перешли на блок androidTarget, чтобы имя android можно было зарезервировать для нового плагина.
Теперь команда Android предоставляет плагин com.android.kotlin.multiplatform.library, который можно использовать с исходными блоками android.
В Kotlin 2.3.0 появляется предупреждение об устаревании, если в проектах Kotlin Multiplatform используется имя androidTarget. Если вам нужно больше времени для перехода на блок android, используйте Kotlin 2.3.10 с AGP 8.x, где это предупреждение не появляется.
Как теперь лучше поступить?
Перейдите на новый плагин com.android.kotlin.multiplatform.library. Переименуйте все вхождения блока androidTarget в android. Подробные инструкции по переходу см. в руководстве по миграции Google.
Когда изменения вступят в силу?
Ниже приведен цикл устаревания для плагина Kotlin Multiplatform Gradle:
1.9.0: добавить предупреждение об устаревании при использовании имени
androidв проектах Kotlin Multiplatform2.1.0: повысить уровень этого предупреждения до ошибки
2.2.0: удалить DSL целевой платформы
androidиз плагина Kotlin Multiplatform Gradle2.3.0: становится доступен новый плагин Android; добавить предупреждение об устаревании при использовании имени
androidTargetв проектах Kotlin Multiplatform.2.3.10: отменить предупреждение об устаревании при использовании имени
androidTargetв проектах Kotlin Multiplatform.
Устаревшее встраивание биткода
Что изменилось?
Встраивание биткода устарело в Xcode 14 и было удалено в Xcode 15 для всех целевых платформ Apple. В связи с этим в Kotlin устаревают параметр embedBitcode для конфигурации фреймворка, а также аргументы командной строки -Xembed-bitcode и -Xembed-bitcode-marker.
Как теперь лучше поступить?
Если вы по-прежнему используете более ранние версии Xcode, но хотите перейти на Kotlin 2.0.20 или более позднюю версию, отключите встраивание биткода в проектах Xcode.
Когда изменения вступят в силу?
Ниже приведен планируемый цикл устаревания:
2.0.20: компилятор Kotlin/Native больше не поддерживает встраивание биткода
2.1.0: DSL
embedBitcodeустаревает в плагине Kotlin Multiplatform Gradle с выдачей предупреждения2.2.0: предупреждение повышается до ошибки
2.3.0: DSL
embedBitcodeудаляется
Наборы исходного кода Java создаются по умолчанию
Что изменилось?
Чтобы привести Kotlin Multiplatform в соответствие с предстоящими изменениями в Gradle, мы постепенно отказываемся от функции withJava(). Функция withJava() обеспечивала интеграцию с плагинами Java для Gradle, создавая необходимые наборы исходного кода Java. Начиная с Kotlin 2.1.20 эти наборы исходного кода Java создаются по умолчанию.
Как теперь лучше поступить?
Раньше для создания наборов исходного кода src/jvmMain/java и src/jvmTest/java требовалось явно использовать функцию withJava():
kotlin {
jvm {
withJava()
}
}
Начиная с Kotlin 2.1.20, функцию withJava() можно удалить из скрипта сборки.
Кроме того, теперь Gradle запускает задачи компиляции Java, только если в проекте есть исходный код Java. Это приводит к выполнению диагностики проверки JVM, которая раньше не запускалась. Диагностика завершается ошибкой, если для задач KotlinJvmCompile или внутри compilerOptions явно настроена несовместимая целевая платформа JVM. Рекомендации по обеспечению совместимости целевых платформ JVM см. в разделе Проверка совместимости целевых платформ JVM связанных задач компиляции.
Если в вашем проекте используется версия Gradle выше 8.7 и он не зависит от плагинов Java для Gradle, таких как Java, Java Library или Application, либо от стороннего плагина Gradle, зависящего от плагина Java для Gradle, функцию withJava() можно удалить.
Если в проекте используется плагин Java для Gradle Application, рекомендуем перейти на новый экспериментальный DSL. Начиная с Gradle 8.7 плагин Application больше не будет работать с плагином Kotlin Multiplatform Gradle.
Если в многоплатформенном проекте вы хотите использовать плагин Kotlin Multiplatform Gradle вместе с другими плагинами Gradle для Java, см. раздел Устаревшая совместимость плагина Kotlin Multiplatform Gradle с плагинами Java.
Если вы используете плагин Gradle Java test fixtures с Kotlin 2.1.20 и версией Gradle выше 8.7, этот плагин не работает. Вместо этого перейдите на Kotlin 2.1.21, где эта проблема устранена.
Если у вас возникнут проблемы, сообщите о них в трекере задач или попросите о помощи в нашем открытом канале Slack.
Когда изменения вступят в силу?
Ниже приведен планируемый цикл устаревания:
Gradle >8.6: добавить предупреждение об устаревании для любой предыдущей версии Kotlin в многоплатформенных проектах, использующих функцию
withJava().Gradle 9.0: повысить уровень этого предупреждения до ошибки.
2.1.20: добавить предупреждение об устаревании при использовании функции
withJava()с любой версией Gradle.
Объявление нескольких схожих целевых платформ
Что изменилось?
Мы не рекомендуем объявлять несколько схожих целевых платформ в одном проекте Gradle. Например:
kotlin {
jvm("jvmKtor")
jvm("jvmOkHttp") // Not recommended and produces a deprecation warning
}
Один из распространенных вариантов — объединить два связанных фрагмента кода. Например, в проекте Gradle :shared может потребоваться использовать jvm("jvmKtor") и jvm("jvmOkHttp") для реализации сетевого взаимодействия с помощью библиотек Ktor или OkHttp:
// shared/build.gradle.kts:
kotlin {
jvm("jvmKtor") {
attributes.attribute(/* ... */)
}
jvm("jvmOkHttp") {
attributes.attribute(/* ... */)
}
sourceSets {
val commonMain by getting
val commonJvmMain by sourceSets.creating {
dependsOn(commonMain)
dependencies {
// Shared dependencies
}
}
val jvmKtorMain by getting {
dependsOn(commonJvmMain)
dependencies {
// Ktor dependencies
}
}
val jvmOkHttpMain by getting {
dependsOn(commonJvmMain)
dependencies {
// OkHttp dependencies
}
}
}
}
Такая реализация требует нетривиальной настройки:
Необходимо настроить атрибуты Gradle на стороне
:sharedи на стороне каждого потребителя. Иначе Gradle не сможет разрешить зависимости в таких проектах, поскольку без дополнительной информации неясно, следует ли предоставить потребителю реализацию на основе Ktor или OkHttp.Необходимо вручную настроить набор исходного кода
commonJvmMain.Для настройки используются несколько низкоуровневых абстракций и API Gradle и плагина Kotlin Gradle.
Как теперь лучше поступить?
Настройка сложна, потому что реализации на основе Ktor и OkHttp находятся в одном проекте Gradle. Во многих случаях эти части можно вынести в отдельные проекты Gradle. Ниже приведен общий план такого рефакторинга:
-
Замените две дублирующиеся целевые платформы в исходном проекте одной целевой платформой. Если у этих целевых платформ есть общий набор исходного кода, перенесите его исходный код и конфигурацию в набор исходного кода по умолчанию новой целевой платформы:
// shared/build.gradle.kts: kotlin { jvm() sourceSets { jvmMain { // Copy the configuration of jvmCommonMain here } } } -
Добавьте два новых проекта Gradle, обычно вызвав
includeв файлеsettings.gradle.kts. Например:include(":okhttp-impl") include(":ktor-impl") -
Настройте каждый новый проект Gradle:
Скорее всего, вам не потребуется применять плагин
kotlin("multiplatform"), поскольку эти проекты компилируются только для одной целевой платформы. В этом примере можно применитьkotlin("jvm").Перенесите содержимое исходных наборов, относящихся к целевым платформам, в соответствующие проекты, например из
jvmKtorMainвktor-impl/src.Скопируйте конфигурацию наборов исходного кода: зависимости, параметры компилятора и т. д.
Добавьте зависимость нового проекта Gradle от исходного проекта.
// ktor-impl/build.gradle.kts: plugins { kotlin("jvm") } dependencies { project(":shared") // Add dependency on the original project // Copy dependencies of jvmKtorMain here } kotlin { compilerOptions { // Copy compiler options of jvmKtorMain here } }
Хотя такой подход требует больше усилий при первоначальной настройке, он не использует низкоуровневые сущности Gradle и плагина Kotlin Gradle, поэтому итоговую сборку проще использовать и поддерживать.
Когда изменения вступят в силу?
Ниже приведен планируемый цикл устаревания:
1.9.20: добавить предупреждение об устаревании при использовании нескольких схожих целевых платформ в проектах Kotlin Multiplatform
2.1.0: сообщать об ошибке в таких случаях, за исключением целевых платформ Kotlin/JS; подробнее об этом исключении см. запрос в YouTrack
Устаревшая поддержка многоплатформенных библиотек, опубликованных в устаревшем режиме
Что изменилось?
Ранее мы объявили устаревшим устаревший режим в проектах Kotlin Multiplatform, который предотвращает публикацию «устаревших» бинарных файлов, и рекомендовали перенести проекты на иерархическую структуру.
Чтобы продолжить постепенный отказ от «устаревших» бинарных файлов в экосистеме, начиная с Kotlin 1.9.0 мы также не рекомендуем использовать устаревшие библиотеки. Если проект зависит от устаревших библиотек, вы увидите следующее предупреждение:
The dependency group:artifact:1.0 was published in the legacy mode. Support for such dependencies will be removed in the future
Как теперь лучше поступить?
Если вы используете многоплатформенные библиотеки, большинство из них уже перешло в режим «иерархической структуры», поэтому достаточно обновить версию библиотеки. Подробности см. в документации соответствующих библиотек.
Если библиотека пока не поддерживает бинарные файлы, не относящиеся к устаревшему режиму, свяжитесь с ее сопровождающими и сообщите им об этой проблеме совместимости.
Если вы автор библиотеки, обновите плагин Kotlin Gradle до последней версии и убедитесь, что вы исправили устаревшие свойства Gradle.
Команда Kotlin стремится помочь экосистеме выполнить переход, поэтому, если у вас возникнут проблемы, создайте запрос в YouTrack.
Когда изменения вступят в силу?
Ниже приведен планируемый цикл устаревания:
1.9.0: добавить предупреждение об устаревании для зависимостей от устаревших библиотек
2.0.0: повысить уровень предупреждения для зависимостей от устаревших библиотек до ошибки
>2.0.0: удалить поддержку зависимостей от устаревших библиотек; использование таких зависимостей может привести к сбоям сборки
Устаревшие свойства Gradle для поддержки иерархической структуры
Что изменилось?
В ходе развития Kotlin поддержка иерархической структуры постепенно добавлялась в многоплатформенные проекты. Она позволяет создавать промежуточные наборы исходного кода между общим набором исходного кода commonMain и набором для конкретной платформы, например jvmMain.
На переходный период, пока цепочка инструментов была недостаточно стабильной, были добавлены несколько свойств Gradle, позволяющих гибко включать и отключать эту возможность.
Начиная с Kotlin 1.6.20 поддержка иерархической структуры проекта включена по умолчанию. Однако эти свойства сохранили, чтобы можно было отключить ее при возникновении блокирующих проблем. После обработки всех отзывов мы начинаем полностью отказываться от этих свойств.
Теперь следующие свойства объявлены устаревшими:
kotlin.internal.mpp.hierarchicalStructureByDefaultkotlin.mpp.enableCompatibilityMetadataVariantkotlin.mpp.hierarchicalStructureSupportkotlin.mpp.enableGranularSourceSetsMetadatakotlin.native.enableDependencyPropagation
Как теперь лучше поступить?
Удалите эти свойства из файлов
gradle.propertiesиlocal.properties.Не задавайте их программно в скриптах сборки Gradle или плагинах Gradle.
Если устаревшие свойства задаются сторонним плагином Gradle, используемым в вашей сборке, попросите сопровождающих плагина не задавать эти свойства.
Поскольку с Kotlin 1.6.20 поведение цепочки инструментов Kotlin по умолчанию не зависит от таких свойств, мы не ожидаем серьезных последствий. Большинство изменений будет заметно сразу после повторной сборки проекта.
Если вы автор библиотеки и хотите подстраховаться, проверьте, что потребители могут использовать вашу библиотеку.
Когда изменения вступят в силу?
Ниже приведен планируемый цикл устаревания:
1.8.20: выводить предупреждение при использовании устаревших свойств Gradle
1.9.20: повысить уровень этого предупреждения до ошибки
2.0.0: удалить устаревшие свойства; плагин Kotlin Gradle игнорирует их использование
Если маловероятные проблемы все же возникнут после удаления этих свойств, создайте запрос в YouTrack.
Устаревший API предустановок целевых платформ
Что изменилось?
На самых ранних этапах разработки в Kotlin Multiplatform появился API для работы с так называемыми предустановками целевых платформ. Каждая предустановка по сути представляла собой фабрику целевых платформ Kotlin Multiplatform. Этот API оказался во многом избыточным, поскольку функции DSL, такие как jvm() или iosSimulatorArm64(), решают те же задачи, но значительно проще и лаконичнее.
Чтобы уменьшить путаницу и предоставить более ясные рекомендации, все API, связанные с предустановками, теперь объявлены устаревшими в публичном API плагина Kotlin Gradle. К ним относятся:
Свойство
presetsвorg.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtensionИнтерфейс
org.jetbrains.kotlin.gradle.plugin.KotlinTargetPresetи все его наследникиПерегрузки
fromPreset
Как теперь лучше поступить?
Вместо них используйте соответствующие целевые платформы Kotlin, например:
Раньше |
Теперь |
|---|---|
kotlin {
targets {
fromPreset(presets.iosArm64, 'ios')
}
}
|
kotlin {
iosArm64()
}
|
Когда изменения вступят в силу?
Ниже приведен планируемый цикл устаревания:
1.9.20: выводить предупреждение при любом использовании API, связанного с предустановками
2.0.0: повысить уровень этого предупреждения до ошибки
2.2.0: удалить API, связанный с предустановками, из публичного API плагина Kotlin Gradle; исходный код, в котором он по-прежнему используется, завершит компиляцию с ошибками «unresolved reference», а бинарные файлы (например, плагины Gradle) могут завершиться ошибками связывания, если их не перекомпилировать с последними версиями плагина Kotlin Gradle
Устаревшие сокращения целевых платформ Apple
Что изменилось?
Мы объявляем устаревшими сокращения целевых платформ ios(), watchos() и tvos() в DSL Kotlin Multiplatform. Они были предназначены для частичного создания иерархии наборов исходного кода для целевых платформ Apple. Однако их оказалось сложно расширять, и иногда они вызывали путаницу.
Например, сокращение ios() создавало целевые платформы iosArm64 и iosX64, но не включало целевую платформу iosSimulatorArm64, необходимую для работы на компьютерах с чипами Apple M. Однако это сокращение было сложно изменить, не вызвав проблем в существующих проектах пользователей.
Как теперь лучше поступить?
Теперь плагин Kotlin Gradle предоставляет встроенный шаблон иерархии. Начиная с Kotlin 1.9.20 он включен по умолчанию и содержит предопределенные промежуточные наборы исходного кода для распространенных случаев использования.
Вместо сокращений следует указать список целевых платформ, после чего плагин автоматически настроит промежуточные наборы исходного кода на основе этого списка.
Например, если в проекте есть целевые платформы iosArm64 и iosSimulatorArm64, плагин автоматически создаст промежуточные наборы исходного кода iosMain и iosTest. Если в проекте есть целевые платформы iosArm64 и macosArm64, будут созданы наборы исходного кода appleMain и appleTest.
Подробнее см. в разделе Иерархическая структура проекта
Когда изменения вступят в силу?
Ниже приведен планируемый цикл устаревания:
1.9.20: выводить предупреждение при использовании сокращений целевых платформ
ios(),watchos()иtvos(); вместо них по умолчанию включается шаблон иерархии2.1.0: выводить ошибку при использовании сокращений целевых платформ
2.2.0: удалить DSL сокращений целевых платформ из плагина Kotlin Multiplatform Gradle
Неверная версия фреймворка iOS после обновления Kotlin
В чем проблема?
При использовании прямой интеграции изменения в коде Kotlin могут не отображаться в приложении iOS в Xcode. Прямая интеграция настраивается с помощью задачи embedAndSignAppleFrameworkForXcode, которая связывает фреймворк iOS из многоплатформенного проекта с приложением iOS в Xcode.
Это может произойти, если в многоплатформенном проекте вы обновите Kotlin с версии 1.9.2x до 2.0.0 (или вернетесь с 2.0.0 на 1.9.2x), затем внесете изменения в файлы Kotlin и попробуете собрать приложение: Xcode может ошибочно использовать предыдущую версию фреймворка iOS. Поэтому изменения не будут видны в приложении iOS в Xcode.
Как обойти эту проблему?
В Xcode очистите каталоги сборки с помощью команды Продукт | Очистить папку сборки.
-
В терминале выполните следующую команду:
./gradlew clean
Соберите приложение еще раз, чтобы убедиться, что используется новая версия фреймворка iOS.
Когда проблема будет устранена?
Мы планируем устранить эту проблему в Kotlin 2.0.10. Проверить, доступны ли предварительные версии Kotlin 2.0.10, можно в разделе Участие в программе раннего доступа Kotlin.
Подробнее см. в соответствующем запросе в YouTrack.
Kotlin 1.9.0−1.9.25
В этом разделе рассматриваются несовместимые изменения, для которых завершился цикл устаревания и которые вступают в силу в Kotlin 1.9.0−1.9.25.
Удаление API для непосредственного добавления наборов исходного кода Kotlin в компиляцию Kotlin
Что изменилось?
Доступ к KotlinCompilation.source удален. Такой код больше не поддерживается:
kotlin {
jvm()
js()
iosArm64()
iosSimulatorArm64()
sourceSets {
val commonMain by getting
val myCustomIntermediateSourceSet by creating {
dependsOn(commonMain)
}
targets["jvm"].compilations["main"].source(myCustomIntermediateSourceSet)
}
}
Как теперь лучше поступить?
Вместо KotlinCompilation.source(someSourceSet) добавьте исходные файлы непосредственно в соответствующий набор исходного кода с помощью функции .srcDir(). Или создайте новый набор исходного кода, добавив связь dependsOn от набора исходного кода по умолчанию KotlinCompilation к someSourceSet. Также можно напрямую обратиться к исходному коду с помощью соглашений для наборов исходного кода: они удобны для работы в IDE и считаются наиболее надежным подходом. Наконец, можно использовать KotlinCompilation.defaultSourceSet.dependsOn(someSourceSet), который работает во всех случаях.
Изменить код выше можно одним из следующих способов:
kotlin {
jvm()
js()
iosArm64()
iosSimulatorArm64()
sourceSets {
val myCustomIntermediateSourceSet by creating {
// The commonMain source set needs to be accessed with the
// .get() function
dependsOn(commonMain.get())
}
// Option #1. Add your sources directly to the appropriate source
// set:
commonMain {
kotlin.srcDir(layout.projectDirectory.dir("src/commonMain/my-custom-kotlin"))
}
// Option #2. Use the conventions provided with default
// Kotlin Multiplatform targets for their main and test
// source sets:
jvmMain {
dependsOn(myCustomIntermediateSourceSet)
}
// Option #3. A more generic solution. Use it if your build script
// requires a more advanced approach:
targets["jvm"].compilations["main"].defaultSourceSet.dependsOn(myCustomIntermediateSourceSet)
}
}
Когда изменения вступят в силу?
Цикл устаревания:
1.9.0: при использовании
KotlinCompilation.sourceпоявляется предупреждение об устаревании1.9.20: предупреждение становится ошибкой
2.3.0:
KotlinCompilation.sourceудаляется из плагина Kotlin Gradle, попытки использовать его приводят к ошибке «unresolved reference» при компиляции скрипта сборки
Переход с плагина kotlin-js Gradle на плагин kotlin-multiplatform Gradle
Что изменилось?
Начиная с Kotlin 1.9.0, плагин kotlin-js Gradle считается устаревшим. По сути, он дублировал функциональность плагина kotlin-multiplatform с целевой платформой js() и использовал ту же реализацию. Такое дублирование вызывало путаницу и увеличивало нагрузку на команду Kotlin по сопровождению. Рекомендуем перейти на плагин kotlin-multiplatform Gradle с целевой платформой js().
Как теперь лучше поступить?
-
Удалите плагин
kotlin-jsGradle из проекта и применитеkotlin-multiplatformв файлеsettings.gradle.kts, если используете блокpluginManagement {}:// settings.gradle.kts: pluginManagement { plugins { // Remove the following line: kotlin("js") version "1.9.0" } repositories { // ... } }// settings.gradle.kts: pluginManagement { plugins { // Add the following line instead: kotlin("multiplatform") version "1.9.0" } repositories { // ... } }Если вы применяете плагины другим способом, инструкции по миграции см. в документации Gradle.
Переместите исходные файлы из папок
mainиtestв папкиjsMainиjsTestв том же каталоге.-
Измените объявления зависимостей:
Рекомендуем использовать блок
sourceSets {}и настраивать зависимости соответствующих наборов исходного кода:jsMain {}для зависимостей production-кода иjsTest {}для тестовых зависимостей. Подробнее см. в разделе Добавление зависимостей.-
Однако, если вы хотите объявлять зависимости в блоке верхнего уровня, замените объявления
api("group:artifact:1.0")наadd("jsMainApi", "group:artifact:1.0")и так далее.
Изменить код в файле
build.gradle.ktsможно одним из следующих способов:// build.gradle.kts: plugins { kotlin("js") version "1.9.0" } dependencies { testImplementation(kotlin("test")) implementation("org.jetbrains.kotlinx:kotlinx-html:0.8.0") } kotlin { js { // ... } }// build.gradle.kts: plugins { kotlin("multiplatform") version "1.9.0" } kotlin { js { // ... } // Option #1. Declare dependencies in the sourceSets {} block: sourceSets { val jsMain by getting { dependencies { // No need for the js prefix here, you can just copy and paste it from the top-level block implementation("org.jetbrains.kotlinx:kotlinx-html:0.8.0") } } } } dependencies { // Option #2. Add the js prefix to the dependency declaration: add("jsTestImplementation", kotlin("test")) } В большинстве случаев DSL, предоставляемый плагином Kotlin Gradle внутри блока
kotlin {}, остается без изменений. Однако, если вы обращались к низкоуровневым сущностям Gradle, таким как задачи и конфигурации, по именам, теперь их нужно изменить, обычно добавив префиксjs. Например, задачуbrowserTestтеперь можно найти под именемjsBrowserTest.
Когда изменения вступят в силу?
Цикл устаревания плагина kotlin-js Gradle:
1.9.0: при использовании плагина
kotlin-jsпоявляется предупреждение об устаревании
Устаревшая предустановка jvmWithJava
Что изменилось?
targetPresets.jvmWithJava считается устаревшим, и его использование не рекомендуется.
Как теперь лучше поступить?
Вместо этого используйте целевую платформу jvm { withJava() }. Обратите внимание: после перехода на jvm { withJava() } потребуется изменить пути к каталогам с исходными файлами .java.
Например, если вы используете целевую платформу jvm с именем по умолчанию «jvm»:
Раньше |
Теперь |
|---|---|
|
|
|
|
Когда изменения вступят в силу?
Планируемый цикл устаревания:
1.3.40: при использовании
targetPresets.jvmWithJavaпоявляется предупреждение1.9.20: предупреждение становится ошибкой
>1.9.20: API
targetPresets.jvmWithJavaудаляется; попытки его использовать приводят к сбою компиляции скрипта сборки
Устаревшая компоновка наборов исходного кода Android
Что изменилось?
Новая компоновка наборов исходного кода Android используется по умолчанию начиная с Kotlin 1.9.0. Поддержка устаревшей компоновки прекращается, и использование свойства Gradle kotlin.mpp.androidSourceSetLayoutVersion теперь вызывает предупреждение об устаревании.
Когда изменения вступят в силу?
Цикл устаревания:
<=1.9.0: при использовании
kotlin.mpp.androidSourceSetLayoutVersion=1выводится предупреждение; его можно подавить с помощью свойства Gradlekotlin.mpp.androidSourceSetLayoutVersion1.nowarn=true1.9.20: предупреждение становится ошибкой; эту ошибку нельзя подавить
2.4.0: поддержка устаревшей компоновки наборов исходного кода Android прекращается, а свойство Gradle
kotlin.mpp.androidSourceSetLayoutVersion=1удаляется
Устаревшие commonMain и commonTest с пользовательским dependsOn
Что изменилось?
Наборы исходного кода commonMain и commonTest обычно представляют собой корневые наборы иерархий исходного кода main и test соответственно. Однако это поведение можно было переопределить, вручную настроив связи dependsOn для этих наборов исходного кода.
Поддержка такой конфигурации требует дополнительных усилий и знания внутренних механизмов многоплатформенной сборки. Кроме того, это снижает читаемость и повторное использование кода, поскольку приходится изучать конкретный скрипт сборки, чтобы убедиться, что commonMain является корнем иерархии набора исходного кода main.
Поэтому доступ к dependsOn в commonMain и commonTest теперь считается устаревшим.
Как теперь лучше поступить?
Предположим, вам нужно перейти на версию 1.9.20 для набора исходного кода customCommonMain, использующего commonMain.dependsOn(customCommonMain). В большинстве случаев customCommonMain участвует в тех же компиляциях, что и commonMain, поэтому можно объединить customCommonMain с commonMain:
Скопируйте исходные файлы из
customCommonMainвcommonMain.Добавьте все зависимости
customCommonMainвcommonMain.Добавьте все настройки параметров компилятора из
customCommonMainвcommonMain.
В редких случаях customCommonMain может участвовать в большем количестве компиляций, чем commonMain. Такая конфигурация требует дополнительной низкоуровневой настройки скрипта сборки. Если вы не уверены, что это ваш случай, скорее всего, это не так.
Если это ваш случай, поменяйте эти наборы исходного кода местами: перенесите исходные файлы и настройки из customCommonMain в commonMain и наоборот.
Когда изменения вступят в силу?
Планируемый цикл устаревания:
1.9.0: при использовании
dependsOnвcommonMainвыводится предупреждение>=1.9.20: при использовании
dependsOnвcommonMainилиcommonTestвыводится ошибка
Новый подход к предварительным объявлениям
Что изменилось?
Команда JetBrains изменила подход к предварительным объявлениям в Kotlin, чтобы сделать их поведение более предсказуемым:
Импортировать предварительные объявления можно только из пакетов
cnamesилиobjcnames.Преобразование типов к соответствующему предварительному объявлению C и Objective-C и обратно необходимо выполнять явно.
Как теперь лучше поступить?
Рассмотрим библиотеку C с
library.package, в которой объявлено предварительное объявлениеcstructName. Раньше его можно было импортировать непосредственно из библиотеки с помощьюimport library.package.cstructName. Теперь для этого можно использовать только специальный пакет предварительных объявлений:import cnames.structs.cstructName. То же относится кobjcnames.-
Рассмотрим две библиотеки objcinterop: одна использует
objcnames.protocols.ForwardDeclaredProtocolProtocol, а другая содержит его фактическое определение:// First objcinterop library #import <Foundation/Foundation.h> @protocol ForwardDeclaredProtocol; NSString* consumeProtocol(id<ForwardDeclaredProtocol> s) { return [NSString stringWithUTF8String:"Protocol"]; }// Second objcinterop library // Header: #import <Foundation/Foundation.h> @protocol ForwardDeclaredProtocol @end // Implementation: @interface ForwardDeclaredProtocolImpl : NSObject <ForwardDeclaredProtocol> @end id<ForwardDeclaredProtocol> produceProtocol() { return [ForwardDeclaredProtocolImpl new]; }Раньше объекты можно было беспрепятственно передавать между ними. Теперь для предварительного объявления требуется явное приведение типа
as:// Kotlin code: fun test() { consumeProtocol(produceProtocol() as objcnames.protocols.ForwardDeclaredProtocolProtocol) }
Когда изменения вступят в силу?
Начиная с Kotlin 1.9.20, преобразование типов к соответствующим предварительным объявлениям C и Objective-C и обратно необходимо выполнять явно. Кроме того, импортировать предварительные объявления теперь можно только с помощью специальных пакетов.
Kotlin 1.7.0−1.8.22
В этом разделе рассматриваются несовместимые изменения, для которых завершился цикл устаревания и которые вступают в силу в Kotlin 1.7.0−1.8.22.
Устаревшая совместимость плагина Kotlin Multiplatform Gradle с плагинами Java для Gradle
Что изменилось?
Из-за проблем совместимости плагина Kotlin Multiplatform Gradle с плагинами Gradle Java, Java Library и Application теперь при применении этих плагинов к одному проекту выводится предупреждение об устаревании. Предупреждение также появляется, если другой плагин Gradle в вашем многоплатформенном проекте применяет плагин Java для Gradle. Например, плагин Spring Boot Gradle автоматически применяет плагин Application.
Мы добавили это предупреждение об устаревании из-за фундаментальных проблем совместимости между моделью проекта Kotlin Multiplatform и плагинами экосистемы Java в Gradle. Плагины экосистемы Java в Gradle сейчас не учитывают, что другие плагины могут:
Публиковать артефакты или выполнять компиляцию для целевой платформы JVM иначе, чем плагины экосистемы Java.
Использовать в одном проекте две разные целевые платформы JVM, например JVM и Android.
Иметь сложную структуру многоплатформенного проекта с несколькими целевыми платформами, отличными от JVM.
К сожалению, в настоящее время Gradle не предоставляет API для решения этих проблем.
Ранее в Kotlin Multiplatform мы использовали обходные решения, упрощающие интеграцию с плагинами экосистемы Java. Однако эти решения так и не устранили проблемы совместимости, а после выпуска Gradle 8.8 использовать их стало невозможно. Подробнее см. в задаче в YouTrack.
Хотя мы пока не знаем, как именно решить эту проблему совместимости, мы намерены и дальше поддерживать некоторую форму компиляции исходного кода Java в ваших проектах Kotlin Multiplatform. Как минимум мы будем поддерживать компиляцию исходных файлов Java и использование плагина java-base Gradle в многоплатформенных проектах.
Как теперь лучше поступить?
Если вы видите это предупреждение об устаревании в многоплатформенном проекте, рекомендуем:
Определить, действительно ли вам нужен плагин Java для Gradle в проекте. Если нет, рассмотрите возможность его удаления.
Проверить, используется ли плагин Java для Gradle только для одной задачи. Если да, возможно, вы сможете без особых усилий удалить плагин. Например, если задача использует плагин Java для Gradle, чтобы создать JAR-файл с Javadoc, вместо этого можно определить задачу Javadoc вручную.
Если же вы хотите использовать в многоплатформенном проекте и плагин Kotlin Multiplatform Gradle, и эти плагины Java для Gradle, рекомендуем:
Создать отдельный подпроект в проекте Gradle.
Применить плагин Java для Gradle в отдельном подпроекте.
Добавить в отдельный подпроект зависимость от родительского многоплатформенного проекта.
Например, у вас есть многоплатформенный проект с названием my-main-project, и вы хотите использовать плагин Java Library для Gradle.
После создания подпроекта, назовем его subproject-A, структура родительского проекта должна выглядеть так:
.
├── build.gradle
├── settings.gradle.kts
├── subproject-A
└── build.gradle.kts
└── src
└── Main.java
В файле build.gradle.kts подпроекта примените плагин Java Library в блоке plugins {}:
plugins {
id("java-library")
}
plugins {
id('java-library')
}
В файле build.gradle.kts подпроекта добавьте зависимость от родительского многоплатформенного проекта:
dependencies {
implementation(project(":my-main-project")) // The name of your parent multiplatform project
}
dependencies {
implementation project(':my-main-project') // The name of your parent multiplatform project
}
Теперь родительский проект настроен для работы с обоими плагинами.
Новый подход к автоматически создаваемым целевым платформам
Что изменилось?
Создаваемые Gradle автоматически аксессоры целевых платформ больше не доступны в блоке kotlin.targets {}. Вместо них используйте метод findByName("targetName").
Обратите внимание: такие аксессоры по-прежнему доступны в случае kotlin.targets {}, например kotlin.targets.linuxX64.
Как теперь лучше поступить?
Раньше |
Теперь |
|---|---|
kotlin {
targets {
configure(['windows',
'linux']) {
}
}
}
|
kotlin {
targets {
configure([findByName('windows'),
findByName('linux')]) {
}
}
}
|
Когда изменения вступят в силу?
В Kotlin 1.7.20 при использовании аксессоров целевых платформ в блоке kotlin.targets {} появляется ошибка.
Подробнее см. в соответствующей задаче в YouTrack.
Изменения входных и выходных данных задач компиляции Gradle
Что изменилось?
Задачи компиляции Kotlin больше не наследуют задачу Gradle AbstractCompile с входными данными sourceCompatibility и targetCompatibility, поэтому они недоступны в скриптах пользователей Kotlin.
Другие несовместимые изменения в задачах компиляции:
Как теперь лучше поступить?
Раньше |
Теперь |
|---|---|
Входные данные |
Вместо них используйте входные данные |
Входные данные |
Задачи компиляции по-прежнему реализуют интерфейс |
Выходные данные |
Вместо них используйте выходные данные |
Свойство |
Теперь все задачи компиляции используют входные данные |
Когда изменения вступят в силу?
В Kotlin 1.7.20 входные данные становятся недоступны, выходные данные заменяются, а свойство classpath считается устаревшим.
Подробнее см. в соответствующей задаче в YouTrack.
Новые имена конфигураций зависимостей компиляции
Что изменилось?
Конфигурации компиляции, созданные плагином Kotlin Multiplatform Gradle, получили новые имена.
В целевой платформе проекта Kotlin Multiplatform есть две компиляции по умолчанию: main и test. Для каждой из этих компиляций предусмотрен собственный набор исходного кода по умолчанию, например jvmMain и jvmTest. Раньше имена конфигурации тестовой компиляции и ее набора исходного кода по умолчанию совпадали. Это могло приводить к конфликту имен и проблемам при включении конфигурации с атрибутами для конкретной платформы в другую конфигурацию.
Теперь к именам конфигураций компиляции добавлен суффикс Compilation, поэтому проекты и плагины со старыми жестко заданными именами конфигураций больше не компилируются.
Имена конфигураций зависимостей соответствующего набора исходного кода не изменились.
Как теперь лучше поступить?
Раньше |
Теперь |
|
|---|---|---|
Зависимости компиляции |
jvm<Scope> |
jvmCompilation<Scope> |
dependencies {
add("jvmImplementation",
"foo.bar.baz:1.2.3")
}
|
dependencies {
add("jvmCompilationImplementation",
"foo.bar.baz:1.2.3")
}
|
|
Зависимости набора исходного кода |
jvmMain<Scope> |
|
Зависимости компиляции |
jvmTest<Scope> |
jvmTestCompilation<Scope> |
Зависимости набора исходного кода |
jvmTest<Scope> |
|
Доступны области Api, Implementation, CompileOnly и RuntimeOnly.
Когда изменения вступят в силу?
В Kotlin 1.8.0 при использовании старых имен конфигураций в жестко заданных строках появляется ошибка.
Подробнее см. в соответствующей задаче в YouTrack.
© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/multiplatform/multiplatform-compatibility-guide.html