0.2.6 package() Function

recommended

A 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:

Won't build
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

Reproduce this error

default_testonly is a package-wide default that individual targets can still override3.

extra

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.

key takeaway

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

package() may appear at most once per BUILD file.
A target's explicit visibility attribute is overridden by the package's default_visibility.
Setting package(default_testonly = True) prevents non-test targets from depending on this package's targets by default.
package() should be placed after all target declarations so defaults are applied once all targets are known.

2.What is the practical risk of setting default_visibility = ["//visibility:public"] in package()?

Select one answer

0 of 2 answered

Footnotes

  1. BUILD filespackage() applies metadata to the whole package, appears at most once, and belongs right after load() statements 1 2 3

  2. Visibilitydefault_visibility fallback behavior, explicit target override, package self-visibility, public-default caution, and symbolic-macro caveat 1 2 3 4 5 6

  3. Preventing production code depending on experiments — concrete use of package(default_testonly = True), enforcement error, and per-target override 1 2 3

  4. Macros — symbolic macros may not call native.package(), and package defaults do not apply to macro-created targets in the ordinary way