Skip to content

Commit 45f1fdf

Browse files
committed
Bazel: extract pack filtering logic out of _zipmerge
1 parent de48477 commit 45f1fdf

File tree

1 file changed

+113
-55
lines changed

1 file changed

+113
-55
lines changed

misc/bazel/pkg.bzl

Lines changed: 113 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ load("@rules_pkg//pkg:providers.bzl", "PackageFilegroupInfo", "PackageFilesInfo"
99
load("@rules_python//python:defs.bzl", "py_binary")
1010

1111
def _make_internal(name):
12-
def internal(suffix = "internal"):
13-
return "%s-%s" % (name, suffix)
12+
def internal(suffix = "internal", *args):
13+
args = (name, suffix) + args
14+
return "-".join(args)
1415

1516
return internal
1617

@@ -133,17 +134,63 @@ _extract_pkg_filegroup = rule(
133134
} | _PLAT_DETECTION_ATTRS,
134135
)
135136

136-
def _imported_zips_manifest_impl(ctx):
137+
_ZipInfo = provider(fields = {"zips_to_prefixes": "mapping of zip files to prefixes"})
138+
139+
def _zip_info_impl(ctx):
140+
zips = {}
141+
for zip_target, prefix in ctx.attr.srcs.items():
142+
for zip in zip_target.files.to_list():
143+
zips[zip] = prefix
144+
return [
145+
_ZipInfo(zips_to_prefixes = zips),
146+
]
147+
148+
_zip_info = rule(
149+
implementation = _zip_info_impl,
150+
doc = """
151+
This internal rule simply instantiates a _ZipInfo provider out of `zips`.
152+
""",
153+
attrs = {
154+
"srcs": attr.label_keyed_string_dict(
155+
doc = "mapping from zip files to install prefixes",
156+
allow_files = [".zip"],
157+
),
158+
},
159+
)
160+
161+
def _zip_info_filter_impl(ctx):
137162
platform = _detect_platform(ctx)
163+
filtered_zips = {}
164+
for zip_info in ctx.attr.srcs:
165+
for zip, prefix in zip_info[_ZipInfo].zips_to_prefixes.items():
166+
zip_kind, expanded_prefix = _expand_path(prefix, platform)
167+
if zip_kind == ctx.attr.kind:
168+
filtered_zips[zip] = expanded_prefix
169+
return [
170+
_ZipInfo(zips_to_prefixes = filtered_zips),
171+
]
172+
173+
_zip_info_filter = rule(
174+
implementation = _zip_info_filter_impl,
175+
doc = """
176+
This internal rule transforms a _ZipInfo provider so that:
177+
* only zips matching `kind` are included
178+
* a kind of a zip is given by its prefix: if it contains {CODEQL_PLATFORM} it is arch, otherwise it's generic
179+
* in the former case, {CODEQL_PLATFORM} is expanded
180+
""",
181+
attrs = {
182+
"srcs": attr.label_list(doc = "_ZipInfos to transform", providers = [_ZipInfo]),
183+
"kind": attr.string(doc = "Which zip kind to consider", values = ["generic", "arch"]),
184+
} | _PLAT_DETECTION_ATTRS,
185+
)
138186

187+
def _imported_zips_manifest_impl(ctx):
139188
manifest = []
140189
files = []
141-
for zip, prefix in ctx.attr.zips.items():
142-
# we don't care about the kind here, as we're taking all zips together
143-
_, expanded_prefix = _expand_path(prefix, platform)
144-
zip_files = zip.files.to_list()
145-
manifest += ["%s:%s" % (expanded_prefix, f.short_path) for f in zip_files]
146-
files += zip_files
190+
for zip_info in ctx.attr.srcs:
191+
zip_info = zip_info[_ZipInfo]
192+
manifest += ["%s:%s" % (p, z.short_path) for z, p in zip_info.zips_to_prefixes.items()]
193+
files += list(zip_info.zips_to_prefixes)
147194

148195
output = ctx.actions.declare_file(ctx.label.name + ".params")
149196
ctx.actions.write(
@@ -162,30 +209,39 @@ _imported_zips_manifest = rule(
162209
{CODEQL_PLATFORM} can be used as zip prefixes and will be expanded to the relevant codeql platform.
163210
""",
164211
attrs = {
165-
"zips": attr.label_keyed_string_dict(
166-
doc = "mapping from zip files to install prefixes",
167-
allow_files = [".zip"],
212+
"srcs": attr.label_list(
213+
doc = "mappings from zip files to install prefixes in _ZipInfo format",
214+
providers = [_ZipInfo],
168215
),
169-
} | _PLAT_DETECTION_ATTRS,
216+
},
170217
)
171218

172219
def _zipmerge_impl(ctx):
173220
zips = []
174-
filename = ctx.attr.zip_name + "-"
175-
platform = _detect_platform(ctx)
176-
filename = "%s-%s.zip" % (ctx.attr.zip_name, platform if ctx.attr.kind == "arch" else "generic")
177-
output = ctx.actions.declare_file(filename)
178-
args = [output.path, "--prefix=%s" % ctx.attr.prefix, ctx.file.base.path]
179-
for zip, prefix in ctx.attr.zips.items():
180-
zip_kind, expanded_prefix = _expand_path(prefix, platform)
181-
if zip_kind == ctx.attr.kind:
182-
args.append("--prefix=%s/%s" % (ctx.attr.prefix, expanded_prefix.rstrip("/")))
183-
args += [f.path for f in zip.files.to_list()]
184-
zips.append(zip.files)
221+
transitive_zips = []
222+
output = ctx.actions.declare_file(ctx.attr.out)
223+
args = [output.path]
224+
for zip_target in ctx.attr.srcs:
225+
if _ZipInfo in zip_target:
226+
zip_info = zip_target[_ZipInfo]
227+
for zip, prefix in zip_info.zips_to_prefixes.items():
228+
args += [
229+
"--prefix=%s/%s" % (ctx.attr.prefix, prefix.rstrip("/")),
230+
zip.path,
231+
]
232+
zips.append(zip)
233+
else:
234+
zips = zip_target.files.to_list()
235+
for zip in zips:
236+
if zip.extension != "zip":
237+
fail("%s file found while expecting a .zip file " % zip.short_path)
238+
args.append("--prefix=%s" % ctx.attr.prefix)
239+
args += [z.path for z in zips]
240+
transitive_zips.append(zip_target.files)
185241
ctx.actions.run(
186242
outputs = [output],
187243
executable = ctx.executable._zipmerge,
188-
inputs = depset([ctx.file.base], transitive = zips),
244+
inputs = depset(zips, transitive = transitive_zips),
189245
arguments = args,
190246
)
191247

@@ -196,30 +252,22 @@ def _zipmerge_impl(ctx):
196252
_zipmerge = rule(
197253
implementation = _zipmerge_impl,
198254
doc = """
199-
This internal rule merges a `base` zip file with the ones indicated by the `zips` mapping where the prefix
200-
indicates a matching kind between arch and generic. An imported zip file will be considered arch-specific
201-
if its prefix contains `{CODEQL_PLATFORM}` (and this prefix will have that expanded to the appropriate
202-
platform).
203-
204-
The output filename will be either `{zip_name}-generic.zip` or `{zip_name}-{CODEQL_PLATFORM}.zip`, depending on
205-
the requested `kind`.
255+
This internal rule merges a zip files together
206256
""",
207257
attrs = {
208-
"base": attr.label(
209-
doc = "Base zip file to which zips from `zips` will be merged with",
210-
allow_single_file = [".zip"],
211-
),
212-
"zips": attr.label_keyed_string_dict(
213-
doc = "mapping from zip files to install prefixes",
214-
allow_files = [".zip"],
215-
),
216-
"zip_name": attr.string(doc = "Prefix to use for the output file name"),
217-
"kind": attr.string(doc = "Which zip kind to consider", values = ["generic", "arch"]),
258+
"srcs": attr.label_list(doc = "Zip file to include, either as straight up `.zip` files or `_ZipInfo` data"),
259+
"out": attr.string(doc = "output file name"),
218260
"prefix": attr.string(doc = "Prefix posix path to add to the zip contents in the archive"),
219261
"_zipmerge": attr.label(default = "//misc/bazel/internal/zipmerge", executable = True, cfg = "exec"),
220-
} | _PLAT_DETECTION_ATTRS,
262+
},
221263
)
222264

265+
def _get_zip_filename(name_prefix, kind):
266+
if kind == "arch":
267+
return name_prefix + "-" + _detect_platform() + ".zip" # using + because there's a select
268+
else:
269+
return "%s-generic.zip" % name_prefix
270+
223271
def codeql_pack(
224272
*,
225273
name,
@@ -252,47 +300,57 @@ def codeql_pack(
252300
zip_filename = zip_filename or name
253301
zips = zips or {}
254302
pkg_filegroup(
255-
name = internal("base"),
303+
name = internal("all"),
256304
srcs = srcs,
257305
visibility = ["//visibility:private"],
258306
**kwargs
259307
)
308+
if zips:
309+
_zip_info(
310+
name = internal("zip-info"),
311+
srcs = zips,
312+
visibility = ["//visibility:private"],
313+
)
260314
for kind in ("generic", "arch"):
261315
_extract_pkg_filegroup(
262316
name = internal(kind),
263-
src = internal("base"),
317+
src = internal("all"),
264318
kind = kind,
265319
visibility = ["//visibility:private"],
266320
)
267321
if zips:
268322
pkg_zip(
269-
name = internal(kind + "-zip-base"),
323+
name = internal(kind, "zip-base"),
270324
srcs = [internal(kind)],
271325
visibility = ["//visibility:private"],
272326
compression_level = compression_level,
273327
)
274-
_zipmerge(
275-
name = internal(kind + "-zip"),
276-
base = internal(kind + "-zip-base"),
277-
zips = zips,
278-
zip_name = zip_filename,
328+
_zip_info_filter(
329+
name = internal(kind, "zip-info"),
279330
kind = kind,
331+
srcs = [internal("zip-info")],
332+
visibility = ["//visibility:private"],
333+
)
334+
_zipmerge(
335+
name = internal(kind, "zip"),
336+
srcs = [internal(kind, "zip-base"), internal(kind, "zip-info")],
337+
out = _get_zip_filename(name, kind),
280338
prefix = name,
281339
visibility = visibility,
282340
)
283341
else:
284342
pkg_zip(
285-
name = internal(kind + "-zip"),
343+
name = internal(kind, "zip"),
286344
srcs = [internal(kind)],
287-
visibility = ["//visibility:private"],
345+
visibility = visibility,
288346
package_dir = name,
289-
package_file_name = name + "-" + (_detect_platform() if kind == "arch" else "generic") + ".zip",
347+
package_file_name = _get_zip_filename(name, kind),
290348
compression_level = compression_level,
291349
)
292350
if zips:
293351
_imported_zips_manifest(
294352
name = internal("zip-manifest"),
295-
zips = zips,
353+
srcs = [internal("generic-zip-info"), internal("arch-zip-info")],
296354
visibility = ["//visibility:private"],
297355
)
298356

0 commit comments

Comments
 (0)