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

С самого появления 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:\Users\sala\projects\gradle-compose\lib1
: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 включенной сборкой.

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


  • Документация
  • Репозиторий с примерами

Комментарии (0)

© Habrahabr.ru