Как перенести конфигурацию сборки с Groovy на Kotlin

В плагине Android Gradle 4.0 добавлена поддержка Kotlin в конфигурации сборки Gradle вместо Groovy – языка программирования, который традиционно используется в файлах конфигурации Gradle.

Kotlin предпочтительнее Groovy для написания скриптов Gradle, поскольку Kotlin более читабелен и предлагает лучшую проверку во время компиляции и поддержку IDE.

Хотя Kotlin в настоящее время предлагает лучшую интеграцию в редакторе кода Android Studio по сравнению с Groovy, сборки с использованием Kotlin, как правило, работают медленнее, чем сборки с использованием Groovy, поэтому при принятии решения о миграции учитывайте производительность сборки.

На этой странице представлена базовая информация о преобразовании файлов сборки Gradle вашего приложения Android из Groovy в Kotlin. Более подробное руководство по переносу можно найти в официальной документации Gradle.

Хронология

Начиная с версии Android Studio Giraffe, в новых проектах для конфигурации сборки по умолчанию используется Kotlin DSL (build.gradle.kts). Это обеспечивает более удобное редактирование, чем Groovy DSL (build.gradle), с подсветкой синтаксиса, автозаполнением кода и переходом к объявлениям. Подробную информацию можно найти в руководстве по Gradle Kotlin DSL.

Общие термины

Kotlin DSL. В основном относится к Kotlin DSL плагина Android Gradle, но иногда и к базовому Kotlin DSL Gradle.

В этом руководстве по переносу термины "Kotlin" и "Kotlin DSL" используются как взаимозаменяемые. Аналогично, термины "Groovy" и "Groovy DSL" взаимозаменяемы.

Название файла скрипта

Расширения файлов скриптов зависят от языка, на котором написан файл сборки:

  • Файлы сборки Gradle, написанные на Groovy, имеют расширение .gradle.
  • Файлы сборки Gradle, написанные на Kotlin, имеют расширение .gradle.kts.

Преобразование синтаксиса

Синтаксис Groovy и Kotlin различается, поэтому вам нужно будет внести изменения во все скрипты сборки.

Добавьте скобки к вызовам методов

В Groovy можно опускать скобки в вызовах методов, а в Kotlin они обязательны. Чтобы перенести конфигурацию, добавьте скобки в вызовы методов. В этом коде показано, как задать настройку в Groovy:

compileSdkVersion 30

Вот тот же код, написанный на Kotlin:

compileSdkVersion(30)

Добавить = к звонкам по заданию

Groovy DSL позволяет опускать оператор присваивания = при назначении свойств, тогда как Kotlin требует его. В этом коде показано, как назначать свойства в Groovy:

java {
    sourceCompatibility JavaVersion.VERSION_17
    targetCompatibility JavaVersion.VERSION_17
}

В этом коде показано, как назначить свойства в Kotlin:

java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}

Преобразование строк

Вот различия в строках между Groovy и Kotlin:

  • Двойные кавычки для строк. В Groovy строки можно заключать в одинарные кавычки, а в Kotlin – только в двойные.

  • Интерполяция строк в выражениях с точкой. В Groovy для интерполяции строк в выражениях с точкой можно использовать только префикс $, а в Kotlin такие выражения нужно заключать в фигурные скобки. Например, в Groovy можно использовать $project.rootDir, как показано в следующем фрагменте кода:

    myRootDirectory = "$project.rootDir/tools/proguard-rules-debug.pro"
    

    Однако в Kotlin приведенный выше код вызывает toString() для project, а не для project.rootDir. Чтобы получить значение корневого каталога, заключите выражение ${project.rootDir} в фигурные скобки:

    myRootDirectory = "${project.rootDir}/tools/proguard-rules-debug.pro"
    

    Подробную информацию можно найти в разделе Шаблоны строк документации по Kotlin.

Переименовать расширения файлов

Добавьте .kts в каждый файл сборки при переносе его содержимого. Например, выберите файл сборки, такой как settings.gradle. Переименуйте файл в settings.gradle.kts и преобразуйте его содержимое в Kotlin. Убедитесь, что проект по-прежнему компилируется после переноса каждого файла сборки.

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

Замените def на val или var.

Замените def на val или var. Так определяются переменные в Kotlin. Вот как выглядит объявление переменной в Groovy:

def building64Bit = false

Вот тот же код, написанный на Kotlin:

val building64Bit = false

Добавьте префикс is к логическим свойствам.

Groovy использует логику вывода свойств на основе их названий. Для логического свойства foo выведенными методами могут быть getFoo, setFoo или isFoo. Поэтому после преобразования в Kotlin вам нужно изменить названия свойств на выведенные методы, которые не поддерживаются Kotlin. Например, для логических элементов buildTypes DSL необходимо использовать префикс is. В этом коде показано, как задать логические свойства в Groovy:

android {
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            ...
        }
        debug {
            debuggable true
            ...
        }
    ...

Ниже приведен тот же код на Kotlin. Обратите внимание, что перед свойствами указан префикс is.

android {
    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            isShrinkResources = true
            ...
        }
        getByName("debug") {
            isDebuggable = true
            ...
        }
    ...

Преобразование списков и карт

Списки и сопоставления в Groovy и Kotlin определяются с помощью разного синтаксиса. В Groovy используется [], а в Kotlin методы создания коллекций вызываются явно с помощью listOf или mapOf. При переносе замените [] на listOf или mapOf.

Вот как определить список в Groovy и Kotlin:

jvmOptions += ["-Xms4000m", "-Xmx4000m", "-XX:+HeapDumpOnOutOfMemoryError</code>"]

Вот тот же код, написанный на Kotlin:

jvmOptions += listOf("-Xms4000m", "-Xmx4000m", "-XX:+HeapDumpOnOutOfMemoryError")

Вот как определить карту в Groovy и Kotlin:

def myMap = [key1: 'value1', key2: 'value2']

Вот тот же код, написанный на Kotlin:

val myMap = mapOf("key1" to "value1", "key2" to "value2")

Как настроить типы сборки

В Kotlin DSL неявно доступны только типы сборки debug и release. Все остальные типы пользовательских сборок необходимо создавать вручную.

В Groovy можно использовать типы сборки debug, release и некоторые другие, не создавая их. В следующем фрагменте кода показана конфигурация с типами сборки debug, release и benchmark в Groovy.

buildTypes {
 debug {
   ...
 }
 release {
   ...
 }
 benchmark {
   ...
 }
}

Чтобы создать эквивалентную конфигурацию в Kotlin, необходимо явно создать тип сборки benchmark.

buildTypes {
 debug {
   ...
 }

 release {
   ...
 }
 register("benchmark") {
    ...
 }
}

Как перейти с buildscript на блок plugins

Если в вашей сборке для добавления плагинов в проект используется блок buildscript {}, вам следует провести рефакторинг и использовать вместо него блок plugins {}. Блок plugins {} упрощает применение плагинов и хорошо работает с каталогами версий.

Кроме того, когда вы используете блок plugins {} в файлах сборки, Android Studio учитывает контекст, даже если сборка завершается неудачно. Это помогает исправлять ошибки в файлах Kotlin DSL, поскольку позволяет Studio IDE выполнять автозаполнение кода и предлагать другие полезные подсказки.

Как найти идентификаторы плагинов

Блок buildscript {} добавляет плагины в путь к классам сборки, используя координаты Maven плагина, например com.android.tools.build:gradle:7.4.0, а блок plugins {} использует идентификаторы плагинов.

Для большинства плагинов идентификатор – это строка, которая используется при их применении с помощью apply plugin. Например, следующие идентификаторы плагинов являются частью плагина Android Gradle:

  • com.android.application
  • com.android.library
  • com.android.lint
  • com.android.test

Полный список плагинов можно найти в репозитории Google Maven.

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

Сокращенные идентификаторы плагинов Идентификаторы плагинов с пространством имен
kotlin org.jetbrains.kotlin.jvm
kotlin-android org.jetbrains.kotlin.android
kotlin-kapt org.jetbrains.kotlin.kapt
kotlin-parcelize org.jetbrains.kotlin.plugin.parcelize

Вы также можете искать плагины на портале плагинов Gradle, в центральном репозитории Maven и в репозитории Google Maven. Подробнее о том, как работают идентификаторы плагинов, рассказывается в статье Developing Custom Gradle Plugins (Разработка собственных плагинов Gradle).

Выполните рефакторинг

Узнав идентификаторы используемых плагинов, выполните следующие действия:

  1. Если у вас все ещё есть хранилища для плагинов, объявленные в блоке buildscript {}, переместите их в файл settings.gradle.

  2. Добавьте плагины в блок plugins {} в файле build.gradle верхнего уровня. Здесь нужно указать идентификатор и версию плагина. Если плагин не нужно применять к корневому проекту, используйте apply false.

  3. Удалите записи classpath из файла build.gradle.kts верхнего уровня.

  4. Примените плагины, добавив их в блок plugins {} в файле build.gradle на уровне модуля. Здесь нужно указать только идентификатор плагина, поскольку версия наследуется от корневого проекта.

  5. Удалите вызов apply plugin для плагина из файла build.gradle на уровне модуля.

Например, в этой настройке используется блок buildscript {}:

// Top-level build.gradle file
buildscript {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:7.4.0")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0")
        ...
    }
}

// Module-level build.gradle file
apply(plugin: "com.android.application")
apply(plugin: "kotlin-android")

Вот как это выглядит в блоке plugins {}:

// Top-level build.gradle file
plugins {
   id 'com.android.application' version '7.4.0' apply false
   id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
   ...
}

// Module-level build.gradle file
plugins {
   id 'com.android.application'
   id 'org.jetbrains.kotlin.android'
   ...
}

// settings.gradle
pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}

Преобразование блока плагинов

Применение плагинов из блока plugins {} в Groovy и Kotlin выполняется похожим образом. В следующем коде показано, как применять плагины в Groovy при использовании каталогов версий:

// Top-level build.gradle file
plugins {
   alias libs.plugins.android.application apply false
   ...
}

// Module-level build.gradle file
plugins {
   alias libs.plugins.android.application
   ...
}

Ниже показано, как сделать то же самое в Kotlin.

// Top-level build.gradle.kts file
plugins {
   alias(libs.plugins.android.application) apply false
   ...
}

// Module-level build.gradle.kts file
plugins {
   alias(libs.plugins.android.application)
   ...
}

В следующем коде показано, как применять плагины в Groovy, если вы не используете каталоги версий:

// Top-level build.gradle file
plugins {
   id 'com.android.application' version '7.3.0' apply false
   ...
}

// Module-level build.gradle file
plugins {
   id 'com.android.application'
   ...
}

Ниже показано, как сделать то же самое в Kotlin.

// Top-level build.gradle.kts file
plugins {
   id("com.android.application") version "7.3.0" apply false
   ...
}

// Module-level build.gradle.kts file
plugins {
   id("com.android.application")
   ...
}

Подробные сведения о блоке plugins {} можно найти в разделе Применение плагинов документации по Gradle.

Другое

Примеры кода Kotlin для других функций можно найти на следующих страницах документации:

Известные проблемы

Известная проблема: скорость сборки с Kotlin может быть ниже, чем с Groovy.

Как сообщить о проблеме

Инструкции о том, как предоставить информацию, необходимую для сортировки проблемы, можно найти в разделе Сведения об ошибках в инструментах сборки и Gradle. Затем сообщите об ошибке, используя общедоступную систему отслеживания ошибок.

Дополнительные ресурсы

Пример файлов сборки Gradle, написанных на Kotlin, можно найти в примере приложения Now In Android на GitHub.