Bazel应用方法

Bazel应用方法

Bazel简单应用

1.创建工作空间workspace

工作空间是一个保留你工程的源文件以及Bazel build输出的目录。
Bazel应用方法
创建方法为:指定一个目录作为Bazel工作空间,创建一个名为WORKSPACE的空文件在该目录下。

当Bazel编译工程时,所有的输入和依赖必须在相同的workspace下。

2.书写BUILD文件

在github上可以下载bazel教程包含一些例子。

git clone https://github.com/bazelbuild/examples

一个BUILD文件包含几个不同类型的bazel指令。
最重要的类型是build rule,告知Bazel如何去build想要的输出,比如execuatable binaries或者libraries。
每一个BUILD文件中的build rule叫做一个target,该target指向对应的源文件或依赖集合。一个target也可以指向其他target

参考examples/cpp-tutorial/stage1/main目录下的一个简单的BUILD文件。里面仅包含一个target和一个build rule。
Bazel应用方法
在这个例子中,hello-worldtarget示例cc_binaries规则,该规则告知Bazel根据hello-world.cc源文件去build一个可执行binary。
其中targetsrc表明Bazel build的target是哪个源文件。

3.编译工程

拿着教程的例子来尝试编译。将目录转到examples/cpp-tutorial/stage1下,跑以下命令:

bazel build //main:hello-world

注意到target label,//main:部分是该BUILD文件相对于workspace根目录的位置,hello-world是我们命名的target。

之后Bazel会输出以下类似的消息:

INFO: Found 1 target...
Target //main:hello-world up-to-date:
  bazel-bin/main/hello-world
INFO: Elapsed time: 2.267s, Critical Path: 0.25s

表明你编译成功。Bazel将build的输出放在workspace根下的bazel-bin目录下。
编译成功后会生成一个可执行文件,可以输入以下command:

bazel-bin/main/hello-world

4.可视化文件依赖图

生成一个表示依赖图的text,在workspace的根目录下运行command:

bazel query --notool_deps --noimplicit_deps 'deps(//main:hello-world)' \
  --output graph

上述command告知Bazel去寻找对于target//main:hello-world的所有依赖,并表示成一个图。

接着paste the text into GraphViz

Bazel应用方法
现在我们已经建立了workspace,built我们的project,检查了我们的依赖。让我们来些更复杂的吧。

Refine your Bazel build

当一个单一的target对于一个小project已经足够,我们会想要将一个大工程拆分成几个targets和packages,使得每次只需编译更改的部分,来加速builds。

1.详细的多重build targets

以官方教程来做例子,以下为cpp-tutorial/stage2/main目录下的BUILD文档:
Bazel应用方法
在这个BUILD文档中,Bazel首先编译hello-greetlibrary,接着是hello-worldbinary。在hello-worldtarget中的deps属性,告知Bazel,编译hello-worldbinary需要hello-greetlibrary。

接下来我们需要编译我们的工程,转到cpp-tutorial/stage2目录下,运行以下conmand:

bazel build //main:hello-world

同样会生成以下信息:

INFO: Found 1 target...
Target //main:hello-world up-to-date:
  bazel-bin/main/hello-world
INFO: Elapsed time: 2.399s, Critical Path: 0.30s

接着可以运行可执行文件:

bazel-bin/main/hello-world

如果这时你修改了hello-greet.cc,并rebuild the project,Bazel将会仅仅重新编译该file。
Bazel应用方法
以上,我们现在已经build过包含两个target的project。

2.应用多重packages

我们将工程分成多个packages,比如官方教程cpp-tutorial/stage3的目录内容:
Bazel应用方法
上图中,一个project包含两个子目录(sub-directories),每个目录都包含一个BUILD文件。对于Bazel来说,这个workspace包含两个packages,lib和main。

其中lib/BUILD文档:
Bazel应用方法
main/BUILD文档:
Bazel应用方法
As we can see,在main package中的 hello-worldtarget依赖lib包中的 hello-time(因此在deps中写作//lib:hello-time)。
Dependency Graph:
Bazel应用方法
注意到我们将lib/BUILD中的//lib:hello-timetarget对于main/BUILDtarget清晰地可视化,通过visibility属性。因为默认target只会将在同一个BUILD文档中的target可视化。(Bazel使用target visibility来防止像公有API中库的实现细节的泄露等情况)

接着我们来编译该工程,切换目录到cpp-tutorial/stage3and run the following command:

bazel build //main:hello-world

输出:

INFO: Found 1 target...
Target //main:hello-world up-to-date:
  bazel-bin/main/hello-world
INFO: Elapsed time: 0.167s, Critical Path: 0.00s

最后运行:

bazel-bin/main/hello-world

以上,我们已经build过包含两个package的project。

3.应用labels对于引用的targets

Bazel应用labels对于引用的targets,例如://main:hello-worldor//lib:hello-time
语法为:

//path/to/package:target-name

如果target是一个规范的target,则path/to/package是到包含BUILD文档的目录,target-name就是在BUILD文档中命名的target。
如果target是一个file target,则path/to/package是到package的根目录,target-name就是target file的名字。

如果该target在仓库的根目录,the package path is empty,只需要//:target-name。当该target与原先target位于用一个BUILD文档,则可直接跳过//,仅仅用:target-name

参考:
Bazel官网

Bazel应用方法Bazel应用方法 Charles_zzh 发布了7 篇原创文章 · 获赞 0 · 访问量 188 私信 关注
上一篇:Java开发环境配置


下一篇:PAT甲级1004