Каждый проект состоит из тасок Project -> [Task1, Task2]
, которые в свою очередь состоят из набора
действий Task -> [Action1, Action2]
, у которых вызвается метод execute()
на фазе Execution.
Схематично task-graph выглядит так(ацкиличный граф, который параллельно может выполнять задачи, которые не зависят от других задач):
Файлы типа .gradle можно передавать в build-файл через команду apply from: 'script.gradle'
.
Либо можно написать класс своего кастомного плагина class CustomPlugin implements Plugin
, у
которого нужно переопредилить 1 метод void apply (Project project)
. И также через
apply plugin: CustomPlugin.class
передаем наш плагин.
Плагины можно подключать через блок plugins{id 'plugin_id'}
. Кастомные плагины можно засунуть в buildSrc
и дать им id, чтобы их можно было подключать через блок, указанный выше.
gradle tasks
- посмотреть все доступные таски в нашем проекте.
compileJava
- компилирует наши Java классы.
processResources
- компилирует ресуры из директории /main/java/resources.
classes
- выполняет compileJava, processResources
.
jar
- собирает наши скомпилированные файлы в какой-то артефакт: jar, war
. Артефакт можно
найти в папке /build/libs/project_name.jar|war
assemble
- вызывает все предыдущие сверху таски.
compileTestJava
- компилирует наши тестовые Java классы.
processTestResources
- компилирует ресуры из директории /test/java/resources.
testClasses
- выполняет compileTestJava, processTestResources
.
test
- запускает наши тесты.
check
- проверяет выполняемсость наших тестов и генерирование отчетов по тестам.
build
- запускает все вышеперечисленные таски.
clean
- удаляет директорию build(чистит кэш).
buildNeeded
- билдит все проекты, от которых зависит наш текущий проект.
buildDependents
- наоборот билдит все прокты, которые зависят от нашего текущего проекта.
Указать директорые новых классов Java или файлов resources можно сделать следующим образом:
sourceSets { main { java { srcDir("$buildDir") } resources { } } test { } }
repositories {}
в ней указываются источники поиска ваших зависимостей.
maven {}
указывается для своих репозиториев на своих серверах. Сначала gradle будет искать нужные
зависимости в mavenLocal
, т.к. мы указали его раньше чем maven{...}
. И все эти зависимости
он кэширует в своей локальной папке.
implementation
- используется для подключения зависимостей в нашем исходном коде.
compileOnly
- используется только во время комплияций. Во время выполнения она(зависимость) нам не
нужна.
compileClassPath
- включает в себя compileOnly, implementation
.
annotationProcessor
- используется для обработки наших аннотаций.
runtimeOnly
- аналог compileOnly
, но она доступна только во время выполнения. Во время
компиляции она нам не нужна. Например, драйверы БД.
runtimeClasspath extends runtimeOnly, implementation
- включает в себя runtimeOnly,
implementation
.
testImplementation extends implementation
- используется для подключения зависимостей в нашем исходном
коде, которые лежат в папке test.
testCompileOnly
- используется только во время комплияций тестов. Во время выполнения она(зависимость)
нам не нужна.
testCompileClassPath extends testCompileOnly, testImplementation
- включает в себя
testCompileOnly, testImplementation
.
testRuntimeOnly extends runtimeOnly
- аналог testCompileOnly
, но она доступна только во
время выполнения. Во время компиляции она нам не нужна.
testRuntimeClasspath extends testRuntimeOnly, testImplementation
- включает в себя
testRuntimeOnly, testImplementation
.
С помощью блока configurations{...}
можно создавать свои конфигурации.
Транзитивные зависимости - зависимости, которые были подключены неявно. Например, при подключении spring-webmvc подключается spring-core и т.п.
Для исключения транзитивных зависимостей у implementation
можно вызвать exclude{}
и
перечислить там зависимости для удаления. Либо можно указать transitive = false
.
platform()
резолвит конфликты зависимостей. По факту BOM - это просто xml-файл со всеми зависимостями и
версиями, которые совместимы друг с другом.
Для того, чтобы запустить jar-файл со всеми зависимости, есть вариант получить все зависимости и разархивировать их.
jar { manifest { attributes 'Main-Class': 'ru.atom.gradle.HelloWorld' } duplicatesStrategy(DuplicatesStrategy.EXCLUDE) from(configurations.runtimeClasspath.files.collect { zipTree(it) }) }
Пишем таску, которая копирует все зависимости в папку lib. Затем делаем таску jar, зависимой от нашей таски копирования зависимостей, и добавляем аттрибут Class-Path.
task copyAllDependencies(type: Copy) { from(configurations.runtimeClasspath.files) into("$buildDir/libs/lib") }jar { dependsOn(copyAllDependencies) def jars = configurations.runtimeClasspath.files.collect{"lib/$it.name"} manifest {
attributes 'Main-Class': 'ru.atom.gradle.HelloWorld', 'Class-Path': jars.join(' ') } }
Применяя plugin {'java-library'}
и указывая в dependencies {api project (project_name)}
,
проекты, которые включают в себя эту библиотеку, будут и включать эту зависимость.
Пример.
С помощью директивы allprojects{}
можно настроть общую конфигурацию для всех проектов. А с помощью
subprojects{}
для подпроектов.
Jacoco наподобие sonarqube анализирует покрытие кода тестами. Также можно устанавливать quality gates на покрытие тестами, исключать какие-то классы из анализа и т.п.
Тесты можно выполнять параллельно. Достаточно указать maxParallelForks = n
.
Каждая таска на вход принимает входные данные inputs
и отдает выходные данные outputs
. На
это и строится cache.
- Gradle in action by Benjamin Muscho