Глава 8. Введение в многопроектные сборки.

Только крошечные проекты имеют один-единственный сборочный файл и дерево исходных кодов, иначе они будут массивными, монолитными приложениями. Часто, гораздо проще классифицировать и понять проект, который разделен на небольшие, взаимозависимые модули. Слово "взаимозависимые" важно и обычно является причиной, по которой вы хотели бы связать модули вместе в одной сборке.

Gradle поддерживает такой сценарий через многопроектные сборки.

8.1. Структура многопроектной сборки.

Такие виды сборок могут быть самых разных размеров и очертаний, но все они имеют общие характеристики:

  • Файл settings.gradle в корневой или master папке проекта.
  • Файл build.gradle в корневой или master папке.
  • Дочерние папки, которые содержать свои собственные файлы сборок *.gradle (в некоторых многопроектных сборках могут отсутствовать сборочные скрипты дочерних проектов).

Файл settings.gradle говорит Gradle как проект и подпроекты структурированы. К счатью, вам нет необходимости читать этот файл только для того, чтобы изучить структуру проекта, ведь для этого можно выполнить команду gradle projects. Ниже приведет вывод этой команды в на многопроектной Java сборке в примерах Gradle:

Пример 8.1. Вывод списка проектов в сборке

Вывод команды gradle -q projects

> gradle -q projects

------------------------------------------------------------
Root project
------------------------------------------------------------

Root project 'multiproject'
+--- Project ':api'
+--- Project ':services'
|    +--- Project ':services:shared'
|    \--- Project ':services:webservice'
\--- Project ':shared'

To see a list of the tasks of a project, run gradle :tasks
For example, try running gradle :api:tasks
	  

Из этого вывода можно понять, что в общем проекте есть три непосредственных дочерних проекта: api, service и shared. У проекта service есть свои собственные "дети", share и webservice. Все это ложиться на папочную структуру, так что найти эти проекты не составит труда. Например, вы можете найти проект webservice в /services/webservice.

По умолчанию, Gradle использует имя папки, в которой найден файл settings.gradle, в качестве имени корневого проекта. В большинстве случаев, это не проблема, так как все разработчики получают одинаковое имя папки из системы контроля версий при работа над проектом. В серверах Непрерывной Интеграции, таких как Jenkins, имя папки может быть создано автоматически и не совпадать с именем в системе контроля версий. По этой причине, рекомендуется, чтобы вы всегда устанавливали имя корневого проекта во что-то предсказуемое, даже в сборках одиночных проектов. Вы можете настроить имя корневого проекта, установив rootProject.name.

Каждый проект обычно будет иметь свой собственный сборочный файл, но это не всегда будет так. В примере выше, проект service всего навсего контейнер или группировка других подпроектов. В соответствующей папке нет сборочного файла. Однако, мультипроект должен содержать сборочный файл для корневого проекта.

Корневой build.gradle часто используется для хранения общей конфигурации дочерних проектов, например, применяя одинаковый набор плагинов ко всем дочерним проектам. Также его можно использовать для настройки индивидуальных подпроектов, в том случае, когда предпочтительнее иметь все настройки в одном месте. Это значит, что вы всегда должны проверять корневой сборочный файл, когда исследуете как сконфигурирован определенный подпроект.

Еще одну вещь всегда надо помнить, сборочные файлы не обязательно называются build.gradle. Многие проекты называют сборочные файлы в соответствии со именем подпроекта, например, api.gradle и services.gradle из примера выше. Такой подход очень сильно помогает при работе в IDE, потому что тяжело понять какой файл build.gradle из двадцати возможных вы хотели бы открыть. Эта маленькая часть магии обрабатывается файлом settings.gradle, но вы, как пользователь сборки, не должны понимать все детали того, как это работает. Просто пробегитесь по всем папкам дочерних проектов, чтобы найти все файлы с суфиксом .gradle.

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

8.2. Выполнение многопроектной сборки.

С точки зрения пользователя, многопроектные сборки всего лишь коллекции задач, которые вы можете выполнить. Разница в том, что вы можете захотеть контролировать, задачи какого проекта будут выполнены. У вас есть две возможности:

  • Перейдите в папку проекты, который вас интересует и просто выполните gradle <задача> как вы обычно делаете.
  • Используйте уточненное имя задачи из любой папки, хотя в большинстве случаев используется корневая. Например, gradle :services:webservice:build соберет подпроект webservice и все проекты, от которых он зависит.

Первый подход очень похож однопроектный случай, но Gradle действует немного по-другому в случае многопроектной сборки. Команда gradle test выполнит все задачи test во всех подпроектах, относительно рабочей папки, в которой есть эта задача. Таким образом, если вы запустите команду из корневой папки проекта, вы запустите test в проектах api, share, services:shared и services:webservice. Если вы запустите проект из папки проекта services, то выполните задачу только в services:shared и services:webservice.

Для большего контроля того, чтобы должно выполниться, используйте уточненные имена (второй упомянутый подход). Это пути, похожие на пути к папкам, но вместо испольования '/' или '\' используется ':'. Если путь начинается с ':', то путь разрешается относительно корневой папки проекта. Другими словами, ведущее ':' представляет собой корневой проект. Все остальные двоеточий разделители пути.

Это подход работает для любой задачи, так что, если вы хотите знать какие задачи у конкретного подпроекта, просто используйте задачу tasks, например, gradle :services:webservice:tasks.

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

Осталась последняя вещь, на которую надо обратить внимание. Когда вы используете Gradle Wrapper, первый подход работает не очень хорошо, потому что вам надо указывать путь к скрипту wrapper'а, если вы не находитесь в корневом проекте. Например, если вы находитесь в папке подпроекта webservice, то должны запустить ../../gradlew build.

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