0.3.7 Aliases
recommendedalias() gives an existing target a stable second label. It does not create another implementation or copy the underlying files. Other packages can depend on that handle even if the real target later moves, gets renamed, or already sits behind a long label.1
alias(
name = "my_lib",
actual = "//path/to/real:lib",
)
In the example above, other targets can depend on //path/to:my_lib instead of //path/to/real:lib.1 The visible label and the underlying target are different names that lead to the same implementation.1
The Attributes To Notice
The syntax is small. name gives the alias its own label in the current package, and actual points at the target it redirects to.1,2 An alias can also declare its own visibility, so the access-control rules from 0.2.4 Visibility still matter when you expose a target under an alternate name.1,2
Why deprecation Does Not Mark The Old Name
The alias signature accepts the common deprecation attribute, but do not use
it to migrate callers away from an old alias.2 The generic attribute normally
warns cross-package dependents,3 but alias dependency checks read deprecation
metadata from the resolved actual target rather than from the alias.4
alias(
name = "old_lib",
actual = "//path/to/real:lib",
deprecation = "Use //path/to/real:lib instead of //path/to:old_lib",
)
The alias still resolves, but targets depending on //path/to:old_lib do not get
that message. Bazel may print it when the alias itself is requested as a
top-level target, but that does not provide the dependency warning a rename needs.
This behavior is tracked in bazelbuild/bazel#5802, which was closed without a
fix, and remains visible in Bazel 9.1's alias-resolution path.4
Treat an alias as a silent compatibility label. Track or query remaining uses separately, migrate them, and only then remove the alias.
Why This Rule Exists
The value of alias() is indirection. If a package wants one stable public label while the real implementation target changes over time, an alias keeps consumers decoupled from that internal churn.1 That is why it helps with renames, refactors, and package APIs that want a cleaner public entry point than the underlying target path.1
The separate file-collection case is covered in 0.3.6 filegroup Rule.1
If a package does not naturally have an eponymous default target, alias() can also create one.5 That connects back to the shorthand rules in 0.2.2 Syntactic Sugar & Relative Labels: one label stands in for another target.5
A Legacy Pattern You May Still See
During Bzlmod migration, alias() replaces old bind() entries from WORKSPACE.6 Instead of keeping dependents on //external:openssl, you define a normal alias in a regular package and move callers to that package-local label.6
alias(
name = "openssl",
actual = "@my-ssl//src:openssl-lib",
)
An alias is a stable label that points at an existing target. When you see alias(), read it as a small indirection layer in the target graph: consumers depend on the alias name, and the alias forwards them to the real thing. During a rename, keep the old alias only as a temporary compatibility label and track migration separately — its own deprecation message does not warn dependent targets.1,4
Check your understanding · 2 questions
1.What does alias() actually create in the Bazel build graph?
Select one answer
2.True or false: when and how alias() is used.
Choose True or False for each sentence
Footnotes
-
Ultimate Monorepo and Bazel for Building Apps at Scale — alias as redirect/pointer,
nameandactual, optionalvisibility, and stable-name/refactor use cases ↩1 ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 -
General Rules —
aliassignature listsdeprecationamong common attributes, whilenameandactualare the rule-specific arguments ↩1 ↩2 ↩3 -
Common definitions —
deprecationis a string warning with no build effect. Cross-package dependents warn, but same-package and deprecated-to-deprecated edges do not ↩ -
Bazel core repository map — issue #5802 reproduces the missing dependency warning and was closed without a fix. Bazel 9.1's
AliasProviderandConfiguredTargetAndDatashow why dependency validation observes the resolved target, whileTargetPatternPhaseFunctionchecks the directly requested top-level target ↩1 ↩2 ↩3 -
Bazel Training 101 (Part 9): Packages, Rules, Targets, and Labels — using
alias()to create a package default target when no natural eponymous target exists ↩1 ↩2 -
Bzlmod Migration Guide — replacing legacy
bind()entries with a normalalias()target in a regular package ↩1 ↩2