Visibility controls whether a target can be used by other packages. It is an important tool to structure the code when a codebase grows: it lets developers distinguish between implementation details and libraries other people can depend on.
If you need to disable the visibility check (for example when experimenting), use --check_visibility=false.
There are five forms a visibility label can take:
["//visibility:public"]: Anyone can use this rule.["//visibility:private"]: Only rules in this package can use this rule. Rules in javatests/foo/bar can always use rules in java/foo/bar.["//some/package:__pkg__", "//other/package:__pkg__"]: Only rules in some/package/BUILD and other/package/BUILD have access to this rule. Note that sub-packages do not have access to the rule; for example, //some/package/foo:bar or //other/package/testing:bla wouldn't have access. __pkg__ is a special target and must be used verbatim. It represents all of the rules in the package.["//project:__subpackages__", "//other:__subpackages__"]: Only rules in packages project or other or in one of their sub-packages have access to this rule. For example, //project:rule, //project/library:lib or //other/testing/internal:munge are allowed to depend on this rule (but not //independent:evil)["//some/package:my_package_group"]: A package group is a named set of package names. Package groups can also grant access rights to entire subtrees, e.g.//myproj/....The visibility specifications of //visibility:public and //visibility:private can not be combined with any other visibility specifications.
A visibility specification may contain a combination of package labels (i.e. //foo:__pkg__) and package_groups.
If a rule does specify the visibility attribute, that specification overrides any default_visibility attribute of the package statement in the BUILD file containing the rule.
Otherwise, if a rule does not specify the visibility attribute, the default_visibility of the package is used.
Otherwise, if the default_visibility for the package is not specified, //visibility:private is used.
File //frobber/bin/BUILD:
# This rule is visible to everyone cc_binary( name = "executable", visibility = ["//visibility:public"], deps = [":library"], ) # This rule is visible only to rules declared in the same package cc_library( name = "library", visibility = ["//visibility:private"], ) # This rule is visible to rules 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 rule. cc_library( name = "thingy", visibility = ["//frobber:friends"], )
File //frobber/BUILD:
# This is the package group declaration to which rule # //frobber/bin:thingy refers. # # Our friends are packages //frobber, //fribber and any # subpackage of //fribber. package_group( name = "friends", packages = [ "//fribber/...", "//frobber", ], )
By default, files are visible only from the same package. To make a file accessible from another package, use exports_files.
If the call to exports_files rule does specify the visibility attribute, that specification applies. Otherwise, the file is public (the default_visibility is ignored).
If the flag --incompatible_no_implicit_file_export is not set, a legacy behavior applies instead.
With the legacy behavior, files used by at least one rule in the file are implicitly exported using the default_visibility specification. See the design proposal for more details.
load statements are currently not subject to visibility. It is possible to load a bzl file anywhere in the workspace.
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.
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.