1. Overview
1.概述
Bazel is an open-source tool for building and testing source code, similar to Maven and Gradle. It supports projects in multiple languages and builds outputs for multiple platforms.
Bazel是一个用于构建和测试源代码的开源工具,类似于Maven和Gradle。它支持多种语言的项目,并为多种平台构建输出。
In this tutorial, we’ll go through the steps required to build a simple Java application using Bazel. For illustration, we’ll begin with a multi-module Maven project and then build the source code using Bazel.
在本教程中,我们将通过使用Bazel构建一个简单的Java应用程序所需的步骤。为了说明问题,我们将从一个多模块的Maven项目开始,然后用Bazel构建源代码。
We’ll start by installing Bazel.
我们将从安装Bazel>开始。
2. Project Structure
2.项目结构
Let’s create a multi-module Maven project:
我们来创建一个多模块的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
The presence of the WORKSPACE file sets up the workspace for Bazel. There could be one or a multiple of them in a project. For our example, we’ll keep only one file at the top-level project directory.
WORKSPACE文件的存在为Bazel设置了工作空间。在一个项目中可以有一个或多个这样的文件。在我们的例子中,我们将在项目顶层目录下只保留一个文件。
The next important file is the BUILD file, which contains the build rules. It identifies each rule with a unique target name.
下一个重要的文件是BUILD文件,它包含构建规则。它用唯一的targetname来标识每个规则。
Bazel offers the flexibility to have as many BUILD files as we need, configured to any level of granularity. This would mean we can build a smaller number of Java classes by configuring BUILD rules accordingly. To keep things simple, we will keep minimal BUILD files in our example.
Bazel提供了灵活性,可以根据我们的需要拥有尽可能多的BUILD文件,配置为任何级别的粒度。这将意味着我们可以通过相应地配置BUILD规则来构建较少数量的Java类。为了保持简单,我们将在我们的例子中保持最小的BUILD文件。
Since the output of the Bazel BUILD configuration is typically a jar file, we’ll refer each directory containing the BUILD file as a build package.
由于Bazel BUILD配置的输出通常是一个jar文件,我们将把包含BUILD文件的每个目录称为一个构建包。
3. Build File
3.建立文件
3.1. Rule Configuration
3.1.规则配置
It’s time to configure our first build rule to build the Java binaries. Let’s configure one in the BUILD file belonging to the bazelapp module:
现在是时候配置我们的第一个构建规则来构建Java二进制文件了。让我们在BUILD文件中配置一个属于bazelapp模块的规则。
java_binary (
name = "BazelApp",
srcs = glob(["src/main/java/com/baeldung/*.java"]),
main_class = "com.baeldung.BazelApp"
)
Let’s understand the configuration settings one-by-one:
让我们逐一了解配置设置。
- java_binary – the name of the rule; it requires additional attributes for building the binaries
- name – the name of the build target
- srcs – an array of the file location patterns that tell which Java files to build
- main_class – the name of the application main class (optional)
3.2. Build Execution
3.2.构建执行
We are now good to build the app. From the directory containing the WORKSPACE file, let’s execute the bazel build command in a shell to build our target:
我们现在可以构建该应用程序了。从包含WORKSPACE 文件的目录中,让我们在shell中执行bazel build命令来构建我们的目标。
$ bazel build //bazelapp:BazelApp
The last argument is the target name configured in one of the BUILD files. It has the pattern “//<path_to_build>:<target_name>“.
最后一个参数是在某个BUILD 文件中配置的目标名称。它的模式是”//lt;path_to_build>:<target_name>“。
The first part of the pattern, “//”, indicates we’re starting in our workspace directory. The next, “bazelapp”, is the relative path to the BUILD file from the workspace directory. Finally, “BazelApp” is the target name to build.
模式的第一部分,”//”,表示我们从我们的工作区目录开始。接下来,“bazelapp”,是指向工作区目录中BUILD文件的相对路径。最后,“BazelApp”是要构建的目标名称。
3.3. Build Output
3.3.构建输出
We should now notice two binary output files from the previous step:
现在我们应该注意到上一步的两个二进制输出文件。
bazel-bin/bazelapp/BazelApp.jar
bazel-bin/bazelapp/BazelApp
The BazelApp.jar contains all the classes, while BazelApp is a wrapper script to execute the jar file.
BazelApp.jar包含所有的类,而BazelApp是一个执行jar文件的封装脚本。
3.4. Deployable JAR
3.4.可部署的JAR
We may need to ship the jar and its dependencies to different locations for deployment.
我们可能需要将jar和它的依赖项运送到不同的地方进行部署。
The wrapper script from the section above specifies all the dependencies (jar files) as part of BazelApp.jar‘s startup command.
上文中的包装脚本指定了所有的依赖项(jar文件),作为BazelApp.jar的启动命令的一部分。
However, we can also make a fat jar containing all the dependencies:
然而,我们也可以制作一个包含所有依赖关系的胖子jar。
$ bazel build //bazelapp:BazelApp_deploy.jar
Suffixing the name of the target with “_deploy” instructs Bazel to package all the dependencies within the jar and make it ready for deployment.
在目标名称后面加上“_deploy” 指示Bazel在jar中打包所有的依赖项,使其准备好进行部署。
4. Dependencies
4.依赖性
So far, we’ve only built using the files in bazelapp. But, most every app has dependencies.
到目前为止,我们只使用bazelapp中的文件进行构建。但是,大多数应用程序都有依赖性。
In this section, we’ll see how to package the dependencies together with the jar file.
在这一节中,我们将看到如何将依赖项与jar文件打包在一起。
4.1. Building Libraries
4.1.构建库
Before we do that, though, we need a dependency that bazelapp can use.
不过在这之前,我们需要一个bazelapp可以使用的依赖关系。
Let’s create another Maven module named bazelgreeting and configure the BUILD file for the new module with the java_library rule. We’ll name this target “greeter”:
我们再创建一个名为bazelgreeting的Maven模块,用java_library规则为新模块配置BUILD文件。我们将这个目标命名为”greeter”。
java_library (
name = "greeter",
srcs = glob(["src/main/java/com/baeldung/*.java"])
)
Here, we’ve used the java_library rule for creating the library. After building this target, we’ll get the libgreetings.jar file:
这里,我们使用了java_library规则来创建库。在构建这个目标后,我们将得到libgreetings.jar文件。
INFO: Found 1 target...
Target //bazelgreeting:greetings up-to-date:
bazel-bin/bazelgreeting/libgreetings.jar
4.2. Configuring Dependencies
4.2.配置依赖关系
To use greeter in bazelapp, we’ll need some additional configurations. First, we need to make the package visible to bazelapp. We can achieve this by adding the visibility attribute in the java_library rule of the greeter package:
要在bazelapp中使用greeter,我们需要一些额外的配置。首先,我们需要使包对bazelapp可见。我们可以通过在greeter包的java_library规则中添加visibility属性来实现。
java_library (
name = "greeter",
srcs = glob(["src/main/java/com/baeldung/*.java"]),
visibility = ["//bazelapp:__pkg__"]
)
The visibility attribute makes the current package visible to those listed in the array.
visibility属性使当前包对阵列中列出的人可见。
Now in the bazelapp package, we must configure the dependency on the greeter package. Let’s do this with the deps attribute:
现在在bazelapp包中,我们必须配置对greeter包的依赖性。让我们用deps属性来做这件事。
java_binary (
name = "BazelApp",
srcs = glob(["src/main/java/com/baeldung/*.java"]),
main_class = "com.baeldung.BazelApp",
deps = ["//bazelgreeting:greeter"]
)
The deps attribute makes the current package dependent on those listed in the array.
deps属性使当前软件包依赖于阵列中列出的那些软件包。
5. External Dependencies
5.外部依赖性
We can work on projects that have multiple workspaces and depend on each other. Or, we can import libraries from remote locations. We can categorize such external dependencies as:
我们可以在有多个工作空间并相互依赖的项目上工作。或者,我们可以从远程位置导入库。我们可以将这种外部依赖关系归类为:
- Local Dependencies: We manage them within the same workspace as we have seen in the previous section or span across multiple workspaces
- HTTP Archives: We import the libraries from a remote location over HTTP
There are many Bazel rules available to manage external dependencies. We’ll see how to import jar files from the remote location in the subsequent sections.
有许多Bazel规则可用于管理外部依赖性。我们将在随后的章节中看到如何从远程位置导入jar文件。
5.1. HTTP URL Locations
5.1.HTTP URL位置
For our example, let’s import Apache Commons Lang into our application. Since we have to import this jar from the HTTP location, we will use the http_jar rule. We’ll first load the rule from the Bazel HTTP build definitions and configure it in the WORKSPACE file with Apache Commons’s location:
对于我们的例子,让我们把Apache Commons Lang导入我们的应用程序。由于我们必须从HTTP位置导入这个jar,我们将使用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"
)
We must further add dependencies in the BUILD file of the “bazelapp” package:
我们必须在”bazelapp”包的BUILD文件中进一步添加依赖项。
deps = ["//bazelgreeting:greeter", "@apache-commons-lang//jar"]
Note, we need to specify the same name used in the http_jar rule from the WORKSPACE file.
注意,我们需要指定与http_jar文件中WORKSPACE规则所使用的相同名称。
5.2. Maven Dependencies
5.2.Maven的依赖性
Managing individual jar files becomes a tedious task. Alternatively, we can configure the Maven repository using the rules_jvm_external rule in our WORKSPACE file. This will enable us to fetch as many dependencies we want in our project from repositories.
管理单个jar文件成为一项繁琐的工作。另外,我们可以使用rules_jvm_external规则在WORKSPACE文件中配置Maven资源库。这将使我们能够在项目中尽可能多地从资源库中获取我们想要的依赖项。
First, we must import the rules_jvm_external rule from a remote location using the http_archive rule in the WORKSPACE file:
首先,我们必须使用WORKSPACE文件中的http_archive规则从远程位置导入rules_jvm_external规则。
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,
)
Next, we’ll use the maven_install rule and configure the Maven repository URL and the required artifacts:
接下来,我们将使用maven_install规则,配置Maven仓库的URL和所需工件。
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",
] )
At last, we’ll add the dependency in the BUILD file:
最后,我们将在BUILD文件中添加依赖关系。
deps = ["//bazelgreeting:greeter", "@maven//:org_apache_commons_commons_lang3"]
It resolves the names of the artifacts using underscore (_) characters.
它使用下划线(_)字符来解析工件的名称。
6. Conclusion
6.结语
In this tutorial, we learned basic configurations to build a Maven style Java project with the Bazel build tool.
在本教程中,我们学习了用Bazel构建工具构建Maven风格Java项目的基本配置。
The source code is also available over GitHub. It exists as a Maven project and is also configured with the Bazel WORKSPACE and BUILD files.
源代码也可以通过GitHub获得。它作为一个Maven项目存在,并且还配置了Bazel WORKSPACE和BUILD文件。