Bazel 是由 Google 开发的一款高效的构建和测试工具,广泛应用于大型项目中。Bazel 使用一套特定的文件结构和配置文件来描述项目的构建过程。以下是 Bazel 常见的文件结构及各个文件的详细作用介绍:
一个典型的 Bazel 项目根目录结构可能如下所示:
my_project/
├── WORKSPACE
├── .bazelrc
├── BUILD
├── src/
│ ├── BUILD
│ ├── main/
│ │ ├── BUILD
│ │ ├── app/
│ │ │ ├── BUILD
│ │ │ └── ...
│ │ └── lib/
│ │ ├── BUILD
│ │ └── ...
│ └── test/
│ ├── BUILD
│ └── ...
├── third_party/
│ ├── BUILD
│ └── ...
└── README.md
WORKSPACE
作用:WORKSPACE 文件位于项目的根目录,用于定义项目的外部依赖和工作区信息。通过此文件,Bazel 知道如何获取和管理项目所依赖的第三方库、工具链等。
内容示例:
workspace(name = "my_project")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "rules_python",
url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.1.0.tar.gz",
strip_prefix = "rules_python-0.1.0",
)
load("@rules_python//python:repositories.bzl", "py_repositories")
py_repositories()
.bazelrc
作用:.bazelrc 文件用于配置 Bazel 的构建选项和参数。通过此文件,用户可以为不同的构建命令(如 build、test 等)设置默认参数,简化命令行操作。
内容示例:
common --copt=-O2
build --jobs=4
test --test_output=errors
BUILD
作用:根目录下的 BUILD 文件用于定义项目的顶层构建规则。虽然通常在子目录中定义具体的 BUILD 文件,但根目录的 BUILD 文件适用于需要在整个项目级别管理的构建目标。
内容示例:
load("//src/main:defs.bzl", "my_app")
my_app(
name = "my_app",
srcs = glob(["src/main/app/**/*.java"]),
deps = [
"//src/main/lib:lib",
],
)
src/
main/
和 test/
。src/BUILD
src/main/BUILD
src/main/app/
src/main/app/BUILD
src/main/lib/
src/main/lib/BUILD
src/test/
src/test/BUILD
third_party/
third_party/BUILD
README.md
WORKSPACE 文件是 Bazel 项目的入口文件,用于定义工作区的根,并管理外部依赖。它的主要职责包括:
workspace(name = "my_project")
指定工作区的名称。http_archive
、git_repository
等规则下载和管理第三方库。load
语句引入自定义规则或工具链配置。常见用法示例:
workspace(name = "my_project")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "rules_go",
urls = ["https://github.com/bazelbuild/rules_go/releases/download/v0.29.0/rules_go-v0.29.0.tar.gz"],
strip_prefix = "rules_go-0.29.0",
)
load("@rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
go_rules_dependencies()
go_register_toolchains()
BUILD 文件定义了项目中的构建目标和规则。每个 BUILD 文件对应一个目录,并描述该目录下的源代码如何被构建。
主要构建规则类型:
BUILD 文件示例:
cc_library(
name = "math_lib",
srcs = ["math.cpp"],
hdrs = ["math.h"],
visibility = ["//visibility:public"],
)
cc_binary(
name = "app",
srcs = ["main.cpp"],
deps = [":math_lib"],
)
BUILD 文件中的关键字段:
.bazelrc 文件用于配置 Bazel 构建的默认参数和选项。可以定义不同的构建模式(如 debug、release)、优化选项、并行构建设置等。
常见配置示例:
# 全局通用选项
build --copt=-O2
build --host_copt=-O2
# 调试模式
build:debug --compilation_mode=dbg
build:debug --strip=never
# 发布模式
build:release --compilation_mode=opt
build:release --strip=always
# 测试配置
test --test_output=errors
test --cache_test_results=no
# 并行构建
common --jobs=8
# 限制 Bazel 的内存使用, HOST_RAM 表示系统总内存(需替换为实际值),*.5 表示使用总内存的 50%
# 限制 CPU 核心数:可并行使用的 CPU 核心数为 6
build --local_ram_resources=HOST_RAM*.5 --local_cpu_resources=6
# 启用磁盘缓存:将构建中间结果(如编译的 .o 文件、生成的代码)缓存到指定目录(~/bazel-cache)
build --disk_cache=~/bazel-cache
使用方法:
可以通过命令行指定使用特定的配置,例如:
bazel build --config=release //src/main:app
.gitignore
作用:列出应被 Git 忽略的文件和目录,通常包括 Bazel 的输出目录(如 bazel-bin/
、bazel-out/
等)和临时文件。
示例:
bazel-*
*.launch
*.log
BUILD.bazel
BUILD.bazel
作为构建文件的名称,以避免与目录中的其他 BUILD 文件混淆。在 Bazel 的构建过程中,Bazel 会维护一组中间文件和输出文件,这些文件主要存储在 Bazel 的输出目录(默认是 bazel-out/
)中。以下是相关目录及其作用:
bazel-out/
bazel-bin/
bazel-out/
中对应的实际文件。bazel-genfiles/
genrule
、proto_library
等)生成的文件。bazel-testlogs/
这些目录通常会被自动管理,用户无需手动干预。
以下是一个简单的 Bazel 项目示例,帮助理解上述文件结构及其作用:
my_project/
├── WORKSPACE
├── .bazelrc
├── BUILD
├── src/
│ ├── BUILD
│ ├── main/
│ │ ├── BUILD
│ │ ├── app/
│ │ │ ├── BUILD
│ │ │ ├── main.cpp
│ │ │ └── ...
│ │ └── lib/
│ │ ├── BUILD
│ │ ├── math.cpp
│ │ └── math.h
│ └── test/
│ ├── BUILD
│ ├── test_main.cpp
│ └── ...
└── third_party/
├── BUILD
└── external_lib/
├── lib.cpp
└── lib.h
workspace(name = "my_project")
# 引入第三方 C++ 库示例
http_archive(
name = "external_lib",
urls = ["https://example.com/external_lib.tar.gz"],
strip_prefix = "external_lib-1.0.0",
)
load("@external_lib//:defs.bzl", "external_lib_rules")
external_lib_rules()
# 定义顶层应用程序目标
cc_binary(
name = "my_app",
srcs = ["src/main/app/main.cpp"],
deps = [
"//src/main/lib:math_lib",
"@external_lib//:external_lib",
],
)
cc_library(
name = "math_lib",
srcs = ["math.cpp"],
hdrs = ["math.h"],
visibility = ["//visibility:public"],
)
cc_test(
name = "math_test",
srcs = ["test_main.cpp"],
deps = [
"//src/main/lib:math_lib",
"@external_lib//:external_lib",
],
)
# 优化构建选项
build --copt=-O2
build --host_copt=-O2
# 并行构建设置
common --jobs=8
# 测试配置
test --test_output=errors
Bazel 允许用户通过 Starlark(Bazel 的配置语言)自定义构建规则和扩展功能。这些自定义规则通常放在 defs.bzl
或类似的 .bzl
文件中,并在 BUILD 文件中加载和使用。
defs.bzl 文件内容:
def my_app(name, srcs, deps=[]):
cc_binary(
name = name,
srcs = srcs,
deps = deps + ["//src/main/lib:math_lib"],
)
BUILD 文件中的使用:
load("//src/main:defs.bzl", "my_app")
my_app(
name = "my_custom_app",
srcs = ["app/custom_main.cpp"],
deps = [
"@external_lib//:external_lib",
],
)
通过自定义规则,可以简化构建过程,避免在多个 BUILD 文件中重复定义相似的构建逻辑。
Bazel 通过明确的文件结构和配置文件,实现了高效、可重复和可扩展的构建流程。