@@ -5,11 +5,12 @@ Wrappers and helpers around `rules_pkg` to build codeql packs.
55load ("@rules_pkg//pkg:install.bzl" , "pkg_install" )
66load ("@rules_pkg//pkg:mappings.bzl" , "pkg_attributes" , "pkg_filegroup" , "pkg_files" , _strip_prefix = "strip_prefix" )
77load ("@rules_pkg//pkg:pkg.bzl" , "pkg_zip" )
8+ load ("@rules_pkg//pkg:providers.bzl" , "PackageFilegroupInfo" , "PackageFilesInfo" )
89load ("@rules_python//python:defs.bzl" , "py_binary" )
910load ("//:defs.bzl" , "codeql_platform" )
1011
1112def _make_internal (name ):
12- def internal (suffix ):
13+ def internal (suffix = "internal" ):
1314 return "%s-%s" % (name , suffix )
1415
1516 return internal
@@ -20,151 +21,173 @@ def _get_subrule(label, suffix):
2021 path , _ , pkg = label .rpartition ("/" )
2122 return "%s/%s:%s-%s" % (path , pkg , pkg , suffix )
2223
24+ _PackageFileWrapperInfo = provider (fields = {"pfi" : "" , "src" : "" , "arch_specific" : "" })
25+
26+ CodeqlFilesInfo = provider (
27+ doc = """Wrapper around `rules_pkg` `PackageFilesInfo` carrying information about generic and arch-specific files.""" ,
28+ fields = {
29+ "files" : "list of `_PackageFileWrapperInfo`." ,
30+ },
31+ )
32+
33+ def _codeql_pkg_filegroup_impl (ctx ):
34+ prefix = ctx .attr .prefix
35+ if prefix :
36+ prefix += "/"
37+ generic_prefix = prefix
38+ if ctx .attr .arch_specific :
39+ if ctx .target_platform_has_constraint (ctx .attr ._windows [platform_common .ConstraintValueInfo ]):
40+ plat = "windows64"
41+ elif ctx .target_platform_has_constraint (ctx .attr ._macos [platform_common .ConstraintValueInfo ]):
42+ plat = "osx64"
43+ else :
44+ plat = "linux64"
45+ prefix = prefix + plat + "/"
46+
47+ def transform_pfi (pfi , src , prefix = prefix , arch_specific = ctx .attr .arch_specific ):
48+ return _PackageFileWrapperInfo (
49+ pfi = PackageFilesInfo (
50+ attributes = pfi .attributes ,
51+ dest_src_map = {prefix + d : s for d , s in pfi .dest_src_map .items ()},
52+ ),
53+ src = src ,
54+ arch_specific = arch_specific ,
55+ )
56+
57+ files = []
58+
59+ for src in ctx .attr .srcs :
60+ if PackageFilesInfo in src :
61+ pfi = src [PackageFilesInfo ]
62+ files .append (transform_pfi (pfi , src .label ))
63+ elif PackageFilegroupInfo in src :
64+ pfgi = src [PackageFilegroupInfo ]
65+ if pfgi .pkg_dirs or pfgi .pkg_symlinks :
66+ fail ("while assembling %s found %s which contains `pkg_dirs` or `pkg_symlinks` targets" %
67+ (ctx .label , src .label ) + ", which is not currently supported" )
68+ files += [transform_pfi (pfi , src ) for pfi , src in pfgi .pkg_files ]
69+ else :
70+ cfi = src [CodeqlFilesInfo ]
71+ files += [
72+ transform_pfi (
73+ pfwi .pfi ,
74+ pfwi .src ,
75+ # if it was already arch specific the plat prefix was already added
76+ generic_prefix if pfwi .arch_specific else prefix ,
77+ pfwi .arch_specific or ctx .attr .arch_specific ,
78+ )
79+ for pfwi in cfi .files
80+ ]
81+
82+ return [
83+ CodeqlFilesInfo (
84+ files = files ,
85+ ),
86+ DefaultInfo (
87+ files = depset (transitive = [src [DefaultInfo ].files for src in ctx .attr .srcs ]),
88+ ),
89+ ]
90+
91+ codeql_pkg_filegroup = rule (
92+ implementation = _codeql_pkg_filegroup_impl ,
93+ doc = """CodeQL specific packaging mapping. No `pkg_mkdirs` or `pkg_symlink` rules are supported, either directly
94+ or transitively. Only `pkg_files` and `pkg_filegroup` thereof are allowed.""" ,
95+ attrs = {
96+ "srcs" : attr .label_list (
97+ doc = "List of arch-agnostic `pkg_files`, `pkg_filegroup` or `codeql_pkg_filegroup` targets" ,
98+ providers = [
99+ [PackageFilesInfo , DefaultInfo ],
100+ [PackageFilegroupInfo , DefaultInfo ],
101+ [CodeqlFilesInfo , DefaultInfo ],
102+ ],
103+ default = [],
104+ ),
105+ "prefix" : attr .string (doc = "Prefix to add to the files" , default = "" ),
106+ "arch_specific" : attr .bool (doc = "Whether the included files should be treated as arch-specific" ),
107+ "_windows" : attr .label (default = "@platforms//os:windows" ),
108+ "_macos" : attr .label (default = "@platforms//os:macos" ),
109+ },
110+ )
111+
23112def codeql_pkg_files (
24113 * ,
25114 name ,
26- arch_specific = False ,
27115 srcs = None ,
28116 exes = None ,
29- renames = None ,
117+ arch_specific = False ,
30118 prefix = None ,
31119 visibility = None ,
32120 ** kwargs ):
33121 """
34122 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.
123+ * `exes` will get their file attributes set to be executable. This is important only for POSIX files, there's no
124+ need to mark windows executables as such
125+ If `exes` and `srcs` are both used, the resulting rule is a `pkg_filegroup` one.
40126 """
41127 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 )
128+ if "attributes" in kwargs :
129+ fail ("codeql_pkg_files does not support `attributes`. Use `exes` to mark executable files." )
130+ internal_srcs = []
54131 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
61132 pkg_files (
62133 name = internal ("srcs" ),
63134 srcs = srcs ,
64- renames = src_renames ,
65- prefix = prefix ,
66135 visibility = ["//visibility:private" ],
67136 ** kwargs
68137 )
69138 pkg_files (
70139 name = internal ("exes" ),
71140 srcs = exes ,
72- renames = exe_renames ,
73- prefix = prefix ,
74141 visibility = ["//visibility:private" ],
75- attributes = pkg_attributes (mode = "0755 " ),
142+ attributes = pkg_attributes (mode = "755 " ),
76143 ** kwargs
77144 )
78- pkg_filegroup (
79- name = main_rule ,
80- srcs = [internal ("srcs" ), internal ("exes" )],
81- visibility = visibility ,
82- )
145+ internal_srcs = [internal ("srcs" ), internal ("exes" )]
83146 else :
84147 pkg_files (
85- name = main_rule ,
148+ name = internal () ,
86149 srcs = srcs or exes ,
87- attributes = pkg_attributes (mode = "0755" ) if exes else None ,
88- prefix = prefix ,
89150 visibility = visibility ,
151+ attributes = pkg_attributes (mode = "755" ) if exes else None ,
90152 ** kwargs
91153 )
92- native .filegroup (
154+ internal_srcs = [internal ()]
155+ codeql_pkg_filegroup (
93156 name = name ,
94- srcs = [main_rule ],
95- visibility = visibility ,
96- )
97-
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 ,
157+ srcs = internal_srcs ,
158+ arch_specific = arch_specific ,
112159 prefix = prefix ,
113160 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 ,
125161 )
126162
127- def codeql_pkg_filegroup (
163+ def _extract_pkg_filegroup_impl (ctx ):
164+ src = ctx .attr .src [CodeqlFilesInfo ]
165+ pfi_lbls = [(pfwi .pfi , pfwi .src ) for pfwi in src .files if pfwi .arch_specific == ctx .attr .arch_specific ]
166+ files = [depset (pfi .dest_src_map .values ()) for pfi , _ in pfi_lbls ]
167+ return [
168+ PackageFilegroupInfo (pkg_files = pfi_lbls , pkg_dirs = [], pkg_symlinks = []),
169+ DefaultInfo (files = depset (transitive = files )),
170+ ]
171+
172+ _extrac_pkg_filegroup = rule (
173+ implementation = _extract_pkg_filegroup_impl ,
174+ attrs = {
175+ "src" : attr .label (providers = [CodeqlFilesInfo , DefaultInfo ]),
176+ "arch_specific" : attr .bool (),
177+ },
178+ )
179+
180+ def codeql_pack (
128181 * ,
129182 name ,
130- srcs ,
131- srcs_select = None ,
183+ srcs = None ,
184+ zip_prefix = None ,
185+ zip_filename = "extractor" ,
132186 visibility = None ,
187+ install_dest = "extractor-pack" ,
133188 ** kwargs ):
134189 """
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:
190+ Define a codeql pack. This accepts `pkg_files`, `pkg_filegroup` or their `codeql_*` counterparts as `srcs`.
168191 * defines a `<name>-generic-zip` target creating a `<zip_filename>-generic.zip` archive with the generic bits,
169192 prefixed with `zip_prefix` (`name` by default)
170193 * defines a `<name>-arch-zip` target creating a `<zip_filename>-<codeql_platform>.zip` archive with the
@@ -182,31 +205,32 @@ def codeql_pack(*, name, srcs, zip_prefix = None, zip_filename = "extractor", vi
182205 visibility = visibility ,
183206 ** kwargs
184207 )
185- codeql_pkg_filegroup (
186- name = internal ("zip-contents" ),
187- srcs = [name ],
188- prefix = zip_prefix ,
189- visibility = ["//visibility:private" ],
190- )
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 ,
202- )
208+ for kind in ("generic" , "arch" ):
209+ _extrac_pkg_filegroup (
210+ name = internal (kind ),
211+ src = name ,
212+ arch_specific = kind == "arch" ,
213+ visibility = ["//visibility:private" ],
214+ )
215+ pkg_filegroup (
216+ name = internal (kind + "-zip-contents" ),
217+ srcs = [internal (kind )],
218+ prefix = zip_prefix ,
219+ visibility = ["//visibility:private" ],
220+ )
221+ pkg_zip (
222+ name = internal (kind + "-zip" ),
223+ srcs = [internal (kind + "-zip-contents" )],
224+ package_file_name = zip_filename + "-" + (codeql_platform if kind == "arch" else kind ) + ".zip" ,
225+ visibility = visibility ,
226+ )
203227 pkg_install (
204228 name = internal ("script" ),
205229 srcs = [internal ("generic" ), internal ("arch" )],
206230 visibility = ["//visibility:private" ],
207231 )
208232 native .filegroup (
209- # used to locate current source directory
233+ # used to locate current src directory
210234 name = internal ("build-file" ),
211235 srcs = ["BUILD.bazel" ],
212236 visibility = ["//visibility:private" ],
0 commit comments