«1. Обзор

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

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

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()
    }
}

Мы можем определять задачи, которые зависят от других задач. Зависимость задачи может быть определена путем передачи аргумента dependOn: 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"
}

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

3. Управление подключаемыми модулями

В Gradle есть два типа подключаемых модулей — сценарии и двоичные файлы.

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

Разрешение означает поиск правильной версии jar-файла плагина и добавление ее в путь к классам проекта.

Применение плагинов — это выполнение 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'
}

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

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

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

Ограничения плагинов DSL:

    Он не поддерживает код Groovy внутри блока плагинов. Блок плагинов должен быть оператором верхнего уровня в скриптах сборки проекта (перед ним разрешен только блок 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, доступные для группировки наших зависимостей. Конфигурация по умолчанию расширяет «время выполнения».

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 в разных форматах.

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

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

Здесь мы добавили нотацию @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, чтобы воспринимать эти три этапа.

println 'At initialization phase.'

В settings.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.'
}

В build.gradle:

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

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

allprojects {
    repositories {
        mavenCentral() 
    }
}

subprojects {
    version = '1.0'
}

Вся общая конфигурация будет сохранена в корневом скрипте сборки:

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

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

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

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

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

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

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

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

gradle wrapper --gradle-version 4.2.1

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

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

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

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

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

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

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

Next »

Ant vs Maven vs Gradle