Избавляемся от бинарных зависимостей с композитной сборкой в Gradle 3.1

в 20:24, , рубрики: gradle, java

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

Композитные сборки

В готовящейся к релизу версии 3.1 в Gradle появляется новый поход к организации сборок, состоящих из нескольких компонентов: композитные сборки (ориг. Composite Builds).

Композитные сборки позволяют:

  • Быстро подложить исправленную версию исходников библиотеки в другой проект без необходимости собирать её, опубликовывать и править сборку.
  • Делить большие проекты на несколько небольших, изолированных сборок, над каждой из которых можно работать как по отдельности, так и одновременно.
  • Отделить разработку плагина для системы сборки от проекта, его использующего (аналог buildSrc)

Разберем простой пример использования новой возможности.

Для этого создадим простенький проектик:

--app/
|-src/main/java/Main.java
|-build.gradle
- lib/
|-src/main/java/A.java
|-build.gradle
|-settings.gradle

lib/build.gradle:

apply plugin: 'java'

group "ru.shadam"
version "1.0"

task wrapper(type: Wrapper) {
    gradleVersion = '3.1-rc-1'
}

app/build.gradle

apply plugin: 'java'
apply plugin: 'application'

mainClassName='Main'

dependencies {
    compile 'ru.shadam:lib1:1.0'
}

task wrapper(type: Wrapper) {
    gradleVersion = '3.1-rc-1'
}

Теперь, если мы попробуем запустить app с помощью команды ./gradlew run Gradle будет ругаться на неразрешенную зависимость:

$ ./gradlew run
:compileJava
FAILURE: Build failed with an exception.

* What went wrong:
Could not resolve all dependencies for configuration ':compileClasspath'.
> Cannot resolve external dependency ru.shadam:lib1:1.0 because no repositories are defined.
  Required by:
      project :

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 1.027 secs

Но, если мы добавим новый флаг --include-build, то Gradle разрешит зависимости автоматически:

$ ./gradlew run --include-build ../lib1
[composite-build] Configuring build: C:Userssalaprojectsgradle-composelib1
:compileJava
:lib1:compileJava UP-TO-DATE
:lib1:processResources UP-TO-DATE
:lib1:classes UP-TO-DATE
:lib1:jar UP-TO-DATE
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:run
Hello

BUILD SUCCESSFUL

Total time: 1.092 secs

Продвинутые варианты использования.

Встраиваем --include-build в скрипт

Представленный выше вариант больше подходит для одноразового использования — здесь и сейчас. Каждый раз указывать флаги не хочется — даже если зашить их во wrapper.

Для этого gradle предлагает использовать конфигурацию с использованием settings.gradle. Так, указанный выше флаг можно заменить с помощью следующего settings.gradle:

includeBuild('../lib1')

Подстановки

Что если в проекте, который вы хотите включить не указаны координаты артефакта? (группа, версия)

На помощь приходят подстановки:

includeBuild('../lib1') {
    dependencySubstitution {
        substitute('ru.shadam:lib1') with project(':')
    }
}

Эта возможность позволяет подставить любую зависимость на ru.shadam:lib1 зависимостью на проект lib1.

Зависимости между задачами

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

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

 task run {
    dependsOn gradle.includedBuild('lib1').task(':jar')
}

Что пока не работает?

  • Не поддерживаются в качестве включаемых проекты, у которых есть публикуемые артифакты, которые не соответствуют конфигурации по умолчанию. ссылка
  • Пока нет поддержки в IDE (но поддерживается генерация проекта с помощью команды ./gradlew idea)
  • Не поддерживаются native builds.

Планы команды

  • Добавить возможность вызывать задачи напрямую из включенных сборок.
  • Добавить возможность параллельно исполнять включенные сборки
  • Добавить обнаружение изменений во включенных сборках, когда используется флаг -t.
  • Сделать неявный проект buildSrc включенной сборкой.

Использованные материалы

Автор: saladinkzn

Источник

Поделиться новостью

* - обязательные к заполнению поля