Bazel-如何获取目标的所有传递源
Bazel- How to get all transitive sources of a target
我需要编写一个规则来压缩可执行文件的所有传递配置文件 (*.foo
)(可以是自定义规则,java_binary 和 docker container_image).
配置文件可以出现在可执行文件的任何属性的 srcs
属性上(tars
、deps
、runtime_deps
等)
这听起来应该很容易用 aspect 附加到我的规则,但我在各种示例之间迷路了。
sources_aspect.bzl
:
SourceFiles = provider(
fields = {
'transitive_source_files' : 'list of transitive source files of a target'
}
)
#add 'resources' ? if so _accumulate_transitive_config_files needs to check for dep in deps if ConfigFiles in dep
SourceAttr = ['tars','deps','runtime_deps','exports',]
def _accumulate_transitive_source_files(accumulated, deps):
return depset(
transitive = [dep[SourceFiles].transitive_source_files for dep in deps] + [accumulated])
def _collect_current_source_files(srcs):
return [file for src in srcs for file in src.files.to_list()]
def _collect_source_files_aspect_impl(target, ctx):
current_source_files = []
if hasattr(ctx.rule.attr, 'srcs'):
current_source_files = _collect_current_source_files(ctx.rule.attr.srcs)
if hasattr(ctx.rule.attr, 'resources'):
current_source_files = current_source_files + _collect_current_source_files(ctx.rule.attr.resources)
accumulated_source_files = depset(current_source_files)
for attr in SourceAttr:
if hasattr(ctx.rule.attr, attr):
accumulated_source_files = _accumulate_transitive_source_files(accumulated_source_files, getattr(ctx.rule.attr, attr))
return [SourceFiles(transitive_source_files=accumulated_source_files)]
collect_source_files_aspect = aspect(implementation = _collect_source_files_aspect_impl,
attr_aspects = SourceAttr,
)
sources.bzl
load("//sources/src/main:sources_aspect.bzl", "collect_source_files_aspect", "SourceFiles")
def _owner_to_bazel_file(fileLabel):
workspace = fileLabel.workspace_root
package = fileLabel.package
if 0 < len(workspace):
workspace = workspace + '/'
if 0 < len(package):
package = package + '/'
return workspace + package + 'BUILD.bazel'
def _collect_source_files_rule_impl(ctx):
metadata = [ctx.attr.group_id, ctx.attr.artifact_id]
paths = sorted([f.path for f in ctx.attr.main_artifact_name[SourceFiles].transitive_source_files.to_list()])
owners = sorted(depset([_owner_to_bazel_file(f.owner) for f in ctx.attr.main_artifact_name[SourceFiles].transitive_source_files.to_list()] + [_owner_to_bazel_file(ctx.label)]).to_list())
ctx.actions.write(ctx.outputs.sources, "\n".join(metadata + paths + owners))
ctx.actions.write(ctx.outputs.source_files, "{\"groupId\": \"%s\", \"artifactId\": \"%s\", \"sources\": %s, \"buildFiles\": %s}" % (ctx.attr.group_id, ctx.attr.artifact_id, paths, owners))
return DefaultInfo(
runfiles=ctx.runfiles(files=[ctx.outputs.sources, ctx.outputs.source_files])
)
source_files = rule(
implementation = _collect_source_files_rule_impl,
attrs = {
'main_artifact_name' : attr.label(aspects = [collect_source_files_aspect, ]),
"group_id" : attr.string(mandatory=True),
"artifact_id" : attr.string(mandatory=True),
},
outputs={"sources": "%{name}.sources.txt", "source_files": "%{name}.sources.json"},
)
我需要编写一个规则来压缩可执行文件的所有传递配置文件 (*.foo
)(可以是自定义规则,java_binary 和 docker container_image).
配置文件可以出现在可执行文件的任何属性的 srcs
属性上(tars
、deps
、runtime_deps
等)
这听起来应该很容易用 aspect 附加到我的规则,但我在各种示例之间迷路了。
sources_aspect.bzl
:
SourceFiles = provider(
fields = {
'transitive_source_files' : 'list of transitive source files of a target'
}
)
#add 'resources' ? if so _accumulate_transitive_config_files needs to check for dep in deps if ConfigFiles in dep
SourceAttr = ['tars','deps','runtime_deps','exports',]
def _accumulate_transitive_source_files(accumulated, deps):
return depset(
transitive = [dep[SourceFiles].transitive_source_files for dep in deps] + [accumulated])
def _collect_current_source_files(srcs):
return [file for src in srcs for file in src.files.to_list()]
def _collect_source_files_aspect_impl(target, ctx):
current_source_files = []
if hasattr(ctx.rule.attr, 'srcs'):
current_source_files = _collect_current_source_files(ctx.rule.attr.srcs)
if hasattr(ctx.rule.attr, 'resources'):
current_source_files = current_source_files + _collect_current_source_files(ctx.rule.attr.resources)
accumulated_source_files = depset(current_source_files)
for attr in SourceAttr:
if hasattr(ctx.rule.attr, attr):
accumulated_source_files = _accumulate_transitive_source_files(accumulated_source_files, getattr(ctx.rule.attr, attr))
return [SourceFiles(transitive_source_files=accumulated_source_files)]
collect_source_files_aspect = aspect(implementation = _collect_source_files_aspect_impl,
attr_aspects = SourceAttr,
)
sources.bzl
load("//sources/src/main:sources_aspect.bzl", "collect_source_files_aspect", "SourceFiles")
def _owner_to_bazel_file(fileLabel):
workspace = fileLabel.workspace_root
package = fileLabel.package
if 0 < len(workspace):
workspace = workspace + '/'
if 0 < len(package):
package = package + '/'
return workspace + package + 'BUILD.bazel'
def _collect_source_files_rule_impl(ctx):
metadata = [ctx.attr.group_id, ctx.attr.artifact_id]
paths = sorted([f.path for f in ctx.attr.main_artifact_name[SourceFiles].transitive_source_files.to_list()])
owners = sorted(depset([_owner_to_bazel_file(f.owner) for f in ctx.attr.main_artifact_name[SourceFiles].transitive_source_files.to_list()] + [_owner_to_bazel_file(ctx.label)]).to_list())
ctx.actions.write(ctx.outputs.sources, "\n".join(metadata + paths + owners))
ctx.actions.write(ctx.outputs.source_files, "{\"groupId\": \"%s\", \"artifactId\": \"%s\", \"sources\": %s, \"buildFiles\": %s}" % (ctx.attr.group_id, ctx.attr.artifact_id, paths, owners))
return DefaultInfo(
runfiles=ctx.runfiles(files=[ctx.outputs.sources, ctx.outputs.source_files])
)
source_files = rule(
implementation = _collect_source_files_rule_impl,
attrs = {
'main_artifact_name' : attr.label(aspects = [collect_source_files_aspect, ]),
"group_id" : attr.string(mandatory=True),
"artifact_id" : attr.string(mandatory=True),
},
outputs={"sources": "%{name}.sources.txt", "source_files": "%{name}.sources.json"},
)