blob: bb47db02ddeae7505e9e2462df880bae2951ee0c [file] [log] [blame] [view]
Yun Peng1f63afa2016-06-24 18:01:03 +00001---
dzc22b85a22017-05-31 20:37:50 +02002layout: documentation
Googler8af9dc52017-06-07 13:49:48 -04003title: Build Tutorial - Java
daroberts223aebd2021-02-18 17:53:30 -08004category: getting-started
Yun Peng1f63afa2016-06-24 18:01:03 +00005---
dzc22b85a22017-05-31 20:37:50 +02006
Googler22230e42020-12-02 15:18:28 -08007# Bazel Tutorial: Build a Java Project
dzc22b85a22017-05-31 20:37:50 +02008
Googler22230e42020-12-02 15:18:28 -08009This tutorial covers the basics of building Java applications with
Googler8af9dc52017-06-07 13:49:48 -040010Bazel. You will set up your workspace and build a simple Java project that
11illustrates key Bazel concepts, such as targets and `BUILD` files.
dzc22b85a22017-05-31 20:37:50 +020012
Googler8af9dc52017-06-07 13:49:48 -040013Estimated completion time: 30 minutes.
dzc22b85a22017-05-31 20:37:50 +020014
Googler8af9dc52017-06-07 13:49:48 -040015## What you'll learn
dzc22b85a22017-05-31 20:37:50 +020016
Googler22230e42020-12-02 15:18:28 -080017In this tutorial you learn how to:
dzc22b85a22017-05-31 20:37:50 +020018
Googler8af9dc52017-06-07 13:49:48 -040019* Build a target
20* Visualize the project's dependencies
21* Split the project into multiple targets and packages
22* Control target visibility across packages
23* Reference targets through labels
24* Deploy a target
dzc22b85a22017-05-31 20:37:50 +020025
26## Before you begin
27
Googler1c6a9822017-08-04 19:31:14 +020028### Install Bazel
29
dzc205125b2017-06-26 11:01:47 +020030To prepare for the tutorial, first [Install Bazel](../install.md) if
Googler1c6a9822017-08-04 19:31:14 +020031you don't have it installed already.
32
Laszlo Csomor75748652018-07-26 07:38:14 -070033### Install the JDK
34
Ivo List2fb9f3c2020-12-17 10:19:09 -0800351. Install Java JDK (preferred version is 11, however versions between 8 and 15 are supported).
Laszlo Csomor75748652018-07-26 07:38:14 -070036
372. Set the JAVA\_HOME environment variable to point to the JDK.
38 * On Linux/macOS:
39
40 export JAVA_HOME="$(dirname $(dirname $(realpath $(which javac))))"
41 * On Windows:
42 1. Open Control Panel.
43 2. Go to "System and Security" > "System" > "Advanced System Settings" > "Advanced" tab > "Environment Variables..." .
44 3. Under the "User variables" list (the one on the top), click "New...".
45 4. In the "Variable name" field, enter `JAVA_HOME`.
46 5. Click "Browse Directory...".
Salty Egg5f17a762018-10-11 07:21:51 -070047 6. Navigate to the JDK directory (for example `C:\Program Files\Java\jdk1.8.0_152`).
Laszlo Csomor75748652018-07-26 07:38:14 -070048 7. Click "OK" on all dialog windows.
49
Googler1c6a9822017-08-04 19:31:14 +020050### Get the sample project
51
52Retrieve the sample project from Bazel's GitHub repository:
dzc22b85a22017-05-31 20:37:50 +020053
dzc51dcd282017-06-14 22:52:27 +020054```sh
Ruben Das32fc4372019-10-28 10:35:02 -070055git clone https://github.com/bazelbuild/examples
Googler8af9dc52017-06-07 13:49:48 -040056```
dzc22b85a22017-05-31 20:37:50 +020057
Googler8af9dc52017-06-07 13:49:48 -040058The sample project for this tutorial is in the `examples/java-tutorial`
59directory and is structured as follows:
dzc22b85a22017-05-31 20:37:50 +020060
Googler8af9dc52017-06-07 13:49:48 -040061```
62java-tutorial
Googler8af9dc52017-06-07 13:49:48 -040063├── BUILD
64├── src
65│ └── main
66│ └── java
67│ └── com
68│ └── example
69│ ├── cmdline
70│ │ ├── BUILD
71│ │ └── Runner.java
72│ ├── Greeting.java
73│ └── ProjectRunner.java
74└── WORKSPACE
75```
dzc22b85a22017-05-31 20:37:50 +020076
77## Build with Bazel
78
79### Set up the workspace
80
Googler8af9dc52017-06-07 13:49:48 -040081Before you can build a project, you need to set up its workspace. A workspace is
82a directory that holds your project's source files and Bazel's build outputs. It
83also contains files that Bazel recognizes as special:
dzc22b85a22017-05-31 20:37:50 +020084
Googler8af9dc52017-06-07 13:49:48 -040085* The `WORKSPACE` file, which identifies the directory and its contents as a
86 Bazel workspace and lives at the root of the project's directory structure,
dzc22b85a22017-05-31 20:37:50 +020087
Googler8af9dc52017-06-07 13:49:48 -040088* One or more `BUILD` files, which tell Bazel how to build different parts of
89 the project. (A directory within the workspace that contains a `BUILD` file
90 is a *package*. You will learn about packages later in this tutorial.)
dzc22b85a22017-05-31 20:37:50 +020091
Googler8af9dc52017-06-07 13:49:48 -040092To designate a directory as a Bazel workspace, create an empty file named
93`WORKSPACE` in that directory.
dzc22b85a22017-05-31 20:37:50 +020094
Googler8af9dc52017-06-07 13:49:48 -040095When Bazel builds the project, all inputs and dependencies must be in the same
96workspace. Files residing in different workspaces are independent of one
97another unless linked, which is beyond the scope of this tutorial.
dzc22b85a22017-05-31 20:37:50 +020098
Googler8af9dc52017-06-07 13:49:48 -040099### Understand the BUILD file
dzc22b85a22017-05-31 20:37:50 +0200100
Googler8af9dc52017-06-07 13:49:48 -0400101A `BUILD` file contains several different types of instructions for Bazel.
102The most important type is the *build rule*, which tells Bazel how to build the
103desired outputs, such as executable binaries or libraries. Each instance
104of a build rule in the `BUILD` file is called a *target* and points to a
105specific set of source files and dependencies. A target can also point to other
106targets.
dzc22b85a22017-05-31 20:37:50 +0200107
Googler8af9dc52017-06-07 13:49:48 -0400108Take a look at the `java-tutorial/BUILD` file:
dzc22b85a22017-05-31 20:37:50 +0200109
vladmos4e9208a2020-03-11 12:16:42 -0700110```python
Googler8af9dc52017-06-07 13:49:48 -0400111java_binary(
Googler006659e2017-07-20 19:48:05 +0200112 name = "ProjectRunner",
Googler8af9dc52017-06-07 13:49:48 -0400113 srcs = glob(["src/main/java/com/example/*.java"]),
114)
115```
dzc22b85a22017-05-31 20:37:50 +0200116
Googler8af9dc52017-06-07 13:49:48 -0400117In our example, the `ProjectRunner` target instantiates Bazel's built-in
dzc205125b2017-06-26 11:01:47 +0200118[`java_binary` rule](../be/java.html#java_binary). The rule tells Bazel to
Googler8af9dc52017-06-07 13:49:48 -0400119build a `.jar` file and a wrapper shell script (both named after the target).
dzc22b85a22017-05-31 20:37:50 +0200120
Googler8af9dc52017-06-07 13:49:48 -0400121The attributes in the target explicitly state its dependencies and options.
122While the `name` attribute is mandatory, many are optional. For example, in the
123`ProjectRunner` rule target, `name` is the name of the target, `srcs` specifies
124the source files that Bazel uses to build the target, and `main_class` specifies
125the class that contains the main method. (You may have noticed that our example
dzc205125b2017-06-26 11:01:47 +0200126uses [glob](../be/functions.html#glob) to pass a set of source files to Bazel
Googler8af9dc52017-06-07 13:49:48 -0400127instead of listing them one by one.)
dzc22b85a22017-05-31 20:37:50 +0200128
Googler8af9dc52017-06-07 13:49:48 -0400129### Build the project
dzc22b85a22017-05-31 20:37:50 +0200130
Googlerec7ecd72021-03-19 16:20:52 -0700131To build your sample project, navigate to the `java-tutorial` directory
132and run:
dzc22b85a22017-05-31 20:37:50 +0200133
Googler8af9dc52017-06-07 13:49:48 -0400134```
Googler006659e2017-07-20 19:48:05 +0200135bazel build //:ProjectRunner
Googler8af9dc52017-06-07 13:49:48 -0400136```
Googlerec7ecd72021-03-19 16:20:52 -0700137In the target label, the `//` part is the location of the `BUILD` file
138relative to the root of the workspace (in this case, the root itself),
139and `ProjectRunner` is the target name in the `BUILD` file. (You will
Googler8af9dc52017-06-07 13:49:48 -0400140learn about target labels in more detail at the end of this tutorial.)
dzc22b85a22017-05-31 20:37:50 +0200141
Googler8af9dc52017-06-07 13:49:48 -0400142Bazel produces output similar to the following:
dzc22b85a22017-05-31 20:37:50 +0200143
Googler8af9dc52017-06-07 13:49:48 -0400144```bash
Googler006659e2017-07-20 19:48:05 +0200145 INFO: Found 1 target...
146 Target //:ProjectRunner up-to-date:
147 bazel-bin/ProjectRunner.jar
148 bazel-bin/ProjectRunner
149 INFO: Elapsed time: 1.021s, Critical Path: 0.83s
Googler8af9dc52017-06-07 13:49:48 -0400150```
dzc22b85a22017-05-31 20:37:50 +0200151
Googler8af9dc52017-06-07 13:49:48 -0400152Congratulations, you just built your first Bazel target! Bazel places build
153outputs in the `bazel-bin` directory at the root of the workspace. Browse
154through its contents to get an idea for Bazel's output structure.
dzc22b85a22017-05-31 20:37:50 +0200155
Googler8af9dc52017-06-07 13:49:48 -0400156Now test your freshly built binary:
dzc22b85a22017-05-31 20:37:50 +0200157
dzc51dcd282017-06-14 22:52:27 +0200158```sh
Googler8af9dc52017-06-07 13:49:48 -0400159bazel-bin/ProjectRunner
160```
dzc22b85a22017-05-31 20:37:50 +0200161
162### Review the dependency graph
163
Googler8af9dc52017-06-07 13:49:48 -0400164Bazel requires build dependencies to be explicitly declared in BUILD files.
165Bazel uses those statements to create the project's dependency graph, which
166enables accurate incremental builds.
dzc22b85a22017-05-31 20:37:50 +0200167
Googlerec7ecd72021-03-19 16:20:52 -0700168To visualize the sample project's dependencies, you can generate a text
169representation of the dependency graph by running this command at the
170workspace root:
dzc22b85a22017-05-31 20:37:50 +0200171
Googler8af9dc52017-06-07 13:49:48 -0400172```
wtroberts5a0cf9b2019-09-06 07:55:15 -0700173bazel query --notool_deps --noimplicit_deps "deps(//:ProjectRunner)" --output graph
Googler8af9dc52017-06-07 13:49:48 -0400174```
dzc22b85a22017-05-31 20:37:50 +0200175
Googler8af9dc52017-06-07 13:49:48 -0400176The above command tells Bazel to look for all dependencies for the target
177`//:ProjectRunner` (excluding host and implicit dependencies) and format the
178output as a graph.
dzc22b85a22017-05-31 20:37:50 +0200179
Googler8af9dc52017-06-07 13:49:48 -0400180Then, paste the text into [GraphViz](http://www.webgraphviz.com/).
dzc22b85a22017-05-31 20:37:50 +0200181
dzc22b85a22017-05-31 20:37:50 +0200182
Googler8af9dc52017-06-07 13:49:48 -0400183As you can see, the project has a single target that build two source files with
184no additional dependencies:
dzc22b85a22017-05-31 20:37:50 +0200185
Googler8af9dc52017-06-07 13:49:48 -0400186![Dependency graph of the target 'ProjectRunner'](/assets/tutorial_java_01.svg)
dzc22b85a22017-05-31 20:37:50 +0200187
Googlerec7ecd72021-03-19 16:20:52 -0700188After you set up your workspace, build your project, and examine its
189dependencies, then you can add some complexity.
dzc22b85a22017-05-31 20:37:50 +0200190
191## Refine your Bazel build
192
Googler8af9dc52017-06-07 13:49:48 -0400193While a single target is sufficient for small projects, you may want to split
194larger projects into multiple targets and packages to allow for fast incremental
195builds (that is, only rebuild what's changed) and to speed up your builds by
196building multiple parts of a project at once.
dzc22b85a22017-05-31 20:37:50 +0200197
Googler8af9dc52017-06-07 13:49:48 -0400198### Specify multiple build targets
dzc22b85a22017-05-31 20:37:50 +0200199
Googlerec7ecd72021-03-19 16:20:52 -0700200You can split the sample project build into two targets. Replace the contents of
Googler8af9dc52017-06-07 13:49:48 -0400201the `java-tutorial/BUILD` file with the following:
dzc22b85a22017-05-31 20:37:50 +0200202
vladmos4e9208a2020-03-11 12:16:42 -0700203```python
Googler8af9dc52017-06-07 13:49:48 -0400204java_binary(
205 name = "ProjectRunner",
206 srcs = ["src/main/java/com/example/ProjectRunner.java"],
207 main_class = "com.example.ProjectRunner",
208 deps = [":greeter"],
209)
dzc22b85a22017-05-31 20:37:50 +0200210
Googler8af9dc52017-06-07 13:49:48 -0400211java_library(
212 name = "greeter",
213 srcs = ["src/main/java/com/example/Greeting.java"],
214)
215```
dzc22b85a22017-05-31 20:37:50 +0200216
Googler8af9dc52017-06-07 13:49:48 -0400217With this configuration, Bazel first builds the `greeter` library, then the
Passw473a9162017-12-22 14:13:12 -0800218`ProjectRunner` binary. The `deps` attribute in `java_binary` tells Bazel that
Googler8af9dc52017-06-07 13:49:48 -0400219the `greeter` library is required to build the `ProjectRunner` binary.
dzc22b85a22017-05-31 20:37:50 +0200220
Googlerec7ecd72021-03-19 16:20:52 -0700221To build this new version of the project, run the following command:
dzc22b85a22017-05-31 20:37:50 +0200222
Googler8af9dc52017-06-07 13:49:48 -0400223```
224bazel build //:ProjectRunner
225```
dzc22b85a22017-05-31 20:37:50 +0200226
Googler8af9dc52017-06-07 13:49:48 -0400227Bazel produces output similar to the following:
dzc22b85a22017-05-31 20:37:50 +0200228
Googler8af9dc52017-06-07 13:49:48 -0400229```
230INFO: Found 1 target...
231Target //:ProjectRunner up-to-date:
232 bazel-bin/ProjectRunner.jar
233 bazel-bin/ProjectRunner
234INFO: Elapsed time: 2.454s, Critical Path: 1.58s
235```
dzc22b85a22017-05-31 20:37:50 +0200236
Googler8af9dc52017-06-07 13:49:48 -0400237Now test your freshly built binary:
dzc22b85a22017-05-31 20:37:50 +0200238
Googler8af9dc52017-06-07 13:49:48 -0400239```
240bazel-bin/ProjectRunner
241```
dzc22b85a22017-05-31 20:37:50 +0200242
Googler8af9dc52017-06-07 13:49:48 -0400243If you now modify `ProjectRunner.java` and rebuild the project, Bazel only
244recompiles that file.
dzc22b85a22017-05-31 20:37:50 +0200245
Googler8af9dc52017-06-07 13:49:48 -0400246Looking at the dependency graph, you can see that `ProjectRunner` depends on the
247same inputs as it did before, but the structure of the build is different:
dzc22b85a22017-05-31 20:37:50 +0200248
laurentlb79b94312018-11-07 05:18:59 -0800249![Dependency graph of the target 'ProjectRunner' after adding a dependency](
250/assets/tutorial_java_02.svg)
dzc22b85a22017-05-31 20:37:50 +0200251
Googler8af9dc52017-06-07 13:49:48 -0400252You've now built the project with two targets. The `ProjectRunner` target builds
253two source files and depends on one other target (`:greeter`), which builds
254one additional source file.
dzc22b85a22017-05-31 20:37:50 +0200255
256### Use multiple packages
257
Googler8af9dc52017-06-07 13:49:48 -0400258Lets now split the project into multiple packages. If you take a look at the
259`src/main/java/com/example/cmdline` directory, you can see that it also contains
260a `BUILD` file, plus some source files. Therefore, to Bazel, the workspace now
261contains two packages, `//src/main/java/com/example/cmdline` and `//` (since
262there is a `BUILD` file at the root of the workspace).
dzc22b85a22017-05-31 20:37:50 +0200263
Googler8af9dc52017-06-07 13:49:48 -0400264Take a look at the `src/main/java/com/example/cmdline/BUILD` file:
dzc22b85a22017-05-31 20:37:50 +0200265
vladmos4e9208a2020-03-11 12:16:42 -0700266```python
Googler8af9dc52017-06-07 13:49:48 -0400267java_binary(
268 name = "runner",
269 srcs = ["Runner.java"],
270 main_class = "com.example.cmdline.Runner",
vladmos4e9208a2020-03-11 12:16:42 -0700271 deps = ["//:greeter"],
Googler8af9dc52017-06-07 13:49:48 -0400272)
273```
dzc22b85a22017-05-31 20:37:50 +0200274
Googler8af9dc52017-06-07 13:49:48 -0400275The `runner` target depends on the `greeter` target in the `//` package (hence
276the target label `//:greeter`) - Bazel knows this through the `deps` attribute.
277Take a look at the dependency graph:
dzc22b85a22017-05-31 20:37:50 +0200278
Googler8af9dc52017-06-07 13:49:48 -0400279![Dependency graph of the target 'runner'](/assets/tutorial_java_03.svg)
dzc22b85a22017-05-31 20:37:50 +0200280
Googlerec7ecd72021-03-19 16:20:52 -0700281However, for the build to succeed, you must explicitly give the `runner` target
282in `//src/main/java/com/example/cmdline/BUILD` visibility to targets in
Googler8af9dc52017-06-07 13:49:48 -0400283`//BUILD` using the `visibility` attribute. This is because by default targets
284are only visible to other targets in the same `BUILD` file. (Bazel uses target
285visibility to prevent issues such as libraries containing implementation details
286leaking into public APIs.)
dzc22b85a22017-05-31 20:37:50 +0200287
Googler8af9dc52017-06-07 13:49:48 -0400288To do this, add the `visibility` attribute to the `greeter` target in
289`java-tutorial/BUILD` as shown below:
dzc22b85a22017-05-31 20:37:50 +0200290
vladmos4e9208a2020-03-11 12:16:42 -0700291```python
Googler8af9dc52017-06-07 13:49:48 -0400292java_library(
293 name = "greeter",
294 srcs = ["src/main/java/com/example/Greeting.java"],
295 visibility = ["//src/main/java/com/example/cmdline:__pkg__"],
vladmos4e9208a2020-03-11 12:16:42 -0700296)
Googler8af9dc52017-06-07 13:49:48 -0400297```
dzc22b85a22017-05-31 20:37:50 +0200298
Googlerec7ecd72021-03-19 16:20:52 -0700299Now you can build the new package by running the following command at the root
300of the workspace:
dzc22b85a22017-05-31 20:37:50 +0200301
Googler8af9dc52017-06-07 13:49:48 -0400302```
303bazel build //src/main/java/com/example/cmdline:runner
304```
dzc22b85a22017-05-31 20:37:50 +0200305
Googler8af9dc52017-06-07 13:49:48 -0400306Bazel produces output similar to the following:
dzc22b85a22017-05-31 20:37:50 +0200307
Googler8af9dc52017-06-07 13:49:48 -0400308```
309INFO: Found 1 target...
310Target //src/main/java/com/example/cmdline:runner up-to-date:
311 bazel-bin/src/main/java/com/example/cmdline/runner.jar
312 bazel-bin/src/main/java/com/example/cmdline/runner
313 INFO: Elapsed time: 1.576s, Critical Path: 0.81s
314```
dzc22b85a22017-05-31 20:37:50 +0200315
Googler8af9dc52017-06-07 13:49:48 -0400316Now test your freshly built binary:
dzc22b85a22017-05-31 20:37:50 +0200317
Googler8af9dc52017-06-07 13:49:48 -0400318```
319./bazel-bin/src/main/java/com/example/cmdline/runner
Googler8af9dc52017-06-07 13:49:48 -0400320```
dzc22b85a22017-05-31 20:37:50 +0200321
Googler8af9dc52017-06-07 13:49:48 -0400322You've now modified the project to build as two packages, each containing one
323target, and understand the dependencies between them.
dzc22b85a22017-05-31 20:37:50 +0200324
dzc22b85a22017-05-31 20:37:50 +0200325
326## Use labels to reference targets
327
Googler8af9dc52017-06-07 13:49:48 -0400328In `BUILD` files and at the command line, Bazel uses target labels to reference
329targets - for example, `//:ProjectRunner` or
330`//src/main/java/com/example/cmdline:runner`. Their syntax is as follows:
dzc22b85a22017-05-31 20:37:50 +0200331
332```
Googler8af9dc52017-06-07 13:49:48 -0400333//path/to/package:target-name
dzc22b85a22017-05-31 20:37:50 +0200334```
335
Googler8af9dc52017-06-07 13:49:48 -0400336If the target is a rule target, then `path/to/package` is the path to the
337directory containing the `BUILD` file, and `target-name` is what you named the
338target in the `BUILD` file (the `name` attribute). If the target is a file
339target, then `path/to/package` is the path to the root of the package, and
340`target-name` is the name of the target file, including its full path.
dzc22b85a22017-05-31 20:37:50 +0200341
laurentlbd22331d2019-09-09 06:52:56 -0700342When referencing targets at the repository root, the package path is empty,
343just use `//:target-name`. When referencing targets within the same `BUILD`
Googler8af9dc52017-06-07 13:49:48 -0400344file, you can even skip the `//` workspace root identifier and just use
345`:target-name`.
dzc22b85a22017-05-31 20:37:50 +0200346
Googler8af9dc52017-06-07 13:49:48 -0400347For example, for targets in the `java-tutorial/BUILD` file, you did not have to
348specify a package path, since the workspace root is itself a package (`//`), and
349your two target labels were simply `//:ProjectRunner` and `//:greeter`.
dzc22b85a22017-05-31 20:37:50 +0200350
Googler8af9dc52017-06-07 13:49:48 -0400351However, for targets in the `//src/main/java/com/example/cmdline/BUILD` file you
352had to specify the full package path of `//src/main/java/com/example/cmdline`
353and your target label was `//src/main/java/com/example/cmdline:runner`.
dzc22b85a22017-05-31 20:37:50 +0200354
355## Package a Java target for deployment
356
Googler8af9dc52017-06-07 13:49:48 -0400357Let’s now package a Java target for deployment by building the binary with all
358of its runtime dependencies. This lets you run the binary outside of your
359development environment.
dzc22b85a22017-05-31 20:37:50 +0200360
dzc205125b2017-06-26 11:01:47 +0200361As you remember, the [java_binary](../be/java.html#java_binary) build rule
Googler8af9dc52017-06-07 13:49:48 -0400362produces a `.jar` and a wrapper shell script. Take a look at the contents of
363`runner.jar` using this command:
dzc22b85a22017-05-31 20:37:50 +0200364
Googler8af9dc52017-06-07 13:49:48 -0400365```
366jar tf bazel-bin/src/main/java/com/example/cmdline/runner.jar
367```
dzc22b85a22017-05-31 20:37:50 +0200368
Googler8af9dc52017-06-07 13:49:48 -0400369The contents are:
dzc22b85a22017-05-31 20:37:50 +0200370
Googler8af9dc52017-06-07 13:49:48 -0400371```
372META-INF/
373META-INF/MANIFEST.MF
374com/
375com/example/
376com/example/cmdline/
377com/example/cmdline/Runner.class
378```
379As you can see, `runner.jar` contains `Runner.class`, but not its dependency,
380`Greeting.class`. The `runner` script that Bazel generates adds `greeter.jar`
381to the classpath, so if you leave it like this, it will run locally, but it
382won't run standalone on another machine. Fortunately, the `java_binary` rule
wyv007cba02020-05-12 04:17:23 -0700383allows you to build a self-contained, deployable binary. To build it, append
384`_deploy.jar` to the target name:
dzc22b85a22017-05-31 20:37:50 +0200385
Googler8af9dc52017-06-07 13:49:48 -0400386```
387bazel build //src/main/java/com/example/cmdline:runner_deploy.jar
388```
dzc22b85a22017-05-31 20:37:50 +0200389
Googler8af9dc52017-06-07 13:49:48 -0400390Bazel produces output similar to the following:
dzc22b85a22017-05-31 20:37:50 +0200391
Googler8af9dc52017-06-07 13:49:48 -0400392```
393INFO: Found 1 target...
394Target //src/main/java/com/example/cmdline:runner_deploy.jar up-to-date:
395 bazel-bin/src/main/java/com/example/cmdline/runner_deploy.jar
396INFO: Elapsed time: 1.700s, Critical Path: 0.23s
397```
398You have just built `runner_deploy.jar`, which you can run standalone away from
399your development environment since it contains the required runtime
400dependencies.
dzc22b85a22017-05-31 20:37:50 +0200401
Googler8af9dc52017-06-07 13:49:48 -0400402## Further reading
dzc22b85a22017-05-31 20:37:50 +0200403
Googler22230e42020-12-02 15:18:28 -0800404For more details, see:
405
jingwenc541dd12019-09-16 22:12:21 -0700406* [rules_jvm_external](https://github.com/bazelbuild/rules_jvm_external) for
407 rules to manage transitive Maven dependencies.
408
dzc205125b2017-06-26 11:01:47 +0200409* [External Dependencies](../external.html) to learn more about working with
410 local and remote repositories.
dzc22b85a22017-05-31 20:37:50 +0200411
laurentlb374d1652019-09-13 13:11:22 -0700412* The [other rules](../rules.html) to learn more about Bazel.
dzc22b85a22017-05-31 20:37:50 +0200413
dzc205125b2017-06-26 11:01:47 +0200414* The [C++ build tutorial](../tutorial/cpp.md) to get started with building
Googler8af9dc52017-06-07 13:49:48 -0400415 C++ projects with Bazel.
dzc22b85a22017-05-31 20:37:50 +0200416
Laszlo Csomor5d357942018-06-12 01:56:45 -0700417* The [Android application tutorial](../tutorial/android-app.md) and
418 [iOS application tutorial](../tutorial/ios-app.md) to get started with
Googler8af9dc52017-06-07 13:49:48 -0400419 building mobile applications for Android and iOS with Bazel.
dzc22b85a22017-05-31 20:37:50 +0200420
Googler8af9dc52017-06-07 13:49:48 -0400421Happy building!
dzc22b85a22017-05-31 20:37:50 +0200422