Bazel 扩展程序 (.bzl) 文件

扩展文件包含可导入到多个其他文件中的额外定义:

  • 其名称始终以 .bzl 文件扩展名结尾。

  • 它们必须属于某个 Bazel 软件包,因此由标签标识。 例如 //bazel_utils:defs.bzl。

  • 它们采用 Starlark 语言编写,并且应遵循特定准则。

  • 它们是定义 Starlark 函数的唯一位置!换句话说,不能在 BUILD.bazel 文件中定义函数!

  • 即使多次导入,它们也始终只评估一次,并且它们定义的变量和函数会记录为常量。

  • 可以使用 load() 语句从其他文件导入它们。

例如:

  • 从 $PROJECT/my_definitions.bzl 开始:

    # The official release number
    release_version = "1.0.0"
    
  • 从 $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 = [ … ],
    )
    

load() 语句具有特殊的语义:

  • 其第一个实参必须是 .bzl 文件的标签字符串(例如 "//src:definitions.bzl")。

  • 其他实参用于命名导入的常量或函数:

    • 如果实参是字符串,则必须是 .bzl 文件定义的导入符号的名称。例如:

      load("//src:defs.bzl", "my_var", "my_func")
      
    • 如果实参是变量赋值,则它会为导入的符号定义本地别名。E.g.:

      load("//src:defs.bzl", "my_var", func = "my_func")
      
    • 没有通配符:所有导入的常量和函数都必须明确命名。

    • 当 load() 出现在 .bzl 文件中时,系统绝不会记录导入的符号。

    • 同样,名称以下划线开头的符号(例如 _foo)永远不会被记录,也无法导入。也就是说,它们仅对定义它们的 .bzl 文件私有。

有时,一个 .bzl 文件想要从另一个文件导入符号,并以相同的名称重新导出该符号。这需要一个别名,如:

# 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