如何让项目的构建更有效率是工程中不可忽视的问题,特别是在项目的规模不断增大之后。传统的 C/C++ 项目,有诸如 Make、CMake 这样的工具,Java 项目则有 Maven/Gradle。但在真正企业级的大型项目里,可能会同时有 C++、Python、Go 或者 Java 项目,并且互相可能会有依赖关系。
Bazel 便是由 Google 开发和开源的项目构建测试工具,支持多种语言多个平台。Bazel 凭借其企业级的背景、远程执行的特性,被许多公司使用。Dropbox 在 2019 年末的博文中介绍了全面使用 Bazel 作为 CI/CD 工具。这篇文章将会以一个简单的项目为例,介绍 Bazel 的基本使用。
Bazel 的安装相对比较简单,在它的 GitHub Releases 页面就可以下载对应的二进制安装包。
构建 C++ 项目
Bazel 中比较重要的两个文件是:
WORKSPACE
:含有该文件的目录将会被视为根目录BUILD
:含有该构建规则文件的目录被视为项目的一个模块
下面以官方的 examples 为例。首先克隆项目到本地:
|
|
进入 examples/cpp-tutorial/stage1
目录下,有一个 WORKSPACE
文件,因为没有用到自定义的一些规则,所以该文件是空的。在 main
和目录下面有 BUILD
文件,包含了构建的目标:
|
|
第一行 load
导入了内置的 cc_binary
规则,之后的 hello-world
则实例化了这个规则,通过 srcs
参数指定了源文件。
在 stage1
目录下,通过命令 $ bazel run //main:hello-world
即可编译并执行 hello-world
目标。如果是使用 bazel build
命令的话则只是进行编译,构建的目标则是相对于根目录 //
的 main
目录下的 BUILD
里声明的 hello-world
目标。
|
|
在 stage2
的例子里,展示了如何使用 cc_library
库并定义依赖关系。
|
|
同样的,在 load
里引入 cc_binary
和 cc_library
两个规则。hello-world
目标在 deps
中指定了依赖当前目录下的 hello-greet
模块。如果需要用到其它目录下的模块,在 stage3
下面就有例子,deps
中的模块需要像 "//lib:hello-time"
这样指定根目录下的子模块。
构建 Python 项目
在 Bazel 中使用 Python,需要引入自定义的 Python 规则。Bazel 官方开源了 rules_python
。
首先确保默认的 Python 在 /usr/bin/python
路径下,可以输入 which python
来确认。如果没有的话,需要手动进行一下软链接:
|
|
接下来,创建一个新的工程目录 project
,首先需要在根目录下创建 WORKSPACE
文件,包含有 WORKSPACE
文件的目录将会被 Bazel 视为根目录。为了能够在这个工作区中使用 Python 构建规则,需要添加 Python 构建的规则到 WORKSPACE
:
|
|
在根目录下创建 hello/main.py
文件:
|
|
之后在 hello
下添加 BUILD
文件:
|
|
同样,运行 $ bazel run //hello:main
,便可以执行 main.py
。如果脚本需要参数的话,可以在中间用 --
分隔,并紧跟在后面指定参数: $ bazel run //hello:main -- <Arguments>
远程执行
远程执行也是 Bazel 的一个亮点。远程执行的好处是可以利用云平台的多个机器进行分布式构建,并且缓存编译,这样可以大大加快构建速度。关于远程执行,具体参考官方的 Remote execution overview。好像要自己搭。
参考: