Extension files contain extra definitions that can be imported into several
other files:

- Their name always ends with the `.bzl` file extension.

- They must belong to a Bazel package, and hence identified by a label.
  For example `//bazel_utils:defs.bzl`.

- They are written in the [Starlark language](https://bazel.build/rules/language),
  and should follow [specific guidelines](https://bazel.build/rules/bzl-style).

- They are the *only* place where Starlark functions can be defined!
  In other words, one cannot define a function in a `BUILD.bazel` file!

- They are always *evaluated once*, even if they are imported multiple times,
  and the variables and functions they define are recorded as constants.

- They can be imported from other files using the
  [`load()`](https://bazel.build/concepts/build-files#load) statement.

For example:

- From `$PROJECT/my_definitions.bzl`:

      # The official release number
      release_version = "1.0.0"

- From `$PROJECT/BUILD.bazel`:

      # Import the value of `release_version` from my_definitions.bzl
      load("//:my_definitions.bzl", "release_version")

      # Compile C++ executable, hard-coding its version number with a macro.
      cc_binary(
        name = "my_program",
        defines = [ "RELEASE_VERSION=" + release_version ],
        sources = [ ... ],
      )

The [`load()`](https://bazel.build/concepts/build-files#load) statement has special semantics:

- Its first argument must be a label string to a `.bzl` file (e.g.
  `"//src:definitions.bzl"`).

- Other arguments name imported constants or functions:

  - If the argument is a string, it must be the name of an imported symbol
    defined by the `.bzl` file. e.g.:

        load("//src:defs.bzl", "my_var", "my_func")

  - If the argument is a variable assignment, it defines a local alias for an
    imported symbol. E.g.:

        load("//src:defs.bzl", "my_var", func = "my_func")

  - *There are no wildcards*: all imported constants and functions must be
    named explicitly.

  - Imported symbols are never recorded when the `load()` appears within a
    `.bzl` file.

  - Similarly, symbols whose name begins with and underscore (e.g. `_foo`) are
    never recorded, and cannot be imported. I.e. they are private to the `.bzl`
    file that defines them.

Sometimes a `.bzl` file wants to import a symbol from another one, and
re-export it with the same name. This requires an alias as in:

    # From //src:utils.bzl

    # Import "my_vars" from defs.bzl as '_my_var'.
    load("//src:defs.bzl", _my_var = "my_var")

    # Define my_var in the current scope as a copy of _my_var
    # This symbol and its value will be recorded, and available for import
    # to any other file that loads //src:utils.bzl.
    my_var = _my_var

[](https://issues.fuchsia.dev/issues/new?component=1439230&template=1881640&description=Issue+on:+https://fuchsia.dev/docs/development/build/bazel_concepts/bzl_files.md "Report a bug or suggest improvements on this page") [](https://cs.opensource.google/fuchsia/fuchsia/+/main:docs/development/build/bazel_concepts/bzl_files.md "View the source code of this page") [](https://ci.android.com/edit?repo=fuchsia/fuchsia/main&file=docs/development/build/bazel_concepts/bzl_files.md&cloneRepo=fuchsia/fuchsia:refs/heads/main&fullPath=fuchsia/docs/development/build/bazel_concepts/bzl_files.md "Edit the source code of this page")