bazel-lib/lib/private/output_files.bzl

88 lines
3.2 KiB
Python

"""output_files implementation
"""
load("//lib:utils.bzl", _to_label = "to_label")
def _output_files(ctx):
files = []
files_depset = depset()
if ctx.attr.output_group:
if OutputGroupInfo not in ctx.attr.target:
msg = "%s output_group is specified but %s does not provide an OutputGroupInfo" % (ctx.attr.output_group, ctx.attr.target)
fail(msg)
if ctx.attr.output_group not in ctx.attr.target[OutputGroupInfo]:
msg = "%s output_group is specified but %s does not provide this output group" % (ctx.attr.output_group, ctx.attr.target)
fail(msg)
files_depset = ctx.attr.target[OutputGroupInfo][ctx.attr.output_group]
else:
files_depset = ctx.attr.target[DefaultInfo].files
for path in ctx.attr.paths:
file = _find_short_path_in_files_depset(files_depset, path)
if not file:
if ctx.attr.output_group:
msg = "%s file not found within the %s output group of %s" % (path, ctx.attr.output_group, ctx.attr.target)
else:
msg = "%s file not found within the DefaultInfo of %s" % (path, ctx.attr.target)
fail(msg)
files.append(file)
return [DefaultInfo(
files = depset(direct = files),
runfiles = ctx.runfiles(files = files),
)]
output_files = rule(
doc = "A rule that provides file(s) specific via DefaultInfo from a given target's DefaultInfo or OutputGroupInfo",
implementation = _output_files,
attrs = {
"target": attr.label(
doc = "the target to look in for requested paths in its' DefaultInfo or OutputGroupInfo",
mandatory = True,
),
"paths": attr.string_list(
doc = "the paths of the file(s), relative to their roots, to provide via DefaultInfo from the given target's DefaultInfo or OutputGroupInfo",
mandatory = True,
allow_empty = False,
),
"output_group": attr.string(
doc = "if set, we look in the specified output group for paths instead of DefaultInfo",
),
},
provides = [DefaultInfo],
)
def make_output_files(name, target, paths, **kwargs):
"""Helper function to generate a output_files target and return its label.
Args:
name: unique name for the generated `output_files` target
target: `target` attribute passed to generated `output_files` target
paths: `paths` attribute passed to generated `output_files` target
**kwargs: parameters to pass to generated `output_files` target
Returns:
The label `name`
"""
output_files(
name = name,
target = target,
paths = paths,
**kwargs
)
return _to_label(name)
def _find_short_path_in_files_depset(files_depset, short_path):
"""Helper function find a file in a DefaultInfo by short path
Args:
files_depset: a depset
short_path: the short path (path relative to root) to search for
Returns:
The File if found else None
"""
if files_depset:
for file in files_depset.to_list():
if file.short_path == short_path:
return file
return None