aboutsummaryrefslogtreecommitdiffhomepage
path: root/site/docs/tutorial
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2017-06-07 13:49:48 -0400
committerGravatar John Cater <jcater@google.com>2017-06-08 10:52:28 -0400
commit8af9dc526050d84856ebd4624c37d8cbb4ec7847 (patch)
tree34b201ee321625528df8a2ffefe4aebc42c7020d /site/docs/tutorial
parente398b02227204f79caaa4c29861da93af1c1051e (diff)
Update the Java tutorial for flow, readability, and to use a GitHub-hosted companion project.
This depends on pull request #23 in bazelbuild/examples which uploads the required Java companion project. Staged at [] RELNOTES: None. PiperOrigin-RevId: 158287971
Diffstat (limited to 'site/docs/tutorial')
-rw-r--r--site/docs/tutorial/java.md747
1 files changed, 284 insertions, 463 deletions
diff --git a/site/docs/tutorial/java.md b/site/docs/tutorial/java.md
index a916aeb5be..4a80d472a0 100644
--- a/site/docs/tutorial/java.md
+++ b/site/docs/tutorial/java.md
@@ -1,576 +1,397 @@
---
layout: documentation
-title: Introduction to Bazel
+title: Build Tutorial - Java
---
-Introduction to Bazel: Build Java
+Introduction to Bazel: Build a Java Project
==========
-This tutorial is an introduction for anyone getting started with Bazel. It
-focuses on the concepts, setup, and use of Bazel using a Java sample project.
+In this tutorial, you'll learn the basics of building Java applications with
+Bazel. You will set up your workspace and build a simple Java project that
+illustrates key Bazel concepts, such as targets and `BUILD` files.
-Estimated time: 30 min
+Estimated completion time: 30 minutes.
-## What you will learn
+## What you'll learn
In this tutorial you'll learn how to:
-* Build a target from source files
-* Produce a visual representation of the dependency graph
-* Break a monolithic binary into smaller libraries
-* Use multiple Bazel packages
-* Control the visibility of a target between packages
-* Use labels to reference a target
-* Deploy your target
+* Build a target
+* Visualize the project's dependencies
+* Split the project into multiple targets and packages
+* Control target visibility across packages
+* Reference targets through labels
+* Deploy a target
## Before you begin
-* [Install Bazel](/docs/install.md)
+To prepare for the tutorial, first [Install Bazel](/docs/install.md) if
+you don't have it installed already. Then, retrieve the sample project from
+Bazel's GitHub repository:
-## Create the sample Java project
-
-The first step in this tutorial is to create a small Java project. Even though
-the project is in Java, this tutorial will focus on concepts that are helpful
-for using Bazel in any language.
-
-1. Create the directory `~/my-project/`
-
-2. Move to this directory:
-
- ```
- cd ~/my-project
- ```
-
-3. Create the following directories under `my-project`:
-
- ```
- mkdir -p src/main/java/com/example
- ```
-
- Note that path uses conventions specific to Java programs. Programs written
- in other languages may have a different workspace path and directory
- structure.
-
-4. In the directory you created, add a file called `Greeting.java` with the
- following contents:
-
- ```java
- package com.example;
-
- public class Greeting {
- public static void sayHi() {
- System.out.println("Hi!");
- }
- }
- ```
-
-5. Add a second file `ProjectRunner.java` with the following contents:
-
- ```java
- package com.example;
-
- public class ProjectRunner {
- public static void main(String args[]) {
- Greeting.sayHi();
- }
- }
- ```
+```
+git clone https://github.com/bazelbuild/examples/
+```
-You’ve now created a small Java project. It contains one file that will be
-compiled into a library, and another which will be an executable that uses the
-library.
+The sample project for this tutorial is in the `examples/java-tutorial`
+directory and is structured as follows:
-The rest of this tutorial focuses on setting up and using Bazel to build these
-source files.
+```
+java-tutorial
+│
+├── BUILD
+├── src
+│ └── main
+│ └── java
+│ └── com
+│ └── example
+│ ├── cmdline
+│ │ ├── BUILD
+│ │ └── Runner.java
+│ ├── Greeting.java
+│ └── ProjectRunner.java
+└── WORKSPACE
+```
## Build with Bazel
### Set up the workspace
-Workspaces are directories that contain the source files for one or more
-software projects, as well as a WORKSPACE file and BUILD files that contain
-the instructions that Bazel uses to build the software. The workspace may also
-contain symbolic links to output directories.
-
-To define the workspace, create an empty text file at the root of the project
-and name it `WORKSPACE`. You now have: `~/my-project/WORKSPACE`.
-
-This directory and its subdirectories are now part of the same workspace. When
-Bazel builds an output, all inputs and dependencies must be in the same
-workspace. Anything in different workspaces are independent of each other,
-though there are ways to link workspaces that are beyond the scope of this
-introduction tutorial.
-
-If you also do the [C++ tutorial](/docs/tutorial/cpp.md), you’ll notice it uses
-the same workspace. Bazel can understand multiple targets in multiple languages
-in a single workspace.
-
-### Create a BUILD file
-
-Bazel looks for files named `BUILD` which describe how to build the project.
-
-1. In the `~/my-project` directory, create a file and name it BUILD. This BUILD
- file is a sibling of the WORKSPACE file.
-
- In the BUILD file, you use a declarative language similar to Python to
- create instances of Bazel rules. These instances are called *rule targets*.
- In Bazel, *targets* are either files or rule targets and they are the
- elements in a workspace that you can ask Bazel to build.
-
- For this project, you’ll use the built-in rule `java_binary`. Bazel's
- built-in rules are all documented in the
- [Build Encyclopedia](/docs/be/overview.html). You can also create your own
- rules using the [Bazel rule extension framework](/docs/skylark/concepts.md).
+Before you can build a project, you need to set up its workspace. A workspace is
+a directory that holds your project's source files and Bazel's build outputs. It
+also contains files that Bazel recognizes as special:
-2. Add this text to the BUILD file:
+* The `WORKSPACE` file, which identifies the directory and its contents as a
+ Bazel workspace and lives at the root of the project's directory structure,
- ```
- java_binary(
- name = "my-runner",
- srcs = glob(["src/main/java/com/example/*.java"]),
- main_class = "com.example.ProjectRunner",
- )
- ```
-As you can see, the text in the BUILD file doesn’t describe what Bazel does
-when it executes this rule target. The rule’s implementation handles the
-complexity of how it works (such as the compiler used).
-
-You can treat the rule as a black box, focusing on what inputs it needs, and
-the outputs it produces. This rule builds a Java archive ("jar file") as well
-as a wrapper shell script with the same name as the rule target.
-
-When you’re writing your own BUILD file, go to the
-[Build Encyclopedia](/docs/be/overview.html) for a description of what a rule
-does and for its list of possible attributes you can define. For example,
-here’s the entry for the [java_binary](/docs/be/java.html#java_binary) rule in
-the Build Encyclopedia. The Build Encyclopedia has information about all of the
-rules that are compiled into Bazel.
-
-Let’s take a look at the rule target that you added to the BUILD file.
+* One or more `BUILD` files, which tell Bazel how to build different parts of
+ the project. (A directory within the workspace that contains a `BUILD` file
+ is a *package*. You will learn about packages later in this tutorial.)
-Each rule instantiation in the BUILD file creates one rule target. Here, you’ve
-instantiated the rule `java_binary`, creating the target `my-runner`.
+To designate a directory as a Bazel workspace, create an empty file named
+`WORKSPACE` in that directory.
-Different rules will require different attributes, though all must include a
-“name” attribute. You use these attributes to explicitly list all of the
-target’s dependencies and options. In the target above:
+When Bazel builds the project, all inputs and dependencies must be in the same
+workspace. Files residing in different workspaces are independent of one
+another unless linked, which is beyond the scope of this tutorial.
-* `my-runner` is the name of the rule target created
+### Understand the BUILD file
-* `glob(["src/main/java/com/example/*.java"])` includes every file in that
- directory that ends with .java (see the Build Encyclopedia for more
- information about [globbing](/docs/be/functions.html#glob))
+A `BUILD` file contains several different types of instructions for Bazel.
+The most important type is the *build rule*, which tells Bazel how to build the
+desired outputs, such as executable binaries or libraries. Each instance
+of a build rule in the `BUILD` file is called a *target* and points to a
+specific set of source files and dependencies. A target can also point to other
+targets.
-* `"com.example.ProjectRunner"` specifies the class that contains the main
- method.
+Take a look at the `java-tutorial/BUILD` file:
-### Build with Bazel
-
-Now you’re ready to build the Java binary. To do so, you’ll use the command
-`bazel build` with the target label `//:my-runner`. You reference targets by
-using their label. Label syntax is described later in this tutorial.
+```
+java_binary(
+ name = "ProjectRunner",
+ srcs = glob(["src/main/java/com/example/*.java"]),
+)
+```
-1. Build my-runner by using this command:
+In our example, the `ProjectRunner` target instantiates Bazel's built-in
+[`java_binary` rule](/docs/be/java.html#java_binary). The rule tells Bazel to
+build a `.jar` file and a wrapper shell script (both named after the target).
- ```
- bazel build //:my-runner
- ```
+The attributes in the target explicitly state its dependencies and options.
+While the `name` attribute is mandatory, many are optional. For example, in the
+`ProjectRunner` rule target, `name` is the name of the target, `srcs` specifies
+the source files that Bazel uses to build the target, and `main_class` specifies
+the class that contains the main method. (You may have noticed that our example
+uses [glob](/docs/be/functions.html#glob) to pass a set of source files to Bazel
+instead of listing them one by one.)
- You’ll see output similar to:
+### Build the project
- ```
- INFO: Found 1 target...
- Target //:my-runner up-to-date:
- bazel-bin/my-runner.jar
- bazel-bin/my-runner
- INFO: Elapsed time: 1.021s, Critical Path: 0.83s
- ```
+Let's build your sample project. Change into the `java-tutorial` directory
+and run the following command:
-2. Now execute the file by using this command:
+```
+bazel build //:ProjectRunner
+```
+Notice the target label - the `//` part is the location of our `BUILD` file
+relative to the root of the workspace (in this case, the root itself), and
+`ProjectRunner` is what we named that target in the `BUILD` file. (You will
+learn about target labels in more detail at the end of this tutorial.)
+
+Bazel produces output similar to the following:
+
+```bash
+ INFO: Found 1 target...
+ Target //:ProjectRunner up-to-date:
+ bazel-bin/ProjectRunner.jar
+ bazel-bin/ProjectRunner
+ INFO: Elapsed time: 1.021s, Critical Path: 0.83s
+```
- ```
- bazel-bin/my-runner
- ```
+Congratulations, you just built your first Bazel target! Bazel places build
+outputs in the `bazel-bin` directory at the root of the workspace. Browse
+through its contents to get an idea for Bazel's output structure.
-Congratulations, you've built your first Bazel target!
+Now test your freshly built binary:
-Let’s take a look at what you built. In `~/my-project`, Bazel created the
-directory `bazel-bin` as well as other directories to store information about
-the build. Open this directory to look at the files created during the build
-process. These output directories keep the outputs separate from your source
-tree.
+```shell
+bazel-bin/ProjectRunner
+```
### Review the dependency graph
-Bazel requires build dependencies to be explicitly declared in BUILD
-files. The build will fail if dependencies are missing, so when a build works
-the declared dependencies are accurate. With this explicit information about
-dependencies, Bazel creates a build graph and uses it to accurately perform
-incremental builds. Our small Java project isn’t too exciting, but let’s check
-out its build graph.
+Bazel requires build dependencies to be explicitly declared in BUILD files.
+Bazel uses those statements to create the project's dependency graph, which
+enables accurate incremental builds.
-The command `bazel query` retrieves information about the graph and the
-relationships between targets. Let’s use it to produce a visual representation
-of the build graph.
+Let's visualize our sample project's dependencies. First, generate a text
+representation of the dependency graph (run the command at the workspace root):
-1. From the root of the workspace (`my-project`), produce a text description
- of the graph by using the command:
+```
+bazel query --nohost_deps --noimplicit_deps 'deps(//:ProjectRunner)' \
+ --output graph
+```
- ```
- bazel query --noimplicit_deps 'deps(//:my-runner)' --output graph
- ```
+The above command tells Bazel to look for all dependencies for the target
+`//:ProjectRunner` (excluding host and implicit dependencies) and format the
+output as a graph.
-2. Then, paste the output into Graphviz
- ([http://www.webgraphviz.com/](http://www.webgraphviz.com/)) to see the
- visual representation.
+Then, paste the text into [GraphViz](http://www.webgraphviz.com/).
- The graph for the target my-runner will look like this:
- ![Dependency graph of the target 'my-runner'](/assets/tutorial_java_01.svg)
+As you can see, the project has a single target that build two source files with
+no additional dependencies:
-You can see that `my-runner` depends on the two source files in your Java
-project.
+![Dependency graph of the target 'ProjectRunner'](/assets/tutorial_java_01.svg)
-You have now set up the workspace and BUILD file, and used Bazel to build your
-project. You have also created a visual representation of the build graph to
-see the structure of your build.
+Now that you have set up your workspace, built your project, and examined its
+dependencies, let's add some complexity.
## Refine your Bazel build
-### Add dependencies
+While a single target is sufficient for small projects, you may want to split
+larger projects into multiple targets and packages to allow for fast incremental
+builds (that is, only rebuild what's changed) and to speed up your builds by
+building multiple parts of a project at once.
-Creating one rule target to build your entire project may be sufficient for
-small projects. As projects get larger it's important to break up the build
-into self-contained libraries that can be assembled into a final product.
-Self-contained libraries mean that everything doesn't need to be rebuilt after
-small changes and that Bazel can parallelize more of the build steps. These
-self-contained libraries also encourages good code hygiene.
+### Specify multiple build targets
-To break up a project, create a separate rule target for the each subcomponent
-and then add the subcomponents as dependencies. For the project in this
-tutorial, create a rule target to compile the library, and make the executable
-depend on it.
+Let's split our sample project build into two targets. Replace the contents of
+the `java-tutorial/BUILD` file with the following:
-1. Replace the text in the BUILD file with the text below:
-
- ```
- java_binary(
- name = "my-runner",
- srcs = ["src/main/java/com/example/ProjectRunner.java"],
- main_class = "com.example.ProjectRunner",
- deps = [":greeter"],
- )
-
- java_library(
- name = "greeter",
- srcs = ["src/main/java/com/example/Greeting.java"],
- )
- ```
-
-The new `deps` attribute in `java_binary` tells Bazel that the `greeter` library
-will be needed to compile the binary. Rules for many languages support the
-`deps` attribute, though the exact semantics of the attribute will vary based
-on the language and the type of target. The rule
-[java_library](/docs/be/java.html#java_library) compiles sources into
-a .jar file. Remember to go to the [Build Encyclopedia](/docs/be/overview.html)
-for details about specific rules.
-
-This BUILD file builds the same files as before, but in a different way: now
-Bazel will first build the `greeter` library and then build `my-runner`.
-
-2. Try building //:my-runner using the command:
+```
+java_binary(
+ name = "ProjectRunner",
+ srcs = ["src/main/java/com/example/ProjectRunner.java"],
+ main_class = "com.example.ProjectRunner",
+ deps = [":greeter"],
+)
+
+java_library(
+ name = "greeter",
+ srcs = ["src/main/java/com/example/Greeting.java"],
+)
+```
- ```
- bazel build //:my-runner
- ```
+With this configuration, Bazel first builds the `greeter` library, then the
+`ProjectRunner` library. The `deps` attribute in `java_binary` tells Bazel that
+the `greeter` library is required to build the `ProjectRunner` binary.
- You’ll see output similar to:
+Let's build this new version of our project. Run the following command:
- ```
- INFO: Found 1 target...
- Target //:my-runner up-to-date:
- bazel-bin/my-runner.jar
- bazel-bin/my-runner
- INFO: Elapsed time: 2.454s, Critical Path: 1.58s
- ```
+```
+bazel build //:ProjectRunner
+```
- 3. Execute the file by using this command::
+Bazel produces output similar to the following:
- ```
- bazel-bin/my-runner
- ```
+```
+INFO: Found 1 target...
+Target //:ProjectRunner up-to-date:
+ bazel-bin/ProjectRunner.jar
+ bazel-bin/ProjectRunner
+INFO: Elapsed time: 2.454s, Critical Path: 1.58s
+```
-If you now edit `ProjectRunner.java` and rebuild `my-runner`, the source file
-`Greeting.java` will not be recompiled. When the BUILD file had only the one
-target, both source files would be recompiled after any change.
+Now test your freshly built binary:
-Looking at the dependency graph, you can see that `my-runner` depends on the
-same inputs as it did before, but the structure of the build is different.
+```
+bazel-bin/ProjectRunner
+```
-The original dependency graph for `my-runner` looked link this:
+If you now modify `ProjectRunner.java` and rebuild the project, Bazel only
+recompiles that file.
-![Original dependency graph of the target 'my-runner'](/assets/tutorial_java_01.svg)
+Looking at the dependency graph, you can see that `ProjectRunner` depends on the
+same inputs as it did before, but the structure of the build is different:
-The dependency graph for `my-runner` after adding a dependency looks like this:
+![Dependency graph of the target 'ProjectRunner' after adding a dependency]
+(/assets/tutorial_java_02.svg)
-![Dependency graph of the target 'my-runner' after adding a dependency](/assets/tutorial_java_02.svg)
+You've now built the project with two targets. The `ProjectRunner` target builds
+two source files and depends on one other target (`:greeter`), which builds
+one additional source file.
### Use multiple packages
-For larger projects, you will often be dealing with several directories in your
-workspace. You can organize your build process by adding a BUILD file to the
-top directory of source files that you want to organize together. A directory
-containing a BUILD file is called a package.
-
-Note that Bazel and Java both have the concept of a package. These are
-unrelated to each other, though both are related to the structure of the
-directories.
-
-Let’s build the java project using multiple packages.
-
-1. First, let’s make the Java project a bit more complex.
-
- 1. Add the following directory and file:
-
- ```
- mkdir -p src/main/java/com/example/cmdline
- ```
- 2. In the directory cmdline, add the file Runner.java with the following
- contents:
-
- ```java
- package com.example.cmdline;
-
- import com.example.Greeting;
-
- public class Runner {
- public static void main(String args[]) {
- Greeting.sayHi();
- }
- }
- ```
-
- Now you have a slightly larger Java project that you can organize with
- multiple packages.
-
-2. In the directory `src/main/java/com/example/cmdline`, add an empty text
- file and name it BUILD. The structure of the Java project is now:
+Let’s now split the project into multiple packages. If you take a look at the
+`src/main/java/com/example/cmdline` directory, you can see that it also contains
+a `BUILD` file, plus some source files. Therefore, to Bazel, the workspace now
+contains two packages, `//src/main/java/com/example/cmdline` and `//` (since
+there is a `BUILD` file at the root of the workspace).
- ```
- ├── BUILD
- ├── src
- │ └── main
- │ └── java
- │ └── com
- │ └── example
- │ ├── cmdline
- │ │ ├── BUILD
- │ │ └── Runner.java
- │ ├── Greeting.java
- │ └── ProjectRunner.java
- └── WORKSPACE
- ```
+Take a look at the `src/main/java/com/example/cmdline/BUILD` file:
- Each directory in the workspace can be part of only one package. The
- workspace now has two BUILD files, and so has two packages:
-
- 1. The directory `my-project` and its subdirectories (but not including
- subdirectories with their own BUILD file, such as `cmdline`), and
-
- 2. The directory `cmdline` and any subdirectories.
-
-3. In the new BUILD file, add the following text:
-
- ```
- java_binary(
- name = "runner",
- srcs = ["Runner.java"],
- main_class = "com.example.cmdline.Runner",
- deps = ["//:greeter"]
- )
- ```
-
- The file `Runner.java` depends on `com.example.Greeting`. In the BUILD file
- this dependency is shown by listing the rule target `greeter` (with the
- label `//:greeter`).
-
- Below is what the dependency graph for runner will look like. You can see
- how `//:greeter` gives the dependency on `Greeting.java`.
-
- ![Dependency graph of the target 'runner'](/assets/tutorial_java_03.svg)
-
-
-4. However, if you try to build runner right now you'll get a permissions
- error. You can see the permission error by trying to build the target using
- the command:
+```
+java_binary(
+ name = "runner",
+ srcs = ["Runner.java"],
+ main_class = "com.example.cmdline.Runner",
+ deps = ["//:greeter"]
+)
+```
- ```
- bazel build //src/main/java/com/example/cmdline:runner
- ```
+The `runner` target depends on the `greeter` target in the `//` package (hence
+the target label `//:greeter`) - Bazel knows this through the `deps` attribute.
+Take a look at the dependency graph:
- By default, rule targets are private, which means that they can only be
- depended on by targets in the same BUILD file. This privacy prevents
- libraries that are implementation details from leaking into public APIs,
- but it also means that you must explicitly allow `runner` to depend on
- `//:greeter`.
+![Dependency graph of the target 'runner'](/assets/tutorial_java_03.svg)
+However, for the build to succeed, you must make the `runner` target in
+`//src/main/java/com/example/cmdline/BUILD` explicitly visible to targets in
+`//BUILD` using the `visibility` attribute. This is because by default targets
+are only visible to other targets in the same `BUILD` file. (Bazel uses target
+visibility to prevent issues such as libraries containing implementation details
+leaking into public APIs.)
-5. Make a rule target visible to rule targets in other BUILD files by adding
- a `visibility` attribute. To make the `greeter` rule target in
- `~/my-project/BUILD` visible to any rule target in the new package, add the
- following visibility attribute:
+To do this, add the `visibility` attribute to the `greeter` target in
+`java-tutorial/BUILD` as shown below:
- ```
- java_library(
- name = "greeter",
- srcs = ["src/main/java/com/example/Greeting.java"],
- visibility = ["//src/main/java/com/example/cmdline:__pkg__"],
+```
+java_library(
+ name = "greeter",
+ srcs = ["src/main/java/com/example/Greeting.java"],
+ visibility = ["//src/main/java/com/example/cmdline:__pkg__"],
)
- ```
-
- The target `//:greeter` is now visible to any target in the
- `//src/main/java/com/example/cmdline` package.
-
- See the Build Encyclopedia for more
- [visibility options](/docs/be/common-definitions.html#common.visibility).
+```
+Let's now build the new package. Run the following command at the root of the
+workspace:
-6. Now you can build the runner binary by using the command:
+```
+bazel build //src/main/java/com/example/cmdline:runner
+```
- ```
- bazel build //src/main/java/com/example/cmdline:runner
- ```
+Bazel produces output similar to the following:
- You’ll see output similar to:
+```
+INFO: Found 1 target...
+Target //src/main/java/com/example/cmdline:runner up-to-date:
+ bazel-bin/src/main/java/com/example/cmdline/runner.jar
+ bazel-bin/src/main/java/com/example/cmdline/runner
+ INFO: Elapsed time: 1.576s, Critical Path: 0.81s
+```
- ```
- INFO: Found 1 target...
- Target //src/main/java/com/example/cmdline:runner up-to-date:
- bazel-bin/src/main/java/com/example/cmdline/runner.jar
- bazel-bin/src/main/java/com/example/cmdline/runner
- INFO: Elapsed time: 1.576s, Critical Path: 0.81s
- ```
+Now test your freshly built binary:
+```
+./bazel-bin/src/main/java/com/example/cmdline/runner
-7. Execute the file by using this command:
+```
- ```
- bazel-bin/src/main/java/com/example/cmdline/runner
- ```
+You've now modified the project to build as two packages, each containing one
+target, and understand the dependencies between them.
-You’ve now refined your build so that it is broken down into smaller
-self-contained libraries, and so that the explicit dependencies are more
-granular. You’ve also built the Java project using multiple packages.
## Use labels to reference targets
-In the BUILD files and in the command line, you have been using target labels
-to reference targets. The label’s syntax is: `//path/to/package:target-name`,
-where “`//`” is the workspace’s root, and “`:`” separates the package name and
-the target name. If the target is a rule target and so defined in a BUILD file,
-“`path/to/package`” would be the path of the BUILD file itself. “`Target-name`”
-would be the same as the “`name`” attribute in the target in the BUILD file.
-
-The first BUILD file you created in this tutorial is in the same directory as
-the WORKSPACE file. When referencing rule targets defined in that file, nothing
-is needed for the path to the package because the workspace root and the package
-root are the same directory. Here are the labels of the two targets defined
-in that first BUILD file:
+In `BUILD` files and at the command line, Bazel uses target labels to reference
+targets - for example, `//:ProjectRunner` or
+`//src/main/java/com/example/cmdline:runner`. Their syntax is as follows:
```
-//:my-runner
-//:greeter
+//path/to/package:target-name
```
-The second BUILD file has a longer path from the workspace root to the package
-root. The label for the target in that BUILD file is:
+If the target is a rule target, then `path/to/package` is the path to the
+directory containing the `BUILD` file, and `target-name` is what you named the
+target in the `BUILD` file (the `name` attribute). If the target is a file
+target, then `path/to/package` is the path to the root of the package, and
+`target-name` is the name of the target file, including its full path.
-```
-//src/main/java/com/example/cmdline:runner
-```
+When referencing targets within the same package, you can skip the package path
+and just use `//:target-name`. When referencing targets within the same `BUILD`
+file, you can even skip the `//` workspace root identifier and just use
+`:target-name`.
-Target labels can be shortened in a variety of ways. Within a BUILD file, if
-you’re referencing a target from the same package, you can write the label
-starting at “`:`”. For example, the rule target `greeter` can always be written
-as `//:greeter`, and in the BUILD file where it’s defined, it can also be
-written as `:greeter`. This shortened label in a BUILD file makes it immediately
-clear which targets are in the current package.
+For example, for targets in the `java-tutorial/BUILD` file, you did not have to
+specify a package path, since the workspace root is itself a package (`//`), and
+your two target labels were simply `//:ProjectRunner` and `//:greeter`.
-A rule target’s name will always be defined by its name attribute. A target’s
-name is a bit more complex when it’s in a directory other than the root
-of the package. In that case, the target’s label is:
-`//path/to/package:path/to/file/file_name`.
+However, for targets in the `//src/main/java/com/example/cmdline/BUILD` file you
+had to specify the full package path of `//src/main/java/com/example/cmdline`
+and your target label was `//src/main/java/com/example/cmdline:runner`.
## Package a Java target for deployment
-To understand what you’ve built and what else can be built with Bazel, you need
-to understand the capabilities of the rules used in your BUILD files. Always go
-to the [Build Encyclopedia](/docs/be/overview.html) for this information.
+Let’s now package a Java target for deployment by building the binary with all
+of its runtime dependencies. This lets you run the binary outside of your
+development environment.
-Let’s look at packaging a Java target for deployment, which requires you to
-know the capabilities of the rule `java_binary`.
+As you remember, the [java_binary](/docs/be/java.html#java_binary) build rule
+produces a `.jar` and a wrapper shell script. Take a look at the contents of
+`runner.jar` using this command:
-You’re able to run the Java binaries you created in this tutorial, but you
-can’t simply run it on a server, because it relies on the greeting library jar
-to actually run. "Packaging an artifact so it can be run reliably outside the
-development environment involves bundling it with all of its runtime
-dependencies. Let's see now what’s needed to package the binaries.
-
-The rule [java_binary](/docs/be/java.html#java_binary) produces a Java archive
-(“jar file”) and a wrapper shell script. The file `<target-name>_deploy.jar`
-is suitable for deployment, but it’s only built by this rule if explicitly
-requested. Let’s investigate.
-
-1. Look at the contents of the output `runner.jar` by using this command:
-
- ```
- jar tf bazel-bin/src/main/java/com/example/cmdline/runner.jar
- ```
-
- You’ll see output similar to:
+```
+jar tf bazel-bin/src/main/java/com/example/cmdline/runner.jar
+```
- ```
- META-INF/
- META-INF/MANIFEST.MF
- com/
- com/example/
- com/example/cmdline/
- com/example/cmdline/Runner.class
- ```
+The contents are:
- You can see that `runner.jar` contains `Runner.class`, but not its
- dependency `Greeting.class`. The `runner` script that Bazel generates adds
- the greeter jar to the classpath, so running this program works locally. It
- will not work if you want to copy `runner.jar` to another machine and use
- it as a standalone binary.
+```
+META-INF/
+META-INF/MANIFEST.MF
+com/
+com/example/
+com/example/cmdline/
+com/example/cmdline/Runner.class
+```
+As you can see, `runner.jar` contains `Runner.class`, but not its dependency,
+`Greeting.class`. The `runner` script that Bazel generates adds `greeter.jar`
+to the classpath, so if you leave it like this, it will run locally, but it
+won't run standalone on another machine. Fortunately, the `java_binary` rule
+allows you to build a self-contained, deployable binary. To build it, add the
+`_deploy.jar` suffix to the file name when building `runner.jar`
+(<target-name>_deploy.jar):
+```
+bazel build //src/main/java/com/example/cmdline:runner_deploy.jar
+```
-2. The rule `java_binary` allows you to build a self-contained binary that can
- be deployed. To create this binary, build `runner_deploy.jar` (or, more
- generally, `<target-name>_deploy.jar`) by using this command:
+Bazel produces output similar to the following:
- ```
- bazel build //src/main/java/com/example/cmdline:runner_deploy.jar
- ```
+```
+INFO: Found 1 target...
+Target //src/main/java/com/example/cmdline:runner_deploy.jar up-to-date:
+ bazel-bin/src/main/java/com/example/cmdline/runner_deploy.jar
+INFO: Elapsed time: 1.700s, Critical Path: 0.23s
+```
+You have just built `runner_deploy.jar`, which you can run standalone away from
+your development environment since it contains the required runtime
+dependencies.
- You’ll see output similar to:
+## Further reading
- ```
- INFO: Found 1 target...
- Target //src/main/java/com/example/cmdline:runner_deploy.jar up-to-date:
- bazel-bin/src/main/java/com/example/cmdline/runner_deploy.jar
- INFO: Elapsed time: 1.700s, Critical Path: 0.23s
- ```
+* [External Dependencies](https://bazel.build/versions/master/docs/external.html)
+ to learn more about working with local and remote repositories.
- The file runner_deploy.jar will contain all of its dependencies, and so can
- be used as a standalone binary.
+* The [Build Encyclopedia](/docs/be/overview.html) to learn more about Bazel.
-You’ve now created a Java target that you can distribute and deploy. To do so,
-you had to be aware of what outputs the Bazel Java rule `java_binary` is able to
-produce.
+* The [C++ build tutorial](/docs/tutorial/cpp.md) to get started with building
+ C++ projects with Bazel.
-## Further topics
+* The [mobile application tutorial](/docs/tutorial/app.md) to get started with
+ building mobile applications for Android and iOS with Bazel.
-* Try the tutorial [Build C++](/docs/tutorial/cpp.md).
-* Try the tutorial [Build Mobile Application](/docs/tutorial/app.md).
+Happy building!