summaryrefslogtreecommitdiffstats
path: root/meta/classes-global/package_rpm.bbclass
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2022-08-10 14:35:29 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2022-08-12 15:27:17 +0100
commitfd1517e2b51a170f2427122c6b95396db251d827 (patch)
treedabfe3e631339c2fc99a9ee7febb0f9c128e325e /meta/classes-global/package_rpm.bbclass
parent10317912ee319ccf7f83605d438b5cbf9663f296 (diff)
downloadpoky-fd1517e2b51a170f2427122c6b95396db251d827.tar.gz
classes: Update classes to match new bitbake class scope functionality
Move classes to classes-global or classes-recipe as appropriate to take advantage of new bitbake functionality to check class scope/usage. (From OE-Core rev: f5c128008365e141082c129417eb72d2751e8045) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/classes-global/package_rpm.bbclass')
-rw-r--r--meta/classes-global/package_rpm.bbclass761
1 files changed, 761 insertions, 0 deletions
diff --git a/meta/classes-global/package_rpm.bbclass b/meta/classes-global/package_rpm.bbclass
new file mode 100644
index 0000000000..63c1b077a3
--- /dev/null
+++ b/meta/classes-global/package_rpm.bbclass
@@ -0,0 +1,761 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
6
7inherit package
8
9IMAGE_PKGTYPE ?= "rpm"
10
11RPM="rpm"
12RPMBUILD="rpmbuild"
13
14PKGWRITEDIRRPM = "${WORKDIR}/deploy-rpms"
15
16# Maintaining the perfile dependencies has singificant overhead when writing the
17# packages. When set, this value merges them for efficiency.
18MERGEPERFILEDEPS = "1"
19
20# Filter dependencies based on a provided function.
21def filter_deps(var, f):
22 import collections
23
24 depends_dict = bb.utils.explode_dep_versions2(var)
25 newdeps_dict = collections.OrderedDict()
26 for dep in depends_dict:
27 if f(dep):
28 newdeps_dict[dep] = depends_dict[dep]
29 return bb.utils.join_deps(newdeps_dict, commasep=False)
30
31# Filter out absolute paths (typically /bin/sh and /usr/bin/env) and any perl
32# dependencies for nativesdk packages.
33def filter_nativesdk_deps(srcname, var):
34 if var and srcname.startswith("nativesdk-"):
35 var = filter_deps(var, lambda dep: not dep.startswith('/') and dep != 'perl' and not dep.startswith('perl('))
36 return var
37
38# Construct per file dependencies file
39def write_rpm_perfiledata(srcname, d):
40 workdir = d.getVar('WORKDIR')
41 packages = d.getVar('PACKAGES')
42 pkgd = d.getVar('PKGD')
43
44 def dump_filerdeps(varname, outfile, d):
45 outfile.write("#!/usr/bin/env python3\n\n")
46 outfile.write("# Dependency table\n")
47 outfile.write('deps = {\n')
48 for pkg in packages.split():
49 dependsflist_key = 'FILE' + varname + 'FLIST' + ":" + pkg
50 dependsflist = (d.getVar(dependsflist_key) or "")
51 for dfile in dependsflist.split():
52 key = "FILE" + varname + ":" + dfile + ":" + pkg
53 deps = filter_nativesdk_deps(srcname, d.getVar(key) or "")
54 depends_dict = bb.utils.explode_dep_versions(deps)
55 file = dfile.replace("@underscore@", "_")
56 file = file.replace("@closebrace@", "]")
57 file = file.replace("@openbrace@", "[")
58 file = file.replace("@tab@", "\t")
59 file = file.replace("@space@", " ")
60 file = file.replace("@at@", "@")
61 outfile.write('"' + pkgd + file + '" : "')
62 for dep in depends_dict:
63 ver = depends_dict[dep]
64 if dep and ver:
65 ver = ver.replace("(","")
66 ver = ver.replace(")","")
67 outfile.write(dep + " " + ver + " ")
68 else:
69 outfile.write(dep + " ")
70 outfile.write('",\n')
71 outfile.write('}\n\n')
72 outfile.write("import sys\n")
73 outfile.write("while 1:\n")
74 outfile.write("\tline = sys.stdin.readline().strip()\n")
75 outfile.write("\tif not line:\n")
76 outfile.write("\t\tsys.exit(0)\n")
77 outfile.write("\tif line in deps:\n")
78 outfile.write("\t\tprint(deps[line] + '\\n')\n")
79
80 # OE-core dependencies a.k.a. RPM requires
81 outdepends = workdir + "/" + srcname + ".requires"
82
83 dependsfile = open(outdepends, 'w')
84
85 dump_filerdeps('RDEPENDS', dependsfile, d)
86
87 dependsfile.close()
88 os.chmod(outdepends, 0o755)
89
90 # OE-core / RPM Provides
91 outprovides = workdir + "/" + srcname + ".provides"
92
93 providesfile = open(outprovides, 'w')
94
95 dump_filerdeps('RPROVIDES', providesfile, d)
96
97 providesfile.close()
98 os.chmod(outprovides, 0o755)
99
100 return (outdepends, outprovides)
101
102
103python write_specfile () {
104 import oe.packagedata
105
106 # append information for logs and patches to %prep
107 def add_prep(d,spec_files_bottom):
108 if d.getVarFlag('ARCHIVER_MODE', 'srpm') == '1' and bb.data.inherits_class('archiver', d):
109 spec_files_bottom.append('%%prep -n %s' % d.getVar('PN') )
110 spec_files_bottom.append('%s' % "echo \"include logs and patches, Please check them in SOURCES\"")
111 spec_files_bottom.append('')
112
113 # append the name of tarball to key word 'SOURCE' in xxx.spec.
114 def tail_source(d):
115 if d.getVarFlag('ARCHIVER_MODE', 'srpm') == '1' and bb.data.inherits_class('archiver', d):
116 ar_outdir = d.getVar('ARCHIVER_OUTDIR')
117 if not os.path.exists(ar_outdir):
118 return
119 source_list = os.listdir(ar_outdir)
120 source_number = 0
121 for source in source_list:
122 # do_deploy_archives may have already run (from sstate) meaning a .src.rpm may already
123 # exist in ARCHIVER_OUTDIR so skip if present.
124 if source.endswith(".src.rpm"):
125 continue
126 # The rpmbuild doesn't need the root permission, but it needs
127 # to know the file's user and group name, the only user and
128 # group in fakeroot is "root" when working in fakeroot.
129 f = os.path.join(ar_outdir, source)
130 os.chown(f, 0, 0)
131 spec_preamble_top.append('Source%s: %s' % (source_number, source))
132 source_number += 1
133
134 # In RPM, dependencies are of the format: pkg <>= Epoch:Version-Release
135 # This format is similar to OE, however there are restrictions on the
136 # characters that can be in a field. In the Version field, "-"
137 # characters are not allowed. "-" is allowed in the Release field.
138 #
139 # We translate the "-" in the version to a "+", by loading the PKGV
140 # from the dependent recipe, replacing the - with a +, and then using
141 # that value to do a replace inside of this recipe's dependencies.
142 # This preserves the "-" separator between the version and release, as
143 # well as any "-" characters inside of the release field.
144 #
145 # All of this has to happen BEFORE the mapping_rename_hook as
146 # after renaming we cannot look up the dependencies in the packagedata
147 # store.
148 def translate_vers(varname, d):
149 depends = d.getVar(varname)
150 if depends:
151 depends_dict = bb.utils.explode_dep_versions2(depends)
152 newdeps_dict = {}
153 for dep in depends_dict:
154 verlist = []
155 for ver in depends_dict[dep]:
156 if '-' in ver:
157 subd = oe.packagedata.read_subpkgdata_dict(dep, d)
158 if 'PKGV' in subd:
159 pv = subd['PV']
160 pkgv = subd['PKGV']
161 reppv = pkgv.replace('-', '+')
162 ver = ver.replace(pv, reppv).replace(pkgv, reppv)
163 if 'PKGR' in subd:
164 # Make sure PKGR rather than PR in ver
165 pr = '-' + subd['PR']
166 pkgr = '-' + subd['PKGR']
167 if pkgr not in ver:
168 ver = ver.replace(pr, pkgr)
169 verlist.append(ver)
170 else:
171 verlist.append(ver)
172 newdeps_dict[dep] = verlist
173 depends = bb.utils.join_deps(newdeps_dict)
174 d.setVar(varname, depends.strip())
175
176 # We need to change the style the dependency from BB to RPM
177 # This needs to happen AFTER the mapping_rename_hook
178 def print_deps(variable, tag, array, d):
179 depends = variable
180 if depends:
181 depends_dict = bb.utils.explode_dep_versions2(depends)
182 for dep in depends_dict:
183 for ver in depends_dict[dep]:
184 ver = ver.replace('(', '')
185 ver = ver.replace(')', '')
186 array.append("%s: %s %s" % (tag, dep, ver))
187 if not len(depends_dict[dep]):
188 array.append("%s: %s" % (tag, dep))
189
190 def walk_files(walkpath, target, conffiles, dirfiles):
191 # We can race against the ipk/deb backends which create CONTROL or DEBIAN directories
192 # when packaging. We just ignore these files which are created in
193 # packages-split/ and not package/
194 # We have the odd situation where the CONTROL/DEBIAN directory can be removed in the middle of
195 # of the walk, the isdir() test would then fail and the walk code would assume its a file
196 # hence we check for the names in files too.
197 for rootpath, dirs, files in os.walk(walkpath):
198 path = rootpath.replace(walkpath, "")
199 if path.endswith("DEBIAN") or path.endswith("CONTROL"):
200 continue
201 path = path.replace("%", "%%%%%%%%")
202 path = path.replace("[", "?")
203 path = path.replace("]", "?")
204
205 # Treat all symlinks to directories as normal files.
206 # os.walk() lists them as directories.
207 def move_to_files(dir):
208 if os.path.islink(os.path.join(rootpath, dir)):
209 files.append(dir)
210 return True
211 else:
212 return False
213 dirs[:] = [dir for dir in dirs if not move_to_files(dir)]
214
215 # Directory handling can happen in two ways, either DIRFILES is not set at all
216 # in which case we fall back to the older behaviour of packages owning all their
217 # directories
218 if dirfiles is None:
219 for dir in dirs:
220 if dir == "CONTROL" or dir == "DEBIAN":
221 continue
222 dir = dir.replace("%", "%%%%%%%%")
223 dir = dir.replace("[", "?")
224 dir = dir.replace("]", "?")
225 # All packages own the directories their files are in...
226 target.append('%dir "' + path + '/' + dir + '"')
227 else:
228 # packages own only empty directories or explict directory.
229 # This will prevent the overlapping of security permission.
230 if path and not files and not dirs:
231 target.append('%dir "' + path + '"')
232 elif path and path in dirfiles:
233 target.append('%dir "' + path + '"')
234
235 for file in files:
236 if file == "CONTROL" or file == "DEBIAN":
237 continue
238 file = file.replace("%", "%%%%%%%%")
239 file = file.replace("[", "?")
240 file = file.replace("]", "?")
241 if conffiles.count(path + '/' + file):
242 target.append('%config "' + path + '/' + file + '"')
243 else:
244 target.append('"' + path + '/' + file + '"')
245
246 # Prevent the prerm/postrm scripts from being run during an upgrade
247 def wrap_uninstall(scriptvar):
248 scr = scriptvar.strip()
249 if scr.startswith("#!"):
250 pos = scr.find("\n") + 1
251 else:
252 pos = 0
253 scr = scr[:pos] + 'if [ "$1" = "0" ] ; then\n' + scr[pos:] + '\nfi'
254 return scr
255
256 def get_perfile(varname, pkg, d):
257 deps = []
258 dependsflist_key = 'FILE' + varname + 'FLIST' + ":" + pkg
259 dependsflist = (d.getVar(dependsflist_key) or "")
260 for dfile in dependsflist.split():
261 key = "FILE" + varname + ":" + dfile + ":" + pkg
262 depends = d.getVar(key)
263 if depends:
264 deps.append(depends)
265 return " ".join(deps)
266
267 def append_description(spec_preamble, text):
268 """
269 Add the description to the spec file.
270 """
271 import textwrap
272 dedent_text = textwrap.dedent(text).strip()
273 # Bitbake saves "\n" as "\\n"
274 if '\\n' in dedent_text:
275 for t in dedent_text.split('\\n'):
276 spec_preamble.append(t.strip())
277 else:
278 spec_preamble.append('%s' % textwrap.fill(dedent_text, width=75))
279
280 packages = d.getVar('PACKAGES')
281 if not packages or packages == '':
282 bb.debug(1, "No packages; nothing to do")
283 return
284
285 pkgdest = d.getVar('PKGDEST')
286 if not pkgdest:
287 bb.fatal("No PKGDEST")
288
289 outspecfile = d.getVar('OUTSPECFILE')
290 if not outspecfile:
291 bb.fatal("No OUTSPECFILE")
292
293 # Construct the SPEC file...
294 srcname = d.getVar('PN')
295 localdata = bb.data.createCopy(d)
296 localdata.setVar('OVERRIDES', d.getVar("OVERRIDES", False) + ":" + srcname)
297 srcsummary = (localdata.getVar('SUMMARY') or localdata.getVar('DESCRIPTION') or ".")
298 srcversion = localdata.getVar('PKGV').replace('-', '+')
299 srcrelease = localdata.getVar('PKGR')
300 srcepoch = (localdata.getVar('PKGE') or "")
301 srclicense = localdata.getVar('LICENSE')
302 srcsection = localdata.getVar('SECTION')
303 srcmaintainer = localdata.getVar('MAINTAINER')
304 srchomepage = localdata.getVar('HOMEPAGE')
305 srcdescription = localdata.getVar('DESCRIPTION') or "."
306 srccustomtagschunk = get_package_additional_metadata("rpm", localdata)
307
308 srcdepends = d.getVar('DEPENDS')
309 srcrdepends = ""
310 srcrrecommends = ""
311 srcrsuggests = ""
312 srcrprovides = ""
313 srcrreplaces = ""
314 srcrconflicts = ""
315 srcrobsoletes = ""
316
317 srcrpreinst = []
318 srcrpostinst = []
319 srcrprerm = []
320 srcrpostrm = []
321
322 spec_preamble_top = []
323 spec_preamble_bottom = []
324
325 spec_scriptlets_top = []
326 spec_scriptlets_bottom = []
327
328 spec_files_top = []
329 spec_files_bottom = []
330
331 perfiledeps = (d.getVar("MERGEPERFILEDEPS") or "0") == "0"
332 extra_pkgdata = (d.getVar("RPM_EXTRA_PKGDATA") or "0") == "1"
333
334 for pkg in packages.split():
335 localdata = bb.data.createCopy(d)
336
337 root = "%s/%s" % (pkgdest, pkg)
338
339 localdata.setVar('ROOT', '')
340 localdata.setVar('ROOT_%s' % pkg, root)
341 pkgname = localdata.getVar('PKG:%s' % pkg)
342 if not pkgname:
343 pkgname = pkg
344 localdata.setVar('PKG', pkgname)
345
346 localdata.setVar('OVERRIDES', d.getVar("OVERRIDES", False) + ":" + pkg)
347
348 conffiles = get_conffiles(pkg, d)
349 dirfiles = localdata.getVar('DIRFILES')
350 if dirfiles is not None:
351 dirfiles = dirfiles.split()
352
353 splitname = pkgname
354
355 splitsummary = (localdata.getVar('SUMMARY') or localdata.getVar('DESCRIPTION') or ".")
356 splitversion = (localdata.getVar('PKGV') or "").replace('-', '+')
357 splitrelease = (localdata.getVar('PKGR') or "")
358 splitepoch = (localdata.getVar('PKGE') or "")
359 splitlicense = (localdata.getVar('LICENSE') or "")
360 splitsection = (localdata.getVar('SECTION') or "")
361 splitdescription = (localdata.getVar('DESCRIPTION') or ".")
362 splitcustomtagschunk = get_package_additional_metadata("rpm", localdata)
363
364 translate_vers('RDEPENDS', localdata)
365 translate_vers('RRECOMMENDS', localdata)
366 translate_vers('RSUGGESTS', localdata)
367 translate_vers('RPROVIDES', localdata)
368 translate_vers('RREPLACES', localdata)
369 translate_vers('RCONFLICTS', localdata)
370
371 # Map the dependencies into their final form
372 mapping_rename_hook(localdata)
373
374 splitrdepends = localdata.getVar('RDEPENDS') or ""
375 splitrrecommends = localdata.getVar('RRECOMMENDS') or ""
376 splitrsuggests = localdata.getVar('RSUGGESTS') or ""
377 splitrprovides = localdata.getVar('RPROVIDES') or ""
378 splitrreplaces = localdata.getVar('RREPLACES') or ""
379 splitrconflicts = localdata.getVar('RCONFLICTS') or ""
380 splitrobsoletes = ""
381
382 splitrpreinst = localdata.getVar('pkg_preinst')
383 splitrpostinst = localdata.getVar('pkg_postinst')
384 splitrprerm = localdata.getVar('pkg_prerm')
385 splitrpostrm = localdata.getVar('pkg_postrm')
386
387
388 if not perfiledeps:
389 # Add in summary of per file dependencies
390 splitrdepends = splitrdepends + " " + get_perfile('RDEPENDS', pkg, d)
391 splitrprovides = splitrprovides + " " + get_perfile('RPROVIDES', pkg, d)
392
393 splitrdepends = filter_nativesdk_deps(srcname, splitrdepends)
394
395 # Gather special src/first package data
396 if srcname == splitname:
397 archiving = d.getVarFlag('ARCHIVER_MODE', 'srpm') == '1' and \
398 bb.data.inherits_class('archiver', d)
399 if archiving and srclicense != splitlicense:
400 bb.warn("The SRPM produced may not have the correct overall source license in the License tag. This is due to the LICENSE for the primary package and SRPM conflicting.")
401
402 srclicense = splitlicense
403 srcrdepends = splitrdepends
404 srcrrecommends = splitrrecommends
405 srcrsuggests = splitrsuggests
406 srcrprovides = splitrprovides
407 srcrreplaces = splitrreplaces
408 srcrconflicts = splitrconflicts
409
410 srcrpreinst = splitrpreinst
411 srcrpostinst = splitrpostinst
412 srcrprerm = splitrprerm
413 srcrpostrm = splitrpostrm
414
415 file_list = []
416 walk_files(root, file_list, conffiles, dirfiles)
417 if not file_list and localdata.getVar('ALLOW_EMPTY', False) != "1":
418 bb.note("Not creating empty RPM package for %s" % splitname)
419 else:
420 spec_files_top.append('%files')
421 if extra_pkgdata:
422 package_rpm_extra_pkgdata(splitname, spec_files_top, localdata)
423 spec_files_top.append('%defattr(-,-,-,-)')
424 if file_list:
425 bb.note("Creating RPM package for %s" % splitname)
426 spec_files_top.extend(file_list)
427 else:
428 bb.note("Creating empty RPM package for %s" % splitname)
429 spec_files_top.append('')
430 continue
431
432 # Process subpackage data
433 spec_preamble_bottom.append('%%package -n %s' % splitname)
434 spec_preamble_bottom.append('Summary: %s' % splitsummary)
435 if srcversion != splitversion:
436 spec_preamble_bottom.append('Version: %s' % splitversion)
437 if srcrelease != splitrelease:
438 spec_preamble_bottom.append('Release: %s' % splitrelease)
439 if srcepoch != splitepoch:
440 spec_preamble_bottom.append('Epoch: %s' % splitepoch)
441 spec_preamble_bottom.append('License: %s' % splitlicense)
442 spec_preamble_bottom.append('Group: %s' % splitsection)
443
444 if srccustomtagschunk != splitcustomtagschunk:
445 spec_preamble_bottom.append(splitcustomtagschunk)
446
447 # Replaces == Obsoletes && Provides
448 robsoletes = bb.utils.explode_dep_versions2(splitrobsoletes)
449 rprovides = bb.utils.explode_dep_versions2(splitrprovides)
450 rreplaces = bb.utils.explode_dep_versions2(splitrreplaces)
451 for dep in rreplaces:
452 if not dep in robsoletes:
453 robsoletes[dep] = rreplaces[dep]
454 if not dep in rprovides:
455 rprovides[dep] = rreplaces[dep]
456 splitrobsoletes = bb.utils.join_deps(robsoletes, commasep=False)
457 splitrprovides = bb.utils.join_deps(rprovides, commasep=False)
458
459 print_deps(splitrdepends, "Requires", spec_preamble_bottom, d)
460 if splitrpreinst:
461 print_deps(splitrdepends, "Requires(pre)", spec_preamble_bottom, d)
462 if splitrpostinst:
463 print_deps(splitrdepends, "Requires(post)", spec_preamble_bottom, d)
464 if splitrprerm:
465 print_deps(splitrdepends, "Requires(preun)", spec_preamble_bottom, d)
466 if splitrpostrm:
467 print_deps(splitrdepends, "Requires(postun)", spec_preamble_bottom, d)
468
469 print_deps(splitrrecommends, "Recommends", spec_preamble_bottom, d)
470 print_deps(splitrsuggests, "Suggests", spec_preamble_bottom, d)
471 print_deps(splitrprovides, "Provides", spec_preamble_bottom, d)
472 print_deps(splitrobsoletes, "Obsoletes", spec_preamble_bottom, d)
473 print_deps(splitrconflicts, "Conflicts", spec_preamble_bottom, d)
474
475 spec_preamble_bottom.append('')
476
477 spec_preamble_bottom.append('%%description -n %s' % splitname)
478 append_description(spec_preamble_bottom, splitdescription)
479
480 spec_preamble_bottom.append('')
481
482 # Now process scriptlets
483 if splitrpreinst:
484 spec_scriptlets_bottom.append('%%pre -n %s' % splitname)
485 spec_scriptlets_bottom.append('# %s - preinst' % splitname)
486 spec_scriptlets_bottom.append(splitrpreinst)
487 spec_scriptlets_bottom.append('')
488 if splitrpostinst:
489 spec_scriptlets_bottom.append('%%post -n %s' % splitname)
490 spec_scriptlets_bottom.append('# %s - postinst' % splitname)
491 spec_scriptlets_bottom.append(splitrpostinst)
492 spec_scriptlets_bottom.append('')
493 if splitrprerm:
494 spec_scriptlets_bottom.append('%%preun -n %s' % splitname)
495 spec_scriptlets_bottom.append('# %s - prerm' % splitname)
496 scriptvar = wrap_uninstall(splitrprerm)
497 spec_scriptlets_bottom.append(scriptvar)
498 spec_scriptlets_bottom.append('')
499 if splitrpostrm:
500 spec_scriptlets_bottom.append('%%postun -n %s' % splitname)
501 spec_scriptlets_bottom.append('# %s - postrm' % splitname)
502 scriptvar = wrap_uninstall(splitrpostrm)
503 spec_scriptlets_bottom.append(scriptvar)
504 spec_scriptlets_bottom.append('')
505
506 # Now process files
507 file_list = []
508 walk_files(root, file_list, conffiles, dirfiles)
509 if not file_list and localdata.getVar('ALLOW_EMPTY', False) != "1":
510 bb.note("Not creating empty RPM package for %s" % splitname)
511 else:
512 spec_files_bottom.append('%%files -n %s' % splitname)
513 if extra_pkgdata:
514 package_rpm_extra_pkgdata(splitname, spec_files_bottom, localdata)
515 spec_files_bottom.append('%defattr(-,-,-,-)')
516 if file_list:
517 bb.note("Creating RPM package for %s" % splitname)
518 spec_files_bottom.extend(file_list)
519 else:
520 bb.note("Creating empty RPM package for %s" % splitname)
521 spec_files_bottom.append('')
522
523 del localdata
524
525 add_prep(d,spec_files_bottom)
526 spec_preamble_top.append('Summary: %s' % srcsummary)
527 spec_preamble_top.append('Name: %s' % srcname)
528 spec_preamble_top.append('Version: %s' % srcversion)
529 spec_preamble_top.append('Release: %s' % srcrelease)
530 if srcepoch and srcepoch.strip() != "":
531 spec_preamble_top.append('Epoch: %s' % srcepoch)
532 spec_preamble_top.append('License: %s' % srclicense)
533 spec_preamble_top.append('Group: %s' % srcsection)
534 spec_preamble_top.append('Packager: %s' % srcmaintainer)
535 if srchomepage:
536 spec_preamble_top.append('URL: %s' % srchomepage)
537 if srccustomtagschunk:
538 spec_preamble_top.append(srccustomtagschunk)
539 tail_source(d)
540
541 # Replaces == Obsoletes && Provides
542 robsoletes = bb.utils.explode_dep_versions2(srcrobsoletes)
543 rprovides = bb.utils.explode_dep_versions2(srcrprovides)
544 rreplaces = bb.utils.explode_dep_versions2(srcrreplaces)
545 for dep in rreplaces:
546 if not dep in robsoletes:
547 robsoletes[dep] = rreplaces[dep]
548 if not dep in rprovides:
549 rprovides[dep] = rreplaces[dep]
550 srcrobsoletes = bb.utils.join_deps(robsoletes, commasep=False)
551 srcrprovides = bb.utils.join_deps(rprovides, commasep=False)
552
553 print_deps(srcdepends, "BuildRequires", spec_preamble_top, d)
554 print_deps(srcrdepends, "Requires", spec_preamble_top, d)
555 if srcrpreinst:
556 print_deps(srcrdepends, "Requires(pre)", spec_preamble_top, d)
557 if srcrpostinst:
558 print_deps(srcrdepends, "Requires(post)", spec_preamble_top, d)
559 if srcrprerm:
560 print_deps(srcrdepends, "Requires(preun)", spec_preamble_top, d)
561 if srcrpostrm:
562 print_deps(srcrdepends, "Requires(postun)", spec_preamble_top, d)
563
564 print_deps(srcrrecommends, "Recommends", spec_preamble_top, d)
565 print_deps(srcrsuggests, "Suggests", spec_preamble_top, d)
566 print_deps(srcrprovides, "Provides", spec_preamble_top, d)
567 print_deps(srcrobsoletes, "Obsoletes", spec_preamble_top, d)
568 print_deps(srcrconflicts, "Conflicts", spec_preamble_top, d)
569
570 spec_preamble_top.append('')
571
572 spec_preamble_top.append('%description')
573 append_description(spec_preamble_top, srcdescription)
574
575 spec_preamble_top.append('')
576
577 if srcrpreinst:
578 spec_scriptlets_top.append('%pre')
579 spec_scriptlets_top.append('# %s - preinst' % srcname)
580 spec_scriptlets_top.append(srcrpreinst)
581 spec_scriptlets_top.append('')
582 if srcrpostinst:
583 spec_scriptlets_top.append('%post')
584 spec_scriptlets_top.append('# %s - postinst' % srcname)
585 spec_scriptlets_top.append(srcrpostinst)
586 spec_scriptlets_top.append('')
587 if srcrprerm:
588 spec_scriptlets_top.append('%preun')
589 spec_scriptlets_top.append('# %s - prerm' % srcname)
590 scriptvar = wrap_uninstall(srcrprerm)
591 spec_scriptlets_top.append(scriptvar)
592 spec_scriptlets_top.append('')
593 if srcrpostrm:
594 spec_scriptlets_top.append('%postun')
595 spec_scriptlets_top.append('# %s - postrm' % srcname)
596 scriptvar = wrap_uninstall(srcrpostrm)
597 spec_scriptlets_top.append(scriptvar)
598 spec_scriptlets_top.append('')
599
600 # Write the SPEC file
601 specfile = open(outspecfile, 'w')
602
603 # RPMSPEC_PREAMBLE is a way to add arbitrary text to the top
604 # of the generated spec file
605 external_preamble = d.getVar("RPMSPEC_PREAMBLE")
606 if external_preamble:
607 specfile.write(external_preamble + "\n")
608
609 for line in spec_preamble_top:
610 specfile.write(line + "\n")
611
612 for line in spec_preamble_bottom:
613 specfile.write(line + "\n")
614
615 for line in spec_scriptlets_top:
616 specfile.write(line + "\n")
617
618 for line in spec_scriptlets_bottom:
619 specfile.write(line + "\n")
620
621 for line in spec_files_top:
622 specfile.write(line + "\n")
623
624 for line in spec_files_bottom:
625 specfile.write(line + "\n")
626
627 specfile.close()
628}
629# Otherwise allarch packages may change depending on override configuration
630write_specfile[vardepsexclude] = "OVERRIDES"
631
632# Have to list any variables referenced as X_<pkg> that aren't in pkgdata here
633RPMEXTRAVARS = "PACKAGE_ADD_METADATA_RPM"
634write_specfile[vardeps] += "${@gen_packagevar(d, 'RPMEXTRAVARS')}"
635
636python do_package_rpm () {
637 workdir = d.getVar('WORKDIR')
638 tmpdir = d.getVar('TMPDIR')
639 pkgd = d.getVar('PKGD')
640 pkgdest = d.getVar('PKGDEST')
641 if not workdir or not pkgd or not tmpdir:
642 bb.error("Variables incorrectly set, unable to package")
643 return
644
645 packages = d.getVar('PACKAGES')
646 if not packages or packages == '':
647 bb.debug(1, "No packages; nothing to do")
648 return
649
650 # Construct the spec file...
651 # If the spec file already exist, and has not been stored into
652 # pseudo's files.db, it maybe cause rpmbuild src.rpm fail,
653 # so remove it before doing rpmbuild src.rpm.
654 srcname = d.getVar('PN')
655 outspecfile = workdir + "/" + srcname + ".spec"
656 if os.path.isfile(outspecfile):
657 os.remove(outspecfile)
658 d.setVar('OUTSPECFILE', outspecfile)
659 bb.build.exec_func('write_specfile', d)
660
661 perfiledeps = (d.getVar("MERGEPERFILEDEPS") or "0") == "0"
662 if perfiledeps:
663 outdepends, outprovides = write_rpm_perfiledata(srcname, d)
664
665 # Setup the rpmbuild arguments...
666 rpmbuild = d.getVar('RPMBUILD')
667 targetsys = d.getVar('TARGET_SYS')
668 targetvendor = d.getVar('HOST_VENDOR')
669
670 # Too many places in dnf stack assume that arch-independent packages are "noarch".
671 # Let's not fight against this.
672 package_arch = (d.getVar('PACKAGE_ARCH') or "").replace("-", "_")
673 if package_arch == "all":
674 package_arch = "noarch"
675
676 sdkpkgsuffix = (d.getVar('SDKPKGSUFFIX') or "nativesdk").replace("-", "_")
677 d.setVar('PACKAGE_ARCH_EXTEND', package_arch)
678 pkgwritedir = d.expand('${PKGWRITEDIRRPM}/${PACKAGE_ARCH_EXTEND}')
679 d.setVar('RPM_PKGWRITEDIR', pkgwritedir)
680 bb.debug(1, 'PKGWRITEDIR: %s' % d.getVar('RPM_PKGWRITEDIR'))
681 pkgarch = d.expand('${PACKAGE_ARCH_EXTEND}${HOST_VENDOR}-linux')
682 bb.utils.mkdirhier(pkgwritedir)
683 os.chmod(pkgwritedir, 0o755)
684
685 cmd = rpmbuild
686 cmd = cmd + " --noclean --nodeps --short-circuit --target " + pkgarch + " --buildroot " + pkgd
687 cmd = cmd + " --define '_topdir " + workdir + "' --define '_rpmdir " + pkgwritedir + "'"
688 cmd = cmd + " --define '_builddir " + d.getVar('B') + "'"
689 cmd = cmd + " --define '_build_name_fmt %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm'"
690 cmd = cmd + " --define '_use_internal_dependency_generator 0'"
691 cmd = cmd + " --define '_binaries_in_noarch_packages_terminate_build 0'"
692 cmd = cmd + " --define '_build_id_links none'"
693 cmd = cmd + " --define '_binary_payload w19T%d.zstdio'" % int(d.getVar("ZSTD_THREADS"))
694 cmd = cmd + " --define '_source_payload w19T%d.zstdio'" % int(d.getVar("ZSTD_THREADS"))
695 cmd = cmd + " --define 'clamp_mtime_to_source_date_epoch 1'"
696 cmd = cmd + " --define 'use_source_date_epoch_as_buildtime 1'"
697 cmd = cmd + " --define '_buildhost reproducible'"
698 cmd = cmd + " --define '__font_provides %{nil}'"
699 if perfiledeps:
700 cmd = cmd + " --define '__find_requires " + outdepends + "'"
701 cmd = cmd + " --define '__find_provides " + outprovides + "'"
702 else:
703 cmd = cmd + " --define '__find_requires %{nil}'"
704 cmd = cmd + " --define '__find_provides %{nil}'"
705 cmd = cmd + " --define '_unpackaged_files_terminate_build 0'"
706 cmd = cmd + " --define 'debug_package %{nil}'"
707 cmd = cmd + " --define '_tmppath " + workdir + "'"
708 if d.getVarFlag('ARCHIVER_MODE', 'srpm') == '1' and bb.data.inherits_class('archiver', d):
709 cmd = cmd + " --define '_sourcedir " + d.getVar('ARCHIVER_OUTDIR') + "'"
710 cmdsrpm = cmd + " --define '_srcrpmdir " + d.getVar('ARCHIVER_RPMOUTDIR') + "'"
711 cmdsrpm = cmdsrpm + " -bs " + outspecfile
712 # Build the .src.rpm
713 d.setVar('SBUILDSPEC', cmdsrpm + "\n")
714 d.setVarFlag('SBUILDSPEC', 'func', '1')
715 bb.build.exec_func('SBUILDSPEC', d)
716 cmd = cmd + " -bb " + outspecfile
717
718 # rpm 4 creates various empty directories in _topdir, let's clean them up
719 cleanupcmd = "rm -rf %s/BUILDROOT %s/SOURCES %s/SPECS %s/SRPMS" % (workdir, workdir, workdir, workdir)
720
721 # Build the rpm package!
722 d.setVar('BUILDSPEC', cmd + "\n" + cleanupcmd + "\n")
723 d.setVarFlag('BUILDSPEC', 'func', '1')
724 bb.build.exec_func('BUILDSPEC', d)
725
726 if d.getVar('RPM_SIGN_PACKAGES') == '1':
727 bb.build.exec_func("sign_rpm", d)
728}
729
730python () {
731 if d.getVar('PACKAGES') != '':
732 deps = ' rpm-native:do_populate_sysroot virtual/fakeroot-native:do_populate_sysroot'
733 d.appendVarFlag('do_package_write_rpm', 'depends', deps)
734 d.setVarFlag('do_package_write_rpm', 'fakeroot', '1')
735}
736
737SSTATETASKS += "do_package_write_rpm"
738do_package_write_rpm[sstate-inputdirs] = "${PKGWRITEDIRRPM}"
739do_package_write_rpm[sstate-outputdirs] = "${DEPLOY_DIR_RPM}"
740# Take a shared lock, we can write multiple packages at the same time...
741# but we need to stop the rootfs/solver from running while we do...
742do_package_write_rpm[sstate-lockfile-shared] += "${DEPLOY_DIR_RPM}/rpm.lock"
743
744python do_package_write_rpm_setscene () {
745 sstate_setscene(d)
746}
747addtask do_package_write_rpm_setscene
748
749python do_package_write_rpm () {
750 bb.build.exec_func("read_subpackage_metadata", d)
751 bb.build.exec_func("do_package_rpm", d)
752}
753
754do_package_write_rpm[dirs] = "${PKGWRITEDIRRPM}"
755do_package_write_rpm[cleandirs] = "${PKGWRITEDIRRPM}"
756do_package_write_rpm[depends] += "${@oe.utils.build_depends_string(d.getVar('PACKAGE_WRITE_DEPS'), 'do_populate_sysroot')}"
757addtask package_write_rpm after do_packagedata do_package do_deploy_source_date_epoch before do_build
758do_build[rdeptask] += "do_package_write_rpm"
759
760PACKAGEINDEXDEPS += "rpm-native:do_populate_sysroot"
761PACKAGEINDEXDEPS += "createrepo-c-native:do_populate_sysroot"