С самого появления 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 включенной сборкой.
