зеркало из https://github.com/github/codeql.git
550 строки
22 KiB
Python
550 строки
22 KiB
Python
"""
|
|
Wrappers and helpers around `rules_pkg` to build codeql packs.
|
|
"""
|
|
|
|
load("@bazel_skylib//lib:paths.bzl", "paths")
|
|
load("@rules_pkg//pkg:install.bzl", "pkg_install")
|
|
load("@rules_pkg//pkg:mappings.bzl", "pkg_attributes", "pkg_filegroup", "pkg_files", _strip_prefix = "strip_prefix")
|
|
load("@rules_pkg//pkg:pkg.bzl", "pkg_zip")
|
|
load("@rules_pkg//pkg:providers.bzl", "PackageFilegroupInfo", "PackageFilesInfo")
|
|
load("@rules_python//python:defs.bzl", "py_binary")
|
|
load("//misc/bazel:os.bzl", "OS_DETECTION_ATTRS", "os_select")
|
|
|
|
def _make_internal(name):
|
|
def internal(suffix = "internal", *args):
|
|
args = (name, suffix) + args
|
|
return "-".join(args)
|
|
|
|
return internal
|
|
|
|
_PLAT_PLACEHOLDER = "{CODEQL_PLATFORM}"
|
|
|
|
def _expand_path(path, platform):
|
|
if _PLAT_PLACEHOLDER in path:
|
|
path = path.replace(_PLAT_PLACEHOLDER, platform)
|
|
return ("arch", path)
|
|
return ("common", path)
|
|
|
|
def _detect_platform(ctx = None):
|
|
return os_select(ctx, linux = "linux64", macos = "osx64", windows = "win64")
|
|
|
|
def codeql_pkg_files(
|
|
*,
|
|
name,
|
|
srcs = None,
|
|
exes = None,
|
|
visibility = None,
|
|
**kwargs):
|
|
""" Wrapper around `pkg_files` adding a distinction between `srcs` and `exes`, where the
|
|
latter will get executable permissions.
|
|
"""
|
|
|
|
internal = _make_internal(name)
|
|
if "attributes" in kwargs:
|
|
fail("do not use attributes with codeql_pkg_* rules. Use `exes` to mark executable files.")
|
|
if srcs and exes:
|
|
pkg_files(
|
|
name = internal("srcs"),
|
|
srcs = srcs,
|
|
visibility = ["//visibility:private"],
|
|
**kwargs
|
|
)
|
|
pkg_files(
|
|
name = internal("exes"),
|
|
srcs = exes,
|
|
visibility = ["//visibility:private"],
|
|
attributes = pkg_attributes(mode = "755"),
|
|
**kwargs
|
|
)
|
|
pkg_filegroup(
|
|
name = name,
|
|
srcs = [internal("srcs"), internal("exes")],
|
|
visibility = visibility,
|
|
)
|
|
else:
|
|
pkg_files(
|
|
name = name,
|
|
srcs = srcs or exes,
|
|
visibility = visibility,
|
|
attributes = pkg_attributes(mode = "755") if exes else None,
|
|
**kwargs
|
|
)
|
|
|
|
_ZipInfo = provider(fields = {"zips_to_prefixes": "mapping of zip files to prefixes"})
|
|
|
|
CodeQLPackInfo = provider(
|
|
"A provider that encapsulates all the information needed to build a codeql pack.",
|
|
fields = {
|
|
"pack_prefix": "A prefix to add to all paths, IF the user requests so. We omit it for local installation targets of single packs (but not pack groups)",
|
|
"files": "PackageFilegroupInfo provider with list of all files in this pack (CODEQL_PLATFORM in paths unresolved)",
|
|
"zips": "A _ZipInfo provider to include in the pack, (CODEQL_PLATFORM unresolved).",
|
|
"arch_overrides": "A list of files that should be included in the arch-specific bit, even though the path doesn't contain CODEQL_PLATFORM.",
|
|
},
|
|
)
|
|
|
|
def _imported_zips_manifest_impl(ctx):
|
|
manifest = []
|
|
files = []
|
|
for zip_info in ctx.attr.srcs:
|
|
zip_info = zip_info[_ZipInfo]
|
|
manifest += ["%s:%s" % (p, z.short_path) for z, p in zip_info.zips_to_prefixes.items()]
|
|
files.extend(zip_info.zips_to_prefixes)
|
|
|
|
output = ctx.actions.declare_file(ctx.label.name + ".params")
|
|
ctx.actions.write(
|
|
output,
|
|
"\n".join(manifest),
|
|
)
|
|
return DefaultInfo(
|
|
files = depset([output]),
|
|
runfiles = ctx.runfiles(files),
|
|
)
|
|
|
|
_imported_zips_manifest = rule(
|
|
implementation = _imported_zips_manifest_impl,
|
|
doc = """
|
|
This internal rule prints a zip manifest file that `misc/bazel/internal/install.py` understands.
|
|
""",
|
|
attrs = {
|
|
"srcs": attr.label_list(
|
|
doc = "mappings from zip files to install prefixes in _ZipInfo format",
|
|
providers = [_ZipInfo],
|
|
),
|
|
},
|
|
)
|
|
|
|
def _zipmerge_impl(ctx):
|
|
zips = []
|
|
transitive_zips = []
|
|
output = ctx.actions.declare_file(ctx.attr.out)
|
|
args = [output.path]
|
|
for zip_target in ctx.attr.srcs:
|
|
if _ZipInfo in zip_target:
|
|
zip_info = zip_target[_ZipInfo]
|
|
for zip, prefix in zip_info.zips_to_prefixes.items():
|
|
args += [
|
|
"--prefix=%s/%s" % (ctx.attr.prefix, prefix.rstrip("/")),
|
|
zip.path,
|
|
]
|
|
zips.append(zip)
|
|
else:
|
|
zip_files = zip_target.files.to_list()
|
|
for zip in zip_files:
|
|
if zip.extension != "zip":
|
|
fail("%s file found while expecting a .zip file " % zip.short_path)
|
|
args.append("--prefix=%s" % ctx.attr.prefix)
|
|
args += [z.path for z in zip_files]
|
|
transitive_zips.append(zip_target.files)
|
|
ctx.actions.run(
|
|
outputs = [output],
|
|
executable = ctx.executable._zipmerge,
|
|
inputs = depset(zips, transitive = transitive_zips),
|
|
arguments = args,
|
|
# Disable remote caching for zipmerge:
|
|
# * One of the inputs to zipmerge (often the larger one) comes from a lazy-lfs rule.
|
|
# Those are retrieved by bazel even in the presence of a build cache, so downloading the whole zipmerged
|
|
# artifact is slower than downloading the smaller bazel-produced zip and rerunning zipmerge on that
|
|
# and the (already-present) LFS artifact.
|
|
# * This prevents unnecessary cache usage - every change to the Swift extractor would otherwise
|
|
# trigger a build of a >500MB zip file that'd quickly fill up the cache.
|
|
execution_requirements = {
|
|
"no-remote-cache": "1",
|
|
},
|
|
)
|
|
|
|
return [
|
|
DefaultInfo(files = depset([output])),
|
|
]
|
|
|
|
_zipmerge = rule(
|
|
implementation = _zipmerge_impl,
|
|
doc = """
|
|
This internal rule merges a zip files together
|
|
""",
|
|
attrs = {
|
|
"srcs": attr.label_list(doc = "Zip file to include, either as straight up `.zip` files or `_ZipInfo` data"),
|
|
"out": attr.string(doc = "output file name"),
|
|
"prefix": attr.string(doc = "Prefix posix path to add to the zip contents in the archive"),
|
|
"_zipmerge": attr.label(default = "//misc/bazel/internal/zipmerge", executable = True, cfg = "exec"),
|
|
},
|
|
)
|
|
|
|
def _get_zip_filename(name_prefix, kind):
|
|
if kind == "arch":
|
|
return name_prefix + "-" + _detect_platform() + ".zip" # using + because there's a select
|
|
else:
|
|
return "%s-common.zip" % name_prefix
|
|
|
|
def _codeql_pack_info_impl(ctx):
|
|
zips_to_prefixes = {}
|
|
for zip_target, prefix in ctx.attr.extra_zips.items():
|
|
for zip in zip_target.files.to_list():
|
|
zips_to_prefixes[zip] = prefix
|
|
return [
|
|
DefaultInfo(files = depset(
|
|
zips_to_prefixes.keys(),
|
|
transitive = [ctx.attr.src[DefaultInfo].files],
|
|
)),
|
|
CodeQLPackInfo(
|
|
arch_overrides = ctx.attr.arch_overrides,
|
|
files = ctx.attr.src[PackageFilegroupInfo],
|
|
zips = _ZipInfo(zips_to_prefixes = zips_to_prefixes),
|
|
pack_prefix = ctx.attr.prefix,
|
|
),
|
|
]
|
|
|
|
_codeql_pack_info = rule(
|
|
implementation = _codeql_pack_info_impl,
|
|
doc = """
|
|
This internal rule is a bit of a catch-all forwarder for the various information we need to forward to allow
|
|
building pack groups.
|
|
We have conflicting requirements for this data:
|
|
To build installer targets, we need to resolve all files, as directly as possible (no intermediate zip step),
|
|
and potentially omit the `prefix`.
|
|
To provide production distribution zips, we need to expose zip targets that distinguish between common and per-platform
|
|
files, and that do contain `prefix` in their path.
|
|
In both cases, we need to pull in the correct extra_zips for some packs.
|
|
Therefore, we preserve the input data from the pack declaration fairly directly,
|
|
and only massage it into the right form once we use it.
|
|
""",
|
|
attrs = {
|
|
"src": attr.label(providers = [PackageFilegroupInfo], mandatory = True, doc = "The files to include in the pack, with unresolved CODEQL_PLATFORM paths (a pkg_filegroup rule instance)."),
|
|
"extra_zips": attr.label_keyed_string_dict(
|
|
doc = "Mapping from zip files to install prefixes.",
|
|
allow_files = [".zip"],
|
|
),
|
|
"prefix": attr.string(doc = "Prefix to add to all files."),
|
|
"arch_overrides": attr.string_list(doc = "A list of files that should be included in the arch package regardless of the path, specify the path _without_ `prefix`."),
|
|
},
|
|
provides = [CodeQLPackInfo],
|
|
)
|
|
|
|
_CODEQL_PACK_GROUP_EXTRACT_ATTRS = {
|
|
"srcs": attr.label_list(providers = [CodeQLPackInfo], mandatory = True, doc = "List of `_codeql_pack_info` rules (generated by `codeql_pack`)."),
|
|
"apply_pack_prefix": attr.bool(doc = "Set to `False` to skip adding the per-pack prefix to all file paths.", default = True),
|
|
"kind": attr.string(doc = "Extract only the commmon, arch-specific, or all files from the pack group.", values = ["common", "arch", "all"]),
|
|
"prefix": attr.string(doc = "Prefix to add to all files, is prefixed after the per-pack prefix has been applied.", default = ""),
|
|
} | OS_DETECTION_ATTRS
|
|
|
|
# common option parsing for _codeql_pack_group_extract_* rules
|
|
def _codeql_pack_group_extract_options(ctx):
|
|
platform = _detect_platform(ctx)
|
|
apply_pack_prefix = ctx.attr.apply_pack_prefix
|
|
include_all_files = ctx.attr.kind == "all"
|
|
return platform, apply_pack_prefix, include_all_files
|
|
|
|
def _codeql_pack_group_extract_files_impl(ctx):
|
|
pkg_files = []
|
|
|
|
platform, apply_pack_prefix, include_all_files = _codeql_pack_group_extract_options(ctx)
|
|
for src in ctx.attr.srcs:
|
|
src = src[CodeQLPackInfo]
|
|
if src.files.pkg_dirs or src.files.pkg_symlinks:
|
|
fail("`pkg_dirs` and `pkg_symlinks` are not supported for codeql packaging rules")
|
|
prefix = paths.join(ctx.attr.prefix, src.pack_prefix) if apply_pack_prefix else ctx.attr.prefix
|
|
|
|
arch_overrides = src.arch_overrides
|
|
|
|
# for each file, resolve whether it's filtered out or not by the current kind, and add the pack prefix
|
|
for pfi, origin in src.files.pkg_files:
|
|
dest_src_map = {}
|
|
for dest, file in pfi.dest_src_map.items():
|
|
pack_dest = paths.join(prefix, dest)
|
|
file_kind, expanded_dest = _expand_path(pack_dest, platform)
|
|
if file_kind == "common" and dest in arch_overrides:
|
|
file_kind = "arch"
|
|
if include_all_files or file_kind == ctx.attr.kind:
|
|
dest_src_map[expanded_dest] = file
|
|
|
|
if dest_src_map:
|
|
pkg_files.append((PackageFilesInfo(dest_src_map = dest_src_map, attributes = pfi.attributes), origin))
|
|
|
|
files = [depset(pfi.dest_src_map.values()) for pfi, _ in pkg_files]
|
|
|
|
return [
|
|
DefaultInfo(files = depset(transitive = files)),
|
|
PackageFilegroupInfo(pkg_files = pkg_files, pkg_dirs = [], pkg_symlinks = []),
|
|
]
|
|
|
|
_codeql_pack_group_extract_files = rule(
|
|
implementation = _codeql_pack_group_extract_files_impl,
|
|
doc = """
|
|
Extract the files from a list of codeql packs (i.e. a pack group), and filter to the requested `kind`.
|
|
See also `_codeql_pack_group_extract_zips`.
|
|
""",
|
|
attrs = _CODEQL_PACK_GROUP_EXTRACT_ATTRS,
|
|
provides = [PackageFilegroupInfo],
|
|
)
|
|
|
|
def _codeql_pack_group_extract_zips_impl(ctx):
|
|
zips_to_prefixes = {}
|
|
|
|
platform, apply_pack_prefix, include_all_files = _codeql_pack_group_extract_options(ctx)
|
|
for src in ctx.attr.srcs:
|
|
src = src[CodeQLPackInfo]
|
|
prefix = paths.join(ctx.attr.prefix, src.pack_prefix) if apply_pack_prefix else ctx.attr.prefix
|
|
|
|
# for each zip file, resolve whether it's filtered out or not by the current kind, and add the pack prefix
|
|
for zip, zip_prefix in src.zips.zips_to_prefixes.items():
|
|
zip_kind, expanded_prefix = _expand_path(paths.join(prefix, zip_prefix), platform)
|
|
if include_all_files or zip_kind == ctx.attr.kind:
|
|
zips_to_prefixes[zip] = expanded_prefix
|
|
|
|
return [
|
|
DefaultInfo(files = depset(zips_to_prefixes.keys())),
|
|
_ZipInfo(zips_to_prefixes = zips_to_prefixes),
|
|
]
|
|
|
|
_codeql_pack_group_extract_zips = rule(
|
|
implementation = _codeql_pack_group_extract_zips_impl,
|
|
doc = """
|
|
Extract the zip files from a list of codeql packs (i.e. a pack group), and filter to the requested `kind`.
|
|
See also `_codeql_pack_group_extract_files`.
|
|
""",
|
|
attrs = _CODEQL_PACK_GROUP_EXTRACT_ATTRS,
|
|
provides = [_ZipInfo],
|
|
)
|
|
|
|
def _codeql_pack_install(name, srcs, install_dest = None, build_file_label = None, prefix = "", apply_pack_prefix = True):
|
|
"""
|
|
Create a runnable target `name` that installs the list of codeql packs given in `srcs` in `install_dest`,
|
|
relative to the directory where the rule is used.
|
|
The base directory can be overwritten by `build_file_label`.
|
|
At run time, you can pass `--destdir` to change the installation directory.
|
|
|
|
If `apply_pack_prefix` is set to `True`, the pack prefix will be added to all paths.
|
|
We skip applying the pack prefix for the single-pack installations in the source tree, and include it when
|
|
installing packs as part of a pack group.
|
|
"""
|
|
internal = _make_internal(name)
|
|
_codeql_pack_group_extract_files(
|
|
name = internal("all-files"),
|
|
srcs = srcs,
|
|
prefix = prefix,
|
|
kind = "all",
|
|
apply_pack_prefix = apply_pack_prefix,
|
|
visibility = ["//visibility:private"],
|
|
)
|
|
_codeql_pack_group_extract_zips(
|
|
name = internal("all-extra-zips"),
|
|
kind = "all",
|
|
srcs = srcs,
|
|
prefix = prefix,
|
|
apply_pack_prefix = apply_pack_prefix,
|
|
visibility = ["//visibility:private"],
|
|
)
|
|
_imported_zips_manifest(
|
|
name = internal("zip-manifest"),
|
|
srcs = [internal("all-extra-zips")],
|
|
visibility = ["//visibility:private"],
|
|
)
|
|
pkg_install(
|
|
name = internal("script"),
|
|
srcs = [internal("all-files")],
|
|
visibility = ["//visibility:private"],
|
|
)
|
|
if build_file_label == None:
|
|
native.filegroup(
|
|
# used to locate current src directory
|
|
name = internal("build-file"),
|
|
srcs = ["BUILD.bazel"],
|
|
visibility = ["//visibility:private"],
|
|
)
|
|
build_file_label = internal("build-file")
|
|
|
|
py_binary(
|
|
name = name,
|
|
srcs = [Label("//misc/bazel/internal:install.py")],
|
|
main = Label("//misc/bazel/internal:install.py"),
|
|
data = [
|
|
internal("script"),
|
|
internal("zip-manifest"),
|
|
Label("//misc/ripunzip"),
|
|
] + ([build_file_label] if build_file_label else []),
|
|
deps = ["@rules_python//python/runfiles"],
|
|
args = [
|
|
"--pkg-install-script=$(rlocationpath %s)" % internal("script"),
|
|
"--ripunzip=$(rlocationpath %s)" % Label("//misc/ripunzip"),
|
|
"--zip-manifest=$(rlocationpath %s)" % internal("zip-manifest"),
|
|
] + ([
|
|
"--build-file=$(rlocationpath %s)" % build_file_label,
|
|
] if build_file_label else []) +
|
|
(["--destdir", "\"%s\"" % install_dest] if install_dest else []),
|
|
)
|
|
|
|
def codeql_pack_group(name, srcs, visibility = None, skip_installer = False, prefix = "", install_dest = None, build_file_label = None, compression_level = 6):
|
|
"""
|
|
Create a group of codeql packs of name `name`.
|
|
Accepts a list of `codeql_pack`s in `srcs` (essentially, `_codeql_pack_info` instantiations).
|
|
A pack group declares the following:
|
|
* a `<name>-common-zip` target creating a `<name>-common.zip` archive with the common parts of the pack group
|
|
* a `<name>-arch-zip` target creating a `<name>-<codeql_platform>.zip` archive with the arch-specific parts of the pack group
|
|
* a `<name>-installer` target that will install the pack group in `install_dest`, relative to where the rule is used.
|
|
The base directory can be overwritten by `build_file_label`, see `codeql_pack_install`.
|
|
The install destination can be overridden appending `-- --destdir=...` to the `bazel run` invocation.
|
|
The installer target will be omitted if `skip_installer` is set to `True`.
|
|
|
|
Prefixes all paths in the pack group with `prefix`.
|
|
|
|
The compression level of the generated zip files can be set with `compression_level`. Note that this doesn't affect the compression
|
|
level of extra zip files that are added to a pack, as these files will not be re-compressed.
|
|
"""
|
|
internal = _make_internal(name)
|
|
|
|
for kind in ("common", "arch"):
|
|
_codeql_pack_group_extract_files(
|
|
name = internal(kind),
|
|
srcs = srcs,
|
|
kind = kind,
|
|
prefix = prefix,
|
|
visibility = ["//visibility:private"],
|
|
)
|
|
pkg_zip(
|
|
name = internal(kind, "zip-base"),
|
|
srcs = [internal(kind)],
|
|
visibility = ["//visibility:private"],
|
|
compression_level = compression_level,
|
|
)
|
|
_codeql_pack_group_extract_zips(
|
|
name = internal(kind, "extra-zips"),
|
|
kind = kind,
|
|
srcs = srcs,
|
|
prefix = prefix,
|
|
visibility = ["//visibility:private"],
|
|
)
|
|
_zipmerge(
|
|
name = internal(kind, "zip"),
|
|
srcs = [internal(kind, "zip-base"), internal(kind, "extra-zips")],
|
|
out = _get_zip_filename(name, kind),
|
|
visibility = visibility,
|
|
)
|
|
if not skip_installer:
|
|
_codeql_pack_install(name, srcs, build_file_label = build_file_label, install_dest = install_dest, prefix = prefix, apply_pack_prefix = True)
|
|
|
|
def codeql_pack(
|
|
*,
|
|
name,
|
|
srcs = None,
|
|
zips = None,
|
|
arch_overrides = None,
|
|
pack_prefix = None,
|
|
install_dest = "extractor-pack",
|
|
**kwargs):
|
|
"""
|
|
Define a codeql pack.
|
|
Packs are used as input to `codeql_pack_group`, which allows convenient building and bundling of packs.
|
|
|
|
This macro accepts `pkg_files`, `pkg_filegroup` or their `codeql_*` counterparts as `srcs`.
|
|
`zips` is a map from `.zip` files to prefixes to import.
|
|
The distinction between arch-specific and common contents is made based on whether the paths (including possible
|
|
prefixes added by rules) contain the special `{CODEQL_PLATFORM}` placeholder, which in case it is present will also
|
|
be replaced by the appropriate platform (`linux64`, `win64` or `osx64`).
|
|
Specific file paths can be placed in the arch-specific package by adding them to `arch_overrides`, even if their
|
|
path doesn't contain the `CODEQL_PLATFORM` placeholder.
|
|
|
|
The codeql pack rules will expand the `{CODEQL_PLATFORM}` marker in paths, and use that to split the files into a common and an arch-specific part.
|
|
This placeholder will be replaced by the appropriate platform (`linux64`, `win64` or `osx64`).
|
|
`arch_overrides` is a list of files that should be included in the arch-specific bits of the pack, even if their path doesn't
|
|
contain the `{CODEQL_PLATFORM}` marker.
|
|
All files in the pack will be prefixed with `name`, unless `pack_prefix` is set, then is used instead.
|
|
|
|
This rule also provides a convenient installer target, with a path governed by `install_dest`.
|
|
This installer is used for installing this pack into the source-tree, relative to the directory where the rule is used.
|
|
See `codeql_pack_install` for more details.
|
|
|
|
This function does not accept `visibility`, as packs are always public to make it easy to define pack groups.
|
|
"""
|
|
internal = _make_internal(name)
|
|
zips = zips or {}
|
|
if pack_prefix == None:
|
|
pack_prefix = name
|
|
pkg_filegroup(
|
|
name = internal("all"),
|
|
srcs = srcs,
|
|
visibility = ["//visibility:private"],
|
|
**kwargs
|
|
)
|
|
_codeql_pack_info(
|
|
name = name,
|
|
src = internal("all"),
|
|
extra_zips = zips,
|
|
prefix = pack_prefix,
|
|
arch_overrides = arch_overrides,
|
|
# packs are always public, so that we can easily bundle them into groups
|
|
visibility = ["//visibility:public"],
|
|
)
|
|
_codeql_pack_install(internal("installer"), [name], install_dest = install_dest, apply_pack_prefix = False)
|
|
|
|
strip_prefix = _strip_prefix
|
|
|
|
def _runfiles_group_impl(ctx):
|
|
files = []
|
|
for src in ctx.attr.srcs:
|
|
rf = src[DefaultInfo].default_runfiles
|
|
if rf != None:
|
|
files.append(rf.files)
|
|
return [
|
|
DefaultInfo(
|
|
files = depset(transitive = files),
|
|
),
|
|
]
|
|
|
|
_runfiles_group = rule(
|
|
implementation = _runfiles_group_impl,
|
|
attrs = {
|
|
"srcs": attr.label_list(),
|
|
},
|
|
)
|
|
|
|
def codeql_pkg_runfiles(*, name, exes, **kwargs):
|
|
"""
|
|
Create a `codeql_pkg_files` with all runfiles from files in `exes`, flattened together.
|
|
"""
|
|
internal = _make_internal(name)
|
|
_runfiles_group(
|
|
name = internal("runfiles"),
|
|
srcs = exes,
|
|
visibility = ["//visibility:private"],
|
|
)
|
|
codeql_pkg_files(
|
|
name = name,
|
|
exes = [internal("runfiles")],
|
|
**kwargs
|
|
)
|
|
|
|
def _pkg_overlay_impl(ctx):
|
|
destinations = {}
|
|
files = []
|
|
depsets = []
|
|
|
|
for src in reversed(ctx.attr.srcs):
|
|
pfi = src[PackageFilesInfo]
|
|
dest_src_map = {k: v for k, v in pfi.dest_src_map.items() if k not in destinations}
|
|
destinations.update({k: True for k in dest_src_map})
|
|
if dest_src_map:
|
|
new_pfi = PackageFilesInfo(
|
|
dest_src_map = dest_src_map,
|
|
attributes = pfi.attributes,
|
|
)
|
|
files.append((new_pfi, src.label))
|
|
depsets.append(depset(dest_src_map.values()))
|
|
return [
|
|
PackageFilegroupInfo(
|
|
pkg_files = reversed(files),
|
|
pkg_dirs = [],
|
|
pkg_symlinks = [],
|
|
),
|
|
DefaultInfo(
|
|
files = depset(transitive = reversed(depsets)),
|
|
),
|
|
]
|
|
|
|
codeql_pkg_files_overlay = rule(
|
|
implementation = _pkg_overlay_impl,
|
|
doc = "Combine `pkg_files` targets so that later targets overwrite earlier ones without warnings",
|
|
attrs = {
|
|
# this could be updated to handle PackageFilegroupInfo as well if we ever need it
|
|
"srcs": attr.label_list(providers = [PackageFilesInfo, DefaultInfo]),
|
|
},
|
|
)
|