1. Обзор
Bazel — это инструмент с открытым исходным кодом для создания и тестирования исходного кода, аналогичный Maven и Gradle. Он поддерживает проекты на нескольких языках и создает результаты для нескольких платформ .
В этом руководстве мы рассмотрим шаги, необходимые для создания простого приложения Java с использованием Bazel. Для иллюстрации мы начнем с многомодульного проекта Maven, а затем создадим исходный код с помощью Bazel.
Начнем с установки Bazel .
2. Структура проекта
Давайте создадим многомодульный проект Maven:
bazel (root)
pom.xml
WORKSPACE (bazel workspace)
|— bazelapp
pom.xml
BUILD (bazel build file)
|— src
|— main
|— java
|— test
|— java
|— bazelgreeting
pom.xml
BUILD (bazel build file)
|— src
|— main
|— java
|— test
|— java
Наличие файла WORKSPACE
устанавливает рабочее пространство для Bazel . В проекте их может быть один или несколько. В нашем примере мы сохраним только один файл в каталоге проекта верхнего уровня.
Следующий важный файл — это файл BUILD
, содержащий правила сборки . Он идентифицирует каждое правило уникальным целевым
именем
.
Bazel
предлагает гибкость, позволяющую иметь столько файлов BUILD
, сколько нам нужно , настроенных на любой уровень детализации. Это означало бы, что мы можем создать меньшее количество классов Java, соответствующим образом настроив правила BUILD .
Для простоты в нашем примере мы будем хранить минимальное количество файлов BUILD .
Поскольку выходные данные конфигурации Bazel BUILD обычно представляют собой JAR-файл, мы будем ссылаться на каждый каталог, содержащий файл
BUILD
, как на пакет сборки.
3. Файл сборки
3.1. Конфигурация правила
Пришло время настроить наше первое правило сборки для сборки двоичных файлов Java. Давайте настроим его в файле BUILD
, принадлежащем модулю bazelapp
:
java_binary (
name = "BazelApp",
srcs = glob(["src/main/java/com/foreach/*.java"]),
main_class = "com.foreach.BazelApp"
)
Давайте разберемся с настройками конфигурации один за другим:
java_binary
— имя правила; требуются дополнительные атрибуты для построения двоичных файловname
— имя цели сборкиsrcs
— массив шаблонов расположения файлов, указывающих, какие файлы Java нужно создавать.main_class
— имя основного класса приложения (необязательно)
3.2. Выполнение сборки
Теперь мы готовы создать приложение. Из каталога, содержащего файл WORKSPACE
,
давайте выполним команду bazel build
в оболочке, чтобы построить нашу цель:
$ bazel build //bazelapp:BazelApp
Последний аргумент — это целевое имя, настроенное в одном из файлов BUILD .
Он имеет шаблон « //<path_to_build>:<target_name>
».
Первая часть шаблона, «//», указывает, что мы начинаем с каталога нашей рабочей области. Следующий, «bazelapp»
, — это относительный путь к файлу BUILD
из каталога рабочей области. Наконец, «BazelApp»
— это целевое имя для сборки.
3.3. Вывод сборки
Теперь мы должны заметить два бинарных выходных файла из предыдущего шага:
bazel-bin/bazelapp/BazelApp.jar
bazel-bin/bazelapp/BazelApp
BazelApp.jar содержит
все классы, а BazelApp
— это сценарий-оболочка для выполнения файла jar.
3.4. Развертываемый JAR
Возможно, нам потребуется отправить банку и ее зависимости в разные места для развертывания.
Сценарий-оболочка из раздела выше указывает все зависимости (файлы jar) как часть команды запуска BazelApp.jar
.
Однако мы также можем сделать толстую банку, содержащую все зависимости:
$ bazel build //bazelapp:BazelApp_deploy.jar
Добавление к имени цели «_deploy»
указывает Bazel упаковать все зависимости в банке и подготовить ее к развертыванию.
4. Зависимости
До сих пор мы строили только с использованием файлов в bazelapp.
Но почти каждое приложение имеет зависимости.
В этом разделе мы увидим, как упаковать зависимости вместе с файлом jar.
4.1. Строительные библиотеки
Однако прежде чем мы это сделаем, нам нужна зависимость, которую может использовать bazelapp .
Давайте создадим еще один модуль Maven с именем bazelgreeting
и настроим файл BUILD
для нового модуля с правилом java_library
. Мы назовем эту цель « greeter»
:
java_library (
name = "greeter",
srcs = glob(["src/main/java/com/foreach/*.java"])
)
Здесь мы использовали правило java_library
для создания библиотеки. После создания этой цели мы получим файл libgreetings.jar
:
INFO: Found 1 target...
Target //bazelgreeting:greetings up-to-date:
bazel-bin/bazelgreeting/libgreetings.jar
4.2. Настройка зависимостей
Чтобы использовать Greeter
в bazelapp
, нам потребуются дополнительные настройки. Во-первых, нам нужно сделать пакет видимым для bazelapp
. Мы можем добиться этого, добавив атрибут видимости
в правило java_library пакета
приветствия
:
``
java_library (
name = "greeter",
srcs = glob(["src/main/java/com/foreach/*.java"]),
visibility = ["//bazelapp:__pkg__"]
)
Атрибут видимости
делает текущий пакет видимым для тех, кто указан в массиве.
Теперь в пакете bazelapp
мы должны настроить зависимость от пакета Greeter
. Сделаем это с помощью атрибута deps :
java_binary (
name = "BazelApp",
srcs = glob(["src/main/java/com/foreach/*.java"]),
main_class = "com.foreach.BazelApp",
deps = ["//bazelgreeting:greeter"]
)
Атрибут deps
делает текущий пакет зависимым от перечисленных в массиве.
5. Внешние зависимости
Мы можем работать над проектами, которые имеют несколько рабочих пространств и зависят друг от друга. Или мы можем импортировать библиотеки из удаленных мест. Мы можем классифицировать такие внешние зависимости как:
- Локальные зависимости : мы управляем ими в одной рабочей области, как мы видели в предыдущем разделе, или охватываем несколько рабочих областей.
- HTTP-архивы : мы импортируем библиотеки из удаленного места по HTTP.
Существует множество правил Bazel для управления внешними зависимостями . В следующих разделах мы увидим, как импортировать файлы jar из удаленного расположения.
5.1. Расположение URL-адресов HTTP
Для нашего примера давайте импортируем Apache Commons Lang в наше приложение. Поскольку нам нужно импортировать этот jar-файл из местоположения HTTP, мы будем использовать правило http_jar
. Сначала мы загрузим правило из определений сборки Bazel HTTP и настроим его в файле WORKSPACE
с расположением Apache Commons:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_jar")
http_jar (
name = "apache-commons-lang",
url = "https://repo1.maven.org/maven2/org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0.jar"
)
Далее мы должны добавить зависимости в файле BUILD пакета «
bazelapp»
:
deps = ["//bazelgreeting:greeter", "@apache-commons-lang//jar"]
Обратите внимание, нам нужно указать то же имя, что и в правиле http_jar
из файла WORKSPACE
.
5.2. Зависимости Maven
Управление отдельными файлами jar становится утомительной задачей. В качестве альтернативы мы можем настроить репозиторий Maven, используя правило rules_jvm_external
в нашем файле WORKSPACE
. Это позволит нам получить из репозиториев столько зависимостей, сколько мы хотим в нашем проекте.
Во-первых, мы должны импортировать правило rules_jvm_external
из удаленного места, используя правило http_archive в файле
WORKSPACE
:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
RULES_JVM_EXTERNAL_TAG = "2.0.1"
RULES_JVM_EXTERNAL_SHA = "55e8d3951647ae3dffde22b4f7f8dee11b3f70f3f89424713debd7076197eaca"
http_archive(
name = "rules_jvm_external",
strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,
sha256 = RULES_JVM_EXTERNAL_SHA,
url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG,
)
Далее мы воспользуемся правилом maven_install
и настроим URL-адрес репозитория Maven и необходимые артефакты:
load("@rules_jvm_external//:defs.bzl", "maven_install")
maven_install(
artifacts = [
"org.apache.commons:commons-lang3:3.12.0" ],
repositories = [
"https://repo1.maven.org/maven2",
] )
Наконец, мы добавим зависимость в файл BUILD :
deps = ["//bazelgreeting:greeter", "@maven//:org_apache_commons_commons_lang3"]
Он разрешает имена артефактов, используя символы подчеркивания (_).
6. Заключение
В этом руководстве мы изучили основные конфигурации для создания проекта Java в стиле Maven с помощью инструмента сборки Bazel.
Исходный код также доступен на GitHub . Он существует как проект Maven и также настроен с помощью файлов Bazel WORKSPACE
и BUILD
.