Настройка плагина Android Gradle Library для KMP

Плагин Gradle com.android.kotlin.multiplatform.library — официально поддерживаемый инструмент для добавления целевой платформы Android в модуль библиотеки Kotlin Multiplatform (KMP). Он упрощает настройку проекта, повышает производительность сборки и обеспечивает лучшую интеграцию с Android Studio.

Предыдущий подход теперь устарел в пользу плагина, также называемого плагином Android-KMP . JetBrains больше не будет поддерживать плагин com.android.library для KMP, и вы не сможете воспользоваться будущими обновлениями и улучшениями.

Чтобы установить этот плагин, обратитесь к разделу «Применение плагина Android-KMP» . Если вам нужно перейти с устаревших API, ознакомьтесь с руководством по миграции .

Основные особенности и отличия

Плагин Android-KMP разработан специально для проектов KMP и отличается от стандартного плагина com.android.library по нескольким ключевым аспектам:

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

  • Оптимизировано для KMP: плагин разработан для библиотек KMP, фокусируется на общем коде Kotlin и взаимодействии, исключая поддержку собственных сборок, специфичных для Android, AIDL и RenderScript.

  • Тесты отключены по умолчанию: тесты модулей и устройств (инструментария) по умолчанию отключены для повышения скорости сборки. При необходимости их можно включить.

  • Нет расширения Android верхнего уровня: конфигурация обрабатывается блоком androidLibrary в Gradle KMP DSL, что обеспечивает согласованную структуру проекта KMP. Блок расширения android верхнего уровня отсутствует.

  • Включенная компиляция Java: компиляция Java по умолчанию отключена. Используйте withJava() в блоке androidLibrary , чтобы включить её. Это ускоряет сборку, когда компиляция Java не требуется.

Преимущества плагина библиотеки Android-KMP

Плагин Android-KMP обеспечивает следующие преимущества для проектов KMP:

  • Улучшенная производительность и стабильность сборки: разработан для оптимизации скорости сборки и повышения стабильности в проектах KMP. Ориентация на рабочие процессы KMP способствует более эффективному и надежному процессу сборки.

  • Улучшенная интеграция с IDE: обеспечивает улучшенное автодополнение кода, навигацию, отладку и общий опыт разработки при работе с библиотеками KMP для Android.

  • Упрощённая конфигурация проекта: плагин упрощает конфигурацию проектов KMP, устраняя сложности, характерные для Android, такие как варианты сборки. Это приводит к созданию более понятных и удобных для поддержки файлов сборки. Ранее использование плагина com.android.library в проекте KMP могло приводить к появлению запутанных имён исходных наборов, например, androidAndroidTest . Такое соглашение об именовании было менее интуитивно понятным для разработчиков, знакомых со стандартными структурами проектов KMP.

Предпосылки

Чтобы использовать плагин com.android.kotlin.multiplatform.library , ваш проект должен быть настроен на следующие минимальные версии или выше:

  • Плагин Android Gradle (AGP) : 8.10.0
  • Плагин Kotlin Gradle (KGP) : 2.0.0

Применить плагин Android-KMP к существующему модулю

Чтобы применить плагин Android-KMP к существующему модулю библиотеки KMP, выполните следующие действия:

  1. Объявите плагины в каталоге версий. Откройте TOML-файл каталога версий (обычно gradle/libs.versions.toml ) и добавьте раздел определений плагинов:

    # To check the version number of the latest Kotlin release, go to
    # https://kotlinlang.org/docs/releases.html
    
    [versions]
    androidGradlePlugin = "8.13.0"
    kotlin = "KOTLIN_VERSION"
    
    [plugins]
    kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
    android-kotlin-multiplatform-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "androidGradlePlugin" }
    
  2. Примените объявление плагина в корневом файле сборки. Откройте файл build.gradle.kts , расположенный в корневом каталоге вашего проекта. Добавьте псевдонимы плагина в блок plugins , используя apply false . Это сделает псевдонимы плагина доступными для всех подпроектов, не применяя логику плагина к самому корневому проекту.

    Котлин

    // Root build.gradle.kts file
    
    plugins {
       alias(libs.plugins.kotlin.multiplatform) apply false
    
       // Add the following
       alias(libs.plugins.android.kotlin.multiplatform.library) apply false
    }

    Круто

    // Root build.gradle file
    
    plugins {
       alias(libs.plugins.kotlin.multiplatform) apply false
    
       // Add the following
       alias(libs.plugins.android.kotlin.multiplatform.library) apply false
    }
  3. Примените плагин в файле сборки модуля библиотеки KMP. Откройте файл build.gradle.kts в модуле библиотеки KMP и примените плагин в начале файла в блоке plugins :

    Котлин

    // Module-specific build.gradle.kts file
    
    plugins {
       alias(libs.plugins.kotlin.multiplatform)
    
       // Add the following
       alias(libs.plugins.android.kotlin.multiplatform.library)
    }

    Круто

    // Module-specific build.gradle file
    
    plugins {
       alias(libs.plugins.kotlin.multiplatform)
    
       // Add the following
       alias(libs.plugins.android.kotlin.multiplatform.library)
    }
  4. Настройте целевой проект Android KMP. Настройте блок Kotlin Multiplatform ( kotlin ) для определения целевого проекта Android. В блоке kotlin укажите целевой проект Android с помощью androidLibrary :

    Котлин

    kotlin {
       androidLibrary {
           namespace = "com.example.kmpfirstlib"
           compileSdk = 33
           minSdk = 24
    
           withJava() // enable java compilation support
           withHostTestBuilder {}.configure {}
           withDeviceTestBuilder {
               sourceSetTreeName = "test"
           }
    
           compilations.configureEach {
               compilerOptions.configure {
                   jvmTarget.set(
                       org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
                   )
               }
           }
       }
    
       sourceSets {
           androidMain {
               dependencies {
                   // Add Android-specific dependencies here
               }
           }
           getByName("androidHostTest") {
               dependencies {
               }
           }
    
           getByName("androidDeviceTest") {
               dependencies {
               }
           }
       }
       // ... other targets (JVM, iOS, etc.) ...
    }

    Круто

    kotlin {
       androidLibrary {
           namespace = "com.example.kmpfirstlib"
           compileSdk = 33
           minSdk = 24
    
           withJava() // enable java compilation support
           withHostTestBuilder {}.configure {}
           withDeviceTestBuilder {
               it.sourceSetTreeName = "test"
           }
    
           compilations.configureEach {
               compilerOptions.options.jvmTarget.set(
                   org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
               )
           }
       }
    
       sourceSets {
           androidMain {
               dependencies {
               }
           }
           androidHostTest {
               dependencies {
               }
           }
           androidDeviceTest {
               dependencies {
               }
           }
       }
       // ... other targets (JVM, iOS, etc.) ...
    }
  5. Примените изменения. После установки плагина и настройки блока kotlin синхронизируйте свой проект Gradle, чтобы изменения вступили в силу.

Миграция с устаревшего плагина

Это руководство поможет вам перейти с устаревшего плагина com.android.library на плагин com.android.kotlin.multiplatform.library .

1. Объявление зависимостей

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

Android-KMP

Новый плагин обеспечивает более чёткую структуру, группируя зависимости Android в исходном наборе androidMain . Помимо основного исходного набора, существуют два тестовых исходных набора, которые создаются по запросу: androidDeviceTest и androidHostTest (для получения дополнительной информации см. раздел «Настройка тестов хоста и устройства »).

// build.gradle.kts

kotlin {
    android {}
    //... other targets

    sourceSets {
        commonMain.dependencies {
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")
        }

        // Dependencies are now scoped to the specific Android source set
        androidMain.dependencies {
            implementation("androidx.appcompat:appcompat:1.7.0")
            implementation("com.google.android.material:material:1.11.0")
        }
    }
}

Исходные наборы имеют соответствующие компиляции Kotlin с именами main , deviceTest и hostTest . Исходные наборы и компиляции можно настроить в скрипте сборки следующим образом:

// build.gradle.kts

kotlin {
    androidLibrary {
        compilations.getByName("deviceTest") {
            kotlinOptions.languageVersion = "2.0"
        }
    }
}

Устаревший плагин

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

// build.gradle.kts

kotlin {
  androidTarget()
  //... other targets
}

// Dependencies for all source sets were often mixed in one block
dependencies {
  // Common dependencies
  commonMainImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")

  // Android-specific dependencies
  implementation("androidx.appcompat:appcompat:1.7.0")
  implementation("com.google.android.material:material:1.11.0")
}

2. Включение ресурсов Android

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

Android-KMP

Необходимо явно включить обработку ресурсов Android. Ресурсы должны быть размещены в src/androidMain/res .

// build.gradle.kts

kotlin {
  android {
    // ...
    // Enable Android resource processing
    androidResources {
      enable = true
    }
  }
}

// Project Structure
// └── src
//     └── androidMain
//         └── res
//             ├── values
//             │   └── strings.xml
//             └── drawable
//                 └── icon.xml

Устаревший плагин

Обработка ресурсов была включена по умолчанию. Можно было сразу добавить каталог res в src/main и начать добавлять XML-контенты, значения и т. д.

// build.gradle.kts

android {
    namespace = "com.example.library"
    compileSdk = 34
    // No extra configuration was needed to enable resources.
}

// Project Structure
// └── src
//     └── main
//         └── res
//             ├── values
//             │   └── strings.xml
//             └── drawable
//                 └── icon.xml

3. Настройка тестов хоста и устройства

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

Эта модель добровольного участия помогает убедиться, что ваш проект остается компактным и включает только ту логику сборки и исходные наборы, которые вы активно используете.

Android-KMP

В новом плагине тесты включаются и настраиваются внутри блока kotlin.android . Это делает настройку более явной и позволяет избежать создания неиспользуемых тестовых компонентов. Исходный набор test становится androidHostTest , а androidTestandroidDeviceTest .

// build.gradle.kts

kotlin {
  android {
    // ...

    // Opt-in to enable and configure host-side (unit) tests
    withHostTest {
      isIncludeAndroidResources = true
    }

    // Opt-in to enable and configure device-side (instrumented) tests
    withDeviceTest {
      instrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
      execution = "ANDROIDX_TEST_ORCHESTRATOR"
    }
  }
}

// Project Structure (After Opt-in)
// └── src
//     ├── androidHostTest
//     └── androidDeviceTest

Устаревший плагин

С плагином com.android.library исходные наборы test и androidTest были созданы по умолчанию. Их поведение настраивалось внутри блока android , обычно с помощью DSL- testOptions .

// build.gradle.kts

android {
  defaultConfig {
    // Runner was configured in defaultConfig
    testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
  }

  testOptions {
    // Configure unit tests (for the 'test' source set)
    unitTests.isIncludeAndroidResources = true

    // Configure device tests (for the 'androidTest' source set)
    execution = "ANDROIDX_TEST_ORCHESTRATOR"
  }
}

// Project Structure (Defaults)
// └── src
//     ├── test
//     └── androidTest

4. Включить компиляцию исходного кода Java

Если вашей библиотеке KMP требуется компилировать исходный код Java для целевой платформы Android, необходимо явно включить эту функцию с помощью нового плагина. Обратите внимание, что это позволяет компилировать файлы Java, расположенные непосредственно в вашем проекте, а не его зависимости. Также изменяется метод установки целевой версии JVM для компилятора Java и Kotlin.

Android-KMP

Необходимо включить компиляцию Java, вызвав метод withJava() . Целевая платформа JVM теперь настраивается непосредственно внутри блока kotlin { androidLibrary {} } для более унифицированной настройки. Настройка jvmTarget здесь применяется как к компиляции Kotlin, так и к компиляции Java для целевой платформы Android.

// build.gradle.kts

kotlin {
  android {
    //  Opt-in to enable Java source compilation
    withJava()
    // Configure the JVM target for both Kotlin and Java sources
    compilerOptions {
      jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8)
    }
  }
  // ...
}

// Project Structure:
// └── src
//     └── androidMain
//         ├── kotlin
//         │   └── com/example/MyKotlinClass.kt
//         └── java
//             └── com.example/MyJavaClass.java

Устаревший плагин

Компиляция Java была включена по умолчанию. Целевая JVM для исходных кодов Java и Kotlin была задана в блоке android с помощью compileOptions.

// build.gradle.kts

android {
  // ...
  compileOptions {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
  }
}

kotlin {
  androidTarget {
    compilations.all {
      kotlinOptions.jvmTarget = "1.8"
    }
  }
}

5. Взаимодействие с вариантами сборки с помощью androidComponents

Расширение androidComponents по-прежнему доступно для программного взаимодействия с артефактами сборки. Хотя большая часть Variant API осталась прежней, новый интерфейс AndroidKotlinMultiplatformVariant стал более ограниченным, поскольку плагин создаёт только один вариант.

Следовательно, свойства, связанные с типами сборки и разновидностями продукта, больше не доступны для объекта варианта.

Android-KMP

Блок onVariants теперь перебирает только один вариант. Вы по-прежнему можете получить доступ к общим свойствам, таким как name и artifacts , но не к свойствам, специфичным для конкретного типа сборки.

// build.gradle.kts

androidComponents {
  onVariants { variant ->
      val artifacts = variant.artifacts
  }
}

Устаревший плагин

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

// build.gradle.kts

androidComponents {
  onVariants(selector().withBuildType("release")) { variant ->
    // ...
  }
}

6. Выберите варианты зависимостей библиотеки Android

Ваша библиотека KMP создаёт единственный вариант для Android. Однако вы можете зависеть от стандартной библиотеки Android ( com.android.library ), которая имеет несколько вариантов (например, free/paid версии продукта). Управление тем, как ваш проект выбирает вариант из этой зависимости, является распространённым требованием.

Android-KMP

Новый плагин централизует и проясняет эту логику в блоке kotlin.android.localDependencySelection . Это значительно упрощает выбор вариантов внешних зависимостей для вашей одновариантной библиотеки KMP.

// build.gradle.kts
kotlin {
  android {
    localDependencySelection {
      // For dependencies with multiple build types, select 'debug' first, and 'release' in case 'debug' is missing
      selectBuildTypeFrom.set(listOf("debug", "release"))

      // For dependencies with a 'type' flavor dimension...
      productFlavorDimension("type") {
        // ...select the 'typeone' flavor.
        selectFrom.set(listOf("typeone"))
      }
    }
  }
}

Устаревший плагин

Вы настраивали стратегии выбора зависимостей в блоках buildTypes and productFlavors . Это часто включало использование missingDimensionStrategy для предоставления разновидности по умолчанию для измерения, отсутствующего в вашей библиотеке, или сопоставление значений matchingFallbacks в рамках конкретной разновидности для определения порядка поиска.

Более подробную информацию об использовании API см. в разделе Устранение ошибок сопоставления .

Справочник API плагина

Новый плагин имеет API, отличный от com.android.library . Подробную информацию о новом DSL и интерфейсах см. в справочных материалах по API:

{% дословно %} {% endverbatim %} {% дословно %} {% endverbatim %}