0.2.6 package() Function
recommendedA BUILD file defines the package boundary described in 0.1.3 Package. The package() function declares metadata that applies to the rules in that package. In Level 0, the two parameters worth remembering are default_visibility and default_testonly1.
Package-Wide Defaults
package() may appear at most once in a BUILD file, and if you use it, it should be the first call after the load() statements1. It belongs in the file header because it declares package-wide policy, not a target.
load("//tools:defs.bzl", "my_macro")
package(
default_visibility = ["//friends:__subpackages__"],
)
cc_library(
name = "util",
srcs = ["util.cc"],
)
Everything after that still defines ordinary targets. package() supplies defaults that those targets inherit unless they override them explicitly1,2.
default_visibility
The most important use of package() is setting default_visibility for targets that omit their own visibility attribute2. This uses the same visibility language introduced in 0.2.4 Visibility. When the same client set has to be reused in many places, that is usually a sign to model it as a named allowlist with 0.2.5 package_group instead of copying long visibility lists by hand.
If a rule has no explicit visibility, Bazel falls back to the package default when one exists. If there is no package default either, the rule falls back to private visibility2. An explicit visibility = [...] on the target wins over the package default.
package(
default_visibility = ["//friends:__subpackages__"],
)
cc_library(
name = "impl",
srcs = ["impl.cc"],
)
cc_library(
name = "api",
srcs = ["api.cc"],
visibility = ["//visibility:public"],
)
Here impl inherits the package default, while api opts out and declares its own visibility. Bazel also treats the package itself as part of the effective visibility, so sibling targets in the same package can still see each other2.
This is convenient, but it is also easy to overuse. Setting default_visibility = ["//visibility:public"] makes every target in the package public unless each one opts back out. The better practice is to avoid that pattern and mark only real public API targets explicitly2. package() is best when most targets in a package genuinely share the same visibility policy.
default_testonly
The second practical default is default_testonly. Setting:
package(default_testonly = True)
marks targets in that package as test-only by default3. This is useful when an entire subtree is meant for experiments, fixtures, or helper code that should not leak into production dependencies3.
Bazel enforces default_testonly during analysis. If a non-test target depends on a test-only target, the build fails:
java_binary(
name = "server",
srcs = ["Main.java"],
main_class = "app.Main",
deps = ["//testutil:test_helpers"],
)
ERROR: .../app/BUILD.bazel:3:12: in java_binary rule //app:server:
non-test target '//app:server' depends on testonly target
'//testutil:test_helpers' and doesn't have testonly attribute set
default_testonly is a package-wide default that individual targets can still override3.
Symbolic Macro Exception
Symbolic macros may not call native.package(), and targets created inside symbolic macros do not inherit the BUILD file's default_visibility the same way ordinary top-level targets do2,4. Hand-written BUILD files follow the ordinary behavior described above. The exception matters later when you start generating targets through reusable macro abstractions.
package() sets defaults for the whole package. Use it when many targets share the same policy, especially for default_visibility, and keep per-target visibility only for exceptions. Treat default_testonly as a focused safety mechanism for packages that should stay out of production dependency paths.
Check your understanding · 2 questions
1.True or false: how package() works.
Choose True or False for each sentence
2.What is the practical risk of setting default_visibility = ["//visibility:public"] in package()?
Select one answer
Footnotes
-
BUILD files —
package()applies metadata to the whole package, appears at most once, and belongs right afterload()statements ↩1 ↩2 ↩3 -
Visibility —
default_visibilityfallback behavior, explicit target override, package self-visibility, public-default caution, and symbolic-macro caveat ↩1 ↩2 ↩3 ↩4 ↩5 ↩6 -
Preventing production code depending on experiments — concrete use of
package(default_testonly = True), enforcement error, and per-target override ↩1 ↩2 ↩3 -
Macros — symbolic macros may not call
native.package(), and package defaults do not apply to macro-created targets in the ordinary way ↩