Bazel 基本使用
本文是 Bazel 学习笔记,记录了 Bazel 的一些核心概念和基本使用方法,构建目标为 Go 语言项目。
概念
Target(目标)
目标是Bazel构建系统中的基本单元,它代表构建过程中的一个输出文件或一个可运行的程序。每个目标都有一个名称和一组属性,例如源文件、依赖项和构建规则。
Rule(规则)
规则定义了如何构建一个目标。规则包括目标类型、名称、属性和构建命令。Bazel提供了许多内置规则,例如cc_library 和 cc_binary,以支持不同类型的目标。
Workspace(工作区)
工作区是Bazel构建系统的最高级别的概念,它包含一个或多个项目。工作区由一个或多个目录组成,每个目录包含一个BUILD文件和其他相关文件。
Package(包)
包是Bazel构建系统中的一个逻辑单元,它包含一个或多个相关的目标和规则。每个包都有一个名称和一个相对路径,例如//myproject/mypackage。
Label(标签)
标签是Bazel中唯一标识一个目标或规则的方式,它由包名和目标名组成,例如//myproject/mypackage:mytarget。
Dependency(依赖)
依赖是指一个目标需要另一个目标才能构建的情况。Bazel使用依赖关系来自动构建和管理项目中的依赖项。
Configuration(配置)
配置是指构建过程中的一组参数,例如编译器选项、库路径和环境变量。Bazel支持多个配置,例如debug和release,以便在不同的环境中构建项目。
文件
WORKSPACE
用于将目录及其内容标识为 Bazel 工作区,并位于项目目录结构的根目录中。Bazel 构建项目时,所有输入都必须位于同一工作区中。除非链接,否则位于不同工作区中的文件彼此独立。
BUILD.bazel
用于告知 Bazel 如何构建项目的不同部分。工作区中包含 BUILD
文件的目录就是一个软件包。每个 BUILD
文件至少需要一条规则(即一组指令),用于告知 Bazel 如何构建所需的输出,例如可执行二进制文件或库。BUILD
文件中构建规则的每个实例都称为目标,指向一组特定的源文件和依赖项。目标还可以指向其他目标。
示例:
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
)
.bazelrc
bazel 是 Java 开发的,可以在该文件中设置 JVM,此外,可以配置 go 代理,可以配置目标系统等。
# 设置JVM
startup --host_jvm_args=-XX:+UseParallelGC --host_jvm_args=-Xmx6g --host_jvm_args=-Xms1g
# 设置CoreDump
startup --unlimit_coredumps
# 设置GOPROXY
test --action_env=GOPROXY=https://goproxy.cn
build --action_env=GOPROXY=https://goproxy.cn
run --action_env=GOPROXY=https://goproxy.cn
# 设置GOSUMDB
test --action_env=GOSUMDB=goproxy.cn/sumdb/sum.golang.org
build --action_env=GOSUMDB=goproxy.cn/sumdb/sum.golang.org
run --action_env=GOSUMDB=goproxy.cn/sumdb/sum.golang.org
# 设置编译目标平台
build --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64
run --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64
自定义 rule (*.bzl)
如果你的项目有一些复杂构造逻辑、或者一些需要复用的构造逻辑,那么可以将这些逻辑以函数形式保存在 .bzl
文件,供 WORKSPACE
或者 BUILD
文件调用。其语法跟 Python 类似:
def download_package():
# 下载 Bazel Go语言 规则集
if not native.existing_rule("io_bazel_rules_go"):
http_archive(
name = "io_bazel_rules_go",
sha256 = "56d8c5a5c91e1af73eca71a6fab2ced959b67c86d12ba37feedb0a2dfea441a6",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.37.0/rules_go-v0.37.0.zip",
"https://github.com/bazelbuild/rules_go/releases/download/v0.37.0/rules_go-v0.37.0.zip",
],
)
# 下载 Bazel Gazelle 规则集
if not native.existing_rule("bazel_gazelle"):
http_archive(
name = "bazel_gazelle",
sha256 = "ecba0f04f96b4960a5b250c8e8eeec42281035970aa8852dda73098274d14a1d",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.29.0/bazel-gazelle-v0.29.0.tar.gz",
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.29.0/bazel-gazelle-v0.29.0.tar.gz",
],
)
.bazelversion
配置 bazel 版本。
步骤
设置 WORKSPACE
workspace(name = "go-bazel")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "io_bazel_rules_go",
sha256 = "c8035e8ae248b56040a65ad3f0b7434712e2037e5dfdcebfe97576e620422709",
urls = [
"https://github.com/bazelbuild/rules_go/releases/download/v0.44.0/rules_go-v0.44.0.zip",
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.44.0/rules_go-v0.44.0.zip",
],
)
http_archive(
name = "bazel_gazelle",
sha256 = "32938bda16e6700063035479063d9d24c60eda8d79fd4739563f50d331cb3209",
urls = [
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.35.0/bazel-gazelle-v0.35.0.tar.gz",
"https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.35.0/bazel-gazelle-v0.35.0.tar.gz",
],
)
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
############################################################
# Define your own dependencies here using go_repository.
# Else, dependencies declared by rules_go/gazelle will be used.
# The first declaration of an external repository "wins".
############################################################
# gazelle:repository go_repository name=org_golang_x_xerrors importpath=golang.org/x/xerrors
load("//:deps.bzl", "go_dependencies")
# gazelle:repository_macro deps.bzl%go_dependencies
go_dependencies()
go_rules_dependencies()
go_register_toolchains(version = "1.21.5")
gazelle_dependencies()
其中,Gazelle 是一个自动生成 Bazel 编译文件的工具,包括给 WORKSPACE
添加外部依赖、扫描源文件依赖自动生成BUILD.bazel
文件等。Gazelle 原生支持Go和 protobuf。
Protobuf
需要在 WORKSPACE 中添加:
http_archive(
name = "com_google_protobuf",
sha256 = "d0f5f605d0d656007ce6c8b5a82df3037e1d8fe8b121ed42e536f569dec16113",
strip_prefix = "protobuf-3.14.0",
urls = [
"https://github.com/protocolbuffers/protobuf/archive/v3.14.0.tar.gz",
"https://mirror.bazel.build/github.com/protocolbuffers/protobuf/archive/v3.14.0.tar.gz",
],
)
protobuf_deps()
命令
使用 Gazelle 构建 BUILD.bazel
:
bazel run //:gazelle
更新 golang 依赖:
bazel run //:gazelle-update-repos
跑测试:
bazel test //...
构建项目:
bazel build //...
Docker 镜像
在 WORKSPACE 中添加:
http_archive(
name = "io_bazel_rules_docker",
sha256 = "b1e80761a8a8243d03ebca8845e9cc1ba6c82ce7c5179ce2b295cd36f7e394bf",
urls = ["https://github.com/bazelbuild/rules_docker/releases/download/v0.25.0/rules_docker-v0.25.0.tar.gz"],
)
load(
"@io_bazel_rules_docker//repositories:repositories.bzl",
container_repositories = "repositories",
)
container_repositories()
load("@io_bazel_rules_docker//repositories:deps.bzl", container_deps = "deps")
container_deps()
基础镜像
在 WOKRSPACE 中拉取:
load("@io_bazel_rules_docker//container:pull.bzl", "container_pull")
container_pull(
name = "alpine_linux_amd64",
registry = "index.docker.io",
repository = "library/alpine",
tag = "latest",
)
构建镜像
在 BUILD 中:
container_image(
name = "image",
base = "@alpine_linux_amd64//image",
entrypoint = ["/servicea"],
files = [
":servicea",
],
)
推送镜像
在 BUILD 中:
container_push(
name = "image-push",
format = "Docker",
image = ":image",
registry = "registry.cn-hangzhou.aliyuncs.com",
repository = "bazel/greeter",
tag = "latest",
)
参考
[3] go-bazel
[4] bazel-gazelle