From 40aaf3831425d472965dd61e58cbd5854abd7214 Mon Sep 17 00:00:00 2001 From: Derek Cormier Date: Mon, 26 Sep 2022 14:39:17 -0700 Subject: [PATCH] feat(bazel): add a rule to filter the first matching output --- bazel/filter_outputs.bzl | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/bazel/filter_outputs.bzl b/bazel/filter_outputs.bzl index 33cab210e..205950fca 100644 --- a/bazel/filter_outputs.bzl +++ b/bazel/filter_outputs.bzl @@ -43,3 +43,39 @@ filter_outputs = rule( This is useful when a target exposes multiple output files but a single output is only needed. """, ) + +def _filter_first_output_impl(ctx): + target_label = ctx.attr.target.label + target_workspace = target_label.workspace_name if target_label.workspace_name else ctx.workspace_name + target_package_manifest_path = "%s/%s" % (target_workspace, target_label.package) + + outputs = ctx.attr.target[DefaultInfo].files.to_list() + for filter in ctx.attr.filters: + for output in outputs: + manifest_path = get_manifest_path(ctx, output) + relative_path = manifest_path[len(target_package_manifest_path) + 1:] + if filter == relative_path: + return [DefaultInfo(files = depset([output]))] + + fail("Could not find output matching any filters in `%s`." % ctx.label) + +filter_first_output = rule( + implementation = _filter_first_output_impl, + attrs = { + "target": attr.label( + mandatory = True, + doc = "Target for which an output should be filtered", + providers = [DefaultInfo], + ), + "filters": attr.string_list( + mandatory = True, + doc = """Filters to apply to the target. The first output matching a filter will be included + in DefaultInfo, with filters earlier in the list taking precedence. Filter paths are expected + to be relative to the package owning the target. + """, + ), + }, + doc = """Rule that can be used to filter a single output from a given target. + This is useful when a target exposes multiple output files but a single output is only needed. + """, +)