我有一个cc_test
定义如下:
filegroup(
name = "test_data",
srcs = [
"abc/abc.txt",
"def.txt",
],
)
cc_test(
name = "my_test",
size = "small",
srcs = [
"test_a.cpp",
],
data = [
":test_data",
],
)
我想使用data
查询用于此测试的runfiles
文件(或abc/abc.txt
)(在这种情况下为def.txt
和bazel query
)。
我需要在脚本中使用一些测试所使用的数据文件列表。
这是我所走的路:
$bazel query 'kind("source file", deps(//xxx/...))'
@bazel_tools//tools/test:test-setup.sh
@bazel_tools//tools/test:collect_coverage.sh
@bazel_tools//tools/def_parser:no_op.bat
@bazel_tools//tools/def_parser:def_parser.exe
@bazel_tools//tools/cpp:link_dynamic_library.sh
@bazel_tools//tools/cpp:grep-includes.sh
@bazel_tools//tools/cpp:build_interface_so
@bazel_tools//tools/coverage:dummy_coverage_report_generator
@bazel_tools//third_party/def_parser:def_parser_main.cc
@bazel_tools//third_party/def_parser:def_parser.h
@bazel_tools//third_party/def_parser:def_parser.cc
//xxx:test_a.cpp
//xxx:def.txt
//xxx:abc/abc.txt
我只想要此列表的子集,也就是测试文件(//xxx:def.txt
和//xxx:abc/abc.txt
)
可以这样做吗?
答案 0 :(得分:2)
我不认为可以使用bazel query
来做到这一点,但是我们可以使用Aspects来做到这一点。
Bazel中的方面允许您遍历属性图边缘(例如deps
和srcs
)的依存关系图并创建自定义动作。
鉴于此BUILD
文件,我们可以创建一个自定义规则和方面以通过deps
遍历依赖关系图,并将data
文件收集到一个文件中。
load("//:collect_data_files.bzl", "collect_data_files")
filegroup(
name = "test_foo_data",
srcs = [
"foo.txt",
"foo/foo.txt",
],
)
cc_test(
name = "test_foo",
size = "small",
srcs = [
"test_foo.cpp",
],
data = [
":test_foo_data",
],
)
filegroup(
name = "test_bar_data",
srcs = [
"bar.txt",
"bar/bar.txt",
],
)
filegroup(
name = "test_bar_lib_data",
srcs = [
"bar_lib.txt",
"bar_lib/bar_lib.txt",
],
)
cc_library(
name = "test_bar_lib",
srcs = ["test_bar_lib.cpp"],
data = [":test_bar_lib_data"],
)
cc_test(
name = "test_bar",
size = "small",
srcs = [
"test_bar.cpp",
],
data = [
":test_bar_data",
],
deps = [":test_bar_lib"],
)
collect_data_files(
name = "collect_data",
testonly = 1,
deps = [
"test_bar",
"test_foo",
],
)
这是依赖关系图:
我们有两个测试,test_foo
和test_bar
,具体取决于数据文件。 test_bar
还取决于拥有自己数据文件的cc_library
。
在collect_data_files.bzl
中,我们可以创建一个方面来通过目标的传递deps
收集目标上的数据文件。
DataFilesInfo = provider(
fields = {
"data_files": "Data files for this target",
},
)
def _collect_data_aspect_impl(target, ctx):
data_files = []
if hasattr(ctx.rule.attr, "data"):
for src in ctx.rule.attr.data:
for f in src.files:
data_files += [f]
for dep in ctx.rule.attr.deps:
data_files += dep[DataFilesInfo].data_files
return [DataFilesInfo(data_files = data_files)]
collect_data_aspect = aspect(
attr_aspects = [
"deps",
],
implementation = _collect_data_aspect_impl,
)
然后在同一文件中,我们可以定义collect_data_files
规则以将目标标签及其数据文件的列表写入文件。
def _collect_data_rule_impl(ctx):
data_files_string = ""
for dep in ctx.attr.deps:
data_files = [f.path for f in dep[DataFilesInfo].data_files]
data_files_string += str(dep.label) + ","
data_files_string += ",".join(data_files) + "\n"
ctx.actions.write(ctx.outputs.data_files, data_files_string)
collect_data_files = rule(
attrs = {
"deps": attr.label_list(aspects = [collect_data_aspect]),
},
outputs = {
"data_files": "%{name}_data_files.txt",
},
implementation = _collect_data_rule_impl,
)
现在,我们可以建立collect_data_files
目标:
$ bazel build :collect_data
INFO: Analysed target //:collect_data (10 packages loaded).
INFO: Found 1 target...
Target //:collect_data up-to-date:
bazel-bin/collect_data_data_files.txt
INFO: Elapsed time: 1.966s, Critical Path: 0.01s
INFO: 0 processes.
INFO: Build completed successfully, 2 total actions
结果被写入输出文件:
$ cat bazel-bin/collect_data_data_files.txt
//:test_bar,bar.txt,bar/bar.txt,bar_lib.txt,bar_lib/bar_lib.txt
//:test_foo,foo.txt,foo/foo.txt