Статьи

Начало работы с Gradle: создание многопроектной сборки

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

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

Этот пост описывает, как мы можем создать многопроектную сборку с Gradle.

Давайте начнем с рассмотрения требований нашей сборки Gradle.

Дополнительное чтение:

Если вы не знакомы с Gradle, вам следует прочитать следующие сообщения в блоге, прежде чем продолжить чтение этого сообщения в блоге:

Требования нашего Gradle Build

В нашем примере приложения есть два модуля:

  • Основной модуль содержит общие компоненты, которые используются другими модулями нашего приложения. В нашем случае он содержит только один класс: класс MessageService возвращает строку «Hello World!». Этот модуль имеет только одну зависимость: он имеет один модульный тест, который использует Junit 4.11.
  • Модуль приложения содержит класс HelloWorld, который запускает наше приложение, получает сообщение от объекта MessageService и записывает полученное сообщение в файл журнала. Этот модуль имеет две зависимости: ему нужен основной модуль и использует Log4j 1.2.17 в качестве библиотеки журналов.

Наша сборка Gradle также имеет два других требования:

  • Мы должны быть в состоянии запустить наше приложение с Gradle.
  • Мы должны быть в состоянии создать исполняемый двоичный дистрибутив, который не использует так называемый подход «толстый фляга».

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

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

Создание мультипроектной сборки

Нашим следующим шагом будет создание многопроектной сборки Gradle с двумя подпроектами: приложение и ядро . Давайте начнем с создания структуры каталогов нашей сборки Gradle.

Создание структуры каталогов

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

  1. Создайте корневой каталог основного модуля ( core ) и создайте следующие подкаталоги:
    • Каталог src / main / java содержит исходный код модуля ядра .
    • Каталог src / test / java содержит модульные тесты модуля ядра .
  2. Создайте корневой каталог модуля приложения ( app ) и создайте следующие подкаталоги:
    • Каталог src / main / java содержит исходный код модуля приложения .
    • Каталог src / main / resources содержит ресурсы модуля приложения .

Теперь мы создали необходимые каталоги. Наш следующий шаг — настроить сборку Gradle. Давайте начнем с настройки проектов, которые включены в нашу многопроектную сборку.

Конфигурирование проектов, которые включены в нашу многопроектную сборку

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

  1. Создайте файл settings.gradle в корневом каталоге корневого проекта. Многопроектная сборка Gradle должна иметь этот файл, поскольку он указывает проекты, включенные в многопроектную сборку.
  2. Убедитесь, что приложение и основные проекты включены в нашу многопроектную сборку.

Наш файл settings.gradle выглядит следующим образом:

1
2
include 'app'
include 'core'

Дополнительное чтение:

Давайте перейдем к настройке основного проекта.

Настройка основного проекта

Мы можем настроить основной проект, выполнив следующие действия:

  1. Создайте файл build.gradle в корневом каталоге основного проекта.
  2. Создайте проект Java с помощью плагина Java.
  3. Убедитесь, что основной проект получает свои зависимости от центрального репозитория Maven2.
  4. Объявите зависимость JUnit (версия 4.11) и используйте конфигурацию testCompile . Эта конфигурация описывает, что базовому проекту требуется библиотека JUnit, прежде чем его модульные тесты могут быть скомпилированы.

Файл build.gradle основного проекта выглядит следующим образом:

1
2
3
4
5
6
7
8
9
apply plugin: 'java'
 
repositories {
    mavenCentral()
}
 
dependencies {
    testCompile 'junit:junit:4.11'
}

Дополнительное чтение:

Давайте перейдем к настройке проекта приложения .

Настройка проекта приложения

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

Если в нашей многопроектной сборке есть проекты A и B, а для компиляции проекта B требуется проект A, мы можем настроить эту зависимость, добавив следующее объявление зависимости в файл build.gradle проекта B:

1
2
3
dependencies {
    compile project(':A')
}

Дополнительное чтение:

Теперь мы можем настроить проект приложения , выполнив следующие действия:

  1. Создайте файл build.gradle в корневом каталоге проекта приложения .
  2. Создайте проект Java с помощью плагина Java.
  3. Убедитесь, что проект приложения получает свои зависимости из центрального хранилища Maven2.
  4. Настройте необходимые зависимости. Проект приложения имеет две зависимости, которые требуются при компиляции:
    • Log4j (версия 1.2.17)
    • Основной модуль
  5. Создайте исполняемый двоичный дистрибутив .

Файл build.gradle проекта приложения выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
apply plugin: 'application'
apply plugin: 'java'
 
repositories {
    mavenCentral()
}
 
dependencies {
    compile 'log4j:log4j:1.2.17'
    compile project(':core')
}
 
mainClassName = 'net.petrikainulainen.gradle.client.HelloWorld'
 
task copyLicense {
    outputs.file new File("$buildDir/LICENSE")
    doLast {
        copy {
            from "LICENSE"
            into "$buildDir"
        }
    }
}
 
applicationDistribution.from(copyLicense) {
    into ""
}

Дополнительное чтение:

Давайте продолжим и удалим дубликат конфигурации, найденный в скриптах сборки ядра и проектов приложений .

Удаление дубликатов конфигурации

Когда мы сконфигурировали подпроекты нашей многопроектной сборки, мы добавили дублирующую конфигурацию в сценарии сборки основного проекта и приложений :

  • Поскольку оба проекта являются проектами Java, они применяют плагин Java.
  • Оба проекта используют центральный репозиторий Maven 2.

Другими словами, оба сценария сборки содержат следующую конфигурацию:

1
2
3
4
5
apply plugin: 'java'
 
repositories {
    mavenCentral()
}

Давайте перенесем эту конфигурацию в файл build.gradle нашего корневого проекта. Прежде чем мы сможем сделать это, мы должны узнать, как мы можем настроить наши подпроекты в файле build.gradle нашего корневого проекта.

Если мы хотим добавить конфигурацию к одному подпроекту под названием core , мы должны добавить следующий фрагмент в файл build.gradle нашего корневого проекта:

1
2
3
project(':core') {
    //Add core specific configuration here
}

Другими словами, если мы хотим переместить дубликат конфигурации в скрипт сборки нашего корневого проекта, мы должны добавить следующую конфигурацию в его файл build.gradle :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
project(':app') {
    apply plugin: 'java'
 
    repositories {
        mavenCentral()
    }
}
 
project(':core') {
    apply plugin: 'java'
 
    repositories {
        mavenCentral()
    }
}

Это действительно не меняет нашу ситуацию. У нас все еще есть дублирующая конфигурация в наших скриптах сборки. Единственное отличие состоит в том, что дублирующую конфигурацию теперь можно найти в файле build.gradle нашего корневого проекта. Давайте избавимся от этой дублированной конфигурации.

Если мы хотим добавить общую конфигурацию для подпроектов нашего корневого проекта, мы должны добавить следующий фрагмент в файл build.gradle нашего корневого проекта:

1
2
3
subprojects {
    //Add common configuration here
}

После того, как мы удалили дубликат конфигурации из файла build.gradle нашего корневого проекта, он выглядит следующим образом:

1
2
3
4
5
6
7
subprojects {
    apply plugin: 'java'
 
    repositories {
        mavenCentral()
    }
}

Если у нас есть конфигурация, которая используется всеми проектами нашей многопроектной сборки, мы должны добавить следующий фрагмент к
Файл build.gradle нашего корневого проекта:

1
2
3
allprojects {
    //Add configuration here
}

Дополнительное чтение:

Теперь мы можем удалить дублирующую конфигурацию из сценариев сборки наших подпроектов. Новые сценарии сборки наших подпроектов выглядят следующим образом:

Файл core / build.gradle выглядит следующим образом:

1
2
3
dependencies {
    testCompile 'junit:junit:4.11'
}

Файл app / build.gradle выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
apply plugin: 'application'
 
dependencies {
    compile 'log4j:log4j:1.2.17'
    compile project(':core')
}
 
mainClassName = 'net.petrikainulainen.gradle.client.HelloWorld'
 
task copyLicense {
    outputs.file new File("$buildDir/LICENSE")
    doLast {
        copy {
            from "LICENSE"
            into "$buildDir"
        }
    }
}
 
applicationDistribution.from(copyLicense) {
    into ""
}

Сейчас мы создали мультипроектную сборку Gradle. Давайте выясним, что мы только что сделали.

Что мы только что сделали?

Когда мы запускаем проекты командной строки в корневом каталоге нашей многопроектной сборки, мы видим следующий вывод:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
> gradle projects
:projects
 
------------------------------------------------------------
Root project
------------------------------------------------------------
 
Root project 'multi-project-build'
+--- Project ':app'
\--- Project ':core'
 
To see a list of the tasks of a project, run gradle <project-path>:tasks
For example, try running gradle :app:tasks
 
BUILD SUCCESSFUL

Как мы видим, эта команда перечисляет подпроекты ( приложение и ядро ) нашего корневого проекта. Это означает, что мы только что создали многопроектную сборку Gradle, которая имеет два подпроекта.

Когда мы запускаем задачи командной строки в корневом каталоге нашей многопроектной сборки, мы видим следующий вывод (ниже показана только соответствующая его часть):

01
02
03
04
05
06
07
08
09
10
11
12
13
> gradle tasks
:tasks
 
------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------
 
Application tasks
-----------------
distTar - Bundles the project as a JVM application with libs and OS specific scripts.
distZip - Bundles the project as a JVM application with libs and OS specific scripts.
installApp -Installs the project as a JVM application along with libs and OS specific scripts
run - Runs this project as a JVM application

Как мы видим, мы можем запустить наше приложение с помощью Gradle и создать бинарный дистрибутив, который не использует так называемый подход «толстый фляга». Это означает, что мы выполнили все требования нашей сборки Gradle.

Дополнительная информация:

Давайте двигаться дальше и узнаем, что мы узнали из этого поста в блоге.

Резюме

Этот пост научил нас трем вещам:

  • Многопроектная сборка должна иметь файл settings.gradle в корневом каталоге корневого проекта, поскольку он указывает проекты, включенные в многопроектную сборку.
  • Если нам нужно добавить общую конфигурацию или поведение ко всем проектам нашей многопроектной сборки, мы должны добавить эту конфигурацию (использовать все проекты ) в файл build.gradle нашего корневого проекта.
  • Если нам нужно добавить общую конфигурацию или поведение в подпроекты нашего корневого проекта, мы должны добавить эту конфигурацию (использовать подпроекты ) в файл build.gradle нашего корневого проекта.

PS Вы можете получить пример приложения этого поста в блоге от Github .