https://www.jayconrod.com/posts/110/writing-bazel-rules—repository-rules

0. Bazel基础

Bazel 构建目标主要有三个阶段:

  • Loading
  • Analysis
  • Execution

在Loading阶段,Bazel读取和评估build文件,Bazel会构建目标及其依赖图。
在Analysis阶段,Bazel会评估目标graph,Analysis的输出是file-action graph(什么样的文件会执行什么操作),需要注意的是 rules本身不能直接执行输入/输出操作,仅仅是告诉Bazel构建过程应该是什么样的。
在Execution阶段,Bazel运行具体的actions来构建,Bazel会有不同的策略去运行actions。

1. 三个结构体

structs
providers
depsets
上面的三个数据结构用于在不同的rules之间传递信息,我们需要他们去收集依赖的相关信息。

Structs是Starlark的一种基本数据结构

  1. my_value = struct(
  2. foo = 12,
  3. bar = 34,
  4. )

使用的时候可以采用以下方法

  1. print(my_value.foo + my_value.bar)

Provider 是一个named 的结构体,包含关于rule的信息。当provider被evaluated时,Rule implementation函数返回provider结构。 Providers可以被任何依赖于这个rule的东西读取到。
例如 cc_binary会返回一个 DefaultInfoprovider(这个是一个内置的provider)

Depsets
Bazel提供一个特殊目的的数据结构 depset,和其他的set一样,depset也是一系列唯一的values。

https://docs.bazel.build/versions/main/skylark/lib/depset.html

举个例子

这里定义一个新的provider LibraryInfo会携带每个library和其相关依赖的信息

  1. LibraryInfo = provider(
  2. doc = "Contains information about a Go Library",
  3. fileds = {
  4. "info": """ A struct containing information about this library """,
  5. "deps": "A depset of info structs for this library's dependencies",
  6. },
  7. )

然后在其他rule中使用这个LibraryInfo

  1. go_library = rule(
  2. _go_library_impl,
  3. attrs = {
  4. "srcs" : attr.label_list(
  5. allow_files = [".go"],
  6. ),
  7. "deps": attr.label_list(
  8. proviers = [LibraryInfo],
  9. ),
  10. }
  11. )

一般情况下,使用Bazel不需要自己定义rule

下载抽取deb包

  1. # deb包的具体属性
  2. deb_packages = repository_rule(
  3. attrs = _deb_packages_attrs,
  4. implementation = _deb_packages_impl,
  5. local = False,
  6. )

其中, repository_ctx[ rctx]

https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#attr

context of repository rule 包含了以下信息

  • attr [rctx.attr] 结构体,用户自定义具体内容
  • delete [rctx.delete(path)] 删除某个文件或路径,返回bool
  • download [rctx.download(url, output=’’,…)] 下载文件到某个path,返回一个结构体,包含文件的hash值
  • download_and_extract [rctx.download_and_extract()] 下载文件并解压
  • execute [rctx.execute(argument)] 执行command
  • extract [rctx.extract(archive)]
  • file [rctx.file(path)] 生成文件 ?
  • name [rctx.name] 外部repository的name
  • os [rctx.os]
  • patch [rctx.patch(patch_file)] Apply a patch file to the root directory of external repository.
  • read
  • report_progress
  • symlink
  • template
  • which

实例1 - 使用bazel安装一个deb包

使用repository_rule()方法安装一个包

实例2 - 使用bazel的rule