Bazel Book

Syntactic Sugar & Relative Labels

The fully written form of a label — @repo//package:target — is precise but verbose. In daily use, most of those components can be omitted. Bazel defines a set of shorthand conventions that make BUILD files more readable and CLI invocations faster to type. Understanding which parts can be dropped, and where, prevents a class of common mistakes.

full written form
@myrepo // app/lib : lib
same repo → drop @repo
most common form
// app/lib : lib
RELATIVE LABEL
:lib
drop the //package prefix
same BUILD file only
EPONYMOUS TARGET
//app/lib
drop the :target suffix
name matches directory
Omit @repo in your own repo, :target when it matches the directory, //package within the same BUILD file.

The Eponymous Target Shorthand

When a target has the same name as the last component of its package path, the :target part can be omitted1. These two labels are equivalent:

//my/app/lib:lib
//my/app/lib

The Bazel style guide recommends this convention explicitly: prefer //x over //x:x when referring to an eponymous target2. This is why naming a package's primary target after its directory is a strong convention — it shortens deps lists, CLI commands, and makes the "main thing" in a package discoverable by name alone3. If a package has no natural eponymous target, an alias() can create one3. But don't create an eponymous target just for the shorthand if nothing in the package warrants it2.

This shorthand applies everywhere — in BUILD files, in .bzl files, and on the command line. But there's a subtle trap: //my/app always means //my/app:app, even if no such target exists1. It never means "all targets in the package" or "the package itself." A common mistake in BUILD files is using //my/app to refer to the package — it refers to the target named app1.

The only context where //my/app means "the package" is inside package_group specifications and in .bzl files that expect a package argument1.

Relative Labels Inside BUILD Files

Inside a BUILD file, you can reference targets in the same package without the //package prefix1. The package part and optionally the colon can be dropped:

cc_binary(
    name = "server",
    srcs = ["main.cc", "server.cc"],
    deps = [":utils"],
)

Here :utils refers to a target named utils in the same package — the full form would be //my/app:utils if this BUILD file lives in my/app/.

Convention matters: source files are referenced without a colon prefix ("main.cc"), while rule targets and generated files use the colon (:utils, :gen_header)2. The colon is not syntactically required for either — it's a readability convention that distinguishes inputs you wrote from outputs that Bazel produces1.

cc_library(
    name = "lib",
    srcs = ["x.cc"],
    hdrs = [":gen_header"],
)

Relative labels cannot cross package boundaries1. If testdata/ is a separate package (it has its own BUILD file), you cannot write testdata/input.txt from the parent package's BUILD file — you must use the full label //my/app/testdata:input.txt1.

Relative Labels on the Command Line

On the command line, labels without a // prefix are resolved relative to the current working directory4. If your working directory is foo/:

You typeBazel resolves to
:foo//foo:foo
bar:wiz//foo/bar:wiz
bar/wiz//foo/bar/wiz:wiz (eponymous target in subpackage)

This is a convenience for quick iteration — bazel run dev_server from the backend/ directory is equivalent to bazel run //backend/dev_server:dev_server3. But in BUILD files, all cross-package references must use the // form3.

Main-Repository Default

For Level 0, the explicit form for targets in your own repository is simply //pkg:target. That is the normal syntax you will read and write in BUILD files and most command lines.

Official docs also describe a rarer @@//pkg:target form for "refer back to the main repository even from another repository"1. That detail belongs with Bzlmod and repo mapping later on. At this level, keep the mental model simple: main repo = //..., external repo = @repo//....

Bare Repository Name

When a repository publishes a single rule from a .bzl file with the same name as the repository, a cascading shorthand applies. For example, with @bazel_env providing bazel_env.bzl that exports a bazel_env rule5:

load("@bazel_env//:bazel_env.bzl", "bazel_env")

And on the command line:

bazel run @bazel_env

This resolves to @bazel_env//:bazel_env — the eponymous target shorthand applied to the root package of the external repository5. This convention keeps load statements short and enables an npx-like bazel run @tool pattern5.

Summary of Shorthand Rules

Full formShorthandWhere valid
//app/lib:lib//app/libEverywhere
//app:utils:utilsSame BUILD file only
//app:main.ccmain.ccSame BUILD file only
@repo//pkg:target//pkg:targetSame repository
@repo//:repo@repoEverywhere
key takeaway

Most labels you encounter in practice are shortened. The two rules to internalize: omit the repository when you're in the same repo (//pkg:target), and omit the target name when it matches the directory name (//pkg). Inside BUILD files, :target is the relative form. On the command line, labels without // resolve from your working directory.

Check your understanding

1.What does the label //my/app/lib mean (without a :target part)?

2.Inside a BUILD file, what does :utils refer to?

3.On the command line (from directory foo/), what does bar:wiz resolve to?

Answer all questions to check

Footnotes

  1. Labels — Shorthand forms, relative labels, eponymous target convention, @@// for main repository, cross-package reference rules 1 2 3 4 5 6 7 8 9

  2. BUILD Style Guide — Colon convention for source vs rule targets, eponymous target naming, prefer local references in same package 1 2 3

  3. Packages, Rules, Targets, and Labels — Terminal labels relative to working directory, BUILD file labels require //, default target shorthand 1 2 3 4

  4. Build programs with Bazel — CLI target patterns resolved relative to working directory, //-prefixed patterns resolved from workspace root

  5. Developer Tooling in Monorepos with bazel_env — Bare repo name shorthand @bazel_env == @bazel_env//:bazel_env, .bzl naming convention for single-rule modules 1 2 3