Bazel BUILD文件的编写

除了公共部分BUILD文件可以使用的规则外,还有一些与语言相关的build rule
https://docs.bazel.build/versions/master/be/overview.html

这里根据不同的语言,来写整理。

Java

Bin rules

build一个java的jar文件,并且套上一个shell的脚本来辅助运行。
隐式的输出target:
name.jar
name-src.jar
name_deploy.jar:这个比较特殊,必须显式的build才会生成,比如 bazel build //package:target_deploy.jar
name_deploy-src.jar

Lib rules

这个rule允许使用预编译好的.jar文件当做lib,来提供给java_library和java_binary规则用。
这个rule编译和链接源码到.jar包中。
隐式输出目标:
libname.jar
libname-src.jar
属性参数介绍:
name:本rule的唯一标识
deps:编译阶段的依赖
srcs:源码文件列表,如果java文件时生成的那么放入生成java文件的target label
exports:称为输出的libs,也就是说这里面定义的libs可以被依赖此rule的父rule所使用。
【敲黑板:这里重点讲下exports和dep的区别和联系。rule X可以访问code Y只要X与Y之间有一个deps边以及0个或多个exports边。接下来再看一个更清楚的例子,假设A依赖于B,B依赖于C,在这种情况下C如果发生改变,那么在build A时重新build所有。但是此时的A并不能访问C中的class,除非让A有个直接的deps到C,或者让B exports C;显然后者操作更为轻松尤其是当有很多C时。还剩下两个重点:1、exports可以传递;2、exports和deps不冲突,根据需要可以将一个target既加在deps里又加在exports中】
javacopts:全局编译选项之后的此target的额外编译选项,会在全局选项之后传给javac
neverlink:Boolean类型,默认0,如果此target的libary只是在编译阶段使用不会再运行阶段使用,那么就需要设置为True
resource_jars:设置包含Java源码的包,将会添加到输出jar中
resource_strip_prefix

Python

Bin rules

这个rule是一个可执行的Python程序,包含了一些Python源码,一个*.runfiles的目录树内含了所有运行时所需的代码和数据,以及一个配置了初始化环境和数据的启动脚本。
在py_binary中可以依赖别的py_library
py_binary(
    name = "foo",
    srcs = ["foo.py"],
    data = [":transform"],  # a cc_binary which we invoke at run time
    deps = [
        "//pyglib",
        ":foolib",  # a py_library
    ],
)
在别的非Python的bin中如果想运行py_binary那么可以放入data属性中:
py_binary(
    name = "test_main",
    srcs = ["test_main.py"],
    deps = [":testlib"],
)

java_library(
    name = "testing",
    srcs = glob(["*.java"]),
    data = [":test_main"]
)

Lib rules

name:唯一名字
depsList of labels; optional依赖,可以是源码但是为了方便阅读还是放在srcs里好
srcsList of labels; optional包含生成目标的源码
dataList of strings; optional运行时所需的文件
importsList of strings; optional要加载的路径,加到PYTHONPATH中
srcs_versionString; optional; default is "PY2AND3"只是为了文档的目的,不会影响python解释器的版本。

一般通用

  • filegroup
使用这个可以得到一个目标的合集名字,方便在其他rule中引用
举例:
filegroup(
    name = "mygroup",
    srcs = [
        "a_file.txt",
        "some/subdirectory/another_file.txt",
    ],
)
filegroup(
    name = "exported_testdata",
    srcs = glob([
        "testdata/*.dat",
        "testdata/logs/**/*.log",
    ]),
)
cc_library(
    name = "my_library",
    srcs = ["foo.cc"],
    data = [
        "//my_package:exported_testdata",
        "//my_package:mygroup",
    ],
)

这个rule的功能是使用用户定义的Bash命令产生一个或多个文件。
当没有特定的rule来完成某个任务时,就可以使用这个通用的build rule。
使用建议:
1、输出应该是确定和封闭的。每次运行不会反生变化
2、广泛使用$(location),来获取文件位置
3、写common Skylark宏代码
4、确保推出代码可以正确只是genrule的成功或失败
5、不要写print,一个成功的genrule应该是无打印的
6、$$表示$,为了避免和shell命令冲突,ls $(dirname $x)应写成ls $$(dirname $$x)
7、避免在genrule中创建软连接以及文件夹。因为Bazel不会复制和检查这些。
8、引用genrule的时候,可以使用genrule的label或者每个genrule输出的label。这两种方法根据实际需要来。

下面这个例子是调用perl脚本来产生一个foo.h文件。
genrule(
    name = "foo",
    srcs = [],
    outs = ["foo.h"],
    cmd = "./$(location create_foo.pl) > \"$@\"",
    tools = ["create_foo.pl"],
)
接下来的例子是使用filegroup和另一个genrule产生的文件作为src:
genrule(
    name = "concat_all_files",
    srcs = [
        "//some:files",  # a filegroup with multiple files in it ==> $(locations)
        "//other:gen",   # a genrule with a single output ==> $(location)
    ],
    outs = ["concatenated.txt"],
    cmd = "cat $(locations //some:files) $(location //other:gen) > $@",
)

参数介绍:
name:唯一名字
srcsList of labels; optional源输入文件
outsList of filenames; required; nonconfigurable输出文件列表,文件处于package内可以被label索引到。
cmdString; required运行的cmd
    1、可以使用$(location)
    2、outs中的文件名不包括在替换中,在cmd中需要以$(@D)$@$(OUTS) or $(location output_name)方式出现。
    3、有了host配置后,环境变量共享库是可在cmd中用的。比如$(JAVA)$(JAVAC) and $(JAVABASE)
    4、如果cmd执行后的返回值不是0那么就认为失败了。
executableBoolean; optional; nonconfigurable; default is 0指示输出文件是否是可执行的。
toolsList of labels; optional表示rule依赖的tool,可以是已有的文件,也可以是一个target或者生成的文件。




评论

此博客中的热门博文

Bazel WORKSPACE文件编写

Bazel的概念和技术