Bazel编写BUILD文件

除了公共部分BUILD文件可以使用的规则外,还有一些与语言相关的build rule。

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

Java

Bin rules

java_binary

java_binary(name, deps, srcs, data, resources, args, classpath_resources, compatible_with, create_executable, deploy_manifest_lines, deprecation, distribs, features, javacopts, jvm_flags, launcher, licenses, main_class, output_licenses, plugins, resource_jars, resource_strip_prefix, restricted_to, runtime_deps, stamp, tags, testonly, toolchains, use_testrunner, visibility)

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

java_import

java_import(name, deps, data, compatible_with, constraints, deprecation, distribs, exports, features, jars, licenses, neverlink, proguard_specs, restricted_to, runtime_deps, srcjar, tags, testonly, visibility)

这个rule允许使用预编译好的.jar文件当做lib,来提供给java_library和java_binary规则用。

java_library

java_library(name, deps, srcs, data, resources, compatible_with, deprecation, distribs, exported_plugins, exports, features, javacopts, licenses, neverlink, plugins, proguard_specs, resource_jars, resource_strip_prefix, restricted_to, runtime_deps, tags, testonly, visibility)

这个rule编译和链接源码到.jar包中。隐式输出目标:
libname.jar
libname-src.jar

属性参数介绍:

  • name:本rule的唯一标识
  • deps:编译阶段的依赖
  • srcs:源码文件列表,如果java文件时生成的那么放入生成java文件的target label
  • exports:称为输出的libs,也就是说这里面定义的libs可以被依赖此rule的父rule所使用。
  • javacopts:全局编译选项之后的此target的额外编译选项,会在全局选项之后传给javac
  • neverlink:Boolean类型,默认0,如果此target的libary只是在编译阶段使用不会再运行阶段使用,那么就需要设置为True
  • resource_jars:设置包含Java源码的包,将会添加到输出jar中

这里重点讲下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中

Python

Bin rules

py_binary

py_binary(name, deps, srcs, data, args, compatible_with, default_python_version, deprecation, distribs, features, imports, legacy_create_init, licenses, main, output_licenses, restricted_to, srcs_version, stamp, tags, testonly, toolchains, visibility)

这个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

py_library

py_library(name, deps, srcs, data, compatible_with, deprecation, distribs, features, imports, licenses, restricted_to, srcs_version, tags, testonly, visibility)

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

一般通用

filegroup

filegroup(name, srcs, data, compatible_with, deprecation, distribs, features, licenses, output_group, output_licenses, path, restricted_to, tags, testonly, visibility)

使用这个可以得到一个目标的合集名字,方便在其他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",
    ],
)

genrule

genrule(name, srcs, outs, cmd, compatible_with, deprecation, distribs, executable, features, licenses, local, message, output_licenses, output_to_bindir, restricted_to, tags, testonly, tools, visibility)

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

转载需保留链接来源:软件玩家 » Bazel编写BUILD文件

赞 (0)