aboutsummaryrefslogtreecommitdiffhomepage
path: root/site/versions/master/docs/tutorial/java.md
diff options
context:
space:
mode:
Diffstat (limited to 'site/versions/master/docs/tutorial/java.md')
-rw-r--r--site/versions/master/docs/tutorial/java.md245
1 files changed, 245 insertions, 0 deletions
diff --git a/site/versions/master/docs/tutorial/java.md b/site/versions/master/docs/tutorial/java.md
new file mode 100644
index 0000000000..ce916667e1
--- /dev/null
+++ b/site/versions/master/docs/tutorial/java.md
@@ -0,0 +1,245 @@
+---
+layout: documentation
+title: Build Java
+---
+
+Build Java
+==========
+
+You can use Bazel to build your Java application. In this tutorial you'll learn how to:
+
+* Build your first Java target
+* Add dependencies to your target
+* Use multiple packages
+* Deploy your target
+
+## Setting up your workspace
+
+Suppose that you have an existing project in a directory, say,
+`~/gitroot/my-project/`. Create an empty file at
+`~/gitroot/my-project/WORKSPACE` to show Bazel where your project's root is.
+
+## Creating Your Own Build File
+
+Use the following commands to make a small Java project for this example:
+
+{% highlight bash %}
+$ # If you're not already there, move to your workspace directory.
+$ cd ~/gitroot/my-project
+$ mkdir -p src/main/java/com/example
+$ cat > src/main/java/com/example/ProjectRunner.java <<'EOF'
+package com.example;
+
+public class ProjectRunner {
+ public static void main(String args[]) {
+ Greeting.sayHi();
+ }
+}
+EOF
+$ cat > src/main/java/com/example/Greeting.java <<'EOF'
+package com.example;
+
+public class Greeting {
+ public static void sayHi() {
+ System.out.println("Hi!");
+ }
+}
+EOF
+{% endhighlight %}
+
+Bazel figures out what to build by looking for files named `BUILD` in your
+workspace, so we'll create a `BUILD` file in the `~/gitroot/my-project`
+directory. Add the following lines to this BUILD file:
+
+{% highlight python %}
+# ~/gitroot/my-project/BUILD
+java_binary(
+ name = "my-runner",
+ srcs = glob(["**/*.java"]),
+ main_class = "com.example.ProjectRunner",
+)
+{% endhighlight %}
+
+`java_binary` is the type of thing this rule will build.
+`glob(["**/*.java"])` is a handy shorthand for "recursively include every file
+that ends with .java" (see the
+[build encyclopedia](be/functions.html#glob) for more information about
+globbing). `com.example.ProjectRunner` specifies the class that contains the
+main method.
+
+Now you are ready to build your Java binary:
+
+{% highlight bash %}
+$ cd ~/gitroot/my-project
+$ bazel build //:my-runner
+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
+$ bazel-bin/my-runner
+Hi!
+{% endhighlight %}
+
+Congratulations, you've just built your first Bazel target!
+
+## Adding Dependencies
+
+Creating one rule to build your entire project may be sufficient for small
+projects, but as projects get larger it's important to break up the build into
+self-contained libraries that can be assembled into a final product. This way
+the entire world doesn't need to be rebuilt on small changes and Bazel can
+parallelize more of the build steps.
+
+To break up a project, create separate rules for each subcomponent and then
+make them depend on each other. For the example above, add the following rules
+to the `BUILD` file:
+
+{% highlight python %}
+java_binary(
+ name = "my-other-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"],
+)
+{% endhighlight %}
+
+This builds the same files as before, but in a different way: now Bazel will
+build the `greeter` library first and then build `my-other-runner`. Try building
+and running `//:my-other-runner`:
+
+{% highlight bash %}
+$ bazel run //:my-other-runner
+INFO: Found 1 target...
+Target //:my-other-runner up-to-date:
+ bazel-bin/my-other-runner.jar
+ bazel-bin/my-other-runner
+INFO: Elapsed time: 2.454s, Critical Path: 1.58s
+
+INFO: Running command line: bazel-bin/my-other-runner
+Hi!
+{% endhighlight %}
+
+Now if you edit `ProjectRunner.java` and rebuild `my-other-runner`,
+`Greeting.java` will not need to be recompiled.
+
+## Using Multiple Packages
+
+For larger projects, you will often be dealing with several directories. You
+can refer to targets defined in other BUILD files using the syntax
+`//path/to/directory:target-name`. For example, suppose
+`src/main/java/com/example/` has a `cmdline/` subdirectory with the following
+file:
+
+{% highlight bash %}
+$ mkdir -p src/main/java/com/example/cmdline
+$ cat > src/main/java/com/example/cmdline/Runner.java <<'EOF'
+package com.example.cmdline;
+
+import com.example.Greeting;
+
+public class Runner {
+ public static void main(String args[]) {
+ Greeting.sayHi();
+ }
+}
+EOF
+{% endhighlight %}
+
+`Runner.java` depends on `com.example.Greeting`, so we could add a `BUILD` file
+at `src/main/java/com/example/cmdline/BUILD` that contained the following rule:
+
+{% highlight python %}
+# ~/gitroot/my-project/src/main/java/com/example/cmdline/BUILD
+java_binary(
+ name = "runner",
+ srcs = ["Runner.java"],
+ main_class = "com.example.cmdline.Runner",
+ deps = ["//:greeter"]
+)
+{% endhighlight %}
+
+However, by default, build rules are _private_. This means that they can only be
+referred to by rules in the same BUILD file. This 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`. As is, if we
+build `runner` we'll get a permissions error:
+
+{% highlight bash %}
+$ bazel build //src/main/java/com/example/cmdline:runner
+ERROR: /home/user/gitroot/my-project/src/main/java/com/example/cmdline/BUILD:2:1:
+ Target '//:greeter' is not visible from target '//src/main/java/com/example/cmdline:runner'.
+ Check the visibility declaration of the former target if you think the dependency is legitimate.
+ERROR: Analysis of target '//src/main/java/com/example/cmdline:runner' failed; build aborted.
+INFO: Elapsed time: 0.091s
+{% endhighlight %}
+
+You can make a rule visible to rules in other BUILD files by adding a
+`visibility = level` attribute. Change the `greeter` rule in
+`~/gitroot/my-project/BUILD` to be visible to our new rule:
+
+{% highlight python %}
+java_library(
+ name = "greeter",
+ srcs = ["src/main/java/com/example/Greeting.java"],
+ visibility = ["//src/main/java/com/example/cmdline:__pkg__"],
+)
+{% endhighlight %}
+
+This makes `//:greeter` visible to any rule in the
+`//src/main/java/com/example/cmdline` package. Now we can build and
+run the `runner` binary:
+
+{% highlight bash %}
+$ bazel run //src/main/java/com/example/cmdline:runner
+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: Running command line: bazel-bin/src/main/java/com/example/cmdline/runner
+Hi!
+{% endhighlight %}
+
+See the [build encyclopedia](be/common-definitions.html#common.visibility) for more
+visibility options.
+
+## Deploying
+
+If you look at the contents of
+_bazel-bin/src/main/java/com/example/cmdline/runner.jar_, you can see that it
+only contains `Runner.class`, not its dependencies (`Greeting.class`):
+
+{% highlight bash %}
+$ 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
+{% endhighlight %}
+
+This works for running locally (the `runner` script Bazel generates adds the
+greeter jar to the classpath) but will not work if we want to copy `runner.jar`
+to another machine and use it as a standalone binary. To build a self-contained
+jar that can be deployed, build `runner_deploy.jar` (or, more generally,
+`<target-name>_deploy.jar`):
+
+{% highlight bash %}
+$ 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
+{% endhighlight %}
+
+`runner_deploy.jar` will contain all of its dependencies.
+
+