| --- | |
| title: 'Dependencies' | |
| --- | |
| A target `A` _depends upon_ a target `B` if `B` is needed by `A` at build or | |
| execution time. The _depends upon_ relation induces a | |
| [Directed Acyclic Graph](https://en.wikipedia.org/wiki/Directed_acyclic_graph) | |
| (DAG) over targets, and it is called a _dependency graph_. | |
| A target's _direct_ dependencies are those other targets reachable by a path | |
| of length 1 in the dependency graph. A target's _transitive_ dependencies are | |
| those targets upon which it depends via a path of any length through the graph. | |
| In fact, in the context of builds, there are two dependency graphs, the graph | |
| of _actual dependencies_ and the graph of _declared dependencies_. Most of the | |
| time, the two graphs are so similar that this distinction need not be made, but | |
| it is useful for the discussion below. | |
| ## Actual and declared dependencies {#actual-and-declared-dependencies} | |
| A target `X` is _actually dependent_ on target `Y` if `Y` must be present, | |
| built, and up-to-date in order for `X` to be built correctly. _Built_ could | |
| mean generated, processed, compiled, linked, archived, compressed, executed, or | |
| any of the other kinds of tasks that routinely occur during a build. | |
| A target `X` has a _declared dependency_ on target `Y` if there is a dependency | |
| edge from `X` to `Y` in the package of `X`. | |
| For correct builds, the graph of actual dependencies _A_ must be a subgraph of | |
| the graph of declared dependencies _D_. That is, every pair of | |
| directly-connected nodes `x --> y` in _A_ must also be directly connected in | |
| _D_. It can be said that _D_ is an _overapproximation_ of _A_. | |
| Important: _D_ should not be too much of an overapproximation of _A_ because | |
| redundant declared dependencies can make builds slower and binaries larger. | |
| `BUILD` file writers must explicitly declare all of the actual direct | |
| dependencies for every rule to the build system, and no more. | |
| Failure to observe this principle causes undefined behavior: the build may fail, | |
| but worse, the build may depend on some prior operations, or upon transitive | |
| declared dependencies the target happens to have. Bazel checks for missing | |
| dependencies and report errors, but it's not possible for this checking to be | |
| complete in all cases. | |
| You need not (and should not) attempt to list everything indirectly imported, | |
| even if it is _needed_ by `A` at execution time. | |
| During a build of target `X`, the build tool inspects the entire transitive | |
| closure of dependencies of `X` to ensure that any changes in those targets are | |
| reflected in the final result, rebuilding intermediates as needed. | |
| The transitive nature of dependencies leads to a common mistake. Sometimes, | |
| code in one file may use code provided by an _indirect_ dependency — a | |
| transitive but not direct edge in the declared dependency graph. Indirect | |
| dependencies don't appear in the `BUILD` file. Because the rule doesn't | |
| directly depend on the provider, there is no way to track changes, as shown in | |
| the following example timeline: | |
| ### 1. Declared dependencies match actual dependencies {#this-is-fine} | |
| At first, everything works. The code in package `a` uses code in package `b`. | |
| The code in package `b` uses code in package `c`, and thus `a` transitively | |
| depends on `c`. | |
| <table class="cyan"> | |
| <tr> | |
| <th><code>a/BUILD</code></th> | |
| <th><code><strong>b</strong>/BUILD</code></th> | |
| </tr> | |
| <tr> | |
| <td> | |
| ``` | |
| rule( | |
| name = "a", | |
| srcs = "a.in", | |
| deps = "//b:b", | |
| ) | |
| ``` | |
| </td> | |
| <td> | |
| ``` | |
| rule( | |
| name = "b", | |
| srcs = "b.in", | |
| deps = "//c:c", | |
| ) | |
| ``` | |
| </td> | |
| </tr> | |
| <tr class="alt"> | |
| <td><code>a / a.in</code></td> | |
| <td><code>b / b.in</code></td> | |
| </tr> | |
| <tr> | |
| <td> | |
| ``` | |
| import b; | |
| b.foo(); | |
| ``` | |
| </td> | |
| <td> | |
| ``` | |
| import c; | |
| function foo() { | |
| c.bar(); | |
| } | |
| ``` | |
| </td> | |
| </tr> | |
| <tr> | |
| <td> | |
| <figure> | |
| <img src="/versions/9.2.0/docs/images/a_b_c.svg" | |
| alt="Declared dependency graph with arrows connecting a, b, and c"/> | |
| <figcaption><b>Declared</b> dependency graph</figcaption> | |
| </figure> | |
| </td> | |
| <td> | |
| <figure> | |
| <img src="/versions/9.2.0/docs/images/a_b_c.svg" | |
| alt="Actual dependency graph that matches the declared dependency | |
| graph with arrows connecting a, b, and c"/> | |
| <figcaption><b>Actual</b> dependency graph</figcaption> | |
| </figure> | |
| </td> | |
| </tr> | |
| </table> | |
| The declared dependencies overapproximate the actual dependencies. All is well. | |
| ### 2. Adding an undeclared dependency {#undeclared-dependency} | |
| A latent hazard is introduced when someone adds code to `a` that creates a | |
| direct _actual_ dependency on `c`, but forgets to declare it in the build file | |
| `a/BUILD`. | |
| <table class="cyan"> | |
| <tr> | |
| <th><code>a / a.in</code></th> | |
| <th> </th> | |
| </tr> | |
| <tr> | |
| <td> | |
| ``` | |
| import b; | |
| import c; | |
| b.foo(); | |
| c.garply(); | |
| ``` | |
| </td> | |
| <td> </td> | |
| </tr> | |
| <tr> | |
| <td> | |
| <figure> | |
| <img src="/versions/9.2.0/docs/images/a_b_c.svg" | |
| alt="Declared dependency graph with arrows connecting a, b, and c"/> | |
| <figcaption><b>Declared</b> dependency graph</figcaption> | |
| </figure> | |
| </td> | |
| <td> | |
| <figure> | |
| <img src="/versions/9.2.0/docs/images/a_b_c_ac.svg" | |
| alt="Actual dependency graph with arrows connecting a, b, and c. An | |
| arrow now connects A to C as well. This does not match the | |
| declared dependency graph"/> | |
| <figcaption><b>Actual</b> dependency graph</figcaption> | |
| </figure> | |
| </td> | |
| </tr> | |
| </table> | |
| The declared dependencies no longer overapproximate the actual dependencies. | |
| This may build ok, because the transitive closures of the two graphs are equal, | |
| but masks a problem: `a` has an actual but undeclared dependency on `c`. | |
| ### 3. Divergence between declared and actual dependency graphs {#divergence} | |
| The hazard is revealed when someone refactors `b` so that it no longer depends on | |
| `c`, inadvertently breaking `a` through no | |
| fault of their own. | |
| <table class="cyan"> | |
| <tr> | |
| <th> </th> | |
| <th><code><strong>b</strong>/BUILD</code></th> | |
| </tr> | |
| <tr> | |
| <td> </td> | |
| <td> | |
| ``` | |
| rule( | |
| name = "b", | |
| srcs = "b.in", | |
| <strong>deps = "//d:d",</strong> | |
| ) | |
| ``` | |
| </td> | |
| </tr> | |
| <tr class="alt"> | |
| <td> </td> | |
| <td><code>b / b.in</code></td> | |
| </tr> | |
| <tr> | |
| <td> </td> | |
| <td> | |
| ``` | |
| import d; | |
| function foo() { | |
| d.baz(); | |
| } | |
| ``` | |
| </td> | |
| </tr> | |
| <tr> | |
| <td> | |
| <figure> | |
| <img src="/versions/9.2.0/docs/images/ab_c.svg" | |
| alt="Declared dependency graph with arrows connecting a and b. | |
| b no longer connects to c, which breaks a's connection to c"/> | |
| <figcaption><b>Declared</b> dependency graph</figcaption> | |
| </figure> | |
| </td> | |
| <td> | |
| <figure> | |
| <img src="/versions/9.2.0/docs/images/a_b_a_c.svg" | |
| alt="Actual dependency graph that shows a connecting to b and c, | |
| but b no longer connects to c"/> | |
| <figcaption><b>Actual</b> dependency graph</figcaption> | |
| </figure> | |
| </td> | |
| </tr> | |
| </table> | |
| The declared dependency graph is now an underapproximation of the actual | |
| dependencies, even when transitively closed; the build is likely to fail. | |
| The problem could have been averted by ensuring that the actual dependency from | |
| `a` to `c` introduced in Step 2 was properly declared in the `BUILD` file. | |
| ## Types of dependencies {#types-of-dependencies} | |
| Most build rules have three attributes for specifying different kinds of | |
| generic dependencies: `srcs`, `deps` and `data`. These are explained below. For | |
| more details, see | |
| [Attributes common to all rules](/versions/9.2.0/reference/be/common-definitions). | |
| Many rules also have additional attributes for rule-specific kinds of | |
| dependencies, for example, `compiler` or `resources`. These are detailed in the | |
| [Build Encyclopedia](/versions/9.2.0/reference/be/). | |
| ### `srcs` dependencies {#srcs-dependencies} | |
| Files consumed directly by the rule or rules that output source files. | |
| ### `deps` dependencies {#deps-dependencies} | |
| Rule pointing to separately-compiled modules providing header files, | |
| symbols, libraries, data, etc. | |
| ### `data` dependencies {#data-dependencies} | |
| A build target might need some data files to run correctly. These data files | |
| aren't source code: they don't affect how the target is built. For example, a | |
| unit test might compare a function's output to the contents of a file. When you | |
| build the unit test you don't need the file, but you do need it when you run | |
| the test. The same applies to tools that are launched during execution. | |
| The build system runs tests in an isolated directory where only files listed as | |
| `data` are available. Thus, if a binary/library/test needs some files to run, | |
| specify them (or a build rule containing them) in `data`. For example: | |
| ``` | |
| # I need a config file from a directory named env: | |
| java_binary( | |
| name = "setenv", | |
| ... | |
| data = [":env/default_env.txt"], | |
| ) | |
| # I need test data from another directory | |
| sh_test( | |
| name = "regtest", | |
| srcs = ["regtest.sh"], | |
| data = [ | |
| "//data:file1.txt", | |
| "//data:file2.txt", | |
| ... | |
| ], | |
| ) | |
| ``` | |
| These files are available using the relative path `path/to/data/file`. In tests, | |
| you can refer to these files by joining the paths of the test's source | |
| directory and the workspace-relative path, for example, | |
| `${TEST_SRCDIR}/workspace/path/to/data/file`. | |
| ## Using labels to reference directories {#using-labels-reference-directories} | |
| As you look over our `BUILD` files, you might notice that some `data` labels | |
| refer to directories. These labels end with `/.` or `/` like these examples, | |
| which you should not use: | |
| <p><span class="compare-worse">Not recommended</span> — | |
| <code>data = ["//data/regression:unittest/."]</code></p> | |
| <p><span class="compare-worse">Not recommended</span> — | |
| <code>data = ["testdata/."]</code></p> | |
| <p><span class="compare-worse">Not recommended</span> — | |
| <code>data = ["testdata/"]</code></p> | |
| This seems convenient, particularly for tests because it allows a test to | |
| use all the data files in the directory. | |
| But try not to do this. In order to ensure correct incremental rebuilds (and | |
| re-execution of tests) after a change, the build system must be aware of the | |
| complete set of files that are inputs to the build (or test). When you specify | |
| a directory, the build system performs a rebuild only when the directory itself | |
| changes (due to addition or deletion of files), but won't be able to detect | |
| edits to individual files as those changes don't affect the enclosing directory. | |
| Rather than specifying directories as inputs to the build system, you should | |
| enumerate the set of files contained within them, either explicitly or using the | |
| [`glob()`](/versions/9.2.0/reference/be/functions#glob) function. (Use `**` to force the | |
| `glob()` to be recursive.) | |
| <p><span class="compare-better">Recommended</span> — | |
| <code>data = glob(["testdata/**"])</code></p> | |
| Unfortunately, there are some scenarios where directory labels must be used. | |
| For example, if the `testdata` directory contains files whose names don't | |
| conform to the [label syntax](/versions/9.2.0/concepts/labels#labels-lexical-specification), | |
| then explicit enumeration of files, or use of the | |
| [`glob()`](/versions/9.2.0/reference/be/functions#glob) function produces an invalid labels | |
| error. You must use directory labels in this case, but beware of the | |
| associated risk of incorrect rebuilds described above. | |
| If you must use directory labels, keep in mind that you can't refer to the | |
| parent package with a relative `../` path; instead, use an absolute path like | |
| `//data/regression:unittest/.`. | |
| Note: Directory labels are only valid for data dependencies. If you try to use | |
| a directory as a label in an argument other than `data`, it will fail and you | |
| will get a (probably cryptic) error message. | |
| Any external rule, such as a test, that needs to use multiple files must | |
| explicitly declare its dependence on all of them. You can use `filegroup()` to | |
| group files together in the `BUILD` file: | |
| ``` | |
| filegroup( | |
| name = 'my_data', | |
| srcs = glob(['my_unittest_data/*']) | |
| ) | |
| ``` | |
| You can then reference the label `my_data` as the data dependency in your test. | |