Bazel中的Symbol, Rule, Macro, Target, Provider, Aspect 等概念

学习Bazel ,就要学习Bazel 的规则定义, 弄清各个概念是重要的一个步骤。 在 Bazel 规则定义中,SymbolRuleMacro 是常见的概念。除此之外,Bazel 还有 TargetProviderAspect Repository、Package、 Workspace、 Configuration、Build Event Protocol、 Starlark、Transition、Action 等重要概念。

概念 类别 作用
Symbol(符号) 基础概念 Bazel 规则、目标、属性等命名的标识符。
Rule(规则) 规则 定义 Bazel 构建逻辑,如 cc_librarypy_binary
Macro(宏) 代码复用 通过 Starlark 编写的函数,封装多个规则以简化 BUILD 文件。
Target(目标) 构建单元 BUILD 文件中的规则实例,如 cc_library(name = "lib")
Provider(提供者) 数据传递 规则间传递构建信息的方式,如 DefaultInfo(files = depset([...]))
Aspect(切面) 依赖扩展 扩展规则行为,访问依赖的构建信息,如 bazel_aspect()
Repository(仓库) 外部依赖管理 定义和下载外部依赖,如 http_archive()git_repository()
Package(包) 代码组织 BUILD 文件为单位的代码组织单元,每个 BUILD 目录即一个 package。
Workspace(工作区) 项目根目录 WORKSPACE 文件定义的 Bazel 项目,管理外部依赖。
Configuration(构建配置) 编译参数 影响构建方式,如 --cpu=x86_64--compilation_mode=opt
Build Event Protocol(BEP) 日志分析 记录 Bazel 构建事件,生成 JSON 或 Proto 格式日志。
Starlark(Bazel 语言) 语言 Bazel 使用的 Python 语法子集,编写规则、宏和构建逻辑。
Transition(配置转换) 配置管理 允许在不同规则间修改构建配置,如改变 --cpu
Action(构建动作) 执行单元 最小的构建执行单位,如 ctx.actions.run_shell() 运行 shell 命令。

下面将对它们做详细的解释:

1. Symbol(符号)

在 Bazel 中,symbol(符号) 指的是 .bzl 文件中定义的变量、函数、规则、宏等。

当你使用 load() 语句时,你在导入的就是 symbols

示例:

python 复制代码
load("@rules_python//python:packaging.bzl", "py_package", "py_wheel")
  • 这里 py_packagepy_wheel 就是 packaging.bzl 文件中定义的 symbols

  • symbols 可以是宏(macro)规则(rule) ,或者普通的 函数/变量


2. Rule(规则)

Bazel rule(规则) 是 Bazel 构建系统的核心 ,用于定义如何构建目标(target)

特性:

  • 规则(rules)是 Starlark 代码 ,它们通常由 native.rule() 定义。

  • 每个规则 都能创建一个或多个 targets(构建目标),并由 Bazel 执行。

  • 规则可以使用 providers 来定义输入/输出关系。

规则示例

Bazel 内置了一些规则,比如 cc_binarypy_binary

python 复制代码
cc_binary( 
name = "hello",
srcs = ["hello.cc"],
deps = [":hello_lib"],
) 
  • cc_binary 是一个规则(rule),用于编译 C++ 可执行文件。

  • name 是目标名称,srcs 是源代码文件,deps 是依赖项。

自定义规则(User-defined Rule)

python 复制代码
def _my_rule_impl(ctx):
    # 规则的核心逻辑 
    pass

my_rule = rule( 
    implementation = _my_rule_impl, 
    attrs = { 
        "srcs": attr.label_list(allow_files=True),
    }, 
)
  • my_rule 是 Bazel 自定义规则 ,用于处理 srcs 作为输入。

  • implementation 是规则的实现函数 _my_rule_impl

官方文档:
Build Rules Guide


3. Macro(宏)

宏(macro)封装多个 Bazel 规则的函数,用于提高可复用性。

  • Macros 只是 Starlark 层面的封装,不会创建新的 build actions

  • 它们只是规则的组合,而不修改规则本身

宏示例

python 复制代码
def my_py_library(name, srcs, deps = []):
    native.py_library(
        name = name,
        srcs = srcs,
        deps = deps + ["//common:utils"],
    )

使用时:

python 复制代码
load("//build_defs:my_macros.bzl", "my_py_library")

my_py_library(
    name = "my_lib",
    srcs = ["lib.py"],
)
  • my_py_library封装了 py_library 规则 ,并默认加上 //common:utils 作为 deps 依赖项。

  • 与规则(rule)不同,宏不会创建新类型的 build target,只是对已有规则的包装


4. Target(目标)

Target(构建目标) 是 Bazel 构建系统的最小单位 ,它由 BUILD 文件中的规则实例化生成。

python 复制代码
cc_library(
    name = "hello_lib",
    srcs = ["hello_lib.cc"],
)
  • 这里 hello_lib 是一个 target ,它是 cc_library 规则的一个实例。

Target vs Rule

  • Rule 是构建的"蓝图"(定义构建逻辑)。

  • Target 是具体的构建对象(每个 name 定义一个 target)。


5. Provider(提供者)

Provider(提供者) 是规则之间的数据传递机制

它允许规则将信息传递给依赖项。

示例

python 复制代码
MyProvider = provider(fields = ["output"])

def _my_rule_impl(ctx):
    output_file = ctx.actions.declare_file(ctx.label.name + ".out")
    ctx.actions.run_shell(
        outputs = [output_file],
        command = "echo 'Hello' > " + output_file.path,
    )
    return [MyProvider(output = output_file)]

my_rule = rule(
    implementation = _my_rule_impl,
)
  • MyProvider 是一个自定义提供者 ,它包含 output 字段。

  • _my_rule_impl 生成一个 output_file 并通过 MyProvider 返回它。

  • 在规则之间,提供者用于共享构建信息

官方文档:
Bazel Providers


6. Aspect(切面)

Aspect(切面) 允许在不修改规则的情况下为规则添加额外的行为

它们通常用于分析或生成额外的输出。

Aspect 示例

python 复制代码
def _my_aspect_impl(target, ctx):
    for src in target[DefaultInfo].files.to_list():
        print("Analyzing file:", src)

my_aspect = aspect(
    implementation = _my_aspect_impl,
)

应用 aspect

python 复制代码
cc_binary(
    name = "hello",
    srcs = ["hello.cc"],
)

my_aspect(
    target = "//:hello",
)
  • my_aspect 允许分析 cc_binary 目标的输入文件 ,而不修改 cc_binary 规则。

官方文档:
Bazel Aspects

7. Repository(外部仓库)

Repository(仓库) 是 Bazel 外部依赖管理的机制,用于拉取和管理外部代码库(如第三方库、工具链等)。

Bazel 支持多种类型的仓库,包括:

  • http_archive(下载 tar/zip 并解压)

  • git_repository(从 Git 拉取)

  • local_repository(使用本地路径)

  • new_local_repository(定义新的本地仓库)

示例

python 复制代码
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "rules_vcc",
    url = "https://example.com/rules_vcc.tar.gz",
    sha256 = "abc123...",
    strip_prefix = "rules_vcc-main",
)
  • @rules_vcc 就是一个 外部仓库 ,可用于 load("@rules_vcc//...")

官方文档:
Bazel External Repositories


8. Package(包)

Package(包)Bazel 代码的组织单元 ,即一个 BUILD 文件及其所在目录。

  • 一个 Bazel 工作区(workspace)可以有多个 package

  • 每个 package 都有一个 BUILD 文件,用于定义规则和目标。

示例

python 复制代码
/workspace_root/
  WORKSPACE
  /src/
    BUILD         # 这是一个 package
    main.cc
    /lib/
      BUILD       # 这是另一个 package
      lib.cc
  • src/src/lib/ 都是 package ,因为它们各自有 BUILD 文件。

官方文档:
Bazel Packages


9. Workspace(工作区)

Workspace(工作区)Bazel 项目的根目录 ,由 WORKSPACE 文件定义。

  • 所有 Bazel 构建都发生在某个工作区中

  • WORKSPACE 文件 用于声明外部依赖 ,如 http_archive()git_repository() 等。

示例

python 复制代码
/my_project/
  WORKSPACE        # 定义 Bazel 工作区
  /src/
    BUILD
    main.cc
  /third_party/
    BUILD
  • my_project/Bazel 工作区 ,因为它有 WORKSPACE 文件。

官方文档:
Bazel Workspaces


10. Configuration(构建配置)

Configuration(构建配置) 指的是 Bazel 对构建参数的管理,如:

  • CPU/架构 (--cpu=x86_64)

  • 编译模式 (--compilation_mode=opt/debug)

  • 工具链选择 (--host_crosstool_top=@bazel_tools//tools/cpp:toolchain)

示例

bash 复制代码
bazel build //src:main --cpu=arm64 --compilation_mode=opt
  • --cpu=arm64 选择 ARM64 架构

  • --compilation_mode=opt 进行优化编译

官方文档:
Bazel Configurations


11. Build Event Protocol(构建事件协议, BEP)

BEP 用于 跟踪和分析 Bazel 构建过程,常用于 CI/CD 系统集成。

BEP 可以输出 构建日志、失败原因、性能数据等,并提供 JSON 或 Proto 格式。

示例

bash 复制代码
bazel build //src:main --build_event_json_file=build_events.json
  • 生成 build_events.json,可用于分析构建信息。

官方文档:
Bazel Build Event Protocol


12. Starlark(Bazel 语言)

Starlark 是 Bazel 的 配置语言 ,基于 Python 语法但有严格限制

  • 无副作用(不能修改全局变量)

  • 无 I/O 操作(不能读写文件)

  • 只能调用 ctx.actions 进行构建

示例

python 复制代码
def _my_rule_impl(ctx):
    output = ctx.actions.declare_file(ctx.label.name + ".txt")
    ctx.actions.write(output, "Hello, Bazel!")
    return [DefaultInfo(files = depset([output]))]

my_rule = rule(implementation = _my_rule_impl)

官方文档:
Bazel Starlark


13. Transition(配置转换)

Transition(配置转换) 允许修改构建配置 ,比如 改变目标平台或优化级别

示例

python 复制代码
def _my_transition_impl(settings, attr):
    return {"//command_line_option:cpu": "arm64"}

my_transition = transition(
    implementation = _my_transition_impl,
    inputs = [],
    outputs = ["//command_line_option:cpu"],
)
  • 默认情况下,Bazel 规则会继承全局构建配置

  • 使用 transition 可以修改某些规则的配置,如强制某些目标在 ARM64 上构建。

官方文档:
Bazel Transitions


14. Action(构建动作)

Action(构建动作) 是 Bazel 执行构建的最小单位,如:

  • 编译(gcc、clang)

  • 链接(ld)

  • 拷贝文件

  • 执行 Shell 脚本

每个 rule多个 action 组成

示例

python 复制代码
def _my_rule_impl(ctx):
    output = ctx.actions.declare_file("output.txt")
    ctx.actions.run_shell(
        outputs = [output],
        command = "echo Hello > " + output.path,
    )
    return [DefaultInfo(files = depset([output]))]
  • ctx.actions.run_shell() 定义了一个 Action,用于执行 shell 命令。

官方文档:
Bazel Actions

相关推荐
搏博16 小时前
软件工程之软件项目管理深度解析
软件工程·软件构建·需求分析·软件需求
爱吃java的羊儿20 小时前
信息系统项目管理师-软考高级(软考高项)2025最新(十八)
信息可视化·软件工程·产品经理·可用性测试
我要学土木1 天前
软件工程期末知识点整理(更新中)
软件工程
meisongqing1 天前
【软件工程】软件缺陷 基于组合的优化方法
软件工程·软件缺陷·组合优化
搏博2 天前
软件工程之需求分析涉及的图与工具
数据库·软件工程·软件构建·软件需求
workflower2 天前
人协同的自动化需求分析
运维·开发语言·自动化·软件工程·需求分析·软件需求
meisongqing2 天前
【软件工程】基于机器学习的多缺陷定位
软件工程
搏博2 天前
软件工程之形式化说明技术深度解析
分布式·软件工程·软件构建·软件需求
meisongqing3 天前
【软件工程】基于频谱的缺陷定位
软件工程
搏博4 天前
软件工程之面向对象分析深度解析
软件工程·软件构建·需求分析·软件需求