Статьи

Gradle Custom Plugin

В этом руководстве описан способ создания отдельного пользовательского плагина Gradle. Он охватывает следующие темы

  • Создание задачи и использование ее в пользовательском плагине
  • Автономный плагин
  • Короткий идентификатор плагина
  • Настройте параметры Gradle с помощью settings.gradle

Информация о проекте:

Версия Gradle: 1.1
Платформа ОС: Ubuntu 12.10
Необходимое условие: базовое понимание сценария Gradle.

Создание автономного пользовательского плагина

  1. создать структуру каталогов
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    |-custom-plugin
    |  |-plugin
    |    |-src
    |      |-main
    |      |  |-groovy
    |      |  | |-com
    |      |  |   |-code4reference
    |      |  |     |-gradle
    |      |  |-resources  
    |      |  | |-META-INF
    |      |  |   |-gradle-plugins
    |      |-test
    |      |  |-groovy
    |      |  | |-com
    |      |  |   |-code4reference
    |      |  |     |-gradle
    |-user

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

    1
    2
    3
    $ mkdir -p custom-plugin/plugin/src/main/groovy/com/code4reference/gradle
    $ mkdir -p custom-plugin/plugin/src/main/resources/META-INF/gradle-plugins
    $ mkdir -p custom-plugin/user
  2. Пользовательский исходный код плагина

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

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    package com.code4reference.gradle;
     
    import org.gradle.api.*;
     
    class Code4ReferencePlugin implements Plugin {
        def void apply(Project project) {
            //c4rTask task has been defined below.
            project.task('c4rTask') << {
                println 'Hi from Code4Reference plugin!'
            }
        }
    }

    Поместите этот файл в каталог custom-plugin / plugin / src / main / groovy / com / code4reference / gradle . Здесь была определена задача c4rTask для печати простой строки.

  3. Короткий идентификатор плагина

    Чтобы применить плагин, мы обычно используем короткий идентификатор, например, применить плагин: ‘java’. Здесь «java» — это короткий идентификатор плагина для класса org.gradle.api.plugins.JavaPlugin . Короткий идентификатор плагина может быть определен в простых шагах. Для этого нам нужно создать файл свойств и поместить его в каталог META-INF / gradle-plugins, который находится в пути к классам. Имя файла будет нашим коротким идентификатором. Этот файл свойств должен содержать строку, показанную ниже, и он должен указывать на класс реализации плагина. Давайте создадим файл свойств как code4reference.properties и укажем его на класс Code4ReferencePlugin.

    1
    implementation-class=com.code4reference.gradle.Code4ReferencePlugin
  4. Gradle скрипт для генерации плагина

    Для компиляции и сборки этого плагина мы напишем скрипт gradle. Создайте файл с именем build.gradle в каталоге плагинов и скопируйте в него содержимое ниже.

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    apply plugin: 'groovy'
    apply plugin: 'maven'
    dependencies {
        compile gradleApi()
        groovy localGroovy()
    }
    repositories {
        mavenCentral()
    }
     
    group='com.code4reference'   //Group name makes easier to manager the packages.
    version='1.1-SNAPSHOT'
     
    uploadArchives {
        repositories {
            mavenDeployer {
                repository(url: uri('../repo'))
            }
        }
    }

    В этом скрипте gradle мы используем плагин groovy для компиляции исходного кода groovy и объявляем gradleAPI как зависимости времени компиляции. Возможно, вы заметили, что мы используем плагин Maven . Он в основном создает файл jar плагина и сохраняет его в репозитории maven. Здесь мы создаем репозиторий maven с именем repo в родительском каталоге и сохраняем в нем файл jar.

  5. Сборка плагина и размещение в репозитории
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    $ gradle uploadArchives   #This will put the plugin-version.jar in maven repository.
     
    :compileJava UP-TO-DATE
    :compileGroovy UP-TO-DATE
    :processResources UP-TO-DATE
    :classes UP-TO-DATE
    :jar
    :uploadArchives
    Uploading: com/code4reference/plugin/1.1-SNAPSHOT/plugin-1.1-20120816.163101-1.jar to repository remote at file:/home/rakesh/programming/mygitrepo/Code4Reference/GradleExample/custom-plugin-1/repo/
    Transferring 5K from remote
    Uploaded 5K
     
    BUILD SUCCESSFUL
     
    Total time: 34.892 secs
  6. Настройки объекта с помощью settings.gradle

    Когда вышеуказанная команда будет выполнена, gradle утомится, чтобы получить имя проекта из settings.gradle. Если файл settings.gradle отсутствует в текущем каталоге, он получает имя текущего каталога и принимает его в качестве имени проекта. Затем он формирует путь для сохранения файла JAR. Соглашение о пути к файлу выглядит следующим образом /group/name/projectName/version/projectname-version-timestamp.jar . В приведенном выше выводе вы можете заметить, что имя пути JAR и имя файла JAR имеют слово плагина, потому что текущим именем каталога является плагин, а Gradle принимает его как имя проекта. Если мы хотим переопределить это свойство и указать в качестве имени проекта code4ReferencePlugin , нам нужно создать файл settings.gradle в каталоге плагинов и поместить следующую строку.

    1
    rootProject.name = 'code4ReferencePlugin'

    Теперь снова выполните команду для создания файла jar плагина.

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    $gradle uploadArchives
    compileJava UP-TO-DATE
    :compileGroovy UP-TO-DATE
    :processResources UP-TO-DATE
    :classes UP-TO-DATE
    :jar UP-TO-DATE
    :uploadArchives
    Uploading: com/code4reference/code4ReferencePlugin/1.1-SNAPSHOT/code4ReferencePlugin-1.1-20120816.164441-5.jar to repository remote at file:/home/rakesh/programming/mygitrepo/Code4Reference/GradleExample/custom-plugin-1/repo/
    Transferring 5K from remote
    Uploaded 5K
     
    BUILD SUCCESSFUL
     
    Total time: 8.61 secs

    Теперь проблема решена. Jar генерируется с именем code4ReferencePlugin- [version] -timestamp.jar. Если вы хотите узнать больше о свойствах gradle и system, найдите их здесь .

Используя пользовательский плагин

Это действительно простой шаг. Хотя мы используем другой плагин, пользовательский плагин также может использоваться аналогичным образом. Теперь создайте еще один файл build.gradle в каталоге пользователя и скопируйте приведенный ниже код.

01
02
03
04
05
06
07
08
09
10
11
12
13
buildscript {
    repositories {
        maven {
            url uri('../repo')
        }
    }
    dependencies {
        classpath group: 'com.code4reference',
                  name: 'code4ReferencePlugin',
                  version: '1.1-SNAPSHOT'
    }
}
apply plugin: 'code4reference'

Сценарий build.gradle обращается к репозиторию maven, который находится в родительском каталоге. Мы также определили зависимость, которая в основном обращается к конкретной версии файла JAR из Maven. И последнее, но не менее важное: мы применяем короткий идентификатор плагина «code4reference». Чтобы запустить этот скрипт gradle, выполните команду ниже на терминале в пользовательском каталоге.

1
2
3
4
5
6
7
8
$ gradle c4rTask   #Remember we have created c4rTask in Code4ReferencePlugin class.
                   #You will get the following output.
:c4rTask
Hi from Code4Reference plugin!
 
BUILD SUCCESSFUL
 
Total time: 3.908 secs

Вуаля !! Вы только что создали собственный плагин и использовали его в другом скрипте проекта. Вы можете найти исходный код этого руководства здесь . Code4Reference

Теперь рассмотрим следующие темы.

  • Определить пользовательский класс задач
  • Передача аргументов в пользовательскую задачу плагина
  • Вложенные аргументы
  • Тестирование пользовательского плагина

Информация о проекте:
Название проекта: пользовательский плагин Gradle
Версия Gradle: 1.1
Платформа ОС: Ubuntu 12.10
Необходимое условие: базовое понимание сценария Gradle.

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

  1. Определить пользовательскую задачу

    Давайте определим пользовательский класс с именем Code4ReferenceTask, который расширяет класс DefaultTask, и поместим этот файл в ту же папку, где хранится Code4ReferencePlugin.groovy. Этот класс содержит метод с именем showMessage (), который аннотируется @TaskAction . Gradle вызывает этот метод при выполнении задачи.

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    package com.code4reference.gradle;
     
    import org.gradle.api.DefaultTask
    import org.gradle.api.tasks.TaskAction
     
    class Code4ReferenceTask extends DefaultTask {
     
        @TaskAction
        def showMessage() {
            println '----------showMessage-------------'
        }
    }

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

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    package com.code4reference.gradle;
     
    import org.gradle.api.*;
     
    class Code4ReferencePlugin implements Plugin {
        def void apply(Project project) {
               //Define the task named c4rTask of type Code4ReferenceTask
               project.task('c4rTask', type: Code4ReferenceTask)
        }
    }

    Вы можете заметить, что только выделенная строка была изменена из прошлой реализации. Теперь «c4rTask» имеет тип Code4ReferenceTask. Выполните команду gradle uploadArchives в каталоге плагинов . Это обновит файл jar в репозитории Maven. Теперь выполните команду ниже в пользовательском каталоге с тем же старым build.gradle. Мы получим следующий вывод.

    1
    2
    3
    4
    5
    6
    $gradle c4rTask
    :c4rTask
    ----------showMessage-------------
    BUILD SUCCESSFUL
     
    Total time: 14.057 secs
  2. Передача аргументов в пользовательскую задачу плагина

    Вышеуказанная реализация является самой простой и не делает много. Что если мы хотим передать аргументы из скрипта Gradle этой задаче? Мы можем достичь этого путем доступа к объекту расширения . Gradle Project имеет связанный объект ExtensionContainer, который помогает отслеживать все параметры и свойства, передаваемые в класс плагинов. Давайте определим класс расширения, который может содержать аргументы и передавать их в класс Task. Выделенные строки в классе Code4ReferencePlugin помогают передавать аргументы в класс Task.

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    package com.code4reference.gradle;
     
    import org.gradle.api.*;
     
    //For passing arguments from gradle script.
    class Code4ReferencePluginExtension {
        String message = 'Hello from Code4Reference'
        String sender = 'Code4Reference'
    }
    class Code4ReferencePlugin implements Plugin {
        def void apply(Project project) {
               project.extensions.create('c4rArgs', Code4ReferencePluginExtension)
               project.task('c4rTask', type: Code4ReferenceTask)
        }
    }

    Мы определили Code4ReferencePluginExtension как класс Extension, который содержит две переменные message и sender. Они служат аргументами для пользовательской задачи. Нам нужно изменить класс Code4RefernceTask для доступа к аргументам. Выделенные строки были добавлены в предыдущую реализацию класса Code4ReferenceTask.

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    package com.code4reference.gradle;
     
    import org.gradle.api.DefaultTask
    import org.gradle.api.tasks.TaskAction
     
    class Code4ReferenceTask extends DefaultTask {
     
        @TaskAction
        def showMessage() {
            println '------------showMessage-------------------'
            println 'From : ${project.c4rArgs.sender},\
                      message : ${project.c4rArgs.message}'
        }
    }

    Выполните команду gradle uploadArchives в каталоге плагинов. Это обновит файл jar в репозитории Maven. Также нам нужно обновить build.gradle в пользовательском каталоге.

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    //custom-plugin-2/user
    buildscript {
        repositories {
            maven {
                url uri('../repo')
            }
        }
        dependencies {
            classpath group: 'com.code4reference',
                      name: 'code4ReferencePlugin',
                      version: '1.2-SNAPSHOT'
        }
    }
     
    apply plugin: 'code4reference'
     
    c4rArgs {
        sender = 'Rakesh'
        message = 'Hello there !!!!'
    }

    Возможно, вы заметили, что закрытие c4rArgs было добавлено и переменные отправителя и сообщения установлены в закрытии. Эти две переменные доступны в методе showMessage (). Теперь запустите build.gradle, присутствующий в пользовательском каталоге. мы получаем следующий вывод.

    1
    2
    3
    4
    5
    6
    7
    8
    $gradle c4rTask
    :c4rTask
    -------------------------showMessage-----------------------------
    From : Rakesh, message : Hello there !!!!
     
    BUILD SUCCESSFUL
     
    Total time: 15.817 secs
  3. Вложенные аргументы

    Что если мы хотим передать вложенные аргументы? Мы можем достичь этого, вложив объекты Extension. Вот код для класса Code4ReferencePlugin. В этом классе были добавлены только выделенные строки.

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    package com.code4reference.gradle;
     
    import org.gradle.api.*;
     
    //Extension class for nested argumetns
    class C4RNestedPluginExtention {
         String receiver = 'Admin'
         String email = '[email protected]'
     
     }
    //For keeping passing arguments from gradle script.
    class Code4ReferencePluginExtension {
        String message = 'Hello from Code4Reference'
        String sender = 'Code4Reference'
        C4RNestedPluginExtention nested = new C4RNestedPluginExtention()
    }
    class Code4ReferencePlugin implements Plugin {
        def void apply(Project project) {
               project.extensions.create('c4rArgs', Code4ReferencePluginExtension)
               project.c4rArgs.extensions.create('nestedArgs',C4RNestedPluginExtention)
               project.task('c4rTask', type: Code4ReferenceTask)
        }
    }

    Пришло время изменить класс Code4ReferenceTask. Выделенные строки были добавлены в этот класс для доступа к вложенным аргументам.

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    package com.code4reference.gradle;
     
    import org.gradle.api.DefaultTask
    import org.gradle.api.tasks.TaskAction
     
    class Code4ReferenceTask extends DefaultTask {
     
        @TaskAction
        def showMessage() {
            println '------------showMessage-------------------'
            println 'From : ${project.c4rArgs.sender},\
                     message : ${project.c4rArgs.message}'
            println 'To : ${project.c4rArgs.nestedArgs.receiver},\
                     email : ${project.c4rArgs.nestedArgs.email}'
        }
    }

    Снова выполните команду gradle uploadArchives в каталоге плагинов, чтобы обновить файл jar в репозитории Maven. Теперь измените файл build.gradle, присутствующий в пользовательском каталоге, чтобы передать вложенные аргументы.

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    buildscript {
        repositories {
            maven {
                url uri('../repo')
            }
        }
        dependencies {
            classpath group: 'com.code4reference',
                      name: 'code4ReferencePlugin',
                      version: '1.2-SNAPSHOT'
        }
    }
     
    apply plugin: 'code4reference'
     
    c4rArgs {
        sender = 'Rakesh'
        message = 'Hello there !!!!'
     
        nestedArgs{
           receiver = 'gradleAdmin'
           email = '[email protected]'
        }
    }

    Мы добавили выделенную строку в файл build.gradle.

  4. Плагин тестирования и задача

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

    1
    $mkdir -p src/test/groovy/com/code4reference/gradle/

    Тестовая структура каталогов следует той же структуре каталогов пакетов, которая использовалась для каталогов пакетов исходного кода. В этом каталоге поместите тестовые классы для Code4ReferencePlugin и Code4ReferenceTask. В тестовом классе ProjectBuilder используется для доступа к объекту проекта. Эти тестовые сценарии легко написать, как и тестовые примеры Junit. Код тестовых классов выглядит следующим образом:

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    package com.code4reference.gradle;
     
    import org.junit.Test
    import org.gradle.testfixtures.ProjectBuilder
    import org.gradle.api.Project
    import static org.junit.Assert.*
     
    class Code4ReferenceTaskTest {
        @Test
        public void canAddTaskToProject() {
            Project project = ProjectBuilder.builder().build()
            def task = project.task('c4rtakstest', type: Code4ReferenceTask)
            assertTrue(task instanceof Code4ReferenceTask)
        }
    }
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    package com.code4reference.gradle;
     
    import org.junit.Test
    import org.gradle.testfixtures.ProjectBuilder
    import org.gradle.api.Project
    import static org.junit.Assert.*
     
    class Code4ReferencePluginTest {
        @Test
        public void code4referencePluginAddsCode4ReferenceTaskToProject() {
            Project project = ProjectBuilder.builder().build()
            project.apply plugin: 'code4reference'
            println 'code4referencePluginAddsCode4ReferenceTaskToProject'
            assertTrue(project.tasks.c4rTask instanceof Code4ReferenceTask)
        }
    }

    Чтобы запустить тест, выполните следующую команду в папке плагина.

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    $gradle test                #For success test cases.
    :compileJava UP-TO-DATE
    :compileGroovy UP-TO-DATE
    :processResources UP-TO-DATE
    :classes UP-TO-DATE
    :compileTestJava UP-TO-DATE
    :compileTestGroovy
    :processTestResources UP-TO-DATE
    :testClasses
    :test
     
    BUILD SUCCESSFUL
     
    Total time: 42.799 secs
     
    $gradle test    #In case of test case failure,
                    #you can expect output similar to given below.
    :compileJava UP-TO-DATE
    :compileGroovy UP-TO-DATE
    :processResources UP-TO-DATE
    :classes UP-TO-DATE
    :compileTestJava UP-TO-DATE
    :compileTestGroovy
    :processTestResources UP-TO-DATE
    :testClasses
    :test
     
    com.code4reference.gradle.Code4ReferencePluginTest > code4referencePluginAddsCode4ReferenceTaskToProject FAILED
        java.lang.AssertionError at Code4ReferencePluginTest.groovy:14
     
    2 tests completed, 1 failed
     
    FAILURE: Build failed with an exception.
     
    * What went wrong:
    Execution failed for task ':test'.
    > There were failing tests. See the report at: file:///home/rakesh/programming/mygitrepo/Code4Reference/GradleExample/custom-plugin-2/plugin/build/reports/tests/index.html
     
    * Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
     
    BUILD FAILED

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

Вы можете найти исходный код здесь .

Справка: пользовательский плагин Gradle (часть-1) ,   Пользовательский плагин Gradle (часть 2) от нашего партнера по JCG Ракеша Кусата в блоге Code4Reference .