Bazel 使用总结

摘要

Bazel是一个支持多语言、跨平台的构建工具。Bazel支持任意大小的构建目标,并支持跨多个仓库的构建,是Google主推的一种构建工具。

开源编译的困境:

1、开源成为当前软件开发的主旋律。如何方便地获取依赖,并做到平滑升级很重要。如果构建工具能够很方便地获取源代码。

2、混合多语言编程成为一种选择。每种语言都有自己适用的场景,但是构建多语言的软件系统非常具有挑战性。例如,Python社区很喜欢搭配C/C++,高性能计算扔个C/C++,Python提供编程接口。

3、代码复用。我只想复用第三方的一个头文件,而不是整个系统。拒绝拷贝是优秀程序员的基本素养,如果构建工具能帮我方便地获取到所依赖的组件,剔除不必要的依赖。

4、增量构建。当只修改了一行代码,构建系统能够准确计算需要构建的依赖目标,而不是全构建;否则生命都浪费在编译上了。

5、云构建, 大型软件公司,复用计算资源,可以带来巨大的收益。

Bazel 优势

构建快。支持增量编译。对依赖关系进行了优化,从而支持并发执行。

可构建多种语言。bazel可用来构建Java C++ Android ios等很多语言和框架,并支持mac windows linux等不同平台

可伸缩。可处理任意大小的代码库,可处理多个库,也可以处理单个库

可扩展。使用bazel扩展语言可支持新语言和新平台。

部署使用

方式一:

wget https://copr.fedorainfracloud.org/coprs/vbatts/bazel/repo/epel-7/vbatts-bazel-epel-7.rep --no-check-certificate
mv vbatts-bazel-epel-7.rep /etc/yum.repos.d/
cd /etc/yum.repos.d
mv vbatts-bazel-epel-7.rep vbatts-bazel-epel-7.repo
yum install -y bazel

方式二:

# 下载 demo 用例
git clone https://github.com/abseil/abseil-cpp.git /src/workspace

# 创建一个文件夹,其中包含要在各 build 之间共享的缓存结果
mkdir -p /tmp/build_output/

# 使用 Bazel 容器构建项目,并在主机的输出文件夹中提供构建输出
docker run \
  -e USER="$(id -u)" \
  -u="$(id -u)" \
  -v /src/workspace:/src/workspace \
  -v /tmp/build_output:/tmp/build_output \
  -w /src/workspace \
  l.gcr.io/google/bazel:latest \
  --output_user_root=/tmp/build_output \
  build //absl/...

# 延申: 使用排错程序构建项目,方法是添加 --config=asan|tsan|msan 构建标志,以便相应地选择 AddressSanitizer (asan)、ThreadSanitizer (tsan) 或 MemorySanitizer (msan)。 
docker run \
  -e USER="$(id -u)" \
  -u="$(id -u)" \
  -v /src/workspace:/src/workspace \
  -v /tmp/build_output:/tmp/build_output \
  -w /src/workspace \
  l.gcr.io/google/bazel:latest \
  --output_user_root=/tmp/build_output \
  build --config={asan | tsan | msan} -- //absl/... -//absl/types:variant_test

用例实践

创建go的运行文件:

package main

import "fmt"

func main() {
	fmt.Println("hello world")
}

创建 WORKSPACE 文件:

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

http_archive(
    name = "io_bazel_rules_go",
    urls = [
        "https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/rules_go/releases/download/0.19.0/rules_go-0.19.0.tar.gz",
        "https://github.com/bazelbuild/rules_go/releases/download/0.19.0/rules_go-0.19.0.tar.gz",
    ],
    sha256 = "9fb16af4d4836c8222142e54c9efa0bb5fc562ffc893ce2abeac3e25daead144",
)

load("@io_bazel_rules_go//go:deps.bzl", "go_rules_dependencies", "go_register_toolchains")

go_rules_dependencies()
go_register_toolchains()

创建 BUILD.bazel 文件:

load("@io_bazel_rules_go//go:def.bzl", "go_binary")

go_binary(
    name = "test",
    srcs = ["main.go"],
    importpath = "test",
    visibility = ["//visibility:private"],
)

编译运行:

bazel run //:test

自动生成

创建t1和t2两个文件夹,写入两个文件:

# 创建 t1 目录
mkdir t1
vi t1/main.go

# 创建 t2 目录
mkdir t2
vi t2/main.go

在项目的根目录的BUILD.bazel中配置加载并配置Gazelle

load("@bazel_gazelle//:def.bzl", "gazelle")
# gazelle:prefix test  
gazelle(name = "gazelle")

需要注意的是 # 后面的内容对于Bazel而言是注释,对于Gazelle来说却是一种语法,会被Gazelle运行时所使用。当然Gazelle除了可以通过bazel rule运行,也可以单独在命令行中执行。

根目录下面执行:

# 自动生成
bazel run //:gazelle

# 编译
bazel run t1:t1

容器编译

posted @ 2023-01-29 18:43  流雨声  阅读(638)  评论(0编辑  收藏  举报