Gradle андроид что это

Содержание
  1. Gradle
  2. Задаём имя APK при компиляции
  3. Оптимизатор кода R8
  4. Сжимаем итоговый APK
  5. Класс BuildConfig
  6. Разделяем отладочную и финальную версию
  7. Прячем секретную информацию
  8. Автогенерация версии кода
  9. settings.gradle
  10. gradle.properties (Project Properties)
  11. Режим параллельного выполнения
  12. Gradle-демон
  13. Режим конфигурации при необходимости
  14. Меняем номер версии библиотек в одном месте
  15. Настройки в Android Studio
  16. Gradle Task
  17. Узнать debug.keystore: MD5 и SHA1
  18. Gradle Console
  19. Terminal
  20. Добавление зависимостей через интерфейс студии
  21. Дополнительное чтение
  22. Gradle Plugin: Что, зачем и как?
  23. Краткое введение в Gradle-плагины
  24. Реализация плагина в build.gradle(.kts)
  25. Реализация плагина в buildSrc
  26. Script-плагины
  27. Попробуем script-плагин в деле
  28. Небольшой, но важный оффтоп про Kotlin-екстеншны для подключения плагинов
  29. Standalone-плагин на примере кодогенерации
  30. Конфигурация плагина
  31. Тестирование плагина
  32. Интеграционное тестирование плагина
  33. Функциональное тестирование плагина
  34. Деплой плагина во внешний репозиторий
  35. Итоги

Gradle

Gradle — система автоматической сборки, построенная на принципах Apache Ant и Apache Maven. В Eclipse использовалась система Ant, но большинство разработчиков даже не замечало её работы. В основном возможности системы использовались в конторах для автоматизации различных задач. В Android Studio такой номер не пройдёт. Gradle сопровождает вас во время разработки постоянно. Поначалу, если вы перешли с Eclipse, Gradle сильно раздражает своими действиями. Но позже вы оцените её удобство и может даже полюбите её.

Gradle не является изобретением для Android Studio, система была разработана раньше и использовалась в приложениях для Java, Scala и других языках.

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

Создайте новый проект или откройте любой существующий проект из Android Studio и посмотрите на структуру проекта.

В последних версиях студии файлы Gradle выделили в отдельную папку Gradle Script. Раскройте её. В основном вас должен интересовать файл build.gradle, который относится к модулю. Рядом с этим файлом в скобках будет написано Module: app. Двойным щелчком откройте его, вы увидите, что файл является текстовым.

Также есть файл build.gradle, который относится к проекту. Но с ним работают реже. Так находятся настройки для репозиториев и самого Gradle.

Вернёмся к файлу модуля, вы увидите много интересной информации. Например, вы там можете увидеть настройки, которые раньше вы могли видеть в манифесте — номера версий, номера SDK и так далее. Забегая вперёд, скажу, что здесь можно добавить всего одну волшебную строчку и нужная библиотека сама скачается из интернета и установится в проекте. Красота!

Однако вернёмся в корневую папку. Кроме файлов build.gradle мы можем заметить файлы gradle.properties, settings.gradle и другие. Трогать их не нужно.

В корневой папке также есть файлы gradlew и gradlew.bat для работы с Gradle Wrapper. В принципе вам не нужно знать о них ничего. Но для параноиков есть информация — если вы часто импортируете проекты из неизвестных источников, то они содержат файл gradle/wrapper/gradle-wrapper.properties. Откройте его текстовым редактором и посмотрите на адрес у distributionUrl. Путь должен вести на официальный сай //services.gradle.org или на внутренний корпоративный сервер. Другие адреса должны вызвать тревогу.

Вы могли заметить, что по сравнению с Eclipse изменилась структура файлов. В папке app находится папка src, а ней папка main, в которых папки java, res и файл манифеста. Новая структура лучше отвечает требованиям Gradle для управления файлами.

Вы, например, можете создавать альтернативные папки с ресурсами и с помощью build.gradle подключить их к проекту.

В этом примере мы указали, что существуют новая папка presentations в папке /src/main/ наряду с существующими папками java и res. Внутри созданной папки есть ещё две папки layout и animations, которые содержат файлы ресурсов.

Только помните, что вам нужно избегать конфликта имён при слиянии всех файлов при сборке.

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

Другая полезная возможность — создавать разные версии приложений, например, демо-версию и платную версию. Немного об этом рассказано здесь.

Номер версии приложения и требования к версии Android прописаны в секции defaultConfig. Если у вас сохранились старые версии приложений, то в манифесте можете удалить данные записи. По-моему, там даже выводится соответствующая подсказка. Даже если вы эти данные в манифесте не удалите, то значения из gradle.build имеют больший приоритет и перепишут значения в манифесте при не совпадении.

Подключение библиотеки происходит одной строчкой. Например, нужно добавить библиотеку Picasso:

В Android Studio 3.0 используется новая версия Gradle, в которой compile считается устаревшей. Вместо него следует использовать новое слово implementation.

Есть похожая команда, которая подключает библиотеку, которая будет использоваться только для отладки приложения и в релизной версии она не нужна.

Далее включаете синхронизацию и через несколько секунд в папке появляется нужная библиотека, готовая к использованию. Сама библиотека скачивается с специального хранилища-репозитория JCenter. Данный репозиторий используется по умолчанию и прописан в buil.gradle проекта.

Можно указать другой репозиторий, например, Maven Central.

Для поиска через Maven-репозиторий используйте The Central Repository Search Engine.

Библиотеку можно подключать и старым способом, используя jar-файл, но такой способ уходит в прошлое.

Сам файл нужно скопировать в папку /libs.

При любом изменении файла недостаточно его сохранить. Нужно также произвести синхронизацию. Наверху обычно появляется жёлтая полоска с ссылкой Sync Now.

Задаём имя APK при компиляции

Можно задать собственное имя при компиляции проекта. Например, так.

Получим имя MyName-1.0.12-release.apk

Оптимизатор кода R8

Оптимизатор кода R8 имеет следующие возможности: урезание байт-кода, сжатие, обфускация, оптимизация, удаление «синтаксического сахара», преобразование в DEX. Оптимизатор может производить все операции за один шаг, что даёт сильное улучшение производительности. R8 был введён в Android Gradle plugin 3.3.0. Вам нужно только включить его.

R8 разработан для работы с существующими ProGuard-правилами, хотя возможны ситуации, когда нужно переработать правила.

Сжимаем итоговый APK

В Gradle 1.4 появилась возможность сжать итоговый файл, убрав неиспользуемые ресурсы, в том числе из библиотек, например, Google Play Services.

Во время сборки приложения вы можете увидеть строку:

Другой способ убрать неиспользуемые ресурсы конфигурации. Например, вам не нужные локализованные ресурсы для всех языков, которые входят в библиотеку Google Play Services или Android Support Library и др. Оставим только нужные языки. Возможно, вы также не хотите поддерживать mdpi или tvdpi-разрешения в своём приложении. Мы можем установить языки и разрешения, которые используются в приложении, остальные будут исключены, что позволит уменьшить вес приложения.

Можно перенести ключи из манифеста.

Чтобы их не светить, например, если выкладывать код на Гитхабе, то сделаем так.

Читайте также:  Экзамен гибдд вождение для андроид

И в манифесте переделаем код.

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

В манифесте пишем.

Класс BuildConfig

В статье LogCat упоминался способ быстрого отключения журналирования.

Суть в следующем. Когда вы создаёте новые переменные в блоках defaultConfig или buildTypes (ветки debug и release), то Gradle создаёт специальный класс BuildConfig, и вы можете получить доступ к этим переменным.

Например, добавим переменную в defaultConfig

На языке Java это равносильно String YOUR_TOKEN = «ABRAKADABRA»;

Теперь мы можем обратиться к созданной строке.

С секцией buildType ситуация интереснее. У секции есть два блока debug и release. Можно создать переменные с разными значениями, которые будут использоваться в зависимости от ситуации. Например, у вас есть собственное API для сервера. Для тестирования вы используете один адрес, а для финальной версии — другой адрес. Тогда вы просто указываете разные адреса в разных ветках. Переменные могут быть не только строковыми.

Создаём код для перехода на веб-страницу.

Теперь вам не нужно переписывать каждый раз код. Загружаться будет страница по нужному адресу автоматически.

Разделяем отладочную и финальную версию

По такому же принципу можно организовать запуск новой версии программы, не затрагивая программу, которую вы установили с Google Play. Допустим вы на своём телефоне установили своё собственное приложение через Google Play. Теперь вам нужно написать новую версию и проверить на своём телефоне. Из-за конфликта имён новое тестируемое приложение перепишет финальную версию или вообще не установится. Поможет следующий трюк.

В специальных переменных applicationIdSuffix и versionNameSuffix мы задаём суффиксы, чтобы избежать конфликта. А в переменной resValue указываем название программы для отладочной и финальных версий, чтобы на устройстве можно было их найти. Не забудьте при этом удалить строковый ресурс app_name в res/values/strings.xml, иначе получите ошибку при компиляции. Теперь можете спокойно запускать приложение с новым кодом, не боясь повредить своё любимое приложение.

Прячем секретную информацию

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

Автогенерация версии кода

Нашёл совет, сам не применял. Не обязательно вручную менять версию приложения в атрибутах versionCode и versionName, можно сделать через переменные, а они сами подставятся в нужное место. На любителя.

settings.gradle

Файл settings.gradle обычно состоит из одной строчки.

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

gradle.properties (Project Properties)

Несколько советов по настройке файла gradle.properties.

Режим параллельного выполнения

В этом файле можно найти закомментированную строку # org.gradle.parallel=true. Если модули вашего проекта не используют друг друга как зависимости, создавая перекрёстные ссылки, можно включать режим параллельного выполнения, что ускорит скорость сборки до

Gradle-демон

Включение на компьютере демона Gradle даст значительный прирост в скорости сборки.

Режим конфигурации при необходимости

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

Меняем номер версии библиотек в одном месте

Очень часто в проекте используются взаимосвязанные библиотеки с одинаковыми номерами.

Можно быстро поменять у всех номера через переменную. Для этого используется секция ext, в которой указывается переменная и номер версии. Затем в секции dependencies номер версии заменяется на имя переменной

Обратите внимание, что одинарные кавычки заменяются на двойные, а символ $ указывает на строковый тип.

Расширенная версия с разными переменными в другом виде.

Если в проекте используются несколько модулей с одинаковыми зависимостями, то эти записи можно перенести в корневой build.gradle, чтобы не менять номера версий в каждом модуле.

Настройки в Android Studio

Рассмотрим настройки, доступные в Android Studio. Закройте текущий проект, чтобы увидеть стартовое окно студии. В правой части нажмите на пункт Configure. В следующем окне выберите пункт Settings, чтобы оказаться в окне настроек студии. В левой части найдите пункт Build, Execution, Deployment, затем подпункт Build Tools, далее подпункт Gradle. По умолчанию, там всё чисто, только указан путь у Service directory path. Это были общие настройки.

Теперь рассмотрим настройки, относящиеся к проекту. Запустите любой проект в Android Studio. Выберите меню File | Settings. . Снова пройдитесь по пунктам Build, Execution, Deployment | Build Tools | Gradle. Вы увидите практически такое же окно с небольшими изменениями. Теперь поле Linked Gradle Projects не будет пустым, а также появятся дополнительные настройки. По умолчанию рекомендуют использовать Use default gradle wrapper.

Gradle Task

На правой стороне Android Studio имеется вертикальная вкладка Gradle, которую можно развернуть. Она содержит список задач (task), которая выполняет Gradle при работе с текущим проектом. Вы можете выделить любую из этих задач и запустить её двойным щелчком. Можно выделить несколько задач.

Узнать debug.keystore: MD5 и SHA1

Иногда требуется узнать значения debug.keystore: MD5 и SHA1. Обычно их получают через командную строку. Но это долго и неудобно, так как нужно помнить все аргументы. Есть способ проще. Открываем вкладку Gradle, нажимаем на кнопку со стрелками Refresh all Gradle Projects. Затем последовательно открываем элементы Tasks | android и запускаем команду signingReport. В нижнем окне Run увидите нужную информацию.

Gradle Console

Когда выполняется какая-то задача Gradle, то ход её выполнения можно увидеть в окне Gradle Console. Открыть её можно через вкладку Gradle Console в нижней правой части студии.

Terminal

Запускать задачи Gradle можно и в окне Terminal.

На панели инструментов имеется значок Sync Project with Gradle Files, которую следует использовать при редактировании файлов Gradle. Как правило, студия также выводит предупреждающее сообщение с ссылкой при изменении файла, которая делает ту же работу.

Добавление зависимостей через интерфейс студии

В статье описывался способ включения библиотеки в проект через редактирование файла build.gradle. Существует альтернативный вариант через настройки студии. Щёлкните правой кнопкой мыши на имени модуля (app) и выберите пункт Open Module Settings (быстрая клавиша F4). В правой части окна находятся вкладки, которые оказывают влияние на файл build.gradle. Например, вкладка Dependencies содержит подключаемые библиотеки.

Чтобы добавить новую зависимость, нажмите на значок с плюсом и выберите нужный вариант, например, Library dependency. Откроется список доступных библиотек из репозитория Maven.

Дополнительное чтение

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

Задачи Gradle — теория для общего развития.

Источник

Gradle Plugin: Что, зачем и как?

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

Читайте также:  Как удалить verse с андроид

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

В первой части статьи проведём небольшой теоретический экскурс и рассмотрим способы реализации плагинов, а во второй части двинемся к практической задаче и проникнемся разработкой плагина для Kotlin-кодогенерации. Для реализации Gradle-задумок по ходу статьи я буду использовать Kotlin. Заваривайте ваш любимый напиток и поехали.

Gradle Plugin: Что, зачем и как?

Краткое введение в Gradle-плагины

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

Плагины полностью автономны и позволяют хранить логику для её повторного использования в нескольких проектах или Gradle-модулях. Они замечательно подходят для любых задач, требующих работы с исходным кодом. Такими задачами могут быть кодогенерация / генерация документации / проверка кода / запуск задач на CI / деплой и многое другое.

С точки зрения кода, плагин представляет собой реализацию примитивного интерфейса с единственным методом apply:

Project-ом является Gradle-проект (или Gradle-модуль), куда подключается плагин. Сам по себе интерфейс Project больше похож на God Object, поскольку в нём доступен сразу весь Gradle API, что, в принципе, достаточно удобно.

Gradle предлагает разработчикам несколько способов реализации плагинов (как и практически всего в Gradle). Дальше рассмотрим каждый способ по-отдельности и определим его плюсы и минусы.

Реализация плагина в build.gradle(.kts)

Самый простой вариант – реализовать плагин прямо внутри файла конфигурации. Да, просто берём и пишем класс по примеру выше в build.gradle(.kts). Если честно, трудно понять, какой пользой обладает такое решение, ведь Gradle уже предоставляет возможность обратиться project-у из файла конфигурации и накрутить его нужной логикой. А вот недостатков получаем сразу несколько.

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

Реализация плагина в buildSrc

Модуль buildSrc компилируется и поставляется на этап конфигурации проекта в виде jar, поэтому реализовав плагин в buildSrc, получаем возможность его использования в Gradle-модулях проекта. Однако из-за известных проблем c инвалидацией кеша, реализация плагинов в buildSrc имеет право на жизнь в том случае, если для вашего проекта buildSrc представляет собой около-константный модуль, в котором редко происходят изменения.

Также такой вариант также является более компромиссным в сравнении со standalone-плагинами с точки зрения затрат на реализацию и вполне может подойти для небольших проектов.

Допустим, такой вариант нам подходит. Выполним подготовительный шаг и подключим в buildSrc плагин Kotlin DSL. Он сделает всю грязную работу по подключению Kotlin, подключит Gradle API и ещё м.

P.S. Поскольку для .kts скриптов используется embedded-версия Kotlin, которая лежит вместе с Gradle, то самостоятельно подключать свежую версию Kotlin для реализации плагинов не рекомендуется во избежание проблем с обратной совместимостью. На практике проблем не встречал, но потенциально может выстрелить.

Кладём реализацию плагина в buildSrc/src/main/kotlin. Охапка дров, плагин готов. Теперь можно подключать плагин в проект с помощью apply :

Нагляднее будет подключать плагин c помощью id, поэтому давайте его зададим. Плагин Kotlin DSL транзитивно подключает Java Gradle Plugin Development Plugin, который предоставляет такую возможность:

В результате будет создан следующий файл:

src/main/resources/META-INF/gradle-plugins/ru.myorg.demo.my-plugin.properties

, который Gradle бережно положит в jar и дальше сможет соотносить id плагина с его реализацией. Теперь подключить плагин к проекту можно так:

Script-плагины

В Gradle присутствует интересная возможность реализовать плагин в виде скрипта. Скриптовый плагин по структуре идентичен скриптам конфигурации build.gradle(.kts) и может быть реализован как на Groovy, так и на Kotlin. При реализации на Kotlin существует достаточно весомое ограничение – скрипты должны находиться либо в buildSrc, либо в standalone Gradle-проекте, чтобы быть скомпилированными.

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

Приятным бонусом script-плагинов является автоматическая генерация id. Это сделает за нас Gradle Plugin Development Plugin, исходя из названия скрипта.

Важно: При реализации и использовании script-плагинов необходимо учесть следующие ограничения, связанные с версиями Gradle:

При реализации script-плагина в отдельном проекте и его подключении через композитную сборку, необходимо использовать Gradle версии 7.1 и выше из-за бага, при котором падала сборка после подключения плагина Kotlin DSL. Во всех проектах, куда подключается плагин с помощью композитной сборки, также необходимо использовать Gradle 7.1 и выше.

Script-плагины, написанные на Kotlin, можно подключать в проекты, использующие Gradle 6 и выше.

Script-плагины, написанные на Groovy, можно подключать в проекты, использующие Gradle 5 и выше.

Script-плагины можно писать на Kotlin, начиная с Gradle 6.0, и на Groovу, начиная с Gradle 6.4.

Лучше всегда держать версию Gradle в актуальном состоянии и не забивать голову лишними вопросами.

Попробуем script-плагин в деле

Давайте проведём небольшой эксперимент. Попробуем вынести в script-плагин на Kotlin общую конфигурацию Android-модулей и сделаем это в buildSrc.

Подключаем Android Gradle Plugin:

Теперь напишем сам плагин:

buildSrc/src/main/kotlin/android-common.gradle.kts:

Жмём Gradle Sync и получаем следующее время конфигурации: BUILD SUCCESSFUL IN 2m 6s

Почему так много? Я начал разбираться и первым делом зашёл в папку buildSrc/build, немного покопался и увидел там следующее:

Оказалось, что для плагинов, которые были объявлены в блоке plugins <> также производится кодогенерация Kotlin-аксессоров для использования в .kts-скриптах. На выходе получаем несколько сотен сгенерированных файлов для плагина com.android.library.

Кстати, именно это происходит при первом подключении Kotlin DSL в Gradle-проект, но лишь за тем отличием, что кодогенерация осуществляется внутри .gradle директории на вашем рабочем устройстве.

Из этой грустной истории можно сделать вывод, что c подключением сторонних плагинов в script-плагине необходимо быть вдвойне аккуратными, а лучше и вовсе отказаться от этой идеи в пользу классов. Потеря в удобстве, на мой взгляд, незначительная. Попробуем реализовать тот же функционал с помощью класса:

В коде выше android <> будет самописным Kotlin-екстеншном:

Получаем следующее время конфигурации: BUILD SUCCESSFUL in 48s

и никакого лишнего кодгена. Not bad, not terrible. Замеры проводил на рабочем проекте, поэтому ваши результаты могут отличаться. А чтобы плагин было удобно подключать, генерируем ему id и в buildSrc самостоятельно напишем Kotlin-екстеншн:

Получилось ничем не хуже, и такой вариант вполне безопасно использовать.

Читайте также:  Лучший стедикам для андроида

Небольшой, но важный оффтоп про Kotlin-екстеншны для подключения плагинов

В ходе статьи можно заметить, что некоторые плагины удобным образом подключаются с помощью Kotlin-екстеншнов. Дело в том, что они хитро вшиты в сам Gradle, и написать собственный екстеншн получится только при реализации плагина в buildSrc. Если же плагин реализован в standalone-проекте, то при попытке использования самописного екстеншна получаем ошибку компиляции. Проблема актуальна вплоть до Gradle 7.1. Очень ждём, что это будет исправлено будущих релизах.

Теперь давайте двинемся дальше и рассмотрим полноценные standalone-плагины.

Standalone-плагин на примере кодогенерации

Standalone-плагин подразумевает реализацию в отдельном Gradle-проекте. Такой способ является наиболее предпочтительным, поскольку позволяет избежать всех недостатков buildSrc и script-плагинов. Если вы не хотите создавать отдельный git-репозиторий и планируете использовать плагин внутри одного проекта, то можно воспользоваться возможностью композитной сборки.

Планомерно приступим к небольшой практической задаче. Создадим новый проект и подключим всё, что нужно:

В зависимости добавим Kotlin Poet, с помощью которого будет реализована кодогенерация и Kotlin Gradle Plugin, который поможет интегрировать сгенерированный код в компиляцию JVM-проекта.

Теперь давайте определимся с параметрами плагина и с тем, как их передавать.

Конфигурация плагина

Для примера в качестве параметра сделаем файл с каким-нибудь сообщением. Это сообщение будет использоваться в качестве значения переменной в сгенерированном классе. Также в параметрах будем передавать рутовую директорию для кодогенерации и название пакета для сгенерированного класса.

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

Контейнер должен быть abstract или open классом, поскольку Gradle будет хитро создавать его инстанс с помощью рефлексии.

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

Создать и зарегистрировать extension-контейнер можно так:

Последним параметром передается аргумент (или аргументы) для конструктора. Идеально, если единственным аргументом будет project, но спроектировать можно как угодно. Созданный extension можно использовать в скриптах конфигурации build.gradle(.kts) следующим образом:

Теперь самое время создать саму Gradle-таску, которая будет выполнять кодогенерацию:

Аннотацией @TaskAction помечена функция, с которой таска начинает своё выполнение. Геттеры и сеттеры для Kotlin-пропертей помечены специальными Gradle-аннотациями, чтобы таска имела возможность выполняться инкрементально, то есть не выполняться, когда на то нет необходимости. Кому любопытно, полный исходный код доступен на моём Github.

Теперь давайте сделаем так, чтобы сгенерированный файл успешно компилировался. Директорию, в которой осуществляется кодогенерация, добавим в основной sourceSet. Таким образом явно объявим, что в директории хранится исходный код, который должен быть скомпилирован. С помощью afterEvaluate дождёмся окончания конфигурации, чтобы убедиться, что sourceSets уже были созданы.

Регистрируем кодген-таску, а саму компиляцию вежливо просим её подождать:

Всё готово к использованию. Получившийся плагин можно изучить под спойлером:

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

settings.gradle.kts:

Прежде чем нажать на Build, положим в корень проекта файл с сообщением. Собираем проект и видим созданный в build/src-gen созданный класс.

Ура! Теперь сгенерированный класс можно использовать в проекте. Самое время протестировать реализованное.

Тестирование плагина

В первую очередь, ребята из Gradle советуют тестировать плагин ручками. То есть, подключаем плагин с помощью композитной сборки к проекту и пользуемся всеми радостями дебаггинга.

Например, чтобы отдебажить конфигурацию плагина, выбираем интересующую нас таску из раздела Run Configurations и жмём Debug. Аналогично можно дебажить любые Gradle-таски.

Для автоматического тестирования Gradle-плагина предусмотрено три варианта: функциональные, интеграционные и модульные тесты.

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

Для функциональных и интеграционных тестов выполним подготовительный шаг и создадим кастомные sourceSets. Никто не запрещает делать всё в одном сете с модульными тестами, однако подход с раздельными sourceSet позволяет подключать только необходимые для конкретного вида тестов зависимости и в целом изолировать тесты друг от друга.

Чтобы запускать тесты из кастомных sourceSet, самостоятельно создадим соответствующие Gradle-таски. Для удобства запуска всех тестов сразу, свяжем их в стандартную таску check. В итоге конфигурация для интеграционных и функциональных тестов будет выглядеть следующим образом:

Конфигурация для интеграционных и функциональных тестов

build.gradle.kts (Gradle-проект с плагином):

Интеграционное тестирование плагина

Теперь приступим к разработке интеграционного теста, в котором проверим взаимодействие плагина с внешней средой, а именно с файловой системой. Здесь мы всё ещё ничего не знаем о Gradle и проверяем работу бизнес-логики.

Создаём одноимённую для соответствующего sourceSet директорию в /src и реализуем тест.

src/integrationTest/kotlin/:

Функциональное тестирование плагина

Теперь перейдём к самому интересному – функциональным тестам. Они позволяют проверить работу плагина целиком совместно с Gradle и его жизненным циклом. Для этого будем запускать настоящий Gradle Daemon. Конфигурация функциональных тестов практически ничем не отличается от конфигурации интеграционных тестов, за тем исключением, что больше не нужна зависимость на модуль с Gradle-плагином.

Чтобы запустить Gradle Daemon, необходимо создать и сконфигурировать Gradle Runner. Для этого добавляем Gradle Runner API в classpath для функциональных тестов следующим образом:

В тесте эмулируем структуру проекта, конфигурируем Gradle Runner, запускаем и смотрим что получилось. Сам тест лежит под спойлером:

src/functionalTest/kotlin/:

Отлично! Плагин протестировали, можно похвалить себя чем-то приятным. Осталось дело за малым – задеплоить плагин.

Деплой плагина во внешний репозиторий

Для этого воспользуемся плагином Maven Publish. Формируем публикацию и объявляем список репозиториев, в которые она сможет публиковаться:

Итоги

Gradle-плагины представляют собой действительно мощный инструмент для дополнения логики сборки необходимыми для вас задачами. К сожалению, в Gradle API по-прежнему много загадок и непонятных проблем, в том числе не до конца раскрытых в документации. Это создаёт препятствия на пути к удобству использования, однако команда Gradle над этим активно работает.

На рабочих проектах мы широко используем Gradle-плагины для хранения общей логики сборки, выполнения специфической кодогенерации, а также выполнения различных инфраструктурных задач на CI. А какие задачи решаете вы с помощью Gradle-плагинов? Напишите в комментариях. Также я открыт к любым обсуждениям по материалу, буду рад замечаниям и предложениям.

Всё изложенное в статье доступно на Github.

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

Источник

Оцените статью