1 Bazel简介
1.1 Bazel是什么
Bazel 是 Google 开源的构建 + 测试一体化工具 ,前身是谷歌内部的构建系统 Blaze,2015 年对外开源;名字 Bazel 就是 Blaze 的字母重组词。

定位:类似 Make / CMake / Gradle,但专门为巨型单体仓库 monorepo、多语言、跨平台、可复现构建设计。
1.2 核心特点
声明式构建,Starlark 语言
- 用
BUILD文件(语法是 Starlark ,Python 子集)描述目标:cc_binary、cc_library、java_library、py_test等。 - 描述的是目标和依赖关系,而不是直接写编译器命令;Bazel 自动推导编译链路,和 Makefile 那种写 shell 命令思路完全不同Bazel。
- 还有
WORKSPACE文件,用来声明外部依赖(远程 Git 仓库、Maven 包等)。
内容哈希缓存 + 增量构建 + 远程缓存
- 只重新编译被改动的目标,并且不是靠文件修改时间,而是文件内容哈希判断是否需要重跑
- 支持远程缓存、远程执行:多开发者、CI 共享构建产物,大仓库构建速度提升巨大,Google 内部缓存命中率极高Bazel。
- 自动并行执行互不依赖的构建 / 测试任务。
多语言、跨平台
- 原生支持 C/C++、Java、Go、Python、Rust、TypeScript、Objective-C
- 同一套 BUILD 文件,可以编译 Linux/macOS/Windows 服务端、Android、iOS 移动端程序,一套定义多平台输
1.3 适合什么项目
- 大型单体仓库 monorepo,多语言混编(C++ + Java + Python 共存)
- 跨平台(同时编译服务器 + 移动端)
- 大量自动化测试,CI 构建压力大
- 要求构建结果可复现,团队多开发者协作
2 在Ubuntu中安装Bazel工具
sh
curl -LO https://github.com/bazelbuild/bazel/releases/download/7.4.0/bazel-7.4.0-linux-x86_64
chmod +x bazel-7.4.0-linux-x86_64
sudo mv bazel-7.4.0-linux-x86_64 /usr/local/bin/bazel
bazel --version
Ubuntu中下载的很慢,试了下Windows中下载的快一点,下载后复制进来,继续操作。

可以看到bazel的版本是7.4.0了。
3 Bazel构建测试
参考bazel的示例代码:https://github.com/bazelbuild/examples/tree/main/cpp-tutorial/stage1
3.1 测试代码
MODEL.bazel
sh
bazel_dep(name = "rules_cc", version = "0.0.17")
main/BUILD
sh
load("@rules_cc//cc:cc_binary.bzl", "cc_binary")
cc_binary(
name = "hello",
srcs = ["hello.cpp"],
)
main/hello.cpp
c++
#include <ctime>
#include <string>
#include <iostream>
std::string get_greet(const std::string& who) {
return "Hello " + who;
}
void print_localtime() {
std::time_t result = std::time(nullptr);
std::cout << std::asctime(std::localtime(&result));
}
int main(int argc, char** argv) {
std::string who = "world";
if (argc > 1) {
who = argv[1];
}
std::cout << get_greet(who) << std::endl;
print_localtime();
return 0;
}
项目结构
sh
xxpcb@xxpcb-ubuntu20:~/myTest/Bazel/test_demo$ tree
.
└── test1
├── main
│ ├── BUILD
│ └── hello.cpp
└── MODULE.bazel
2 directories, 3 files
xxpcb@xxpcb-ubuntu20:~/myTest/Bazel/test_demo$
3.2 开始构建
构建后会从github的bazelbuild下载文件,可能是国内环境受限,报错了。
加了一个国内镜像地址试了也不行。

注意到,在项目中自动生成了一个MODEL.bazel.lock

这个是Bzlmod 去 BCR(Bazel Central Registry)下载 rules_cc,虽然刚才又配置了 ghproxy 的 registry,但ghproxy 有时候访问不稳定,直接超时
3.3 构建失败问题解决
- 方案A:学习 Bazel 入门,直接关掉 Bzlmod,不用 MODULE.bazel,回到老的 WORKSPACE 模式,不需要联网下载 rules_cc
- 方案B:继续 Bzlmod + MODULE.bazel,需要配置
--module_mirrors,比较复杂,后续再研究
开始修改
3.3.1 代码修改
sh
# 删除MODULE.bazel,Bzlmod就不会自动拉取rules_cc了
rm MODULE.bazel
# 创建 WORKSPACE 文件(空文件即可,经典老工作区标记)
touch WORKSPACE
main/BUILD 文件去掉开头load那一行
sh
cc_binary(
name = "hello",
srcs = ["hello.cpp"],
)
3.3.2 关闭Bzlmod
命令行参数(单次生效)
sh
bazel build --noenable_bzlmod //main:hello
写到.bazelrc 永久关闭(推荐,一劳永逸)
sh
echo "common --noenable_bzlmod" >> ~/.bazelrc
3.3.3 再次执行
sh
bazel build //main:hello
//双斜杠:工作区根目录起点//= 项目根(本例test1/,里面放 WORKSPACE)//main就是根目录下的main文件夹
:冒号:分隔 package 路径 和 target 目标名- 冒号前面:package(包路径
//main) - 冒号后面:target(在 BUILD 文件 内定义的目标名称
hello)
- 冒号前面:package(包路径
这次执行成功了,注意到生成了多个bazel的目录

3.4 测试可执行程序的运行

3.5 构建产物分析
- bazel-bin:编译输出的二进制、库、头文件,最终产物在这里
- bazel-out:构建的核心工作目录,存放编译中间产物(体量最大)
- bazel-test1:Bazel 的执行根目录(execution root)
- bazel-testlogs:单元测试的日志目录
3.5.1 bazel目录软链接
生成的bazel目录,实际是软链接,执行~/.cache目录
sh
xxpcb@xxpcb-ubuntu20:~/myTest/Bazel/test_demo/test1$ ls -l
total 20
lrwxrwxrwx 1 xxpcb xxpcb 115 Oct 18 16:29 bazel-bin -> /home/xxpcb/.cache/bazel/_bazel_xxpcb/139b038fc59e32075309080b94868442/execroot/__main__/bazel-out/k8-fastbuild/bin
lrwxrwxrwx 1 xxpcb xxpcb 98 Oct 18 16:29 bazel-out -> /home/xxpcb/.cache/bazel/_bazel_xxpcb/139b038fc59e32075309080b94868442/execroot/__main__/bazel-out
lrwxrwxrwx 1 xxpcb xxpcb 88 Oct 18 16:29 bazel-test1 -> /home/xxpcb/.cache/bazel/_bazel_xxpcb/139b038fc59e32075309080b94868442/execroot/__main__
lrwxrwxrwx 1 xxpcb xxpcb 120 Oct 18 16:29 bazel-testlogs -> /home/xxpcb/.cache/bazel/_bazel_xxpcb/139b038fc59e32075309080b94868442/execroot/__main__/bazel-out/k8-fastbuild/testlogs
drwxrwxr-x 2 xxpcb xxpcb 4096 Oct 18 16:28 main
-rw-rw-r-- 1 xxpcb xxpcb 0 Oct 18 16:27 WORKSPACE
xxpcb@xxpcb-ubuntu20:~/myTest/Bazel/test_demo/test1$
进入.cache目录看下
sh
xxpcb@xxpcb-ubuntu20:~/myTest/Bazel/test_demo/test1/bazel-out$ cd ~/.cache/
xxpcb@xxpcb-ubuntu20:~/.cache$ ls
bazel evolution ibus mesa_shader_cache mozilla thunderbird update-manager-core
bazelisk fontconfig ibus-table Microsoft rhythmbox tracker yelp
event-sound-cache.tdb.9fe5b643f31a452cad31d0c22abb2f43.x86_64-pc-linux-gnu gstreamer-1.0 libgweather motd.legal-displayed thumbnails ubuntu-report
xxpcb@xxpcb-ubuntu20:~/.cache$ cd bazel
xxpcb@xxpcb-ubuntu20:~/.cache/bazel$ ls
_bazel_xxpcb
xxpcb@xxpcb-ubuntu20:~/.cache/bazel$ cd _bazel_xxpcb/
xxpcb@xxpcb-ubuntu20:~/.cache/bazel/_bazel_xxpcb$ ls
139b038fc59e32075309080b94868442 cache install
再进入bazel/_bazel_xxpcb,有3个子目录
路径:~/.cache/bazel/_bazel_xxpcb/,这一层叫 outputUserRoot,当前用户 xxpcb 全部 Bazel 数据都放这里
- 139b038fc59e32075309080b94868442:output_base,输出基目录,MD5 哈希
- cache:全局共享仓库缓存 repository cache
- install:Bazel 二进制第一次运行时,会把内嵌的 Java 服务 jar、linux-sandbox、辅助工具脚本解压到这里Bazel
3.5.2
MD5哈希
- 名字是项目工作区路径做 MD5 哈希 生成的一串字符,一个项目对应一个哈希文件夹
- Bazel Server 进程、编译沙盒、
external/外部仓库、编译 action 缓存、编译中间产物 - 还存 Bazel 服务的 PID、日志、JVM 日志、沙盒执行目录 execroot
- 命令
bazel clean --expunge会清空这个目录

如何确认项目对应的哈希值,可以用这个指令
sh
xxpcb@xxpcb-ubuntu20:~/myTest/Bazel/test_demo/test1$ bazel info output_base
/home/xxpcb/.cache/bazel/_bazel_xxpcb/139b038fc59e32075309080b94868442
xxpcb@xxpcb-ubuntu20:~/myTest/Bazel/test_demo/test1$
cache
- 跨项目共享!所有 Bazel 工程共用这个缓存
- 通过
http_archive/ Bzlmod 下载的外部压缩包(rules_cc、protobuf 等第三方依赖),按 SHA256 哈希存储 - 同一个第三方包,A 项目下载过,B 项目再用直接复用,不用重复联网下载

install
- 不同 Bazel 版本会按哈希分开存放
- 包含
A-server.jar:Bazel 后台 Server 核心程序 - 沙盒工具、process-wrapper 等底层执行工具
- 只要不升级 Bazel 版本,这个目录基本不会变动

3.5.3 构建产物清除
bazel clean:清除bazel软链接那些文件bazel clean --expunge:清除cache中对应的哈希目录

4 总结
本篇介绍了Bazel构建工具的基础知识,并在Ubuntu中进行环境配置,使用一个最基础的hello word程序进行编译运行测试。