Search code examples
bazel

How does Bazel interpret special lexemes like `/`, `:`, `//` and `@` in labels?


I'm having trouble understanding how to construct proper label forms when dealing with external repositories (directories with their own WORKSPACE).

What is the semantic meaning of characters like /, :, // or @?

For example:

  • @foo/bar
  • @foo:bar
  • //foo
  • foo

Do they preserve their meaning when used in an external repository? Also, is //external special in any way?


Solution

  • / is a separator for package and target names.

    • relative/package/to/my:target
    • //absolute/package/to:my/file/target.java

    A package is defined as a directory containing a BUILD or BUILD.bazel file.

    : is the lexeme for selecting a rule or file target in a package.

    • //my/package:my_java_binary

    Selects the target my_java_binary defined in <workspace root>/my/package/BUILD

    • //my/package:file.go

    Selects the file <workspace root>/my/package/file.go if <workspace root>/my/package/BUILD exists, and if there's a rule in that BUILD file that references it.

    • //:my/nested/file.txt

    Selects the file <workspace root>/my/nested/file.txt if <workspace root>/BUILD exists, but not in the my and my/nested subdirectories.

    // is the location of the current or closest parent directory containing a WORKSPACE file.

    Otherwise known as workspace root.

    @ is used for referencing a repository by its name when used to the left of //

    • @io_bazel_rules_scala//scala:scala.bzl: look into your WORKSPACE file for a repository named io_bazel_rules_scala. Usually defined using http_archive or git_repository.
    • @//my/package:target: @ alone refers to the current workspace.

    As of Bazel 0.16.0, @ can be used in package names.

    Do they preserve their meaning when used in an external repository?

    Yes, think of the @<repository> syntax as a namespace mechanism.

    Also, is //external special in any way?

    Yes, it's used for the bind function, which is not recommended anymore. bind lets you give a target an alias in //external.