Skip to content

Commit 57f3a9a

Browse files
committed
Bazel: move codeql packaging rules away from some macros
1 parent 1306d88 commit 57f3a9a

File tree

4 files changed

+174
-164
lines changed

4 files changed

+174
-164
lines changed

misc/bazel/pkg.bzl

+142-120
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ Wrappers and helpers around `rules_pkg` to build codeql packs.
55
load("@rules_pkg//pkg:install.bzl", "pkg_install")
66
load("@rules_pkg//pkg:mappings.bzl", "pkg_attributes", "pkg_filegroup", "pkg_files", _strip_prefix = "strip_prefix")
77
load("@rules_pkg//pkg:pkg.bzl", "pkg_zip")
8+
load("@rules_pkg//pkg:providers.bzl", "PackageFilegroupInfo", "PackageFilesInfo")
89
load("@rules_python//python:defs.bzl", "py_binary")
9-
load("//:defs.bzl", "codeql_platform")
1010

1111
def _make_internal(name):
12-
def internal(suffix):
12+
def internal(suffix = "internal"):
1313
return "%s-%s" % (name, suffix)
1414

1515
return internal
@@ -20,151 +20,166 @@ def _get_subrule(label, suffix):
2020
path, _, pkg = label.rpartition("/")
2121
return "%s/%s:%s-%s" % (path, pkg, pkg, suffix)
2222

23+
CodeqlFilesInfo = provider(
24+
doc = """Wrapper around `rules_pkg` `PackageFilesInfo` splitting into generic and arch-specific files.""",
25+
fields = {
26+
"generic": "list of `(PackageFilesInfo, Label)` tuples for generic files.",
27+
"arch": "list of `(PackageFilesInfo, Label)` tuples for arch-specific files.",
28+
},
29+
)
30+
31+
def _codeql_pkg_filegroup_impl(ctx):
32+
if ctx.target_platform_has_constraint(ctx.attr._windows[platform_common.ConstraintValueInfo]):
33+
plat = "windows64"
34+
elif ctx.target_platform_has_constraint(ctx.attr._macos[platform_common.ConstraintValueInfo]):
35+
plat = "osx64"
36+
else:
37+
plat = "linux64"
38+
generic_prefix = ctx.attr.prefix
39+
if generic_prefix:
40+
generic_prefix += "/"
41+
arch_prefix = generic_prefix + plat + "/"
42+
43+
def transform_pfi_lbl(pfi_lbl, prefix):
44+
pfi, lbl = pfi_lbl
45+
return (PackageFilesInfo(
46+
attributes = pfi.attributes,
47+
dest_src_map = {prefix + d: s for d, s in pfi.dest_src_map.items()},
48+
), lbl)
49+
50+
generic = []
51+
arch = []
52+
for dest, prefix, srcs in (
53+
(generic, generic_prefix, ctx.attr.srcs),
54+
(arch, arch_prefix, ctx.attr.arch_srcs),
55+
):
56+
for src in srcs:
57+
if PackageFilesInfo in src:
58+
dest.append(transform_pfi_lbl((src[PackageFilesInfo], src.label), prefix))
59+
elif PackageFilegroupInfo in src:
60+
pfgi = src[PackageFilegroupInfo]
61+
if pfgi.pkg_dirs or pfgi.pkg_symlinks:
62+
fail("while assembling %s found %s which contains `pkg_dirs` or `pkg_symlinks` targets" %
63+
(ctx.label, src.label))
64+
dest += [transform_pfi_lbl(item, prefix) for item in pfgi.pkg_files]
65+
else:
66+
cfi = src[CodeqlFilesInfo]
67+
generic += [transform_pfi_lbl(item, generic_prefix) for item in cfi.generic]
68+
69+
# arch-specific prefix was already applied
70+
arch += [transform_pfi_lbl(item, generic_prefix) for item in cfi.arch]
71+
72+
srcs = ctx.attr.srcs + ctx.attr.arch_srcs
73+
return [
74+
CodeqlFilesInfo(
75+
generic = generic,
76+
arch = arch,
77+
),
78+
DefaultInfo(
79+
files = depset(transitive = [src[DefaultInfo].files for src in srcs]),
80+
),
81+
]
82+
83+
codeql_pkg_filegroup = rule(
84+
implementation = _codeql_pkg_filegroup_impl,
85+
doc = """CodeQL specific packaging mapping. No `pkg_mkdirs` or `pkg_symlink` rules are supported, either directly
86+
or transitively. Only `pkg_files` and `pkg_filegroup` thereof are allowed.""",
87+
attrs = {
88+
"srcs": attr.label_list(
89+
doc = "List of arch-agnostic `pkg_files`, `pkg_filegroup` or `codeql_pkg_filegroup` targets",
90+
providers = [DefaultInfo],
91+
default = [],
92+
),
93+
"arch_srcs": attr.label_list(
94+
doc = "List of arch-specific `pkg_files` or `pkg_filegroup` targets",
95+
providers = [DefaultInfo],
96+
default = [],
97+
),
98+
"prefix": attr.string(doc = "Prefix to add to the files"),
99+
"_windows": attr.label(default = "@platforms//os:windows"),
100+
"_macos": attr.label(default = "@platforms//os:macos"),
101+
},
102+
)
103+
23104
def codeql_pkg_files(
24105
*,
25106
name,
26-
arch_specific = False,
27107
srcs = None,
28108
exes = None,
29-
renames = None,
30109
prefix = None,
31110
visibility = None,
32111
**kwargs):
33112
"""
34113
Wrapper around `pkg_files`. Added functionality:
35-
* `exes` get their file attributes set to be executable. This is important only for POSIX files, there's no need
36-
to mark windows executables as such
37-
* `arch_specific` auto-adds the codeql platform specific directory (linux64, osx64 or windows64), and will be
38-
consumed by a downstream `codeql_pack` to create the arch specific zip.
39-
This should be consumed by `codeql_pkg_filegroup` and `codeql_pack` only.
114+
* `exes` will get their file attributes set to be executable. This is important only for POSIX files, there's no
115+
need to mark windows executables as such
116+
If `exes` and `srcs` are both used, the resulting rule is a `pkg_filegroup` one.
40117
"""
41118
internal = _make_internal(name)
42-
main_rule = internal("generic")
43-
empty_rule = internal("arch")
44-
if arch_specific:
45-
main_rule, empty_rule = empty_rule, main_rule
46-
prefix = (prefix + "/" if prefix else "") + codeql_platform
47-
pkg_files(
48-
name = empty_rule,
49-
srcs = [],
50-
visibility = visibility,
51-
)
52-
if not srcs and not exes:
53-
fail("either srcs or exes should be specified for %s" % name)
119+
if "attributes" in kwargs:
120+
fail("codeql_pkg_files does not support `attributes`. Use `exes` to mark executable files.")
121+
internal_srcs = []
54122
if srcs and exes:
55-
if renames:
56-
src_renames = {k: v for k, v in renames.items() if k in srcs}
57-
exe_renames = {k: v for k, v in renames.items() if k in exes}
58-
else:
59-
src_renames = None
60-
exe_renames = None
61123
pkg_files(
62124
name = internal("srcs"),
63125
srcs = srcs,
64-
renames = src_renames,
65-
prefix = prefix,
66126
visibility = ["//visibility:private"],
67127
**kwargs
68128
)
69129
pkg_files(
70130
name = internal("exes"),
71131
srcs = exes,
72-
renames = exe_renames,
73-
prefix = prefix,
74132
visibility = ["//visibility:private"],
75-
attributes = pkg_attributes(mode = "0755"),
133+
attributes = pkg_attributes(mode = "755"),
76134
**kwargs
77135
)
78136
pkg_filegroup(
79-
name = main_rule,
137+
name = name,
80138
srcs = [internal("srcs"), internal("exes")],
139+
prefix = prefix,
81140
visibility = visibility,
82141
)
83142
else:
84143
pkg_files(
85-
name = main_rule,
144+
name = name,
86145
srcs = srcs or exes,
87-
attributes = pkg_attributes(mode = "0755") if exes else None,
88-
prefix = prefix,
89146
visibility = visibility,
147+
prefix = prefix,
148+
attributes = pkg_attributes(mode = "755") if exes else None,
90149
**kwargs
91150
)
92-
native.filegroup(
93-
name = name,
94-
srcs = [main_rule],
95-
visibility = visibility,
96-
)
97151

98-
def codeql_pkg_wrap(*, name, srcs, arch_specific = False, prefix = None, visibility = None, **kwargs):
99-
"""
100-
Wrap a native `rules_pkg` rule, providing the `arch_specific` functionality and making it consumable by
101-
`codeql_pkg_filegroup` and `codeql_pack`.
102-
"""
103-
internal = _make_internal(name)
104-
main_rule = internal("generic")
105-
empty_rule = internal("arch")
106-
if arch_specific:
107-
main_rule, empty_rule = empty_rule, main_rule
108-
prefix = (prefix + "/" if prefix else "") + codeql_platform
109-
pkg_filegroup(
110-
name = main_rule,
111-
srcs = srcs,
112-
prefix = prefix,
113-
visibility = visibility,
114-
**kwargs
115-
)
116-
pkg_files(
117-
name = empty_rule,
118-
srcs = [],
119-
visibility = visibility,
120-
)
121-
native.filegroup(
122-
name = name,
123-
srcs = [main_rule],
124-
visibility = visibility,
125-
)
152+
def _extract_pkg_filegroup_impl(ctx):
153+
src = ctx.attr.src[CodeqlFilesInfo]
154+
pfi_lbl_list = src.arch if ctx.attr.arch_specific else src.generic
155+
files = []
156+
for pfi, lbl in pfi_lbl_list:
157+
files.append(depset(pfi.dest_src_map.values()))
158+
return [
159+
PackageFilegroupInfo(pkg_files = pfi_lbl_list, pkg_dirs = [], pkg_symlinks = []),
160+
DefaultInfo(files = depset(transitive = files)),
161+
]
126162

127-
def codeql_pkg_filegroup(
163+
_extrac_pkg_filegroup = rule(
164+
implementation = _extract_pkg_filegroup_impl,
165+
attrs = {
166+
"src": attr.label(providers = [CodeqlFilesInfo, DefaultInfo]),
167+
"arch_specific": attr.bool(),
168+
},
169+
)
170+
171+
def codeql_pack(
128172
*,
129173
name,
130-
srcs,
131-
srcs_select = None,
174+
srcs = None,
175+
arch_srcs = None,
176+
zip_prefix = None,
177+
zip_filename = "extractor",
132178
visibility = None,
179+
install_dest = "extractor-pack",
133180
**kwargs):
134181
"""
135-
Combine `codeql_pkg_files` and other `codeql_pkg_filegroup` rules, similar to what `pkg_filegroup` does.
136-
`srcs` is not selectable, but `srcs_select` accepts the same dictionary that a select would accept.
137-
"""
138-
internal = _make_internal(name)
139-
140-
def transform(srcs, suffix):
141-
return [_get_subrule(src, suffix) for src in srcs]
142-
143-
pkg_filegroup(
144-
name = internal("generic"),
145-
srcs = transform(srcs, "generic") + (select(
146-
{k: transform(v, "generic") for k, v in srcs_select.items()},
147-
) if srcs_select else []),
148-
visibility = visibility,
149-
**kwargs
150-
)
151-
pkg_filegroup(
152-
name = internal("arch"),
153-
srcs = transform(srcs, "arch") + (select(
154-
{k: transform(v, "arch") for k, v in srcs_select.items()},
155-
) if srcs_select else []),
156-
visibility = visibility,
157-
**kwargs
158-
)
159-
native.filegroup(
160-
name = name,
161-
srcs = [internal("generic"), internal("arch")],
162-
visibility = visibility,
163-
)
164-
165-
def codeql_pack(*, name, srcs, zip_prefix = None, zip_filename = "extractor", visibility = visibility, install_dest = "extractor-pack", **kwargs):
166-
"""
167-
Define a codeql pack. This accepts the same arguments as `codeql_pkg_filegroup`, and additionally:
182+
Define a codeql pack. This accepts `pkg_files`, `pkg_filegroup` or their `codeql_*` counterparts as `srcs`.
168183
* defines a `<name>-generic-zip` target creating a `<zip_filename>-generic.zip` archive with the generic bits,
169184
prefixed with `zip_prefix` (`name` by default)
170185
* defines a `<name>-arch-zip` target creating a `<zip_filename>-<codeql_platform>.zip` archive with the
@@ -179,27 +194,34 @@ def codeql_pack(*, name, srcs, zip_prefix = None, zip_filename = "extractor", vi
179194
codeql_pkg_filegroup(
180195
name = name,
181196
srcs = srcs,
197+
arch_srcs = arch_srcs,
182198
visibility = visibility,
183199
**kwargs
184200
)
185-
codeql_pkg_filegroup(
186-
name = internal("zip-contents"),
187-
srcs = [name],
188-
prefix = zip_prefix,
201+
_extrac_pkg_filegroup(
202+
name = internal("generic"),
203+
src = name,
204+
arch_specific = False,
189205
visibility = ["//visibility:private"],
190206
)
191-
pkg_zip(
192-
name = internal("generic-zip"),
193-
srcs = [internal("zip-contents-generic")],
194-
package_file_name = zip_filename + "-generic.zip",
195-
visibility = visibility,
196-
)
197-
pkg_zip(
198-
name = internal("arch-zip"),
199-
srcs = [internal("zip-contents-arch")],
200-
package_file_name = zip_filename + "-" + codeql_platform + ".zip",
201-
visibility = visibility,
207+
_extrac_pkg_filegroup(
208+
name = internal("arch"),
209+
src = name,
210+
arch_specific = True,
211+
visibility = ["//visibility:private"],
202212
)
213+
for kind in ("generic", "arch"):
214+
pkg_filegroup(
215+
name = internal(kind + "-zip-contents"),
216+
srcs = [internal(kind)],
217+
visibility = ["//visibility:private"],
218+
)
219+
pkg_zip(
220+
name = internal(kind + "-zip"),
221+
srcs = [internal(kind + "-zip-contents")],
222+
package_file_name = "%s-%s.zip" % (zip_filename, kind),
223+
visibility = visibility,
224+
)
203225
pkg_install(
204226
name = internal("script"),
205227
srcs = [internal("generic"), internal("arch")],

0 commit comments

Comments
 (0)