Введение в Gradle

1. Обзор

Gradle - основанная на Groovy система управления сборкой, разработанная специально для создания проектов на основе Java.

Инструкции по установке можно найти here .

2. Строительные блоки - проекты и задачи

  • В Gradle сборки состоят из одного или нескольких проектов, а каждый проект состоит из одной или нескольких задач. **

Проект в Gradle может собирать jar , war или даже zip файл.

  • Задача - это отдельная работа. ** Это может включать компиляцию классов или создание и публикацию Java/веб-архивов.

Простая задача может быть определена как:

task hello {
    doLast {
        println 'Baeldung'
    }
}

Если мы выполним вышеуказанную задачу, используя команду gradle -q hello из того же места, где находится build.gradle , мы должны увидеть вывод в консоли.

2.1. Задачи

Сценарии сборки Gradle - это не что иное, как Groovy:

task toLower {
    doLast {
        String someString = 'HELLO FROM BAELDUNG'
        println "Original: "+ someString
        println "Lower case: " + someString.toLowerCase()
    }
}

Мы можем определить задачи, которые зависят от других задач. Зависимость задачи можно определить, передав аргумент dependsOn: taskName в определении задачи:

task helloGradle {
    doLast {
        println 'Hello Gradle!'
    }
}

task fromBaeldung(dependsOn: helloGradle) {
    doLast {
        println "I'm from Baeldung"
    }
}

2.2. Добавление поведения к задаче

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

task helloBaeldung {
    doLast {
        println 'I will be executed second'
    }
}

helloBaeldung.doFirst {
    println 'I will be executed first'
}

helloBaeldung.doLast {
    println 'I will be executed third'
}

helloBaeldung {
    doLast {
        println 'I will be executed fourth'
    }
}

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

2.3. Добавление свойств задачи

Мы также можем определить свойства:

task ourTask {
    ext.theProperty = "theValue"
}

Здесь мы устанавливаем «theValue» как theProperty задачи ourTask .

3. Управление плагинами

В Gradle есть два типа плагинов - script, и binary.

Чтобы воспользоваться дополнительными функциями, каждый плагин должен пройти две фазы: resolving и applying.

  • Resolving означает найти правильную версию jar плагина и добавить ее в classpath проекта.

  • Applying plugins выполняет Plugin.apply (T) для проекта ** .

3.1. Применение скриптовых плагинов

В aplugin.gradle, мы можем определить задачу:

task fromPlugin {
    doLast {
        println "I'm from plugin"
    }
}

Если мы хотим применить этот плагин к нашему файлу build.gradle проекта, все, что нам нужно сделать, это добавить эту строку в наш build.gradle :

apply from: 'aplugin.gradle'

Теперь выполнение команды gradle tasks должно отобразить задачу fromPlugin в списке задач.

3.2. Применение бинарных плагинов с помощью плагинов DSL

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

plugins {
    id 'application'
}

Теперь задача run из плагина application должна быть доступна в проекте для выполнения любого runnable jar. Чтобы применить плагин сообщества, мы должны упомянуть полный идентификатор плагина:

plugins {
    id "org.shipkit.bintray" version "0.9.116"
}

Теперь задачи Shipkit должны быть доступны в списке gradle tasks .

Ограничениями плагинов DSL являются:

  • Он не поддерживает Groovy-код внутри блока plugins

Блок plugins должен быть оператором верхнего уровня в сборке проекта

скрипты (перед ним разрешен только блок buildscripts \ {} ) ** Плагины DSL не могут быть написаны в плагине сценариев, settings.gradle

файл или в скриптах инициализации

Плагины DSL все еще инкубируют. DSL и другая конфигурация могут измениться в более поздних версиях Gradle.

3.3. Устаревшая процедура применения плагинов

Мы также можем применять плагины, используя «apply plugin» :

apply plugin: 'war'

Если нам нужно добавить плагин сообщества, мы должны добавить внешний jar-файл в путь к классу сборки, используя блок buildscript \ {} .

Затем мы можем применить плагин в скриптах сборки, но только после любого существующего plugins \ {} блока :

buildscript {
    repositories {
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }
    dependencies {
        classpath "org.shipkit:shipkit:0.9.117"
    }
}
apply plugin: "org.shipkit.bintray-release"

4. Управление зависимостями

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

Лучшие практики для управления зависимостями в Gradle - управление версиями, динамическое управление версиями, разрешение конфликтов версий и управление переходными зависимостями. **

4.1. Конфигурация зависимостей

Зависимости сгруппированы в разные конфигурации. Конфигурация имеет имя, и они могут расширять друг друга .

Если мы применим плагин Java, у нас будут доступны конфигурации compile, testCompile, runtime для группировки наших зависимостей. _Default c onfiguration расширяет « runtime» ._

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

Давайте рассмотрим пример добавления некоторых зависимостей (Spring и Hibernate) несколькими различными способами:

dependencies {
    compile group:
      'org.springframework', name: 'spring-core', version: '4.3.5.RELEASE'
    compile 'org.springframework:spring-core:4.3.5.RELEASE',
            'org.springframework:spring-aop:4.3.5.RELEASE'
    compile(
       [group: 'org.springframework', name: 'spring-core', version: '4.3.5.RELEASE'],
       [group: 'org.springframework', name: 'spring-aop', version: '4.3.5.RELEASE']    )
    testCompile('org.hibernate:hibernate-core:5.2.12.Final') {
        transitive = true
    }
    runtime(group: 'org.hibernate', name: 'hibernate-core', version: '5.2.12.Final') {
        transitive = false
    }
}

Мы объявляем зависимости в различных конфигурациях: compile , testCompile и runtime в различных форматах.

Иногда нам нужны зависимости, которые имеют несколько артефактов. В таких случаях мы можем добавить обозначения только для артефактов @ extensionName (или ext в расширенной форме), чтобы загрузить нужный артефакт:

runtime "org.codehaus.groovy:groovy-all:[email protected]"
runtime group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.4.11', ext: 'jar'

Здесь мы добавили нотацию @ jar для загрузки только артефакта jar без зависимостей.

Чтобы добавить зависимости в любые локальные файлы, мы можем использовать что-то вроде этого:

compile files('libs/joda-time-2.2.jar', 'libs/junit-4.12.jar')
compile fileTree(dir: 'libs', include: '** .jar')
  • Когда мы хотим избежать транзитивных зависимостей, мы можем сделать это на уровне конфигурации или на уровне зависимости ** :

configurations {
    testCompile.exclude module: 'junit'
}

testCompile("org.springframework.batch:spring-batch-test:3.0.7.RELEASE"){
    exclude module: 'junit'
}

5. Мультипроектные сборки

5.1. Жизненный цикл сборки

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

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

  • На этапе настройки все созданные экземпляры проектов настраиваются на основе конфигурации функций Gradle по требованию. **

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

Наконец, на этапе выполнения выполняется подмножество задач, созданных и настроенных. Мы можем включить код в файлы settings.gradle и build.gradle для восприятия этих трех этапов.

В settings.gradle :

println 'At initialization phase.'

В build.gradle :

println 'At configuration phase.'

task configured { println 'Also at the configuration phase.' }

task execFirstTest { doLast { println 'During the execution phase.' } }

task execSecondTest {
    doFirst { println 'At first during the execution phase.' }
    doLast { println 'At last during the execution phase.' }
    println 'At configuration phase.'
}

5.2. Создание мультипроектной сборки

Мы можем выполнить команду gradle init в корневой папке, чтобы создать каркас для файла settings.gradle и build.gradle .

Все общие настройки будут сохранены в корневом скрипте сборки:

allprojects {
    repositories {
        mavenCentral()
    }
}

subprojects {
    version = '1.0'
}

Файл настроек должен включать имя корневого проекта и имя подпроекта:

rootProject.name = 'multi-project-builds'
include 'greeting-library','greeter'

Теперь нам нужно иметь пару папок подпроектов с именами greeting-library и greeter для демонстрации многопроектной сборки. Каждый подпроект должен иметь отдельный сценарий сборки, чтобы настроить свои индивидуальные зависимости и другие необходимые конфигурации.

Если мы хотим, чтобы наш проект greeter зависел от greeting-library , нам нужно включить зависимость в сценарий сборки greeter :

dependencies {
    compile project(':greeting-library')
}

6. Использование Gradle Wrapper

Если у проекта Gradle есть файл gradlew для Linux и файл gradlew.bat для Windows, нам не нужно устанавливать Gradle для сборки проекта.

Если мы выполним gradlew build в Windows и ./gradlew build в Linux, дистрибутив Gradle, указанный в файле gradlew , будет загружен автоматически.

Если мы хотим добавить оболочку Gradle в наш проект:

gradle wrapper --gradle-version 4.2.1

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

task wrapper(type: Wrapper) {
    gradleVersion = '4.2.1'
}

Теперь нам нужно выполнить задачу wrapper , и задача свяжет наш проект с оберткой. Помимо файлов gradlew , внутри папки gradle создается папка wrapper , содержащая jar и файл свойств.

Если мы хотим перейти на новую версию Gradle, нам нужно только изменить запись в gradle-wrapper.properties .

7. Заключение

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

Исходный код этой статьи доступен на over на GitHub .

Следующий "