aboutsummaryrefslogtreecommitdiffhomepage
path: root/site/docs/external.md
blob: ed4b285ff6d7d0588312adc98690d0abfa3a1b8b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
---
layout: documentation
title: External Dependencies
---

# Working with external dependencies

External dependencies can be specified in the `WORKSPACE` file of the
[workspace directory](/docs/build-ref.html#workspace). This `WORKSPACE` file
uses the same syntax as BUILD files, but allows a different set of
rules. The full list of rules are in the Build Encyclopedia's
[Workspace Rules](/docs/be/workspace.html).

External dependencies are all downloaded and symlinked under a directory named
`external`. You can see this directory by running:

```
ls $(bazel info output_base)/external
```

Note that running `bazel clean` will not actually delete the external
directory. To remove all external artifacts, use `bazel clean --expunge`.

## Supported types of external dependencies

A few basic types of external dependencies can be used:

- [Dependencies on other Bazel projects](#bazel-projects)
- [Dependencies on non-Bazel projects](#non-bazel-projects)
- [Dependencies on external packages](#external-packages)

<a name="bazel-projects"></a>
### Depending on other Bazel projects

If you want to use targets from a second Bazel project, you can
use
[`local_repository`](http://docs.bazel.build/be/workspace.html#local_repository),
[`git_repository`](https://docs.bazel.build/be/workspace.html#git_repository)
or [`http_archive`](http://docs.bazel.build/be/workspace.html#http_archive)
to symlink it from the local filesystem, reference a git repository or download
it (respectively).

For example, suppose you are working on a project, `my-project/`, and you want
to depend on targets from your coworker's project, `coworkers-project/`. Both
projects use Bazel, so you can add your coworker's project as an external
dependency and then use any targets your coworker has defined from your own
BUILD files. You would add the following to `my_project/WORKSPACE`:

```python
local_repository(
    name = "coworkers-project",
    path = "/path/to/coworkers-project",
)
```

If your coworker has a target `//foo:bar`, your project can refer to it as
`@coworkers-project//foo:bar`.

<a name="non-bazel-projects"></a>
### Depending on non-Bazel projects

Rules prefixed with `new_` (e.g.,
[`new_local_repository`](http://docs.bazel.build/be/workspace.html#new_local_repository),
[`new_git_repository`](https://docs.bazel.build/be/workspace.html#new_git_repository)
and [`new_http_archive`](http://docs.bazel.build/be/workspace.html#new_http_archive)
) allow you to create targets from projects that do not use Bazel.

For example, suppose you are working on a project, `my-project/`, and you want
to depend on your coworker's project, `coworkers-project/`. Your coworker's
project uses `make` to build, but you'd like to depend on one of the .so files
it generates. To do so, add the following to `my_project/WORKSPACE`:

```python
new_local_repository(
    name = "coworkers-project",
    path = "/path/to/coworkers-project",
    build_file = "coworker.BUILD",
)
```

`build_file` specifies a BUILD file to overlay on the existing project, for
example:

```python
java_library(
    name = "some-lib",
    srcs = glob(["**"]),
    visibility = ["//visibility:public"],
)
```

You can then depend on `@coworkers-project//:some-lib` from your project's BUILD
files.

<a name="external-packages"></a>
### Depending on external packages

#### Maven repositories

Use the rule [`maven_jar`](https://docs.bazel.build/be/workspace.html#maven_jar)
(and optionally the rule [`maven_server`](https://docs.bazel.build/be/workspace.html#maven_server))
to download a jar from a Maven repository and make it available as a Java
dependency.

## Fetching dependencies

By default, external dependencies are fetched as needed during `bazel build`. If
you would like to disable this behavior or prefetch dependencies, use
[`bazel fetch`](http://docs.bazel.build/bazel-user-manual.html#fetch).

## Using Proxies

Bazel will pick up proxy addresses from the `HTTPS_PROXY` and `HTTP_PROXY`
environment variables and use these to download HTTP/HTTPS files (if specified).

<a name="transitive-dependencies"></a>
## Transitive dependencies

Bazel only reads dependencies listed in your `WORKSPACE` file. If your project
(`A`) depends on another project (`B`) which list a dependency on a third
project (`C`) in its `WORKSPACE` file, you'll have to add both `B`
and `C` to your project's `WORKSPACE` file. This requirement can balloon the
`WORKSPACE` file size, but hopefully limits the chances of having one library
include `C` at version 1.0 and another include `C` at 2.0.

## Generate a `WORKSPACE` file

Bazel provides a tool to help generate these expansive `WORKSPACE` files, called
`generate_workspace`. This tool is not included with the binary installer, so
you'll need to clone the [GitHub repo](https://github.com/bazelbuild/bazel) to
use it. We recommend using the tag corresponding to your current version of
bazel, which you can check by running `bazel version`.

`cd` to the GitHub clone, `git checkout` the appropriate tag, and run the
following to build the tool and see usage:

```
bazel run //src/tools/generate_workspace
```

Note that you need run this command from your Bazel source folder even if you
build your binary from source.

You can specify directories containing Bazel projects (i.e., directories
containing a `WORKSPACE` file), Maven projects (i.e., directories containing a
`pom.xml` file), or Maven artifact coordinates directly. For example:

```bash
$ bazel run //src/tools/generate_workspace -- \
>    --maven_project=/path/to/my/project \
>    --bazel_project=/path/to/skunkworks \
>    --bazel_project=/path/to/teleporter/project \
>    --artifact=groupId:artifactId:version \
>    --artifact=groupId:artifactId:version
Wrote:
/tmp/1437415510621-0/2015-07-20-14-05-10.WORKSPACE
/tmp/1437415510621-0/2015-07-20-14-05-10.BUILD
```

The `WORKSPACE` file will contain the transitive dependencies of the given
projects and artifacts. The `BUILD` file will contain a single target,
`transitive-deps`, that contains all of the dependencies. You can copy these
files to your project and add `transitive-deps` as a dependency of your `java_`
targets in `BUILD` files.

If you specify multiple Bazel projects, Maven projects, or artifacts, they will
all be combined into one `WORKSPACE` file (e.g., if the Bazel project depends on
junit and the Maven project also depends on junit, junit will only appear once
as a dependency in the output).

You may wish to curate the generated `WORKSPACE` file to ensure it is using the
correct version of each dependency. If several different versions of an artifact
are requested (by different libraries that depend on it), then
`generate_workspace` chooses a version and annotates the `maven_jar` with the
other versions requested, for example:

```python
# org.springframework:spring:2.5.6
# javax.mail:mail:1.4
# httpunit:httpunit:1.6 wanted version 1.0.2
# org.springframework:spring-support:2.0.2 wanted version 1.0.2
# org.slf4j:nlog4j:1.2.24 wanted version 1.0.2
maven_jar(
    name = "javax_activation_activation",
    artifact = "javax.activation:activation:1.1",
)
```

The example above indicates that `org.springframework:spring:2.5.6`,
`javax.mail:mail:1.4`, `httpunit:httpunit:1.6`,
`org.springframework:spring-support:2.0.2`, and `org.slf4j:nlog4j:1.2.24`
all depend on javax.activation. However, two of these libraries wanted
version 1.1 and three of them wanted 1.0.2. The `WORKSPACE` file is using
version 1.1, but that might not be the right version to use.

You may also want to break `transitive-deps` into smaller targets, as it is
unlikely that all of your targets depend on the transitive closure of your
maven jars.

## Caching of external dependencies

Bazel caches external dependencies and re-downloads or updates them when
the `WORKSPACE` file changes.