Обзор сборки Gradle

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

Что такое сборка?

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

Задачи инкапсулируют команды, которые преобразуют свои входные данные в выходные. Плагины определяют задачи и их конфигурацию. Применение плагина к вашей сборке регистрирует его задачи и связывает их между собой, используя их входные и выходные данные. Например, применение плагина Android Gradle (AGP) к вашему файлу сборки зарегистрирует все задачи, необходимые для сборки APK или библиотеки Android. Плагин java-library позволяет собирать jar-файл из исходного кода Java. Аналогичные плагины существуют для Kotlin и других языков, но другие плагины предназначены для расширения существующих плагинов. Например, плагин protobuf предназначен для добавления поддержки protobuf к существующим плагинам, таким как AGP или java-library .

Gradle предпочитает соглашения конфигурации, поэтому плагины будут поставляться с хорошими значениями по умолчанию, но вы можете дополнительно настроить сборку с помощью декларативного предметно-ориентированного языка (DSL). DSL разработан таким образом, чтобы вы могли указать, что именно нужно собрать, а не как это сделать. Логика в плагинах управляет «как». Эта конфигурация задается в нескольких файлах сборки вашего проекта (и подпроектов).

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

Хотя Gradle поддерживает написание произвольного кода и объявлений задач в файлах сборки, это может затруднить понимание сборки инструментами и вашу поддержку. Например, вы можете писать тесты для кода внутри плагинов, но не в файлах сборки. Вместо этого следует ограничить логику сборки и объявления задач плагинами (которые определяете вы или кто-то другой) и указать, как вы хотите использовать эту логику, в файлах сборки.

Что происходит при выполнении команды сборки Gradle?

Сборка Gradle выполняется в три этапа. На каждом из этих этапов выполняются различные части кода, которые вы определяете в файлах сборки.

  • На этапе инициализации определяются проекты и подпроекты, которые будут включены в сборку, а также настраиваются пути к классам, содержащие файлы сборки и применяемые плагины. На этом этапе основное внимание уделяется файлу настроек, где вы объявляете проекты для сборки и места, откуда будут загружаться плагины и библиотеки.
  • В разделе конфигурации регистрируются задачи для каждого проекта, и выполняется файл сборки для применения спецификации сборки пользователя. Важно понимать, что ваш код конфигурации не будет иметь доступа к данным или файлам, созданным во время выполнения.
  • На этапе выполнения происходит фактическая «сборка» вашего приложения. Результатом конфигурации является направленный ациклический граф (DAG) задач, представляющий все необходимые этапы сборки, запрошенные пользователем (задачи, указанные в командной строке или заданные по умолчанию в файлах сборки). Этот граф отображает взаимосвязь между задачами, либо явно указанную в объявлении задачи, либо основанную на ее входных и выходных данных. Если входные данные задачи являются выходными данными другой задачи, то она должна выполняться после этой задачи. На этом этапе выполняются устаревшие задачи в порядке, определенном в графе; если входные данные задачи не изменились с момента ее последнего выполнения, Gradle пропустит ее.

Для получения более подробной информации см. жизненный цикл сборки Gradle.

DSL-интерфейсы конфигурации

Gradle использует предметно-ориентированный язык (DSL) для настройки сборок. Этот декларативный подход фокусируется на указании ваших данных, а не на написании пошаговых (императивных) инструкций. Вы можете писать файлы сборки на Kotlin или Groovy, но мы настоятельно рекомендуем использовать Kotlin.

DSL призваны упростить участие в проекте для всех, от экспертов в предметной области до программистов, определяя небольшой язык, который представляет данные более естественным образом. Плагины Gradle могут расширять DSL для настройки данных, необходимых для их задач.

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

Котлин

android {
    namespace = "com.example.app"
    compileSdk {
        version = release(36) {
            minorApiLevel = 1
        }
    }
    // ...

    defaultConfig {
        applicationId = "com.example.app"
        minSdk {
            version = release(23)
        }
        targetSdk {
            version = release(36)
        }
        // ...
    }
}

Классный

android {
    namespace = 'com.example.app'
    compileSdk {
        version = release(36) {
            minorApiLevel = 1
        }
    }
    // ...

    defaultConfig {
        applicationId = 'com.example.app'
        minSdk {
            version = release(23)
        }
        targetSdk {
            version = release(36)
        }
        // ...
    }
}

Внутри код DSL выглядит примерно так:

fun Project.android(configure: ApplicationExtension.() -> Unit) {
    ...
}

interface ApplicationExtension {
    var namespace: String?

    fun compileSdk(configure: CompileSdkSpec.() -> Unit) {
        ...
    }

    val defaultConfig: DefaultConfig

    fun defaultConfig(configure: DefaultConfig.() -> Unit) {
        ...
    }
}

Каждый блок в DSL представлен функцией, которая принимает лямбда-выражение для его настройки и свойство с тем же именем для доступа к нему. Это делает код в ваших файлах сборки более похожим на спецификацию данных.

Внешние зависимости

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

Артефакты Maven идентифицируются по названию группы (компания, разработчик и т. д.), названию артефакта (название библиотеки) и версии этого артефакта. Обычно это представляется в формате group:artifact:version .

Этот подход значительно улучшает управление сборкой. Такие репозитории часто называют «репозиториями Maven», но всё дело в способе упаковки и публикации артефактов. Эти репозитории и метаданные используются в нескольких системах сборки, включая Gradle (и Gradle может публиковать в эти репозитории). Публичные репозитории позволяют всем пользователям совместно использовать их, а корпоративные репозитории хранят внутренние зависимости внутри компании.

Вы также можете разделить свой проект на подпроекты (в Android Studio они называются «модулями»), которые также могут использоваться в качестве зависимостей. Каждый подпроект создает выходные файлы (например, JAR-файлы), которые могут использоваться подпроектами или вашим основным проектом. Это может сократить время сборки, поскольку позволяет изолировать части, требующие пересборки, а также лучше разделить обязанности в приложении.

Мы подробнее рассмотрим, как указывать зависимости в разделе «Добавить зависимости сборки» .

Варианты сборки

При создании Android-приложения обычно требуется создать несколько вариантов . Варианты содержат разный код или создаются с различными параметрами и состоят из типов сборки и вариантов продукта.

Типы сборки различаются заявленными параметрами сборки. По умолчанию AGP устанавливает типы сборки «release» и «debug», но вы можете изменить их и добавить другие (например, для промежуточного тестирования или внутренней проверки).

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

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

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

AGP создает варианты для каждой комбинации типа сборки и варианта продукта. Если вы не определяете варианты, варианты именуются в соответствии с типами сборки. Если вы определяете оба типа, вариант именуется как <flavor><Buildtype> . Например, при типах сборки release и debug и вариантах demo и full , AGP создаст следующие варианты:

  • demoRelease
  • demoDebug
  • fullRelease
  • fullDebug

Следующие шаги

Теперь, когда вы ознакомились с концепциями сборки, взгляните на структуру сборки Android в вашем проекте.