目录
包裹
package(default_deprecation, default_package_metadata, default_testonly, default_visibility, features)
此函数声明适用于软件包中的每个规则的元数据。在软件包 (BUILD 文件) 中最多使用一次。
对于声明将元数据应用于整个中每个规则的副本
代码库中的示例,请使用repo()
REPO.bazel
文件。
repo()
函数所采用的参数与 package()
完全相同。
应在文件顶部的所有 load() 语句之后、任何规则之前调用 package() 函数。
参数
属性 | 说明 |
---|---|
default_applicable_licenses |
|
default_visibility |
标签列表;默认值为 此软件包中规则的默认可见性。 除非规则的 |
default_deprecation |
字符串;默认值为 为此软件包中的所有规则设置默认的 |
default_package_metadata |
标签列表;默认值为 设置适用于软件包中所有其他目标的默认元数据目标列表。 这些通常是与 OSS 软件包和许可声明相关的目标。 有关示例,请参阅 rules_license。 |
default_testonly |
布尔值;默认值为 设置默认
在 |
features |
列出字符串;默认值为 设置影响此 BUILD 文件语义的各种标志。 此功能主要供构建系统的工作人员使用,用于标记需要某种特殊处理的软件包。除非构建系统的工作人员明确要求,否则请勿使用此选项。 |
示例
以下声明声明,此软件包中的规则 仅对文件包的成员可见 群组//foo:target
。单独的可见性声明
如果存在,则覆盖此规范。
package(default_visibility = ["//foo:target"])
package_group
package_group(name, packages, includes)
此函数定义一组软件包,并将标签与该组相关联。您可以在 visibility
属性中引用该标签。
软件包组主要用于控制可见性。源代码树中的每个软件包都可以引用公开可见的目标。私有可见的目标只能在其自己的软件包(而非子软件包)中引用。在这两种极端之间,目标可能会允许访问自己的软件包以及任何 一个或多个软件包组所描述的软件包。如需详细了解公开范围系统,请参阅公开范围属性。
如果给定软件包与 packages
属性匹配,或者已包含在 includes
属性中提及的其他软件包组中,则该软件包会被视为属于该组。
软件包组是技术上的目标,但并不是由规则创建的, 本身没有任何可见性保护。
参数
属性 | 说明 |
---|---|
name |
名称;必需 此目标的唯一名称。 |
packages |
字符串列表;默认值为 零个或多个软件包规范的列表。 每个软件包规范字符串都可以包含以下某一项 表单:
此外,前两种软件包规范还可以加上 软件包组包含与其至少一个正规格匹配且与其任何负规格都不匹配的任何软件包。例如,值 除了公开可见性之外,没有任何方法可以直接指定当前代码库之外的软件包。 如果缺少此属性,则等同于将其设置为空列表,这也等同于将其设置为仅包含 注意:在 Bazel 6.0 之前,规范 注意:在 Bazel 6.0 之前的版本中,此属性会序列化为
“ |
includes |
标签列表;默认值为 此软件包组中包含的其他软件包组。 此属性中的标签必须引用其他软件包组。
引用的软件包组中的软件包会被视为此软件包组的一部分。这是传递信息 - 如果软件包组
请注意,与否定软件包规范搭配使用时,系统会先独立计算每个组的软件包集,然后将结果联接在一起。这意味着 对同一组中的规范没有影响 另一个组。 |
示例
以下 package_group
声明指定了一个名为“tropical”的软件包组,其中包含热带水果。
package_group( name = "tropical", packages = [ "//fruits/mango", "//fruits/orange", "//fruits/papaya/...", ], )
以下声明指定虚构的 应用:
package_group( name = "fooapp", includes = [ ":controller", ":model", ":view", ], ) package_group( name = "model", packages = ["//fooapp/database"], ) package_group( name = "view", packages = [ "//fooapp/swingui", "//fooapp/webui", ], ) package_group( name = "controller", packages = ["//fooapp/algorithm"], )
exports_files
exports_files([label, ...], visibility, licenses)
exports_files()
指定要导出到其他软件包的此软件包所属的文件列表。
软件包的 BUILD 文件只能直接引用属于
导出到另一个软件包
exports_files()
语句。详细了解
文件的公开范围。
作为一种传统行为,系统会同时导出规则输入中提及的文件
标记,
--incompatible_no_implicit_file_export
完全翻转过来但是,您不应依赖这种行为,也不应主动
数据来源。
参数
参数是当前包中的文件名称列表。答
还可以指定可见性声明;在本示例中,这些文件将
对指定目标可见。如果未指定可见性,则文件
将对每个软件包可见,即使软件包默认可见性为
在 package
中指定
函数。您还可以指定许可。
示例
以下示例会从 test_data
软件包导出 golden.txt
(一个文本文件),以便其他软件包可以使用它,例如在测试的 data
属性中使用。
# from //test_data/BUILD exports_files(["golden.txt"])
glob
glob(include, exclude=[], exclude_directories=1, allow_empty=True)
Glob 是一个辅助函数,用于查找与特定路径模式匹配的所有文件,并返回一个可变的、排序的路径新列表。Glob 仅搜索其自身软件包中的文件,并且只会查找源文件(而非生成的文件或其他目标)。
如果源文件的相对路径是相对路径,则结果中会包含该源文件的标签
路径与任意 include
模式匹配,但不匹配
exclude
格式。
include
和 exclude
列表包含路径模式
相对于当前软件包的出价每种格式都可能由一个或
更多路径细分。与 Unix 路径一样,这些段由
/
。路径段可以包含 *
通配符:此通配符可匹配路径段中的任何子字符串(包括空子字符串),但不包括目录分隔符 /
。此通配符可以在一个路径段中多次使用。此外,**
通配符可以匹配
零个或零个以上完整路径段,但必须将其声明为独立的
路径段。
foo/bar.txt
与foo/bar.txt
文件完全匹配 此软件包中的- 如果文件以
.txt
结尾,foo/*.txt
会匹配foo/
目录中的每个文件(除非foo/
是子软件包) foo/a*.htm*
匹配foo/
目录中以a
开头、包含任意字符串(可以为空)、包含.htm
且以另一个任意字符串结尾的每个文件;例如foo/axx.htm
和foo/a.html
或foo/axxx.html
**/a.txt
会匹配以下中的每个a.txt
文件: 该软件包的子目录**/bar/**/*.txt
会匹配以下中的每个.txt
文件: 此软件包的子目录中,如果生成的路径中至少有一个目录是 名为bar
,例如xxx/bar/yyy/zzz/a.txt
或bar/a.txt
(请注意,**
也与零匹配 细分)或bar/zzz/a.txt
**
匹配此软件包的每个子目录中的每个文件foo**/a.txt
是无效格式,因为**
必须 独立成段
如果启用了 exclude_directories
参数(设置为 1),则结果中将省略目录类型的文件(默认值为 1)。
如果 allow_empty
参数设置为 False
,
glob
如果结果为
空列表。
下面是一些重要的限制和注意事项:
-
由于
glob()
在 BUILD 文件评估期间运行,glob()
仅匹配源代码树中的文件,一律不匹配 生成的文件如果您要构建的目标同时需要源文件和生成的文件,则必须将生成的文件的显式列表附加到正则表达式中。请参阅下面使用:mylib
和:gen_java_srcs
的示例。 -
如果规则与匹配的源文件同名,则规则 “阴影”文件。
为了理解这一点,请注意,
glob()
会返回 因此,在其他规则中使用glob()
属性(例如srcs = glob(["*.cc"])
)与列出 匹配路径。例如,如果glob()
生成["Foo.java", "bar/Baz.java"]
中,但还有一条规则 名为“Foo.java”的软件包(这是允许的,但 Bazel 会发出警告), 那么glob()
的使用者将使用“Foo.java”规则 (其输出),而不是“Foo.java”文件。请参阅 GitHub 问题 #10395 了解详情。 - 通配符可以与子目录中的文件匹配。以及子目录名称 可以带有通配符。不过…
-
标签不允许跨越软件包边界,而 glob 则跨越软件包边界 不匹配子包中的文件。
例如,如果
x/y
作为软件包(作为x/y/BUILD
或在软件包路径上的其他位置)存在,则软件包x
中的全局正则表达式**/*.cc
不包含x/y/z.cc
。这个 而 glob 表达式的结果实际上取决于 是否存在 BUILD 文件,也就是说,相同的 glob 表达式将 如果未调用任何软件包,则包含x/y/z.cc
x/y
,或使用 --deleted_packages 标志。 - 上述限制适用于所有 glob 表达式, 无论它们使用哪个通配符。
-
文件名以
.
开头的隐藏文件与**
和*
通配符完全匹配。如果您想使用复合模式匹配隐藏文件,则模式需要以.
开头。例如:*
和.*.txt
将匹配.foo.txt
,但为*.txt
则不能。 系统也会以相同的方式匹配隐藏目录。隐藏目录 可能包含并不需要作为输入的文件, 不必要的全局性文件数量和内存消耗。排除 隐藏目录,请将它们添加到“排除”list 参数。 -
“**”通配符有一个极端情况:模式
"**"
与软件包的目录路径不匹配。也就是说, 例如,glob(["**"], exclude_directories = 0)
会匹配所有文件 和目录间接位于当前软件包的 目录下 (当然,不会进入子软件包的目录,请参阅 的备注)。
一般而言,您应尽量提供适当的扩展名(如 *.html) 而不是对 glob 模式使用裸“*”。更明确的名称 都是自行记录,确保您不会意外匹配备份 或 emacs/vi/... 自动保存文件。
编写 build 规则时,您可以枚举正则表达式的元素。这个 例如,支持为每个输入生成单独的规则。请参阅下面的展开的正则表达式示例部分。
Glob 示例
创建一个 Java 库,该库由此目录中的所有 Java 文件以及 :gen_java_srcs
规则生成的所有文件构建而成。
java_library( name = "mylib", srcs = glob(["*.java"]) + [":gen_java_srcs"], deps = "...", ) genrule( name = "gen_java_srcs", outs = [ "Foo.java", "Bar.java", ], ... )
将目录 testdata 中的所有 txt 文件(experimental.txt 除外)包含在内。 请注意,testdata 的子目录中的文件不包括在内。如果您想包含这些文件,请使用递归正则表达式 (**)。
sh_test( name = "mytest", srcs = ["mytest.sh"], data = glob( ["testdata/*.txt"], exclude = ["testdata/experimental.txt"], ), )
递归 glob 示例
使测试依赖于 testdata 目录及其任何子目录(以及其子目录等)中的所有 txt 文件。 系统会忽略包含 BUILD 文件的子目录。(请参阅上文中的限制和注意事项。)
sh_test( name = "mytest", srcs = ["mytest.sh"], data = glob(["testdata/**/*.txt"]), )
创建一个库,该库由此目录和所有子目录中的所有 Java 文件构建而成,但路径中包含名为 testing 的目录的文件除外。应尽可能避免这种模式,因为它可能会降低构建增量,从而增加构建时间。
java_library( name = "mylib", srcs = glob( ["**/*.java"], exclude = ["**/testing/**"], ), )
展开的 Glob 示例
在当前目录中为 *_test.cc 创建一个单独的 genrule 用于计算文件中的行数。
# Conveniently, the build language supports list comprehensions. [genrule( name = "count_lines_" + f[:-3], # strip ".cc" srcs = [f], outs = ["%s-linecount.txt" % f[:-3]], cmd = "wc -l $< >$@", ) for f in glob(["*_test.cc"])]
如果上述 BUILD 文件位于软件包 //foo 中,并且该软件包包含三个匹配的文件(a_test.cc、b_test.cc 和 c_test.cc),那么运行 bazel query '//foo:all'
将列出生成的所有规则:
$ bazel query '//foo:all' | sort //foo:count_lines_a_test //foo:count_lines_b_test //foo:count_lines_c_test
选择
select( {conditionA: valuesA, conditionB: valuesB, ...}, no_match_error = "custom message" )
select()
是一个辅助函数,用于使规则属性可配置。它可以取代
差不多
因此其值取决于命令行 Bazel 标志。
例如,您可以使用此方法定义平台专用依赖项,或根据规则是在“开发者”模式还是“发布”模式下构建来嵌入不同的资源。
基本用法如下:
sh_binary( name = "mytarget", srcs = select({ ":conditionA": ["mytarget_a.sh"], ":conditionB": ["mytarget_b.sh"], "//conditions:default": ["mytarget_default.sh"] }) )
这会使 srcs
属性成为
可通过替换普通标签进行配置的 sh_binary
使用映射的 select
调用列出分配
配置条件和值相匹配。每个条件都是一个标签
引用
config_setting
或
constraint_value
,
哪些“匹配”如果目标的配置与期望的
值。然后,mytarget#srcs
的值将变为与当前调用匹配的标签列表。
注意:
- 在任何调用中,系统只会选择一个条件。
- 如果多个条件匹配,并且其中一个是其他条件的专精领域,则专精领域优先。如果条件 B 与条件 A 具有完全相同的标志和约束条件值,以及一些额外的标志或约束条件值,则条件 B 被视为条件 A 的特殊化。这也意味着,专精解析并非旨在创建排序,如以下示例 2 所示。
- 如果有多个条件匹配,但有一个条件并非针对所有条件 则 Bazel 会失败并显示错误,除非所有条件都解析为相同的值。
- 特殊伪标签
//conditions:default
如果没有匹配的其他条件,则视为匹配。如果此条件 必须匹配其他规则才能避免错误。 select
可以嵌入到内部 属性分配。因此,srcs = ["common.sh"] + select({ ":conditionA": ["myrule_a.sh"], ...})
和srcs = select({ ":conditionA": ["a.sh"]}) + select({ ":conditionB": ["b.sh"]})
是有效的表达式。select
适用于大多数(但并非所有)属性。不兼容 属性在其文档中标记为nonconfigurable
。子软件包
subpackages(include, exclude=[], allow_empty=True)
subpackages()
是一个辅助函数,类似于glob()
列出子软件包,而不是文件和目录。它使用与 路径模式为glob()
,并且可以匹配是 当前加载的 BUILD 文件的直接后代。如需详细了解包含和排除模式以及相关示例,请参阅 glob。返回的子文件包按已排序顺序排列,且包含 与当前加载软件包的相对路径,该软件包与
include
而不是exclude
中的那些。示例
以下示例列出了软件包
foo/BUILD
的所有直接子软件包# The following BUILD files exist: # foo/BUILD # foo/bar/baz/BUILD # foo/sub/BUILD # foo/sub/deeper/BUILD # # In foo/BUILD a call to subs = subpackages(include = ["**"]) # results in subs == ["sub", "bar/baz"] # # 'sub/deeper' is not included because it is a subpackage of 'foo/sub' not of # 'foo'
一般来说,用户最好使用 skylib 的“subpackages”模块,而不是直接调用此函数。