«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 и увидели, что он обладает большей гибкостью по сравнению с другими существующими инструментами сборки с точки зрения разрешения конфликтов версий и управления транзитивными зависимостями.