# 编译器Bazel
谷歌开源编译器Bazel,运作原理为:加载BUILD与目标相关的文件,编译器分析输入及其依赖关系,应用指定的构建规则,并生成action图。最后对输入执行构建操作,生成最终可执行文件。Bazel在GitHub上的开源地址:https://github.com/bazelbuild/bazel,竟然主要是Java开发的。
优点:
- 构建快。支持增量编译, 对依赖关系进行了优化,从而支持并发执行。
- 可构建多种语言。bazel可用来构建Java、C++、Android、IOS等语言,支持Windows、Linux和macOS等不同的平台。
- 可伸缩。可处理任意大小的代码库,可处理多个库,也可以处理单个库。
- 可扩展。使用bazel扩展语言可支持新语言和新平台。
## 安装
参考官方手册:https://docs.bazel.build/versions/5.1.0/install-ubuntu.html
一、使用apt源安装
这个可能源在国外,在添加apt源时会有问题,所以不如用编译好的安装包的形式进行安装,见方式二。
```bash
###下面使用apt安装
#安装一些必要的工具
sudo apt install apt-transport-https curl gnupg
#添加Bazel分发URI仓库源
curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor > bazel.gpg
sudo mv bazel.gpg /etc/apt/trusted.gpg.d/
echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
#安装和更新Bazel
sudo apt update && sudo apt install bazel
```
二、使用编译好的二进制包方式安装
各种安装包可以在官方开源的GitHub仓库获取:https://github.com/bazelbuild/bazel/releases。尽量选择最新,所以我选择5.1.1版本下的installer安装包进行安装。
```bash
##用二进制编译包安装需要一些依赖,下面先安装这些依赖,如果机器上已经安装过滤,就不用执行安装依赖的步骤
#bazel需要C++编译器,unzip和zip工具
sudo apt install g++ unzip zip
#bazel需要jdk,因为它主要是java开发的
#如果是Ubuntu16.04的默认使用jdk8
sudo apt-get install openjdk-8-jdk
#如果是Ubuntu18.04的默认使用jdk11
sudo apt-get install openjdk-11-jdk
#下载二进制安装包
wget https://github.com/bazelbuild/bazel/releases/download/5.1.1/bazel-5.1.1-installer-linux-x86_64.sh
#添加执行权限
chmod +x bazel-5.1.1-installer-linux-x86_64.sh
#执行安装
./bazel-5.1.1-installer-linux-x86_64.sh --user
#该--user标志将 Bazel 安装到$HOME/bin系统上的目录并将.bazelrc路径设置为$HOME/.bazelrc. 使用该--help命令查看其他安装选项。
#设置环境变量
#如果使用上述--user标志运行 Bazel 安装程序,则 Bazel 可执行文件将安装在您的$HOME/bin目录中。那么需要将这个目录添加到环境变量中
export PATH="$PATH:$HOME/bin"
#添加到~/.bashrc中使其持久化
##如果不想用user模式安装
##先查看一下安装的选项
./bazel-5.1.1-installer-linux-x86_64.sh --help
#用管理员安装
sudo ./bazel-5.1.1-installer-linux-x86_64.sh
#这样就安装好了bazel,现在查询一下版本
bazel --version
#输出: bazel 5.1.1
```
## 使用
使用Bazel编译项目,这里有编译C++的三个例子,https://github.com/bazelbuild/examples/。
**WORKSPACE**
- 存放名为 `WORKSPACE` 的文件的目录,是整个工程的根目录。换言之,整个工程的根目录由 `WORKSPACE` 来标识。整个工程的根目录也被叫做 workspace。
- 大部分情况下 `WORKSPACE` 文件为空。
**BUILD**
在 workspace下,考虑每一个子目录:如果存放了名为 BUILD 的文件,那么这个目录就是一个 package,意思是一个包。
BUILD 文件内容:它的内容包括设定的编译 target,比如 cc_binary 表示一个可执行文件,cc_library 表示一个库;每个 target 里又包括 name 等字段。
```
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
cc_library(
name = "hello-greet",
srcs = ["hello-greet.cc"],
hdrs = ["hello-greet.h"],
)
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
deps = [":hello-greet"],
)
```
Bazel默认编译生成文件会在工程目录下链接到用户的.cache目录下,所以不是太让人舒服。不如CMake等工具直接来的舒服点。