Перейти к основному содержимому

Написание пользовательских плагинов Gradle

· 5 мин. чтения

Задача: Сумма двух чисел

Напишите функцию twoSum. Которая получает массив целых чисел nums и целую сумму target, а возвращает индексы двух чисел, сумма которых равна target. Любой набор входных данных имеет ровно одно решение, и вы не можете использовать один и тот же элемент дважды. Ответ можно возвращать в любом порядке...

ANDROMEDA

1. Введение

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

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

2. Расположение источника плагина

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

2.1. Скрипт сборки

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

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

2.2. Папка BuildSrc

Другая возможность, которую мы можем использовать, — это размещение исходного кода нашего плагина в папке buildSrc/src/main/java .

Когда вы запускаете Gradle, он проверяет наличие папки buildSrc . Если он существует, Gradle автоматически создаст и включит наш плагин.

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

2.3. Автономный проект

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

Однако, чтобы использовать его во внешнем проекте, нам нужно объединить его в файл jar и добавить в проект.

3. Наш первый плагин

Начнем с основ — каждый плагин Gradle должен реализовывать интерфейс com.gradle.api.Plugin .

Интерфейс является общим, поэтому мы можем параметризовать его с помощью различных типов параметров. Обычно тип параметра — org.gradle.api.Project.

Однако мы можем использовать параметры разных типов, чтобы плагин применялся на разных этапах жизненного цикла:

  • использование org.gradle.api.Settings приведет к применению плагина к скрипту настроек
  • использование org.gradle.api.Gradle приведет к применению плагина к скрипту инициализации

Самый простой плагин, который мы можем создать, — это приложение hello world :

public class GreetingPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.task("hello")
.doLast(task -> System.out.println("Hello Gradle!"));
}
}

Теперь мы можем применить его, добавив строку в наш скрипт сборки:

apply plugin: GreetingPlugin

Теперь, после вызова gradle hello, мы увидим в логах сообщение «Hello Gradle» .

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

Большинству плагинов потребуется доступ к внешней конфигурации из скрипта сборки.

Мы можем сделать это, используя объекты расширения :

public class GreetingPluginExtension {
private String greeter = "ForEach";
private String message = "Message from the plugin!"
// standard getters and setters
}

Давайте теперь добавим новый объект расширения в наш класс плагина:

@Override
public void apply(Project project) {
GreetingPluginExtension extension = project.getExtensions()
.create("greeting", GreetingPluginExtension.class);

project.task("hello")
.doLast(task -> {
System.out.println(
"Hello, " + extension.getGreeter());
System.out.println(
"I have a message for You: " + extension.getMessage());
});
}

Теперь, когда мы вызовем gradle hello, мы увидим сообщение по умолчанию, определенное в нашем GreetingPluginExtension.

Но поскольку мы создали расширение, мы можем использовать замыкание внутри скрипта сборки:

greeting {
greeter = "Stranger"
message = "Message from the build script"
}

5. Автономный проект плагина

Для создания автономных плагинов Gradle нам нужно проделать еще немного работы.

5.1. Настраивать

Во-первых, нам нужно импортировать зависимость Gradle API, что довольно просто:

dependencies {
compile gradleApi()
}

Обратите внимание, что для того же в Maven требуется зависимость gradle-tooling-api — из репозитория Gradle:

<dependencies>
<dependency>
<groupId>org.gradle</groupId>
<artifactId>gradle-tooling-api</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>org.gradle</groupId>
<artifactId>gradle-core</artifactId>
<version>3.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>repo.gradle.org</id>
<url>https://repo.gradle.org/gradle/libs-releases-local/</url>
</repository>
</repositories>

5.2. Подключение плагина

Чтобы позволить Gradle найти реализацию нашего автономного плагина, нам нужно создать файл свойств в src/main/resources/META-INF/ gradle -plugins .

Файл ресурсов должен иметь имя, соответствующее идентификатору плагина. Итак, если наш плагин имеет идентификатор org.foreach.greeting, точный путь к файлу будет META-INF/gradle-plugins/org.foreach.greeting.properties.

Далее мы можем определить класс реализации плагина:

implementation-class=org.gradle.GreetingPlugin

Класс реализации должен совпадать с полным именем пакета нашего класса плагина.

5.3. Создание идентификатора плагина

Существуют некоторые правила и соглашения, которым должен следовать идентификатор плагина в Gradle. Большинство из них похожи на правила имен пакетов в Java:

  • Они могут содержать только буквенно-цифровые символы, «.» а также "-"
  • Идентификатор должен иметь хотя бы один «.» отделение доменного имени от имени плагина
  • Пространства имен org.gradle и com.gradleware ограничены
  • Идентификатор не может начинаться или заканчиваться на «.»
  • Нет двух или более последовательных «.» символы разрешены

Наконец, существует соглашение о том, что идентификатор плагина должен быть именем в нижнем регистре, которое соответствует обратному соглашению об именах доменов.

Основное различие между именами пакетов Java и именами плагинов Gradle заключается в том, что имя пакета обычно более подробно, чем идентификатор плагина.

5.4. Плагин публикации

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

Во- первых, мы можем опубликовать JAR-файл нашего плагина во внешнем репозитории, таком как Maven или Ivy.

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

5.5. Плагин разработки Java Gradle

Когда мы пишем наши плагины на Java, мы можем извлечь выгоду из плагина разработки Java Gradle.

Это автоматически скомпилирует и добавит зависимости gradleApi() . Он также будет выполнять проверку метаданных плагина как часть задачи gradle jar .

Мы можем добавить плагин, добавив следующий блок в наш скрипт сборки:

plugins {
id 'java-gradle-plugin'
}

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

Чтобы проверить, правильно ли работает наш плагин и правильно ли он применяется к проекту, мы можем использовать org.gradle.testfixtures.projectBuilder для создания экземпляра проекта .

Затем мы можем проверить, был ли применен плагин и присутствуют ли правильные задачи в нашем экземпляре проекта . Для этого мы можем использовать стандартные тесты JUnit :

@Test
public void greetingTest(){
Project project = ProjectBuilder.builder().build();
project.getPluginManager().apply("com.foreach.greeting");

assertTrue(project.getPluginManager()
.hasPlugin("com.foreach.greeting"));

assertNotNull(project.getTasks().getByName("hello"));
}

7. Резюме

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

И, как всегда, все примеры кода можно найти на Github .