当前位置: 首页 > news >正文

Bazel 教程

Bazel 语法详解

Bazel 的核心是 WORKSPACEBUILD 文件。它们使用 Starlark 语言(一种 Python 方言)编写。以下是 Bazel 语法的详细说明。


1. WORKSPACE 文件

WORKSPACE 文件用于定义工作空间的根目录,并声明外部依赖(如第三方库或工具链)。它是一个全局配置文件。

示例:
workspace(name = "my_project")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

# 下载一个外部依赖(例如 rules_go)
http_archive(
    name = "io_bazel_rules_go",
    sha256 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    urls = ["https://github.com/bazelbuild/rules_go/releases/download/v0.30.0/rules_go-v0.30.0.zip"],
)

# 加载外部依赖
load("@io_bazel_rules_go//go:deps.bzl", "go_rules_dependencies", "go_register_toolchains")
go_rules_dependencies()
go_register_toolchains()
关键点:
  • workspace(name = "my_project"):定义工作空间的名称,必须是唯一的。
  • load():用于加载外部规则或工具。
  • http_archive():用于下载外部依赖。

2. BUILD 文件

BUILD 文件用于定义构建目标(如二进制文件、库、测试等)。每个目录可以有一个或多个 BUILD 文件。

示例:
# 定义一个 C++ 二进制文件
cc_binary(
    name = "hello_world",
    srcs = ["main.cc"],
    deps = [":hello_lib"],
)

# 定义一个 C++ 库
cc_library(
    name = "hello_lib",
    srcs = ["hello.cc"],
    hdrs = ["hello.h"],
    visibility = ["//visibility:public"],
)

# 定义一个 C++ 测试
cc_test(
    name = "hello_test",
    srcs = ["test.cc"],
    deps = [":hello_lib"],
)
关键点:
  • 目标类型
    • cc_binary:生成可执行文件。
    • cc_library:生成库文件(静态库或动态库)。
    • cc_test:生成测试可执行文件。
  • 属性
    • name:目标的名称,必须是唯一的。
    • srcs:源文件列表(如 .cc 文件)。
    • hdrs:头文件列表(如 .h 文件)。
    • deps:依赖的其他目标(如库)。
    • visibility:控制目标的可见性(如 //visibility:public 表示对所有目标可见)。

3. 常用规则(Rules)

Bazel 支持多种编程语言,每种语言都有对应的规则。以下是一些常用规则:

C++ 规则
  • cc_binary:生成可执行文件。
  • cc_library:生成库文件。
  • cc_test:生成测试可执行文件。
Java 规则
  • java_binary:生成可执行 JAR 文件。
  • java_library:生成 Java 库。
  • java_test:生成 Java 测试。
Python 规则
  • py_binary:生成可执行 Python 脚本。
  • py_library:生成 Python 库。
  • py_test:生成 Python 测试。
Go 规则
  • go_binary:生成可执行 Go 程序。
  • go_library:生成 Go 库。
  • go_test:生成 Go 测试。

4. 依赖管理

Bazel 的依赖分为两种:

  1. 内部依赖:同一工作空间内的目标。
  2. 外部依赖:通过 WORKSPACE 文件引入的第三方库。
内部依赖

BUILD 文件中,通过 deps 属性引用其他目标:

cc_binary(
    name = "my_program",
    srcs = ["main.cc"],
    deps = ["//path/to:my_library"],
)
外部依赖

WORKSPACE 文件中,通过 http_archivegit_repository 引入:

http_archive(
    name = "com_google_googletest",
    urls = ["https://github.com/google/googletest/archive/v1.11.0.zip"],
    strip_prefix = "googletest-1.11.0",
)

然后在 BUILD 文件中引用:

cc_test(
    name = "my_test",
    srcs = ["test.cc"],
    deps = ["@com_google_googletest//:gtest"],
)

5. 可见性(Visibility)

Bazel 通过 visibility 属性控制目标的可见性。默认情况下,目标仅对同一 BUILD 文件中的其他目标可见。

示例:
cc_library(
    name = "my_lib",
    srcs = ["lib.cc"],
    hdrs = ["lib.h"],
    visibility = ["//visibility:public"],  # 对所有目标可见
)
  • //visibility:public:对所有目标可见。
  • //visibility:private:仅对同一 BUILD 文件中的目标可见。
  • //path/to:__pkg__:仅对指定路径下的目标可见。

6. 标签(Labels)

Bazel 使用标签(Labels)来唯一标识目标。标签的格式为:

//path/to:target_name
  • //:表示工作空间根目录。
  • path/to:目标所在的目录路径。
  • target_name:目标的名称。
示例:
  • //:hello_world:根目录下的 hello_world 目标。
  • //src:mainsrc 目录下的 main 目标。

7. 构建和运行命令

  • 构建目标
    bazel build //path/to:target_name
    
  • 运行目标
    bazel run //path/to:target_name
    
  • 测试目标
    bazel test //path/to:target_name
    

8. Demo:C++ 项目

以下是一个完整的 C++ 项目示例:

项目结构
my_project/
├── WORKSPACE
├── BUILD
├── main.cc
├── hello.cc
├── hello.h
└── test.cc
WORKSPACE
workspace(name = "my_project")
BUILD
cc_binary(
    name = "hello_world",
    srcs = ["main.cc"],
    deps = [":hello_lib"],
)

cc_library(
    name = "hello_lib",
    srcs = ["hello.cc"],
    hdrs = ["hello.h"],
    visibility = ["//visibility:public"],
)

cc_test(
    name = "hello_test",
    srcs = ["test.cc"],
    deps = [":hello_lib"],
)
main.cc
#include "hello.h"

int main() {
    say_hello();
    return 0;
}
hello.h
#ifndef HELLO_H
#define HELLO_H

void say_hello();

#endif
hello.cc
#include <iostream>
#include "hello.h"

void say_hello() {
    std::cout << "Hello, Bazel!" << std::endl;
}
test.cc
#include "hello.h"
#include <cassert>

void test_say_hello() {
    // Test
    assert(true);
}

int main() {
    test_say_hello();
    return 0;
}
构建和运行
# 构建
bazel build //:hello_world

# 运行
bazel run //:hello_world

# 测试
bazel test //:hello_test

相关文章:

  • MyBatis 中 SqlMapConfig 配置文件详解
  • HTML/CSS中交集选择器
  • 前七章综合练习
  • 集合 数据结构 泛型
  • Element UI常用组件
  • 知识库-登陆接口
  • 《论语别裁》第01章 学而(03) 四书五经的假面目
  • 萌新学 Python 之 if 语句的三目运算符
  • SFT数据指令评估-2.基于困惑度的5种指标(微调白盒模型)
  • 一台服务器将docker image打包去另一天服务器安装这个镜像
  • 在 .NET 8/9 中使用 AppUser 进行 JWT 令牌身份验证
  • Web3.py 入门笔记
  • 避坑:过早的文件结束符(EOF):解决“git clone龙蜥OS源码失败”的失败过程
  • 面试编程题
  • 【DeepSeek问答】QProcess::start是异步的吗?会使UI卡顿吗?
  • Java锁代码解析
  • 迅为RK3568开发板篇Openharmony配置HDF控制UART-UART 接口运作机制
  • Solon —— 容器
  • 【R语言】绘图
  • V4L2驱动之UVC
  • 为何选择上海?两家外企提到营商环境、人才资源……
  • 上海市国防动员办公室副主任吴斌接受审查调查
  • 第1现场 | 美国称将取消制裁,对叙利亚意味着什么
  • 体坛联播|C罗儿子完成国家队首秀,德约结束与穆雷合作
  • 上海建筑领域绿色发展2025年工作要点发布
  • 1156万+1170万,静安、宝山购彩者击中大乐透头奖