Что нового в Kotlin 1.6.20
Дата выхода: 4 апреля 2022 года
Kotlin 1.6.20 предоставляет предварительные версии будущих языковых функций, устанавливает иерархическую структуру в качестве значения по умолчанию для многоплатформенных проектов и вносит эволюционные улучшения в другие компоненты.
Язык
В Kotlin 1.6.20 вы можете опробовать две новые языковые функции:
Прототип контекстных получателей для Kotlin/JVM
С Kotlin 1.6.20 вы больше не ограничены одним получателем. Если вам нужно больше, вы можете сделать функции, свойства и классы контекстно-зависимыми (или контекстуальными), добавив контекстные получатели в их объявление. Контекстно-зависимое объявление выполняет следующие действия:
Требует, чтобы все объявленные контекстные получатели присутствовали в области вызова в качестве неявных получателей.
Вводит объявленные контекстные получатели в область тела в качестве неявных получателей.
interface LoggingContext {
val log: Logger // This context provides a reference to a logger
}
context(LoggingContext)
fun startBusinessOperation() {
// You can access the log property since LoggingContext is an implicit receiver
log.info("Operation has started")
}
fun test(loggingContext: LoggingContext) {
with(loggingContext) {
// You need to have LoggingContext in a scope as an implicit receiver
// to call startBusinessOperation()
startBusinessOperation()
}
}
Чтобы включить контекстные получатели в свой проект, используйте опцию компилятора -Xcontext-receivers. Подробное описание функции и её синтаксиса можно найти в KEEP.
Обратите внимание, что реализация является прототипом:
При включенном
-Xcontext-receivers, компилятор будет генерировать предварительные бинарные файлы, которые нельзя использовать в коде производстваПоддержка контекстных получателей в IDE пока минимальна
Попробуйте эту функцию в своих учебных проектах и поделитесь своими мыслями и опытом с нами в этой задаче на YouTrack. Если у вас возникнут какие-либо проблемы, пожалуйста, создайте новую задачу.
Определенно непустые типы
Для лучшей взаимозаменяемости при расширении общих Java-классов и интерфейсов, Kotlin 1.6.20 позволяет помечать общий параметр типа как определенно непустой на месте использования с новым синтаксисом T & Any. Синтаксическая форма заимствована из обозначения пересечения типов и теперь ограничена параметром типа с непустыми верхними границами слева от & и непустым Any справа:
fun <T> elvisLike(x: T, y: T & Any): T & Any = x ?: y
fun main() {
// OK
elvisLike<String>("", "").length
// Error: 'null' cannot be a value of a non-null type
elvisLike<String>("", null).length
// OK
elvisLike<String?>(null, "").length
// Error: 'null' cannot be a value of a non-null type
elvisLike<String?>(null, null).length
}
Установите версию языка на 1.7 для активации этой функции:
kotlin {
sourceSets.all {
languageSettings.apply {
languageVersion = "1.7"
}
}
}
kotlin {
sourceSets.all {
languageSettings {
languageVersion = '1.7'
}
}
}
Дополнительную информацию об определенно непустых типах см. в KEEP.
Kotlin/JVM
Kotlin 1.6.20 вводит:
Улучшения совместимости методов по умолчанию в интерфейсах JVM: новая аннотация
@JvmDefaultWithCompatibilityдля интерфейсов и изменения совместимости в режимах-Xjvm-defaultПоддержка параллельной компиляции одного модуля в бэкенде JVM
Поддержка вызываемых ссылок на конструкторы функциональных интерфейсов
Новая аннотация @JvmDefaultWithCompatibility для интерфейсов
Kotlin 1.6.20 вводит новую аннотацию @JvmDefaultWithCompatibility: используйте её вместе с опцией компилятора -Xjvm-default=all для создания метода по умолчанию в интерфейсе JVM для любого неабстрактного члена любого Kotlin-интерфейса.
Если у вас есть клиенты, которые используют ваши Kotlin-интерфейсы, скомпилированные без опции -Xjvm-default=all, они могут быть бинарно несовместимы с кодом, скомпилированным с этой опцией. До Kotlin 1.6.20, чтобы избежать этой проблемы совместимости, рекомендуемым подходом было использование режима -Xjvm-default=all-compatibility и также аннотации @JvmDefaultWithoutCompatibility для интерфейсов, которым не нужна такая совместимость.
Этот подход имел некоторые недостатки:
Вы легко могли забыть добавить аннотацию при добавлении нового интерфейса.
Как правило, в непубличных частях кода больше интерфейсов, чем в публичном API, поэтому вам приходилось добавлять эту аннотацию во многих местах кода.
Теперь вы можете использовать режим -Xjvm-default=all и помечать интерфейсы аннотацией @JvmDefaultWithCompatibility. Это позволяет добавить эту аннотацию ко всем интерфейсам в публичном API один раз, и вам не нужно использовать какие-либо аннотации для нового закрытого кода.
Оставьте свой отзыв об этой новой аннотации на этой странице YouTrack.
Изменения совместимости в режимах -Xjvm-default
Kotlin 1.6.20 добавляет возможность компилировать модули в режиме по умолчанию (опция компилятора -Xjvm-default=disable ) по отношению к модулям, скомпилированным в режимах -Xjvm-default=all или -Xjvm-default=all-compatibility. Как и прежде, компиляция также будет успешной, если все модули имеют режимы -Xjvm-default=all или -Xjvm-default=all-compatibility. Вы можете оставить свой отзыв на этой странице YouTrack.
Kotlin 1.6.20 устаревает режимы compatibility и enable опции компилятора -Xjvm-default. Изменения в описаниях других режимов касаются совместимости, но общая логика остается прежней. Вы можете ознакомиться с обновлёнными описаниями.
Для получения дополнительной информации о методах по умолчанию в Java-совместимости, см. документацию по совместимости и эту статью блога.
Поддержка параллельной компиляции одного модуля в бэкенде JVM
Мы продолжаем работу по улучшению времени компиляции нового бэкенда JVM IR. В Kotlin 1.6.20 мы добавили экспериментальный режим бэкенда JVM IR, который позволяет компилировать все файлы модуля параллельно. Параллельная компиляция может уменьшить общее время компиляции до 15%.
Включите экспериментальный режим параллельного бэкенда с помощью опции компилятора -Xbackend-threads. Используйте следующие аргументы для этой опции:
N— количество потоков, которые вы хотите использовать. Оно не должно быть больше количества ядер процессора, иначе параллелизация перестанет быть эффективной из-за переключения контекста между потоками0— использовать отдельный поток для каждого ядра процессора
Gradle может запускать задачи параллельно, но этот тип параллелизации не сильно помогает, когда проект (или большая его часть) — просто одна большая задача с точки зрения Gradle. Если у вас очень большой монолитный модуль, используйте параллельную компиляцию для ускорения компиляции. Если ваш проект состоит из множества небольших модулей и имеет параллельную сборку, добавленная параллелизация может навредить производительности из-за переключения контекста.
Поддержка вызываемых ссылок на конструкторы функциональных интерфейсов
Поддержка вызываемых ссылок на конструкторы функциональных интерфейсов добавляет совместимый с исходным кодом способ миграции от интерфейса с конструкторной функцией к функциональному интерфейсу.
Рассмотрим следующий код:
interface Printer {
fun print()
}
fun Printer(block: () -> Unit): Printer = object : Printer { override fun print() = block() }
При включенной поддержке вызываемых ссылок на конструкторы функциональных интерфейсов этот код может быть заменён просто объявлением функционального интерфейса:
fun interface Printer {
fun print()
}
Его конструктор будет создан неявно, и любой код, использующий ссылку на функцию ::Printer будет компилироваться. Например:
documentsStorage.addPrinter(::Printer)
Сохраните бинарную совместимость, пометив устаревшую функцию Printer аннотацией @Deprecated с DeprecationLevel.HIDDEN:
@Deprecated(message = "Your message about the deprecation", level = DeprecationLevel.HIDDEN)
fun Printer(...) {...}
Используйте опцию компилятора -XXLanguage:+KotlinFunInterfaceConstructorReference для активации этой функции.
Kotlin/Native
Kotlin/Native 1.6.20 продолжает разработку новых компонентов. Мы сделали ещё один шаг к согласованному опыту работы с Kotlin на других платформах:
Конкурентная реализация фазы сбора мусора в новом менеджере памяти
Взаимодействие с Swift async/await: возврат Swift's Void вместо KotlinUnit
Обновление нового менеджера памяти
С Kotlin 1.6.20 вы можете попробовать альфа-версию нового менеджера памяти Kotlin/Native. Она устраняет различия между JVM и Native платформами, чтобы обеспечить согласованный опыт разработчика в кроссплатформенных проектах. Например, вам будет гораздо проще создавать новые кроссплатформенные мобильные приложения, работающие как на Android, так и на iOS.
Новый менеджер памяти Kotlin/Native снимает ограничения на совместное использование объектов между потоками. Он также предоставляет потокобезопасные, не создающие утечек, конкурентные примитивы, которые не требуют специального управления или аннотаций.
Новый менеджер памяти станет стандартным в будущих версиях, поэтому мы рекомендуем вам попробовать его сейчас. Ознакомьтесь с нашей статьей в блоге, чтобы узнать больше о новом менеджере памяти и изучить демонстрационные проекты, или сразу перейти к инструкциям по миграции, чтобы попробовать его самим.
Попробуйте использовать новый менеджер памяти в своих проектах, чтобы увидеть, как он работает, и поделитесь своими отзывами на нашем портале отслеживания задач — YouTrack.
Конкурентная реализация фазы сбора мусора в новом менеджере памяти
Если вы уже перешли на наш новый менеджер памяти, о котором было сообщено в Kotlin 1.6, вы можете заметить значительное улучшение времени выполнения: наши бенчмарки показывают среднее улучшение на 35%. Начиная с версии 1.6.20, для нового менеджера памяти также доступна конкурентная реализация фазы сбора мусора. Это также должно улучшить производительность и сократить продолжительность пауз сборщика мусора.
Для включения этой функции для нового менеджера памяти Kotlin/Native, передайте следующую опцию компилятора:
-Xgc=cms
Пожалуйста, поделитесь своими отзывами о производительности нового менеджера памяти в этой задаче YouTrack.
Инициализация классов аннотаций
В Kotlin 1.6.0 инициализация классов аннотаций стала стабильной для Kotlin/JVM и Kotlin/JS. Версия 1.6.20 предоставляет поддержку Kotlin/Native.
Узнайте больше о инициализации классов аннотаций.
Взаимодействие с Swift async/await: возврат Void вместо KotlinUnit
Мы продолжаем работу над экспериментальным взаимодействием с Swift async/await (доступно с Swift 5.5). Kotlin 1.6.20 отличается от предыдущих версий способом работы с suspend функциями с Unit типом возврата.
Ранее такие функции в Swift представлялись как async функции, возвращающие KotlinUnit. Однако правильный тип возврата для них — Void, аналогично не-отложенным функциям.
Чтобы избежать разрыва существующего кода, мы вводим свойство Gradle, которое заставляет компилятор переводить Unit-возвращающие отложенные функции в async Swift с Void типом возврата:
# gradle.properties kotlin.native.binary.unitSuspendFunctionObjCExport=proper
Мы планируем сделать это поведение стандартным в будущих выпусках Kotlin.
Улучшенные трассировки стека с libbacktrace
Kotlin/Native теперь может создавать подробные трассировки стека с указанием расположения файлов и номеров строк для лучшей отладки linux* (за исключением linuxMips32 и linuxMipsel32) и androidNative* целевых платформ.
Эта функция использует библиотеку libbacktrace в качестве подсистемы. Посмотрите на приведенный ниже код, чтобы увидеть разницу:
fun main() = bar()
fun bar() = baz()
inline fun baz() {
error("")
}
До версии 1.6.20:
1.6.20 с libbacktrace:
На платформах Apple, которые уже имели местоположения файлов и номера строк в трассировках стека, libbacktrace предоставляет больше деталей для вызовов инлайновых функций:
До версии 1.6.20:
1.6.20 с libbacktrace:
Чтобы получить лучшие трассировки стека с libbacktrace, добавьте следующую строку в gradle.properties.
# gradle.properties kotlin.native.binary.sourceInfoType=libbacktrace
Пожалуйста, расскажите нам о работе отладки Kotlin/Native с libbacktrace в этом вопросе на YouTrack.
Поддержка автономных исполняемых файлов Android
Ранее, исполняемые файлы Android Native в Kotlin/Native фактически не были исполняемыми файлами, а являлись разделяемыми библиотеками, которые можно было использовать как NativeActivity. Теперь есть возможность генерировать стандартные исполняемые файлы для целевых платформ Android Native.
Для этого в build.gradle(.kts) части вашего проекта настройте блок исполняемого файла для вашей androidNative целевой платформы. Добавьте следующий бинарный параметр:
kotlin {
androidNativeX64("android") {
binaries {
executable {
binaryOptions["androidProgramType"] = "standalone"
}
}
}
}
Обратите внимание, что эта функция станет по умолчанию в Kotlin 1.7.0. Если вы хотите сохранить текущее поведение, используйте следующую настройку:
binaryOptions["androidProgramType"] = "nativeActivity"
Спасибо Mattia Iavarone за реализацию!
Улучшения производительности
Мы упорно работаем над Kotlin/Native, чтобы ускорить процесс компиляции и улучшить ваш опыт разработки.
Kotlin 1.6.20 включает в себя некоторые обновления производительности и исправления ошибок, которые влияют на LLVM IR, генерируемый Kotlin. Согласно бенчмаркам по нашим внутренним проектам, мы добились следующих средних приростов производительности:
Уменьшение времени выполнения на 15%
Уменьшение размера кода как для релизных, так и для отладочных бинарных файлов на 20%
Уменьшение времени компиляции релизных бинарных файлов на 26%
Эти изменения также обеспечивают снижение времени компиляции отладочного бинарного файла на 10% для крупного внутреннего проекта.
Для достижения этого мы реализовали статическую инициализацию для некоторых сгенерированных компилятором синтетических объектов, улучшили способ структурирования LLVM IR для каждой функции и оптимизировали кэши компилятора.
Улучшенная обработка ошибок при импорте модулей cinterop
В этом релизе улучшена обработка ошибок в случаях, когда вы импортируете модуль Objective-C с помощью инструмента cinterop (как это обычно делается для CocoaPods). Раньше, если при работе с модулем Objective-C возникала ошибка (например, при возникновении ошибки компиляции в заголовке), вы получали неинформативное сообщение об ошибке, такое как fatal error: could not build module $name. Мы расширили эту часть инструмента cinterop, поэтому теперь вы получите сообщение об ошибке с расширенным описанием.
Поддержка библиотек Xcode 13
Библиотеки, предоставляемые Xcode 13, полностью поддерживаются с выходом этого релиза. Вы можете свободно использовать их в любом месте своего кода Kotlin.
Kotlin Мультиплатформа
1.6.20 включает следующие заметные обновления для Kotlin Мультиплатформы:
Поддержка иерархической структуры теперь по умолчанию для всех новых проектов мультиплатформы
Плагин Kotlin CocoaPods Gradle получил несколько полезных функций для интеграции с CocoaPods
Поддержка иерархической структуры для проектов мультиплатформы
Kotlin 1.6.20 поставляется с поддержкой иерархической структуры, включенной по умолчанию. С момента ее введения в Kotlin 1.4.0 мы значительно улучшили фронтенд и обеспечили стабильность импорта в IDE.
Ранее существовало два способа добавления кода в проект мультиплатформы. Первый — вставить его в набор исходных файлов, специфичный для платформы, что ограничено одним целевым устройством и не может быть повторно использовано другими платформами. Второй — использовать общий набор исходных файлов, общий для всех платформ, которые в данный момент поддерживаются Kotlin.
Теперь вы можете разделить исходный код между несколькими похожими целевыми устройствами, которые повторно используют большое количество общей логики и API сторонних библиотек. Технология обеспечит правильные зависимости по умолчанию и найдет точный API, доступный в общем коде. Это устраняет сложную настройку сборки и использование обходных путей для получения поддержки IDE для совместного использования наборов исходных файлов между целевыми устройствами. Это также помогает предотвратить небезопасное использование API, предназначенного для другого целевого устройства.
Эта технология также будет полезна для авторов библиотек, так как иерархическая структура проекта позволяет им публиковать и использовать библиотеки с общими API для подмножества целевых устройств.
По умолчанию библиотеки, опубликованные с помощью иерархической структуры проекта, совместимы только с проектами с иерархической структурой. Подробнее об совместимости проекта и библиотеки.
Улучшение совместного использования кода в вашем проекте
Без поддержки иерархической структуры нет простого способа совместного использования кода между некоторыми, но не всеми целевыми устройствами Kotlin. Один из распространённых примеров — совместное использование кода между всеми целевыми устройствами iOS и доступ к специфическим для iOS зависимостям, например Foundation.
Благодаря поддержке иерархической структуры проекта, вы теперь можете добиться этого по умолчанию. В новой структуре наборы исходных файлов образуют иерархию. Вы можете использовать специфичные для платформы языковые возможности и зависимости, доступные для каждого целевого устройства, к которому компилируется данный набор исходных файлов.
Например, рассмотрим типичный проект мультиплатформы с двумя целевыми устройствами — iosArm64 и iosX64 для устройств и симуляторов iOS. Инструменты Kotlin понимают, что оба целевых устройства имеют одинаковую функцию, и позволяют вам получить доступ к этой функции из промежуточного набора исходных файлов, iosMain.

Инструментарий Kotlin предоставляет правильные зависимости по умолчанию, такие как Kotlin/Native stdlib или родные библиотеки. Более того, инструменты Kotlin будут стараться найти точно область API, доступную в общем коде. Это предотвращает случаи, когда, например, функция, специфичная для macOS, используется в коде, общем для Windows.
Больше возможностей для авторов библиотек
При публикации библиотеки мультиплатформы API ее промежуточных наборов исходных файлов теперь публикуется вместе с ней, что делает его доступным для потребителей. Инструментарий Kotlin автоматически определит API, доступный в наборе исходных файлов потребителя, и будет внимательно следить за небезопасным использованием, например, использованием API, предназначенного для JVM, в коде JS. Узнайте больше о совместном использовании кода в библиотеках.
Настройка
Начиная с Kotlin 1.6.20, все ваши новые проекты мультиплатформы будут иметь иерархическую структуру проекта. Дополнительная настройка не требуется.
-
Если вы уже включили ее вручную, вы можете удалить устаревшие параметры из
gradle.properties:# gradle.properties kotlin.mpp.enableGranularSourceSetsMetadata=true kotlin.native.enableDependencyPropagation=true
Для Kotlin 1.6.20 рекомендуется использовать Android Studio 2021.1.1 (Bumblebee) или более позднюю версию для лучшего опыта.
-
Вы также можете отказаться от нее. Чтобы отключить поддержку иерархической структуры, установите следующие параметры в
gradle.properties:# gradle.properties kotlin.mpp.hierarchicalStructureSupport=false
Оставьте свои отзывы
Это значительное изменение для всей экосистемы. Мы будем рады вашим отзывам, чтобы сделать ее еще лучше.
Попробуйте сейчас и сообщите о любых возникших проблемах в нашем трекере проблем.
Плагин Kotlin CocoaPods Gradle
Для упрощения интеграции с CocoaPods Kotlin 1.6.20 предоставляет следующие функции:
-
Плагин CocoaPods теперь имеет задачи, которые строят XCFrameworks со всеми зарегистрированными целевыми устройствами и генерируют файл Podspec. Это может быть полезно, если вы не хотите интегрироваться напрямую с Xcode, но хотите создавать артефакты и размещать их в локальном репозитории CocoaPods.
Узнайте больше о создании XCFrameworks.
-
Если вы используете интеграцию CocoaPods в своих проектах, вы привыкли указывать необходимую версию Pod для всего проекта Gradle. Теперь у вас больше вариантов:
Укажите версию Pod напрямую в блоке
cocoapodsПродолжайте использовать версию проекта Gradle
Если ни один из этих параметров не настроен, вы получите ошибку.
Теперь вы можете настроить имя CocoaPod в блоке
cocoapodsвместо изменения имени всего проекта Gradle.Плагин CocoaPods вводит новый
extraSpecAttributesпараметр, который вы можете использовать для настройки параметров в файле Podspec, которые ранее были захардкожены, например,librariesилиvendored_frameworks.
kotlin {
cocoapods {
version = "1.0"
name = "MyCocoaPod"
extraSpecAttributes["social_media_url"] = 'https://twitter.com/kotlin'
extraSpecAttributes["vendored_frameworks"] = 'CustomFramework.xcframework'
extraSpecAttributes["libraries"] = 'xml'
}
}
См. полную справку по плагину Kotlin CocoaPods Gradle DSL.
Kotlin/JS
Улучшения Kotlin/JS в версии 1.6.20 в основном касаются компилятора IR:
Инкрементальная компиляция для библиотек разработки с использованием IR-компилятора
Для повышения эффективности разработки Kotlin/JS с использованием IR-компилятора, мы вводим новый режим инкрементальной компиляции.
При построении библиотек разработки с помощью задачи compileDevelopmentExecutableKotlinJs Gradle в этом режиме, компилятор кеширует результаты предыдущих компиляций на уровне модуля. Он использует кэшированные результаты компиляции для неизменённых исходных файлов во время последующих компиляций, что значительно ускоряет процесс, особенно при небольших изменениях. Обратите внимание, что это улучшение предназначено исключительно для процесса разработки (ускорение цикла редактирование-компиляция-отладка) и не влияет на создание производственных артефактов.
Чтобы включить инкрементальную компиляцию для библиотек разработки, добавьте следующую строку в gradle.properties проекта:
# gradle.properties kotlin.incremental.js.ir=true // false by default
В наших тестовых проектах новый режим ускорил инкрементальную компиляцию до 30%. Однако, чистая компиляция в этом режиме стала медленнее из-за необходимости создания и заполнения кэшей.
Пожалуйста, поделитесь своими впечатлениями об использовании инкрементальной компиляции в ваших проектах Kotlin/JS на этой странице YouTrack.
Ленивая инициализация свойств верхнего уровня по умолчанию с использованием IR-компилятора
В Kotlin 1.4.30 мы представили прототип ленивой инициализации свойств верхнего уровня в JS IR-компиляторе. Ленивая инициализация сокращает время запуска приложения, исключая необходимость инициализации всех свойств при запуске приложения. Наши измерения показали ускорение на 10% в реальном приложении Kotlin/JS.
Теперь, отшлифовав и тщательно протестировав этот механизм, мы делаем ленивую инициализацию по умолчанию для свойств верхнего уровня в IR-компиляторе.
// lazy initialization
val a = run {
val result = // intensive computations
println(result)
result
} // run is executed upon the first usage of the variable
Если по какой-то причине вам необходимо инициализировать свойство сразу (при запуске приложения), отметьте его аннотацией @EagerInitialization.
Отдельные JS-файлы для модулей проекта по умолчанию с использованием IR-компилятора
Ранее IR-компилятор Kotlin/JS предлагал возможность генерации отдельных .js файлов для модулей проекта. Это была альтернатива по умолчанию — одному .js файлу для всего проекта. Этот файл может быть слишком большим и неудобным в использовании, так как для использования функции из проекта вам необходимо включать весь JS-файл в качестве зависимости. Наличие нескольких файлов увеличивает гибкость и уменьшает размер таких зависимостей. Эта функция была доступна с опцией компилятора -Xir-per-module.
Начиная с версии 1.6.20, JS IR-компилятор по умолчанию генерирует отдельные .js файлы для модулей проекта.
Компиляция проекта в один .js файл теперь доступна с помощью следующей свойства Gradle:
# gradle.properties kotlin.js.ir.output.granularity=whole-program // `per-module` is the default
Оптимизация класса Char
Класс Char теперь обрабатывается компилятором Kotlin/JS без применения боксрования (аналогично inline-классам). Это ускоряет операции с символами в коде Kotlin/JS.
Помимо повышения производительности, это изменяет способ экспорта Char в JavaScript: теперь он преобразуется в Number.
Улучшения экспорта и генерации TypeScript объявлений
Kotlin 1.6.20 включает в себя множество исправлений и улучшений механизма экспорта (аннотация @JsExport), включая генерацию TypeScript объявлений (.d.ts). Мы добавили возможность экспорта интерфейсов и перечислений, а также исправили поведение экспорта в некоторых ранее обнаруженных особых случаях. Более подробную информацию см. в списке улучшений экспорта в YouTrack.
Узнайте больше о использовании Kotlin-кода из JavaScript.
@AfterTest гарантии для асинхронных тестов
Kotlin 1.6.20 обеспечивает корректную работу функций @AfterTest с асинхронными тестами на Kotlin/JS. Если тип возврата функции теста статически определён как Promise, компилятор теперь планирует выполнение функции @AfterTest в соответствующем обратном вызове then().
Безопасность
Kotlin 1.6.20 добавляет несколько функций для повышения безопасности вашего кода:
Использование относительных путей в klibs
Библиотека в формате klib содержит сериализованное представление IR исходных файлов, которое также включает их пути для генерации правильной отладочной информации. До Kotlin 1.6.20 пути к файлам хранились в абсолютном формате. Так как авторы библиотеки могут не захотеть делиться абсолютными путями, версия 1.6.20 предоставляет альтернативный вариант.
Если вы публикуете klib и хотите использовать только относительные пути к исходным файлам в артефакте, вы можете передать параметр компилятора -Xklib-relative-path-base с одним или несколькими базовыми путями исходных файлов:
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile::class).configureEach {
// $base is a base path of source files
kotlinOptions.freeCompilerArgs += "-Xklib-relative-path-base=$base"
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
kotlinOptions {
// $base is a base path of source files
freeCompilerArgs += "-Xklib-relative-path-base=$base"
}
}
Сохранение yarn.lock для проектов Kotlin/JS Gradle
Плагин Kotlin/JS Gradle теперь предоставляет возможность сохранения файла yarn.lock, что позволяет фиксировать версии зависимостей npm для вашего проекта без дополнительной конфигурации Gradle. Эта функция вносит изменения в стандартную структуру проекта, добавив автоматически сгенерированный каталог kotlin-js-store в корень проекта. Он содержит файл yarn.lock внутри.
Рекомендуется добавить каталог kotlin-js-store и его содержимое в систему управления версиями. Включение файлов блокировки в систему управления версиями — это рекомендуемая практика, поскольку она гарантирует, что ваш проект собирается с точным набором зависимостей на всех машинах, независимо от того, являются ли это среды разработки или сервисы CI/CD. Файлы блокировки также предотвращают неявное обновление зависимостей npm при проверке проекта на новой машине, что является проблемой безопасности.
Инструменты, такие как Dependabot, также могут анализировать файлы yarn.lock ваших проектов Kotlin/JS и предоставлять вам предупреждения, если какой-либо пакет npm, от которого вы зависите, уязвим.
При необходимости вы можете изменить имена каталога и файла блокировки в скрипте сборки:
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin> {
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().lockFileDirectory =
project.rootDir.resolve("my-kotlin-js-store")
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().lockFileName = "my-yarn.lock"
}
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin) {
rootProject.extensions.getByType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension).lockFileDirectory =
file("my-kotlin-js-store")
rootProject.extensions.getByType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension).lockFileName = 'my-yarn.lock'
}
Установка зависимостей npm с --ignore-scripts по умолчанию
Плагин Kotlin/JS Gradle теперь по умолчанию предотвращает выполнение скриптов жизненного цикла во время установки зависимостей npm. Это изменение призвано снизить вероятность выполнения вредоносного кода из уязвимых пакетов npm.
Чтобы вернуться к старой конфигурации, можно явно включить выполнение скриптов жизненного цикла, добавив следующие строки в build.gradle(.kts):
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin> {
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().ignoreScripts = false
}
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin) {
rootProject.extensions.getByType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension).ignoreScripts = false
}
Дополнительную информацию о зависимостях npm проекта Kotlin/JS Gradle вы найдете здесь.
Gradle
Kotlin 1.6.20 вносит следующие изменения в плагин Kotlin Gradle:
Новые свойства
kotlin.compiler.execution.strategyиcompilerExecutionStrategyдля определения стратегии выполнения компилятора KotlinУстаревание опций
kapt.use.worker.api,kotlin.experimental.coroutines, иkotlin.coroutines
Свойства для определения стратегии выполнения компилятора Kotlin
До Kotlin 1.6.20 вы использовали системную переменную -Dkotlin.compiler.execution.strategy для определения стратегии выполнения компилятора Kotlin. В некоторых случаях это свойство было неудобным. Kotlin 1.6.20 вводит свойство Gradle с тем же именем, kotlin.compiler.execution.strategy, и свойство задачи компиляции compilerExecutionStrategy.
Системная переменная по-прежнему работает, но будет удалена в будущих версиях.
Текущий приоритет свойств следующий:
Свойство задачи
compilerExecutionStrategyимеет приоритет над системной переменной и свойством Gradlekotlin.compiler.execution.strategy.Свойство Gradle имеет приоритет над системной переменной.
Существует три стратегии выполнения компилятора, которые вы можете назначить этим свойствам:
Стратегия |
Где выполняется компилятор Kotlin |
Инкрементная компиляция |
Другие характеристики |
|---|---|---|---|
Демон |
Внутри собственного процесса демона |
Да |
По умолчанию. Может быть совместно использовано между различными демонами Gradle |
В процессе |
Внутри процесса демона Gradle |
Нет |
Может совместно использовать кучу с демоном Gradle |
За пределами процесса |
В отдельном процессе для каждого вызова |
Нет |
— |
Соответственно, доступные значения для свойств kotlin.compiler.execution.strategy (как системных, так и Gradle) следующие:
daemon(по умолчанию)in-processout-of-process
Используйте свойство Gradle kotlin.compiler.execution.strategy в gradle.properties:
# gradle.properties kotlin.compiler.execution.strategy=out-of-process
Доступные значения для свойства задачи compilerExecutionStrategy следующие:
org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy.DAEMON(по умолчанию)org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy.IN_PROCESSorg.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy.OUT_OF_PROCESS
Используйте свойство задачи compilerExecutionStrategy в build.gradle.kts buildscript:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy
// …
tasks.withType<KotlinCompile>().configureEach {
compilerExecutionStrategy.set(KotlinCompilerExecutionStrategy.IN_PROCESS)
}
Пожалуйста, оставьте свои отзывы в этой задаче YouTrack.
Устаревание опций сборки для kapt и сопроцедур
В Kotlin 1.6.20 мы изменили уровни устаревания свойств:
-
Мы устарели возможность запуска kapt через демон Kotlin с помощью
kapt.use.worker.api— теперь это генерирует предупреждение в выходные данные Gradle. По умолчанию, kapt использует рабочие процессы Gradle с версии 1.3.70, и мы рекомендуем придерживаться этого метода.Мы собираемся удалить опцию
kapt.use.worker.apiв будущих версиях. -
Мы устарели опцию Gradle DSL
kotlin.experimental.coroutinesи свойствоkotlin.coroutines, используемое вgradle.properties. Используйте просто поддерживаемые функции или добавить зависимостьkotlinx.coroutinesв свой файлbuild.gradle(.kts).Узнайте больше о сопроцедурах в руководстве по сопроцедурам.
Удаление опции сборки kotlin.parallel.tasks.in.project
В Kotlin 1.5.20 мы объявили устаревание опции сборки kotlin.parallel.tasks.in.project. Эта опция была удалена в Kotlin 1.6.20.
В зависимости от проекта, параллельная компиляция в демоне Kotlin может потребовать больше памяти. Для снижения потребления памяти, увеличьте размер кучи для демона Kotlin.
Узнайте больше о поддерживаемых опциях компилятора в плагине Kotlin Gradle.
© 2010–2022 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/whatsnew1620.html