文章目录
- 1. What is bazel?
- 2. bazel的核心原理
- 2.1 bazel的构建模型
- 2.2 bazel的核心概念
- 2.3 bazel的关键特性
- 3. bazel的使用
- 3.1 划分项目结构
- 3.2 编写BUILD文件
- 3.3 bazel常用命令
- 3.4 bazel依赖管理
- 参考内容
1. What is bazel?
bazel是一个开源的构建工具,它基于声明式构建语言和精确的依赖管理,一般大型项目的构建会使用bazel。
2. bazel的核心原理
2.1 bazel的构建模型
- 依赖图DAG:bazel基于依赖图构建。bazel将构建过程建模为有向无环图,每个节点表示一个构建目标(如源文件、库、二进制等),边表示依赖关系。(基于依赖图构建的优势:重构的时候可仅重新构建受影响的节点,实现高效增量构建)
- 内容寻址存储CAS:每个构件产物(如.o文件)的哈希值由其内容决定,避免重复构建相同内容。
- 沙箱机制:在隔离环境中执行构建动作(如编译、链接),确保构建过程不受主机环境影响,提升可重现性。
2.2 bazel的核心概念
- WORKSPACE:WORKSPACE文件一般位于项目的根目录下,用于定义外部依赖和全局配置;
- BUILD:每个目录下的BUILD文件或BUILD.bazel文件,用于声明本目录的构建目标(如cc_library)
- Target:目标,是BUILD文件中定义的最小构建单元,比如库、二进制文件等;
- Rule:规则,用于描述如何从输入(源文件、依赖)生成输出(如编译、打包)。
2.3 bazel的关键特性
- 增量构建:即仅构建受代码变更影响的目标;
- 分布式构建:支持将构建任务分发到多台机器(但需要配置远程执行环境);
- 远程缓存:共享构建缓存,加速团队协作;
- 跨平台:支持多操作系统,同一构建描述文件可跨平台使用
3. bazel的使用
3.1 划分项目结构
首先需要划分项目结构,确定每个BUILD文件的位置。假设项目结构如下:
my_project/
├── WORKSPACE # 工作区配置文件(可留空)
├── src/
│ ├── main.c # 主程序
│ ├── lib/
│ │ ├── utils.c # 库源码
│ │ └── utils.h
│ └── BUILD # 构建规则
└── tests/└── test.c # 测试代码
3.2 编写BUILD文件
示例:
# src/BUILD# 定义静态库
cc_library(name = "utils", # 目标名称srcs = ["lib/utils.c"], # 源文件hdrs = ["lib/utils.h"], # 头文件visibility = ["//visibility:public"], # 对其他目录可见
)# 定义可执行文件
cc_binary(name = "main", # 目标名称srcs = ["main.c"], # 主程序源文件deps = [":utils"], # 依赖的库
)# 定义测试
cc_test(name = "test_utils", # 测试目标名称srcs = ["test.c"], # 测试代码deps = [":utils"], # 依赖的库
)
3.3 bazel常用命令
- 构建目标
# 示例 bazel build //src:main # 用于构建src目录下的main目标,在BUILD文件中包含对应的target # 命令格式 bazel build [flags] <targets...> # 常用的目标模式 //src:main # 指定具体目标 //src/... # src目录下的所有目标 //... # 整个工作区所有目标 @repo//path:target # 外部依赖目标
- 运行程序
bazel run //src:main # 构建并运行main目标
- 执行测试
bazel test //src:test_utils
- 清理构建缓存
bazel clean # 清理所有的构建产物
3.4 bazel依赖管理
内部依赖:使用//path/to:target
语法引用项目内目标;
外部依赖:需要在WORKSPACE文件中声明,并在BUILD文件中使用外部依赖。例如:
当前项目my_project依赖子模块include,include中包含了my_project依赖的头文件,在WORKSPACE中声明:
# new_local_repository规则用于将本地目录或文件引入bazel工作区作为外部依赖;该规则将普通目录转换为bazel仓库
load("@bazel_tools//tools/build_defs/repo:local.bzl", "new_local_repository")
new_local_repository(name = "include" # 仓库名称path = "include" # 绝对路径或相对路径build_file = "include.BUILD" # 可选,指定构建规则文件
)
在src/BUILD
文件中引用外部依赖:
cc_binary(name = "main", # 目标名称srcs = ["main.c"], # 主程序源文件deps = [":utils","@include//:include_headers" # 引用外部依赖。假设include.BUILD中包含了名为include_headers的目标],
)
参考内容
官方文档: https://bazel.build