Перейти к основному содержимому

Создание приложений Java с помощью Bazel

· 6 мин. чтения

Задача: Сумма двух чисел

Напишите функцию twoSum. Которая получает массив целых чисел nums и целую сумму target, а возвращает индексы двух чисел, сумма которых равна target. Любой набор входных данных имеет ровно одно решение, и вы не можете использовать один и тот же элемент дважды. Ответ можно возвращать в любом порядке...

ANDROMEDA

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 .