blob: 9d7432ceda6a49a0362f3a160570f23bdf5f5343 [file] [log] [blame] [view]
Kristina Chodorow974b2082015-03-31 14:49:30 +00001---
Googlera0d555f2015-04-22 08:32:33 +00002layout: documentation
Kristina Chodorow974b2082015-03-31 14:49:30 +00003---
4
Googlerbed62452015-04-14 18:44:55 +00005# Getting Started with Bazel
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01006
Googlerbed62452015-04-14 18:44:55 +00007## Setup
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01008
Googlerbed62452015-04-14 18:44:55 +00009Clone the Bazel [Github repo](https://github.com/google/bazel) and run the
10provided compile script. Make sure that you are running Bazel on a supported
11platform and that you have installed other required software as described in the
12[installation guide](install.html).
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010013
Googlera0d555f2015-04-22 08:32:33 +000014{% highlight bash %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010015$ git clone https://github.com/google/bazel.git
16$ cd bazel
17$ ./compile.sh
Googlera0d555f2015-04-22 08:32:33 +000018{% endhighlight %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010019
Googler08050a32015-03-31 20:50:16 +000020`./compile.sh` creates the `bazel` executable in `output/bazel`.
Googler08050a32015-03-31 20:50:16 +000021
22_**Note:** Bazel may support a binary installation at a later time._
23
Googlerbed62452015-04-14 18:44:55 +000024## Using a workspace
Googler08050a32015-03-31 20:50:16 +000025
Googlerbed62452015-04-14 18:44:55 +000026A *workspace* is a directory on your filesystem that contains source code for
27the software you want to build, as well symbolic links to directories that
28contain the build outputs (for example, `bazel-bin` and `bazel-out`). The
29location of the workspace directory is not significant, but it must contain an
30empty file called `WORKSPACE` in the top-level directory. This file marks the
31directory as the workspace root.
Googler08050a32015-03-31 20:50:16 +000032
Googlerbed62452015-04-14 18:44:55 +000033One workspace can be shared among multiple projects if desired. To get
Googler08050a32015-03-31 20:50:16 +000034started, we'll focus on a simple example with one project.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010035
36Suppose that you have an existing project in a directory, say,
Kristina Chodorow06f446a2015-04-06 15:54:03 +000037`~/gitroot/my-project/`. Create an empty file at
38`~/gitroot/my-project/WORKSPACE` to show Bazel where your project's root is.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010039
Googlerbed62452015-04-14 18:44:55 +000040## Sanity Check: Building an Example
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010041
42To make sure everything is set up correctly in your build root, build one of the
Googler08050a32015-03-31 20:50:16 +000043examples from the `examples/` directory.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010044
Googlera0d555f2015-04-22 08:32:33 +000045{% highlight bash %}
Kristina Chodorow06f446a2015-04-06 15:54:03 +000046$ cd ~/gitroot/my-project
Kristina Chodorow3adbc492015-05-11 17:19:26 +000047$ bazel fetch //...
Lukacs Berkid408df22015-03-25 12:51:17 +000048$ bazel build examples/java-native/src/main/java/com/example/myproject:hello-world
Kristina Chodorow3e6bd722015-03-19 14:30:24 +000049Extracting Bazel installation...
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010050...........
51INFO: Found 1 target...
Lukacs Berkid408df22015-03-25 12:51:17 +000052Target //examples/java-native/src/main/java/com/example/myproject:hello-world up-to-date:
53 bazel-bin/examples/java-native/src/main/java/com/example/myproject/hello-world.jar
54 bazel-bin/examples/java-native/src/main/java/com/example/myproject/hello-world
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010055INFO: Elapsed time: 3.040s, Critical Path: 1.14s
Lukacs Berkid408df22015-03-25 12:51:17 +000056$ bazel-bin/examples/java-native/src/main/java/com/example/myproject/hello-world
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010057Hello world
Googlera0d555f2015-04-22 08:32:33 +000058{% endhighlight %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010059
Googler08050a32015-03-31 20:50:16 +000060Bazel puts binaries it has built under `bazel-bin/`. Note that you can
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010061always look at the `build` command's output to find output file paths.
62
Googlerbed62452015-04-14 18:44:55 +000063## Creating Your Own Build File
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010064
Googler08050a32015-03-31 20:50:16 +000065Now you can create your own BUILD file and start adding build rules. This
66example assumes that `my-project/` is a Java project. See the
Han-Wen Nienhuys361af112015-03-17 13:00:09 +000067[build encyclopedia](build-encyclopedia.html)
Googler3a21f002015-03-18 21:52:07 +000068for advice on adding build rules for other languages.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010069
70Note that when we ran "bazel build" above, the third argument started with a
71filesystem path ("examples/java"), followed by a colon. When you run
Lukacs Berkid408df22015-03-25 12:51:17 +000072`bazel build examples/java-native/src/main/java/com/example/myproject:hello-world`,
73Bazel will look for a special file named BUILD in the
74`examples/java-native/src/main/java/com/example/myproject/` subdirectory. This
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010075BUILD file defines rules about how Bazel should build things in this
76subdirectory.
77
Googler3a21f002015-03-18 21:52:07 +000078Thus, to add build rules to my-project, create a file named `BUILD` in the
Googler08050a32015-03-31 20:50:16 +000079`my-project/` directory. Add the following lines to this BUILD file:
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010080
Googlera0d555f2015-04-22 08:32:33 +000081{% highlight python %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010082# ~/gitroot/base_workspace/my-project/BUILD
83java_binary(
84 name = "my-runner",
85 srcs = glob(["**/*.java"]),
86 main_class = "com.example.ProjectRunner",
87)
Googlera0d555f2015-04-22 08:32:33 +000088{% endhighlight %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010089
90BUILD files are Python-like scripts. BUILD files cannot contain arbitrary
91Python, but each build rule looks like a Python function call and you can use
92"#" to start a single-line comment.
93
94`java_binary` is the type of thing this rule will build.
95`name` is how you'll refer to the rule when you run "bazel build"
96(in the "examples/java:hello-world" build above the `name` was
97"hello-world"). `srcs` lists the Java source files Bazel should
98compile into a Java binary. `glob(["**/*.java"])` is a handy
99shorthand for "recursively include every file that ends with .java" (see the
Han-Wen Nienhuys361af112015-03-17 13:00:09 +0000100[user manual](bazel-user-manual.html)
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100101for more information about globbing). Replace `com.example.ProjectRunner` with
102the class that contains the main method.
103
104If you have no actual Java project you're using, you can use the following
105commands to make a fake project for this example:
106
Googlera0d555f2015-04-22 08:32:33 +0000107{% highlight bash %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100108$ # If you're not already there, move to your build root directory.
109$ cd ~/gitroot/base_workspace
110$ mkdir -p my-project/java/com/example
Ross Lighte7dd23c2015-03-19 16:37:19 +0000111$ cat > my-project/java/com/example/ProjectRunner.java <<EOF
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100112package com.example;
113
114public class ProjectRunner {
115 public static void main(String args[]) {
116 Greeting.sayHi();
117 }
118}
119EOF
Ross Lighte7dd23c2015-03-19 16:37:19 +0000120$ cat > my-project/java/com/example/Greeting.java <<EOF
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100121package com.example;
122
123public class Greeting {
124 public static void sayHi() {
125 System.out.println("Hi!");
126 }
127}
128EOF
Googlera0d555f2015-04-22 08:32:33 +0000129{% endhighlight %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100130
131Now build your project:
132
Googlera0d555f2015-04-22 08:32:33 +0000133{% highlight bash %}
Kristina Chodorow3adbc492015-05-11 17:19:26 +0000134$ bazel fetch my-project:my-runner
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100135$ bazel build my-project:my-runner
136INFO: Found 1 target...
137Target //my-project:my-runner up-to-date:
138 bazel-bin/my-project/my-runner.jar
139 bazel-bin/my-project/my-runner
140INFO: Elapsed time: 1.021s, Critical Path: 0.83s
141$ bazel-bin/my-project/my-runner
142Hi!
Googlera0d555f2015-04-22 08:32:33 +0000143{% endhighlight %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100144
Googler3a21f002015-03-18 21:52:07 +0000145Congratulations, you've created your first Bazel BUILD file!
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100146
Googlerbed62452015-04-14 18:44:55 +0000147## Adding Dependencies
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100148
149Creating one rule to build your entire project may be sufficient for small
150projects, but as projects get larger it's important to break up the build into
151self-contained libraries that can be assembled into a final product. This way
152the entire world doesn't need to be rebuilt on small changes and Bazel can
153parallelize more of the build steps.
154
155To break up a project, create separate rules for each subcomponent and then
156make them depend on each other. For the example above, add the following rules
Googler08050a32015-03-31 20:50:16 +0000157to the `my-project/BUILD` file:
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100158
Googlera0d555f2015-04-22 08:32:33 +0000159{% highlight python %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100160java_binary(
161 name = "my-other-runner",
162 srcs = ["java/com/example/ProjectRunner.java"],
163 main_class = "com.example.ProjectRunner",
164 deps = [":greeter"],
165)
166
167java_library(
168 name = "greeter",
169 srcs = ["java/com/example/Greeting.java"],
170)
Googlera0d555f2015-04-22 08:32:33 +0000171{% endhighlight %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100172
173Now you can build and run `my-project:my-other-runner`:
174
Googlera0d555f2015-04-22 08:32:33 +0000175{% highlight bash %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100176$ bazel run my-project:my-other-runner
177INFO: Found 1 target...
178Target //my-project:my-other-runner up-to-date:
179 bazel-bin/my-project/my-other-runner.jar
180 bazel-bin/my-project/my-other-runner
181INFO: Elapsed time: 2.454s, Critical Path: 1.58s
182
183INFO: Running command line: bazel-bin/my-project/my-other-runner
184Hi!
Googlera0d555f2015-04-22 08:32:33 +0000185{% endhighlight %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100186
187If you edit _ProjectRunner.java_ and rebuild `my-other-runner`, only
Googler08050a32015-03-31 20:50:16 +0000188`ProjectRunner.java` needs to be rebuilt (<code>greeter</code> is unchanged).
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100189
Googlerbed62452015-04-14 18:44:55 +0000190## Using Multiple Packages
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100191
192For larger projects, you will often be dealing with several directories. You
193can refer to targets defined in other BUILD files using the syntax
194`//package-name:target-name`. For example, suppose
Googler08050a32015-03-31 20:50:16 +0000195`my-project/java/com/example/` has a `cmdline/` subdirectory with the following
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100196file:
197
Googlera0d555f2015-04-22 08:32:33 +0000198{% highlight bash %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100199$ mkdir my-project/java/com/example/cmdline
Ross Lighte7dd23c2015-03-19 16:37:19 +0000200$ cat > my-project/java/com/example/cmdline/Runner.java <<EOF
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100201package com.example.cmdline;
202
203import com.example.Greeting;
204
205public class Runner {
206 public static void main(String args[]) {
207 Greeting.sayHi();
208 }
209}
210EOF
Googlera0d555f2015-04-22 08:32:33 +0000211{% endhighlight %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100212
Googler08050a32015-03-31 20:50:16 +0000213We could add a `BUILD` file at `my-project/java/com/example/cmdline/BUILD`
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100214that contained the following rule:
215
Googlera0d555f2015-04-22 08:32:33 +0000216{% highlight python %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100217# ~/gitroot/base_workspace/my-project/java/com/example/cmdline/BUILD
218java_binary(
219 name = "runner",
220 srcs = ["Runner.java"],
221 main_class = "com.example.cmdline.Runner",
222 deps = ["//my-project:greeter"]
223)
Googlera0d555f2015-04-22 08:32:33 +0000224{% endhighlight %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100225
226However, by default, build rules are _private_. This means that they can only be
227referred to by rules in the same BUILD file. This prevents libraries that are
228implementation details from leaking into public APIs, but it also means that you
229must explicitly allow `runner` to depend on `my-project:greeter`. As is, if we
230build `runner` we'll get a permissions error:
231
Googlera0d555f2015-04-22 08:32:33 +0000232{% highlight bash %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100233$ bazel build my-project/java/com/example/cmdline:runner
234ERROR: /usr/local/google/home/kchodorow/gitroot/base_workspace/my-project/java/com/example/cmdline/BUILD:2:1:
235 Target '//my-project:greeter' is not visible from target '//my-project/java/com/example/cmdline:runner'.
236 Check the visibility declaration of the former target if you think the dependency is legitimate.
237ERROR: Analysis of target '//my-project/java/com/example/cmdline:runner' failed; build aborted.
238INFO: Elapsed time: 0.091s
Googlera0d555f2015-04-22 08:32:33 +0000239{% endhighlight %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100240
241You can make a rule visibile to rules in other BUILD files by adding a
242`visibility = level` attribute. Change the `greeter` rule in
243_my-project/BUILD_ to be visible to our new rule:
244
Googlera0d555f2015-04-22 08:32:33 +0000245{% highlight python %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100246java_library(
247 name = "greeter",
248 srcs = ["java/com/example/Greeting.java"],
249 visibility = ["//my-project/java/com/example/cmdline:__pkg__"],
250)
Googlera0d555f2015-04-22 08:32:33 +0000251{% endhighlight %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100252
253This makes `//my-project:greeter` visible to any rule in the
254`//my-project/java/com/example/cmdline` package. Now we can build and
255run the binary:
256
Googlera0d555f2015-04-22 08:32:33 +0000257{% highlight bash %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100258$ bazel run my-project/java/com/example/cmdline:runner
259INFO: Found 1 target...
260Target //my-project/java/com/example/cmdline:runner up-to-date:
261 bazel-bin/my-project/java/com/example/cmdline/runner.jar
262 bazel-bin/my-project/java/com/example/cmdline/runner
263INFO: Elapsed time: 1.576s, Critical Path: 0.81s
264
265INFO: Running command line: bazel-bin/my-project/java/com/example/cmdline/runner
266Hi!
Googlera0d555f2015-04-22 08:32:33 +0000267{% endhighlight %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100268
Han-Wen Nienhuys361af112015-03-17 13:00:09 +0000269See the [build encyclopedia](build-encyclopedia.html) for more visibility options.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100270
Googlerbed62452015-04-14 18:44:55 +0000271## Deploying
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100272
273If you look at the contents of
274_bazel-bin/my-project/java/com/example/cmdline/runner.jar_, you can see that it
275only contains `Runner.class`, not its dependencies (`Greeting.class`):
276
Googlera0d555f2015-04-22 08:32:33 +0000277{% highlight bash %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100278$ jar tf bazel-bin/my-project/java/com/example/cmdline/runner.jar
279META-INF/
280META-INF/MANIFEST.MF
281com/
282com/example/
283com/example/cmdline/
284com/example/cmdline/Runner.class
Googlera0d555f2015-04-22 08:32:33 +0000285{% endhighlight %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100286
287To deploy a `runner` binary, we need a self-contained jar. To build this, build
288runner_deploy.jar (or, more generally, _&lt;target-name&gt;_deploy.jar_):
289
Googlera0d555f2015-04-22 08:32:33 +0000290{% highlight bash %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100291$ bazel build my-project/java/com/example/cmdline:runner_deploy.jar
292INFO: Found 1 target...
293Target //my-project/java/com/example/cmdline:runner_deploy.jar up-to-date:
294 bazel-bin/my-project/java/com/example/cmdline/runner_deploy.jar
295INFO: Elapsed time: 1.700s, Critical Path: 0.23s
Googlera0d555f2015-04-22 08:32:33 +0000296{% endhighlight %}
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100297
298`runner_deploy.jar` will contain all of its dependencies.
299
Googlerbed62452015-04-14 18:44:55 +0000300## Next Steps
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100301
302You can now create your own targets and compose them. See the [build
Han-Wen Nienhuys361af112015-03-17 13:00:09 +0000303encyclopedia](build-encyclopedia.html)
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100304and Bazel
Han-Wen Nienhuys361af112015-03-17 13:00:09 +0000305[user manual](bazel-user-manual.html)
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100306for more information.
307[Let us know](https://groups.google.com/forum/#!forum/bazel-discuss)
308if you have any questions!