File: visibility.md

package info (click to toggle)
bazel-bootstrap 4.2.3%2Bds-11
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 85,704 kB
  • sloc: java: 721,717; sh: 55,859; cpp: 35,360; python: 12,139; xml: 295; objc: 269; makefile: 113; ansic: 106; ruby: 3
file content (201 lines) | stat: -rwxr-xr-x 7,102 bytes parent folder | download | duplicates (2)
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
---
layout: documentation
title: Visibility
---
# Visibility

Visibility controls whether a target can be used (depended on) by targets in
other packages. This helps other people distinguish between your library's
public API and its implementation details, and is an important tool to help
enforce structure as your workspace grows.

If you need to disable the visibility check (for example when experimenting),
use `--check_visibility=false`.

## Visibility specifications

All rule targets have a `visibility` attribute that takes a list of labels. One
target is visible to another if they are in the same package, or if they are
granted visibility by one of the labels.

Each label has one of the following forms:

*   `"//visibility:public"`: Anyone can use this target. (May not be combined
    with any other specification.)

*   `"//visibility:private"`: Only targets in this package can use this
    target. (May not be combined with any other specification.)

*   `"//foo/bar:__pkg__"`: Grants access to targets defined in `//foo/bar` (but
    not its subpackages). Here, `__pkg__` is a special piece of syntax
    representing all of the targets in a package.

*   `"//foo/bar:__subpackages__"`: Grants access to targets defined in
    `//foo/bar`, or any of its direct or indirect subpackages. Again,
    `__subpackages__` is special syntax.

*   `"//foo/bar:my_package_group"`: Grants access to all of the packages named
    by the given [package group](be/functions.html#package_group).

    *   Package groups do not support the special `__pkg__` and
        `__subpackages__` syntax. Within a package group, `"//foo/bar"` is
        equivalent to `"//foo/bar:__pkg__"` and `"//foo/bar/..."` is equivalent
        to `"//foo/bar:__subpackages__"`.

For example, if `//some/package:mytarget` has its `visibility` set to
`[":__subpackages__", "//tests:__pkg__"]`, then it could be used by any target
that is part of the `//some/package/...` source tree, as well as targets defined
in `//tests/BUILD`, but not by targets defined in `//tests/integration/BUILD`.

As a special case, `package_group` targets themselves do not have a `visibility`
attribute; they are always publicly visible.

## Visibility of a rule target

If a rule target does not set the `visibility` attribute, its visibility is
given by the
[`default_visibility`](be/functions.html#package.default_visibility) that was
specified in the [`package`](be/functions.html#package) statement of the
target's BUILD file. If there is no such `default_visibility` declaration, the
visibility is `//visibility:private`.

`config_setting` visibility has historically not been enforced.
`--incompatible_enforce_config_setting_visibility` and
`--incompatible_config_setting_private_default_visibility` provide migration
logic for converging with other rules.

If `--incompatible_enforce_config_setting_visibility=false`, every
`config_setting` is unconditionally visible to all targets.

Else if `--incompatible_config_setting_private_default_visibility=false`, any
`config_setting` that doesn't explicitly set visibility is `//visibility:public`
(ignoring package [`default_visibility`](be/functions.html#package.default_visibility)).

Else if `--incompatible_config_setting_private_default_visibility=true`,
`config_setting` uses the same visibility logic as all other rules.

Best practice is to treat all `config_setting` targets like other rules:
explicitly set `visibility` on any `config_setting` used anywhere outside its
package.

### Example

File `//frobber/bin/BUILD`:

```python
# This target is visible to everyone
cc_binary(
    name = "executable",
    visibility = ["//visibility:public"],
    deps = [":library"],
)

# This target is visible only to targets declared in the same package
cc_library(
    name = "library",
    # No visibility -- defaults to private since no
    # package(default_visibility = ...) was used.
)

# This target is visible to targets in package //object and //noun
cc_library(
    name = "subject",
    visibility = [
        "//noun:__pkg__",
        "//object:__pkg__",
    ],
)

# See package group "//frobber:friends" (below) for who can
# access this target.
cc_library(
    name = "thingy",
    visibility = ["//frobber:friends"],
)
```

File `//frobber/BUILD`:

```python
# This is the package group declaration to which target
# //frobber/bin:thingy refers.
#
# Our friends are packages //frobber, //fribber and any
# subpackage of //fribber.
package_group(
    name = "friends",
    packages = [
        "//fribber/...",
        "//frobber",
    ],
)
```

## Visibility of a file target

By default, file targets are visible only from the same package. To make a file
accessible from another package, use
[`exports_files`](be/functions.html#exports_files).

If the call to `exports_files` specifies the visibility attribute, that
visibility applies. Otherwise, the file is public (the `default_visibility`
is ignored).

When possible, prefer exposing a library or another type of rule instead of a
source file. For example, declare a `java_library` instead of exporting a
`.java` file. It's good form for a rule target to only directly include sources
in its own package.

### Example

File `//frobber/data/BUILD`:

```python
exports_files(["readme.txt"])
```

File `//frobber/bin/BUILD`:

```python
cc_binary(
  name = "my-program",
  data = ["//frobber/data:readme.txt"],
)
```

### Legacy behavior

If the flag [`--incompatible_no_implicit_file_export`](https://github.com/bazelbuild/bazel/issues/10225)
is not set, a legacy behavior applies instead.

With the legacy behavior, files used by at least one rule target in the package
are implicitly exported using the `default_visibility` specification. See the
[design proposal](https://github.com/bazelbuild/proposals/blob/master/designs/2019-10-24-file-visibility.md#example-and-description-of-the-problem)
for more details.

## Visibility of bzl files

`load` statements are currently not subject to visibility. It is possible to
load a `bzl` file anywhere in the workspace.

## Visibility of implicit dependencies

Some rules have implicit dependencies. For example, a C++ rule might implicitly
depend on a C++ compiler.

Currently, implicit dependencies are treated like normal dependencies. They need
to be visible by all instances of the rule. This behavior can be changed using
[`--incompatible_visibility_private_attributes_at_definition`](https://github.com/bazelbuild/proposals/blob/master/designs/2019-10-15-tool-visibility.md).

## Best practices

* Avoid setting the default visibility to public. It may be convenient for
prototyping or in small codebases, but it is discouraged in large codebases: try
to be explicit about which targets are part of the public interface.

* Use `package_group` to share the visibility specifications among multiple
  targets. This is especially useful when targets in many BUILD files should be
  exposed to the same set of packages.

* Use fine-grained visibility specifications when deprecating a target. Restrict
  the visibility to the current users to avoid new dependencies.