blob: aebeaf6932c2b4900a890e12c01e52a7a1262783 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001inherit package
2
3IMAGE_PKGTYPE ?= "rpm"
4
5RPM="rpm"
6RPMBUILD="rpmbuild"
7
8PKGWRITEDIRRPM = "${WORKDIR}/deploy-rpms"
9
Brad Bishop6e60e8b2018-02-01 10:27:11 -050010# Maintaining the perfile dependencies has singificant overhead when writing the
Patrick Williamsc124f4f2015-09-15 14:41:29 -050011# packages. When set, this value merges them for efficiency.
12MERGEPERFILEDEPS = "1"
13
Brad Bishop6e60e8b2018-02-01 10:27:11 -050014# Filter dependencies based on a provided function.
15def filter_deps(var, f):
16 import collections
17
18 depends_dict = bb.utils.explode_dep_versions2(var)
19 newdeps_dict = collections.OrderedDict()
20 for dep in depends_dict:
21 if f(dep):
22 newdeps_dict[dep] = depends_dict[dep]
23 return bb.utils.join_deps(newdeps_dict, commasep=False)
24
25# Filter out absolute paths (typically /bin/sh and /usr/bin/env) and any perl
26# dependencies for nativesdk packages.
27def filter_nativesdk_deps(srcname, var):
28 if var and srcname.startswith("nativesdk-"):
29 var = filter_deps(var, lambda dep: not dep.startswith('/') and dep != 'perl' and not dep.startswith('perl('))
30 return var
31
Patrick Williamsc124f4f2015-09-15 14:41:29 -050032# Construct per file dependencies file
33def write_rpm_perfiledata(srcname, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -050034 workdir = d.getVar('WORKDIR')
35 packages = d.getVar('PACKAGES')
36 pkgd = d.getVar('PKGD')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050037
38 def dump_filerdeps(varname, outfile, d):
Brad Bishop96ff1982019-08-19 13:50:42 -040039 outfile.write("#!/usr/bin/env python3\n\n")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050040 outfile.write("# Dependency table\n")
41 outfile.write('deps = {\n')
42 for pkg in packages.split():
43 dependsflist_key = 'FILE' + varname + 'FLIST' + "_" + pkg
Brad Bishop6e60e8b2018-02-01 10:27:11 -050044 dependsflist = (d.getVar(dependsflist_key) or "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050045 for dfile in dependsflist.split():
46 key = "FILE" + varname + "_" + dfile + "_" + pkg
Brad Bishop6e60e8b2018-02-01 10:27:11 -050047 deps = filter_nativesdk_deps(srcname, d.getVar(key) or "")
48 depends_dict = bb.utils.explode_dep_versions(deps)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050049 file = dfile.replace("@underscore@", "_")
50 file = file.replace("@closebrace@", "]")
51 file = file.replace("@openbrace@", "[")
52 file = file.replace("@tab@", "\t")
53 file = file.replace("@space@", " ")
54 file = file.replace("@at@", "@")
55 outfile.write('"' + pkgd + file + '" : "')
56 for dep in depends_dict:
57 ver = depends_dict[dep]
58 if dep and ver:
59 ver = ver.replace("(","")
60 ver = ver.replace(")","")
61 outfile.write(dep + " " + ver + " ")
62 else:
63 outfile.write(dep + " ")
64 outfile.write('",\n')
65 outfile.write('}\n\n')
66 outfile.write("import sys\n")
67 outfile.write("while 1:\n")
68 outfile.write("\tline = sys.stdin.readline().strip()\n")
69 outfile.write("\tif not line:\n")
70 outfile.write("\t\tsys.exit(0)\n")
71 outfile.write("\tif line in deps:\n")
72 outfile.write("\t\tprint(deps[line] + '\\n')\n")
73
74 # OE-core dependencies a.k.a. RPM requires
75 outdepends = workdir + "/" + srcname + ".requires"
76
Brad Bishop6e60e8b2018-02-01 10:27:11 -050077 dependsfile = open(outdepends, 'w')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050078
79 dump_filerdeps('RDEPENDS', dependsfile, d)
80
81 dependsfile.close()
Patrick Williamsc0f7c042017-02-23 20:41:17 -060082 os.chmod(outdepends, 0o755)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050083
84 # OE-core / RPM Provides
85 outprovides = workdir + "/" + srcname + ".provides"
86
Brad Bishop6e60e8b2018-02-01 10:27:11 -050087 providesfile = open(outprovides, 'w')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050088
89 dump_filerdeps('RPROVIDES', providesfile, d)
90
91 providesfile.close()
Patrick Williamsc0f7c042017-02-23 20:41:17 -060092 os.chmod(outprovides, 0o755)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050093
94 return (outdepends, outprovides)
95
96
97python write_specfile () {
98 import oe.packagedata
99
100 # append information for logs and patches to %prep
101 def add_prep(d,spec_files_bottom):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500102 if d.getVarFlag('ARCHIVER_MODE', 'srpm') == '1' and bb.data.inherits_class('archiver', d):
103 spec_files_bottom.append('%%prep -n %s' % d.getVar('PN') )
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500104 spec_files_bottom.append('%s' % "echo \"include logs and patches, Please check them in SOURCES\"")
105 spec_files_bottom.append('')
106
107 # append the name of tarball to key word 'SOURCE' in xxx.spec.
108 def tail_source(d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500109 if d.getVarFlag('ARCHIVER_MODE', 'srpm') == '1' and bb.data.inherits_class('archiver', d):
110 ar_outdir = d.getVar('ARCHIVER_OUTDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500111 if not os.path.exists(ar_outdir):
112 return
113 source_list = os.listdir(ar_outdir)
114 source_number = 0
115 for source in source_list:
Brad Bishop19323692019-04-05 15:28:33 -0400116 # do_deploy_archives may have already run (from sstate) meaning a .src.rpm may already
117 # exist in ARCHIVER_OUTDIR so skip if present.
118 if source.endswith(".src.rpm"):
119 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500120 # The rpmbuild doesn't need the root permission, but it needs
121 # to know the file's user and group name, the only user and
122 # group in fakeroot is "root" when working in fakeroot.
123 f = os.path.join(ar_outdir, source)
124 os.chown(f, 0, 0)
125 spec_preamble_top.append('Source%s: %s' % (source_number, source))
126 source_number += 1
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500127
128 # In RPM, dependencies are of the format: pkg <>= Epoch:Version-Release
129 # This format is similar to OE, however there are restrictions on the
130 # characters that can be in a field. In the Version field, "-"
131 # characters are not allowed. "-" is allowed in the Release field.
132 #
133 # We translate the "-" in the version to a "+", by loading the PKGV
134 # from the dependent recipe, replacing the - with a +, and then using
135 # that value to do a replace inside of this recipe's dependencies.
136 # This preserves the "-" separator between the version and release, as
137 # well as any "-" characters inside of the release field.
138 #
139 # All of this has to happen BEFORE the mapping_rename_hook as
140 # after renaming we cannot look up the dependencies in the packagedata
141 # store.
142 def translate_vers(varname, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500143 depends = d.getVar(varname)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500144 if depends:
145 depends_dict = bb.utils.explode_dep_versions2(depends)
146 newdeps_dict = {}
147 for dep in depends_dict:
148 verlist = []
149 for ver in depends_dict[dep]:
150 if '-' in ver:
151 subd = oe.packagedata.read_subpkgdata_dict(dep, d)
152 if 'PKGV' in subd:
153 pv = subd['PV']
154 pkgv = subd['PKGV']
155 reppv = pkgv.replace('-', '+')
156 ver = ver.replace(pv, reppv).replace(pkgv, reppv)
157 if 'PKGR' in subd:
158 # Make sure PKGR rather than PR in ver
159 pr = '-' + subd['PR']
160 pkgr = '-' + subd['PKGR']
161 if pkgr not in ver:
162 ver = ver.replace(pr, pkgr)
163 verlist.append(ver)
164 else:
165 verlist.append(ver)
166 newdeps_dict[dep] = verlist
167 depends = bb.utils.join_deps(newdeps_dict)
168 d.setVar(varname, depends.strip())
169
170 # We need to change the style the dependency from BB to RPM
171 # This needs to happen AFTER the mapping_rename_hook
172 def print_deps(variable, tag, array, d):
173 depends = variable
174 if depends:
175 depends_dict = bb.utils.explode_dep_versions2(depends)
176 for dep in depends_dict:
177 for ver in depends_dict[dep]:
178 ver = ver.replace('(', '')
179 ver = ver.replace(')', '')
180 array.append("%s: %s %s" % (tag, dep, ver))
181 if not len(depends_dict[dep]):
182 array.append("%s: %s" % (tag, dep))
183
184 def walk_files(walkpath, target, conffiles, dirfiles):
185 # We can race against the ipk/deb backends which create CONTROL or DEBIAN directories
186 # when packaging. We just ignore these files which are created in
187 # packages-split/ and not package/
188 # We have the odd situation where the CONTROL/DEBIAN directory can be removed in the middle of
189 # of the walk, the isdir() test would then fail and the walk code would assume its a file
190 # hence we check for the names in files too.
191 for rootpath, dirs, files in os.walk(walkpath):
192 path = rootpath.replace(walkpath, "")
193 if path.endswith("DEBIAN") or path.endswith("CONTROL"):
194 continue
195 path = path.replace("%", "%%%%%%%%")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500196 path = path.replace("[", "?")
197 path = path.replace("]", "?")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500198
199 # Treat all symlinks to directories as normal files.
200 # os.walk() lists them as directories.
201 def move_to_files(dir):
202 if os.path.islink(os.path.join(rootpath, dir)):
203 files.append(dir)
204 return True
205 else:
206 return False
207 dirs[:] = [dir for dir in dirs if not move_to_files(dir)]
208
209 # Directory handling can happen in two ways, either DIRFILES is not set at all
210 # in which case we fall back to the older behaviour of packages owning all their
211 # directories
212 if dirfiles is None:
213 for dir in dirs:
214 if dir == "CONTROL" or dir == "DEBIAN":
215 continue
216 dir = dir.replace("%", "%%%%%%%%")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500217 dir = dir.replace("[", "?")
218 dir = dir.replace("]", "?")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500219 # All packages own the directories their files are in...
220 target.append('%dir "' + path + '/' + dir + '"')
221 else:
222 # packages own only empty directories or explict directory.
223 # This will prevent the overlapping of security permission.
224 if path and not files and not dirs:
225 target.append('%dir "' + path + '"')
226 elif path and path in dirfiles:
227 target.append('%dir "' + path + '"')
228
229 for file in files:
230 if file == "CONTROL" or file == "DEBIAN":
231 continue
232 file = file.replace("%", "%%%%%%%%")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500233 file = file.replace("[", "?")
234 file = file.replace("]", "?")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500235 if conffiles.count(path + '/' + file):
236 target.append('%config "' + path + '/' + file + '"')
237 else:
238 target.append('"' + path + '/' + file + '"')
239
240 # Prevent the prerm/postrm scripts from being run during an upgrade
241 def wrap_uninstall(scriptvar):
242 scr = scriptvar.strip()
243 if scr.startswith("#!"):
244 pos = scr.find("\n") + 1
245 else:
246 pos = 0
247 scr = scr[:pos] + 'if [ "$1" = "0" ] ; then\n' + scr[pos:] + '\nfi'
248 return scr
249
250 def get_perfile(varname, pkg, d):
251 deps = []
252 dependsflist_key = 'FILE' + varname + 'FLIST' + "_" + pkg
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500253 dependsflist = (d.getVar(dependsflist_key) or "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500254 for dfile in dependsflist.split():
255 key = "FILE" + varname + "_" + dfile + "_" + pkg
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500256 depends = d.getVar(key)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500257 if depends:
258 deps.append(depends)
259 return " ".join(deps)
260
261 def append_description(spec_preamble, text):
262 """
263 Add the description to the spec file.
264 """
265 import textwrap
266 dedent_text = textwrap.dedent(text).strip()
267 # Bitbake saves "\n" as "\\n"
268 if '\\n' in dedent_text:
269 for t in dedent_text.split('\\n'):
270 spec_preamble.append(t.strip())
271 else:
272 spec_preamble.append('%s' % textwrap.fill(dedent_text, width=75))
273
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500274 packages = d.getVar('PACKAGES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500275 if not packages or packages == '':
276 bb.debug(1, "No packages; nothing to do")
277 return
278
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500279 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500280 if not pkgdest:
281 bb.fatal("No PKGDEST")
282
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500283 outspecfile = d.getVar('OUTSPECFILE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500284 if not outspecfile:
285 bb.fatal("No OUTSPECFILE")
286
287 # Construct the SPEC file...
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500288 srcname = d.getVar('PN')
Andrew Geissler1e34c2d2020-05-29 16:02:59 -0500289 localdata = bb.data.createCopy(d)
290 localdata.setVar('OVERRIDES', d.getVar("OVERRIDES", False) + ":" + srcname)
291 srcsummary = (localdata.getVar('SUMMARY') or localdata.getVar('DESCRIPTION') or ".")
292 srcversion = localdata.getVar('PKGV').replace('-', '+')
293 srcrelease = localdata.getVar('PKGR')
294 srcepoch = (localdata.getVar('PKGE') or "")
295 srclicense = localdata.getVar('LICENSE')
296 srcsection = localdata.getVar('SECTION')
297 srcmaintainer = localdata.getVar('MAINTAINER')
298 srchomepage = localdata.getVar('HOMEPAGE')
299 srcdescription = localdata.getVar('DESCRIPTION') or "."
300 srccustomtagschunk = get_package_additional_metadata("rpm", localdata)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500301
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500302 srcdepends = d.getVar('DEPENDS')
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600303 srcrdepends = ""
304 srcrrecommends = ""
305 srcrsuggests = ""
306 srcrprovides = ""
307 srcrreplaces = ""
308 srcrconflicts = ""
309 srcrobsoletes = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500310
311 srcrpreinst = []
312 srcrpostinst = []
313 srcrprerm = []
314 srcrpostrm = []
315
316 spec_preamble_top = []
317 spec_preamble_bottom = []
318
319 spec_scriptlets_top = []
320 spec_scriptlets_bottom = []
321
322 spec_files_top = []
323 spec_files_bottom = []
324
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500325 perfiledeps = (d.getVar("MERGEPERFILEDEPS") or "0") == "0"
326 extra_pkgdata = (d.getVar("RPM_EXTRA_PKGDATA") or "0") == "1"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500327
328 for pkg in packages.split():
329 localdata = bb.data.createCopy(d)
330
331 root = "%s/%s" % (pkgdest, pkg)
332
333 localdata.setVar('ROOT', '')
334 localdata.setVar('ROOT_%s' % pkg, root)
Patrick Williams213cb262021-08-07 19:21:33 -0500335 pkgname = localdata.getVar('PKG:%s' % pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500336 if not pkgname:
337 pkgname = pkg
338 localdata.setVar('PKG', pkgname)
339
340 localdata.setVar('OVERRIDES', d.getVar("OVERRIDES", False) + ":" + pkg)
341
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500342 conffiles = get_conffiles(pkg, d)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500343 dirfiles = localdata.getVar('DIRFILES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500344 if dirfiles is not None:
345 dirfiles = dirfiles.split()
346
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500347 splitname = pkgname
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500348
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500349 splitsummary = (localdata.getVar('SUMMARY') or localdata.getVar('DESCRIPTION') or ".")
350 splitversion = (localdata.getVar('PKGV') or "").replace('-', '+')
351 splitrelease = (localdata.getVar('PKGR') or "")
352 splitepoch = (localdata.getVar('PKGE') or "")
353 splitlicense = (localdata.getVar('LICENSE') or "")
354 splitsection = (localdata.getVar('SECTION') or "")
355 splitdescription = (localdata.getVar('DESCRIPTION') or ".")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500356 splitcustomtagschunk = get_package_additional_metadata("rpm", localdata)
357
358 translate_vers('RDEPENDS', localdata)
359 translate_vers('RRECOMMENDS', localdata)
360 translate_vers('RSUGGESTS', localdata)
361 translate_vers('RPROVIDES', localdata)
362 translate_vers('RREPLACES', localdata)
363 translate_vers('RCONFLICTS', localdata)
364
365 # Map the dependencies into their final form
366 mapping_rename_hook(localdata)
367
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600368 splitrdepends = localdata.getVar('RDEPENDS') or ""
369 splitrrecommends = localdata.getVar('RRECOMMENDS') or ""
370 splitrsuggests = localdata.getVar('RSUGGESTS') or ""
371 splitrprovides = localdata.getVar('RPROVIDES') or ""
372 splitrreplaces = localdata.getVar('RREPLACES') or ""
373 splitrconflicts = localdata.getVar('RCONFLICTS') or ""
374 splitrobsoletes = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500375
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500376 splitrpreinst = localdata.getVar('pkg_preinst')
377 splitrpostinst = localdata.getVar('pkg_postinst')
378 splitrprerm = localdata.getVar('pkg_prerm')
379 splitrpostrm = localdata.getVar('pkg_postrm')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500380
381
382 if not perfiledeps:
383 # Add in summary of per file dependencies
384 splitrdepends = splitrdepends + " " + get_perfile('RDEPENDS', pkg, d)
385 splitrprovides = splitrprovides + " " + get_perfile('RPROVIDES', pkg, d)
386
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500387 splitrdepends = filter_nativesdk_deps(srcname, splitrdepends)
388
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500389 # Gather special src/first package data
390 if srcname == splitname:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400391 archiving = d.getVarFlag('ARCHIVER_MODE', 'srpm') == '1' and \
392 bb.data.inherits_class('archiver', d)
393 if archiving and srclicense != splitlicense:
394 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.")
395
396 srclicense = splitlicense
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500397 srcrdepends = splitrdepends
398 srcrrecommends = splitrrecommends
399 srcrsuggests = splitrsuggests
400 srcrprovides = splitrprovides
401 srcrreplaces = splitrreplaces
402 srcrconflicts = splitrconflicts
403
404 srcrpreinst = splitrpreinst
405 srcrpostinst = splitrpostinst
406 srcrprerm = splitrprerm
407 srcrpostrm = splitrpostrm
408
409 file_list = []
410 walk_files(root, file_list, conffiles, dirfiles)
411 if not file_list and localdata.getVar('ALLOW_EMPTY', False) != "1":
412 bb.note("Not creating empty RPM package for %s" % splitname)
413 else:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500414 spec_files_top.append('%files')
415 if extra_pkgdata:
416 package_rpm_extra_pkgdata(splitname, spec_files_top, localdata)
417 spec_files_top.append('%defattr(-,-,-,-)')
418 if file_list:
419 bb.note("Creating RPM package for %s" % splitname)
420 spec_files_top.extend(file_list)
421 else:
Brad Bishopa34c0302019-09-23 22:34:48 -0400422 bb.note("Creating empty RPM package for %s" % splitname)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500423 spec_files_top.append('')
424 continue
425
426 # Process subpackage data
427 spec_preamble_bottom.append('%%package -n %s' % splitname)
428 spec_preamble_bottom.append('Summary: %s' % splitsummary)
429 if srcversion != splitversion:
430 spec_preamble_bottom.append('Version: %s' % splitversion)
431 if srcrelease != splitrelease:
432 spec_preamble_bottom.append('Release: %s' % splitrelease)
433 if srcepoch != splitepoch:
434 spec_preamble_bottom.append('Epoch: %s' % splitepoch)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400435 spec_preamble_bottom.append('License: %s' % splitlicense)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500436 spec_preamble_bottom.append('Group: %s' % splitsection)
437
438 if srccustomtagschunk != splitcustomtagschunk:
439 spec_preamble_bottom.append(splitcustomtagschunk)
440
441 # Replaces == Obsoletes && Provides
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600442 robsoletes = bb.utils.explode_dep_versions2(splitrobsoletes)
443 rprovides = bb.utils.explode_dep_versions2(splitrprovides)
444 rreplaces = bb.utils.explode_dep_versions2(splitrreplaces)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500445 for dep in rreplaces:
446 if not dep in robsoletes:
447 robsoletes[dep] = rreplaces[dep]
448 if not dep in rprovides:
449 rprovides[dep] = rreplaces[dep]
450 splitrobsoletes = bb.utils.join_deps(robsoletes, commasep=False)
451 splitrprovides = bb.utils.join_deps(rprovides, commasep=False)
452
453 print_deps(splitrdepends, "Requires", spec_preamble_bottom, d)
454 if splitrpreinst:
455 print_deps(splitrdepends, "Requires(pre)", spec_preamble_bottom, d)
456 if splitrpostinst:
457 print_deps(splitrdepends, "Requires(post)", spec_preamble_bottom, d)
458 if splitrprerm:
459 print_deps(splitrdepends, "Requires(preun)", spec_preamble_bottom, d)
460 if splitrpostrm:
461 print_deps(splitrdepends, "Requires(postun)", spec_preamble_bottom, d)
462
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500463 print_deps(splitrrecommends, "Recommends", spec_preamble_bottom, d)
464 print_deps(splitrsuggests, "Suggests", spec_preamble_bottom, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500465 print_deps(splitrprovides, "Provides", spec_preamble_bottom, d)
466 print_deps(splitrobsoletes, "Obsoletes", spec_preamble_bottom, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500467 print_deps(splitrconflicts, "Conflicts", spec_preamble_bottom, d)
468
469 spec_preamble_bottom.append('')
470
471 spec_preamble_bottom.append('%%description -n %s' % splitname)
472 append_description(spec_preamble_bottom, splitdescription)
473
474 spec_preamble_bottom.append('')
475
476 # Now process scriptlets
477 if splitrpreinst:
478 spec_scriptlets_bottom.append('%%pre -n %s' % splitname)
479 spec_scriptlets_bottom.append('# %s - preinst' % splitname)
480 spec_scriptlets_bottom.append(splitrpreinst)
481 spec_scriptlets_bottom.append('')
482 if splitrpostinst:
483 spec_scriptlets_bottom.append('%%post -n %s' % splitname)
484 spec_scriptlets_bottom.append('# %s - postinst' % splitname)
485 spec_scriptlets_bottom.append(splitrpostinst)
486 spec_scriptlets_bottom.append('')
487 if splitrprerm:
488 spec_scriptlets_bottom.append('%%preun -n %s' % splitname)
489 spec_scriptlets_bottom.append('# %s - prerm' % splitname)
490 scriptvar = wrap_uninstall(splitrprerm)
491 spec_scriptlets_bottom.append(scriptvar)
492 spec_scriptlets_bottom.append('')
493 if splitrpostrm:
494 spec_scriptlets_bottom.append('%%postun -n %s' % splitname)
495 spec_scriptlets_bottom.append('# %s - postrm' % splitname)
496 scriptvar = wrap_uninstall(splitrpostrm)
497 spec_scriptlets_bottom.append(scriptvar)
498 spec_scriptlets_bottom.append('')
499
500 # Now process files
501 file_list = []
502 walk_files(root, file_list, conffiles, dirfiles)
503 if not file_list and localdata.getVar('ALLOW_EMPTY', False) != "1":
504 bb.note("Not creating empty RPM package for %s" % splitname)
505 else:
506 spec_files_bottom.append('%%files -n %s' % splitname)
507 if extra_pkgdata:
508 package_rpm_extra_pkgdata(splitname, spec_files_bottom, localdata)
509 spec_files_bottom.append('%defattr(-,-,-,-)')
510 if file_list:
511 bb.note("Creating RPM package for %s" % splitname)
512 spec_files_bottom.extend(file_list)
513 else:
Brad Bishopa34c0302019-09-23 22:34:48 -0400514 bb.note("Creating empty RPM package for %s" % splitname)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500515 spec_files_bottom.append('')
516
517 del localdata
518
519 add_prep(d,spec_files_bottom)
520 spec_preamble_top.append('Summary: %s' % srcsummary)
521 spec_preamble_top.append('Name: %s' % srcname)
522 spec_preamble_top.append('Version: %s' % srcversion)
523 spec_preamble_top.append('Release: %s' % srcrelease)
524 if srcepoch and srcepoch.strip() != "":
525 spec_preamble_top.append('Epoch: %s' % srcepoch)
526 spec_preamble_top.append('License: %s' % srclicense)
527 spec_preamble_top.append('Group: %s' % srcsection)
528 spec_preamble_top.append('Packager: %s' % srcmaintainer)
529 if srchomepage:
530 spec_preamble_top.append('URL: %s' % srchomepage)
531 if srccustomtagschunk:
532 spec_preamble_top.append(srccustomtagschunk)
533 tail_source(d)
534
535 # Replaces == Obsoletes && Provides
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600536 robsoletes = bb.utils.explode_dep_versions2(srcrobsoletes)
537 rprovides = bb.utils.explode_dep_versions2(srcrprovides)
538 rreplaces = bb.utils.explode_dep_versions2(srcrreplaces)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500539 for dep in rreplaces:
540 if not dep in robsoletes:
541 robsoletes[dep] = rreplaces[dep]
542 if not dep in rprovides:
543 rprovides[dep] = rreplaces[dep]
544 srcrobsoletes = bb.utils.join_deps(robsoletes, commasep=False)
545 srcrprovides = bb.utils.join_deps(rprovides, commasep=False)
546
547 print_deps(srcdepends, "BuildRequires", spec_preamble_top, d)
548 print_deps(srcrdepends, "Requires", spec_preamble_top, d)
549 if srcrpreinst:
550 print_deps(srcrdepends, "Requires(pre)", spec_preamble_top, d)
551 if srcrpostinst:
552 print_deps(srcrdepends, "Requires(post)", spec_preamble_top, d)
553 if srcrprerm:
554 print_deps(srcrdepends, "Requires(preun)", spec_preamble_top, d)
555 if srcrpostrm:
556 print_deps(srcrdepends, "Requires(postun)", spec_preamble_top, d)
557
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500558 print_deps(srcrrecommends, "Recommends", spec_preamble_top, d)
559 print_deps(srcrsuggests, "Suggests", spec_preamble_top, d)
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500560 print_deps(srcrprovides, "Provides", spec_preamble_top, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500561 print_deps(srcrobsoletes, "Obsoletes", spec_preamble_top, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500562 print_deps(srcrconflicts, "Conflicts", spec_preamble_top, d)
563
564 spec_preamble_top.append('')
565
566 spec_preamble_top.append('%description')
567 append_description(spec_preamble_top, srcdescription)
568
569 spec_preamble_top.append('')
570
571 if srcrpreinst:
572 spec_scriptlets_top.append('%pre')
573 spec_scriptlets_top.append('# %s - preinst' % srcname)
574 spec_scriptlets_top.append(srcrpreinst)
575 spec_scriptlets_top.append('')
576 if srcrpostinst:
577 spec_scriptlets_top.append('%post')
578 spec_scriptlets_top.append('# %s - postinst' % srcname)
579 spec_scriptlets_top.append(srcrpostinst)
580 spec_scriptlets_top.append('')
581 if srcrprerm:
582 spec_scriptlets_top.append('%preun')
583 spec_scriptlets_top.append('# %s - prerm' % srcname)
584 scriptvar = wrap_uninstall(srcrprerm)
585 spec_scriptlets_top.append(scriptvar)
586 spec_scriptlets_top.append('')
587 if srcrpostrm:
588 spec_scriptlets_top.append('%postun')
589 spec_scriptlets_top.append('# %s - postrm' % srcname)
590 scriptvar = wrap_uninstall(srcrpostrm)
591 spec_scriptlets_top.append(scriptvar)
592 spec_scriptlets_top.append('')
593
594 # Write the SPEC file
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500595 specfile = open(outspecfile, 'w')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500596
597 # RPMSPEC_PREAMBLE is a way to add arbitrary text to the top
598 # of the generated spec file
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500599 external_preamble = d.getVar("RPMSPEC_PREAMBLE")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500600 if external_preamble:
601 specfile.write(external_preamble + "\n")
602
603 for line in spec_preamble_top:
604 specfile.write(line + "\n")
605
606 for line in spec_preamble_bottom:
607 specfile.write(line + "\n")
608
609 for line in spec_scriptlets_top:
610 specfile.write(line + "\n")
611
612 for line in spec_scriptlets_bottom:
613 specfile.write(line + "\n")
614
615 for line in spec_files_top:
616 specfile.write(line + "\n")
617
618 for line in spec_files_bottom:
619 specfile.write(line + "\n")
620
621 specfile.close()
622}
623# Otherwise allarch packages may change depending on override configuration
624write_specfile[vardepsexclude] = "OVERRIDES"
625
Andrew Geissler1e34c2d2020-05-29 16:02:59 -0500626# Have to list any variables referenced as X_<pkg> that aren't in pkgdata here
627RPMEXTRAVARS = "PACKAGE_ADD_METADATA_RPM"
628write_specfile[vardeps] += "${@gen_packagevar(d, 'RPMEXTRAVARS')}"
629
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500630python do_package_rpm () {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500631 workdir = d.getVar('WORKDIR')
632 tmpdir = d.getVar('TMPDIR')
633 pkgd = d.getVar('PKGD')
634 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500635 if not workdir or not pkgd or not tmpdir:
636 bb.error("Variables incorrectly set, unable to package")
637 return
638
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500639 packages = d.getVar('PACKAGES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500640 if not packages or packages == '':
641 bb.debug(1, "No packages; nothing to do")
642 return
643
644 # Construct the spec file...
645 # If the spec file already exist, and has not been stored into
646 # pseudo's files.db, it maybe cause rpmbuild src.rpm fail,
647 # so remove it before doing rpmbuild src.rpm.
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500648 srcname = d.getVar('PN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500649 outspecfile = workdir + "/" + srcname + ".spec"
650 if os.path.isfile(outspecfile):
651 os.remove(outspecfile)
652 d.setVar('OUTSPECFILE', outspecfile)
653 bb.build.exec_func('write_specfile', d)
654
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500655 perfiledeps = (d.getVar("MERGEPERFILEDEPS") or "0") == "0"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500656 if perfiledeps:
657 outdepends, outprovides = write_rpm_perfiledata(srcname, d)
658
659 # Setup the rpmbuild arguments...
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500660 rpmbuild = d.getVar('RPMBUILD')
661 targetsys = d.getVar('TARGET_SYS')
662 targetvendor = d.getVar('HOST_VENDOR')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500663
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500664 # Too many places in dnf stack assume that arch-independent packages are "noarch".
665 # Let's not fight against this.
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500666 package_arch = (d.getVar('PACKAGE_ARCH') or "").replace("-", "_")
667 if package_arch == "all":
668 package_arch = "noarch"
669
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500670 sdkpkgsuffix = (d.getVar('SDKPKGSUFFIX') or "nativesdk").replace("-", "_")
671 d.setVar('PACKAGE_ARCH_EXTEND', package_arch)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500672 pkgwritedir = d.expand('${PKGWRITEDIRRPM}/${PACKAGE_ARCH_EXTEND}')
673 d.setVar('RPM_PKGWRITEDIR', pkgwritedir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500674 bb.debug(1, 'PKGWRITEDIR: %s' % d.getVar('RPM_PKGWRITEDIR'))
675 pkgarch = d.expand('${PACKAGE_ARCH_EXTEND}${HOST_VENDOR}-linux')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500676 bb.utils.mkdirhier(pkgwritedir)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600677 os.chmod(pkgwritedir, 0o755)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500678
679 cmd = rpmbuild
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500680 cmd = cmd + " --noclean --nodeps --short-circuit --target " + pkgarch + " --buildroot " + pkgd
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500681 cmd = cmd + " --define '_topdir " + workdir + "' --define '_rpmdir " + pkgwritedir + "'"
Brad Bishop316dfdd2018-06-25 12:45:53 -0400682 cmd = cmd + " --define '_builddir " + d.getVar('B') + "'"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500683 cmd = cmd + " --define '_build_name_fmt %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm'"
684 cmd = cmd + " --define '_use_internal_dependency_generator 0'"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500685 cmd = cmd + " --define '_binaries_in_noarch_packages_terminate_build 0'"
686 cmd = cmd + " --define '_build_id_links none'"
William A. Kennington IIIac69b482021-06-02 12:28:27 -0700687 cmd = cmd + " --define '_binary_payload w6T%d.xzdio'" % int(d.getVar("XZ_THREADS"))
688 cmd = cmd + " --define '_source_payload w6T%d.xzdio'" % int(d.getVar("XZ_THREADS"))
Brad Bishop316dfdd2018-06-25 12:45:53 -0400689 cmd = cmd + " --define 'clamp_mtime_to_source_date_epoch 1'"
Andrew Geissler9b4d8b02021-02-19 12:26:16 -0600690 cmd = cmd + " --define 'use_source_date_epoch_as_buildtime 1'"
Brad Bishop316dfdd2018-06-25 12:45:53 -0400691 cmd = cmd + " --define '_buildhost reproducible'"
Andrew Geissler90fd73c2021-03-05 15:25:55 -0600692 cmd = cmd + " --define '__font_provides %{nil}'"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500693 if perfiledeps:
694 cmd = cmd + " --define '__find_requires " + outdepends + "'"
695 cmd = cmd + " --define '__find_provides " + outprovides + "'"
696 else:
697 cmd = cmd + " --define '__find_requires %{nil}'"
698 cmd = cmd + " --define '__find_provides %{nil}'"
699 cmd = cmd + " --define '_unpackaged_files_terminate_build 0'"
700 cmd = cmd + " --define 'debug_package %{nil}'"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500701 cmd = cmd + " --define '_tmppath " + workdir + "'"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500702 if d.getVarFlag('ARCHIVER_MODE', 'srpm') == '1' and bb.data.inherits_class('archiver', d):
703 cmd = cmd + " --define '_sourcedir " + d.getVar('ARCHIVER_OUTDIR') + "'"
Brad Bishop19323692019-04-05 15:28:33 -0400704 cmdsrpm = cmd + " --define '_srcrpmdir " + d.getVar('ARCHIVER_RPMOUTDIR') + "'"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500705 cmdsrpm = cmdsrpm + " -bs " + outspecfile
706 # Build the .src.rpm
707 d.setVar('SBUILDSPEC', cmdsrpm + "\n")
708 d.setVarFlag('SBUILDSPEC', 'func', '1')
709 bb.build.exec_func('SBUILDSPEC', d)
710 cmd = cmd + " -bb " + outspecfile
711
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500712 # rpm 4 creates various empty directories in _topdir, let's clean them up
713 cleanupcmd = "rm -rf %s/BUILDROOT %s/SOURCES %s/SPECS %s/SRPMS" % (workdir, workdir, workdir, workdir)
714
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500715 # Build the rpm package!
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500716 d.setVar('BUILDSPEC', cmd + "\n" + cleanupcmd + "\n")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500717 d.setVarFlag('BUILDSPEC', 'func', '1')
718 bb.build.exec_func('BUILDSPEC', d)
719
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500720 if d.getVar('RPM_SIGN_PACKAGES') == '1':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500721 bb.build.exec_func("sign_rpm", d)
722}
723
724python () {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500725 if d.getVar('PACKAGES') != '':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500726 deps = ' rpm-native:do_populate_sysroot virtual/fakeroot-native:do_populate_sysroot'
727 d.appendVarFlag('do_package_write_rpm', 'depends', deps)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500728 d.setVarFlag('do_package_write_rpm', 'fakeroot', '1')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500729}
730
731SSTATETASKS += "do_package_write_rpm"
732do_package_write_rpm[sstate-inputdirs] = "${PKGWRITEDIRRPM}"
733do_package_write_rpm[sstate-outputdirs] = "${DEPLOY_DIR_RPM}"
734# Take a shared lock, we can write multiple packages at the same time...
735# but we need to stop the rootfs/solver from running while we do...
736do_package_write_rpm[sstate-lockfile-shared] += "${DEPLOY_DIR_RPM}/rpm.lock"
737
738python do_package_write_rpm_setscene () {
739 sstate_setscene(d)
740}
741addtask do_package_write_rpm_setscene
742
743python do_package_write_rpm () {
744 bb.build.exec_func("read_subpackage_metadata", d)
745 bb.build.exec_func("do_package_rpm", d)
746}
747
748do_package_write_rpm[dirs] = "${PKGWRITEDIRRPM}"
749do_package_write_rpm[cleandirs] = "${PKGWRITEDIRRPM}"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500750do_package_write_rpm[depends] += "${@oe.utils.build_depends_string(d.getVar('PACKAGE_WRITE_DEPS'), 'do_populate_sysroot')}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500751addtask package_write_rpm after do_packagedata do_package
752
753PACKAGEINDEXDEPS += "rpm-native:do_populate_sysroot"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500754PACKAGEINDEXDEPS += "createrepo-c-native:do_populate_sysroot"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500755
756do_build[recrdeptask] += "do_package_write_rpm"