blob: 9145717f98ad979d93e3bc86507c8e560c9abc80 [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')
289 srcsummary = (d.getVar('SUMMARY') or d.getVar('DESCRIPTION') or ".")
290 srcversion = d.getVar('PKGV').replace('-', '+')
291 srcrelease = d.getVar('PKGR')
292 srcepoch = (d.getVar('PKGE') or "")
293 srclicense = d.getVar('LICENSE')
294 srcsection = d.getVar('SECTION')
295 srcmaintainer = d.getVar('MAINTAINER')
296 srchomepage = d.getVar('HOMEPAGE')
297 srcdescription = d.getVar('DESCRIPTION') or "."
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500298 srccustomtagschunk = get_package_additional_metadata("rpm", d)
299
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500300 srcdepends = d.getVar('DEPENDS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500301 srcrdepends = []
302 srcrrecommends = []
303 srcrsuggests = []
304 srcrprovides = []
305 srcrreplaces = []
306 srcrconflicts = []
307 srcrobsoletes = []
308
309 srcrpreinst = []
310 srcrpostinst = []
311 srcrprerm = []
312 srcrpostrm = []
313
314 spec_preamble_top = []
315 spec_preamble_bottom = []
316
317 spec_scriptlets_top = []
318 spec_scriptlets_bottom = []
319
320 spec_files_top = []
321 spec_files_bottom = []
322
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500323 perfiledeps = (d.getVar("MERGEPERFILEDEPS") or "0") == "0"
324 extra_pkgdata = (d.getVar("RPM_EXTRA_PKGDATA") or "0") == "1"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500325
326 for pkg in packages.split():
327 localdata = bb.data.createCopy(d)
328
329 root = "%s/%s" % (pkgdest, pkg)
330
331 localdata.setVar('ROOT', '')
332 localdata.setVar('ROOT_%s' % pkg, root)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500333 pkgname = localdata.getVar('PKG_%s' % pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500334 if not pkgname:
335 pkgname = pkg
336 localdata.setVar('PKG', pkgname)
337
338 localdata.setVar('OVERRIDES', d.getVar("OVERRIDES", False) + ":" + pkg)
339
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500340 conffiles = get_conffiles(pkg, d)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500341 dirfiles = localdata.getVar('DIRFILES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500342 if dirfiles is not None:
343 dirfiles = dirfiles.split()
344
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500345 splitname = pkgname
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500346
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500347 splitsummary = (localdata.getVar('SUMMARY') or localdata.getVar('DESCRIPTION') or ".")
348 splitversion = (localdata.getVar('PKGV') or "").replace('-', '+')
349 splitrelease = (localdata.getVar('PKGR') or "")
350 splitepoch = (localdata.getVar('PKGE') or "")
351 splitlicense = (localdata.getVar('LICENSE') or "")
352 splitsection = (localdata.getVar('SECTION') or "")
353 splitdescription = (localdata.getVar('DESCRIPTION') or ".")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500354 splitcustomtagschunk = get_package_additional_metadata("rpm", localdata)
355
356 translate_vers('RDEPENDS', localdata)
357 translate_vers('RRECOMMENDS', localdata)
358 translate_vers('RSUGGESTS', localdata)
359 translate_vers('RPROVIDES', localdata)
360 translate_vers('RREPLACES', localdata)
361 translate_vers('RCONFLICTS', localdata)
362
363 # Map the dependencies into their final form
364 mapping_rename_hook(localdata)
365
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500366 splitrdepends = localdata.getVar('RDEPENDS')
367 splitrrecommends = localdata.getVar('RRECOMMENDS')
368 splitrsuggests = localdata.getVar('RSUGGESTS')
369 splitrprovides = localdata.getVar('RPROVIDES')
370 splitrreplaces = localdata.getVar('RREPLACES')
371 splitrconflicts = localdata.getVar('RCONFLICTS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500372 splitrobsoletes = []
373
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500374 splitrpreinst = localdata.getVar('pkg_preinst')
375 splitrpostinst = localdata.getVar('pkg_postinst')
376 splitrprerm = localdata.getVar('pkg_prerm')
377 splitrpostrm = localdata.getVar('pkg_postrm')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500378
379
380 if not perfiledeps:
381 # Add in summary of per file dependencies
382 splitrdepends = splitrdepends + " " + get_perfile('RDEPENDS', pkg, d)
383 splitrprovides = splitrprovides + " " + get_perfile('RPROVIDES', pkg, d)
384
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500385 splitrdepends = filter_nativesdk_deps(srcname, splitrdepends)
386
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500387 # Gather special src/first package data
388 if srcname == splitname:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400389 archiving = d.getVarFlag('ARCHIVER_MODE', 'srpm') == '1' and \
390 bb.data.inherits_class('archiver', d)
391 if archiving and srclicense != splitlicense:
392 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.")
393
394 srclicense = splitlicense
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500395 srcrdepends = splitrdepends
396 srcrrecommends = splitrrecommends
397 srcrsuggests = splitrsuggests
398 srcrprovides = splitrprovides
399 srcrreplaces = splitrreplaces
400 srcrconflicts = splitrconflicts
401
402 srcrpreinst = splitrpreinst
403 srcrpostinst = splitrpostinst
404 srcrprerm = splitrprerm
405 srcrpostrm = splitrpostrm
406
407 file_list = []
408 walk_files(root, file_list, conffiles, dirfiles)
409 if not file_list and localdata.getVar('ALLOW_EMPTY', False) != "1":
410 bb.note("Not creating empty RPM package for %s" % splitname)
411 else:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500412 spec_files_top.append('%files')
413 if extra_pkgdata:
414 package_rpm_extra_pkgdata(splitname, spec_files_top, localdata)
415 spec_files_top.append('%defattr(-,-,-,-)')
416 if file_list:
417 bb.note("Creating RPM package for %s" % splitname)
418 spec_files_top.extend(file_list)
419 else:
Brad Bishopa34c0302019-09-23 22:34:48 -0400420 bb.note("Creating empty RPM package for %s" % splitname)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500421 spec_files_top.append('')
422 continue
423
424 # Process subpackage data
425 spec_preamble_bottom.append('%%package -n %s' % splitname)
426 spec_preamble_bottom.append('Summary: %s' % splitsummary)
427 if srcversion != splitversion:
428 spec_preamble_bottom.append('Version: %s' % splitversion)
429 if srcrelease != splitrelease:
430 spec_preamble_bottom.append('Release: %s' % splitrelease)
431 if srcepoch != splitepoch:
432 spec_preamble_bottom.append('Epoch: %s' % splitepoch)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400433 spec_preamble_bottom.append('License: %s' % splitlicense)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500434 spec_preamble_bottom.append('Group: %s' % splitsection)
435
436 if srccustomtagschunk != splitcustomtagschunk:
437 spec_preamble_bottom.append(splitcustomtagschunk)
438
439 # Replaces == Obsoletes && Provides
440 robsoletes = bb.utils.explode_dep_versions2(splitrobsoletes or "")
441 rprovides = bb.utils.explode_dep_versions2(splitrprovides or "")
442 rreplaces = bb.utils.explode_dep_versions2(splitrreplaces or "")
443 for dep in rreplaces:
444 if not dep in robsoletes:
445 robsoletes[dep] = rreplaces[dep]
446 if not dep in rprovides:
447 rprovides[dep] = rreplaces[dep]
448 splitrobsoletes = bb.utils.join_deps(robsoletes, commasep=False)
449 splitrprovides = bb.utils.join_deps(rprovides, commasep=False)
450
451 print_deps(splitrdepends, "Requires", spec_preamble_bottom, d)
452 if splitrpreinst:
453 print_deps(splitrdepends, "Requires(pre)", spec_preamble_bottom, d)
454 if splitrpostinst:
455 print_deps(splitrdepends, "Requires(post)", spec_preamble_bottom, d)
456 if splitrprerm:
457 print_deps(splitrdepends, "Requires(preun)", spec_preamble_bottom, d)
458 if splitrpostrm:
459 print_deps(splitrdepends, "Requires(postun)", spec_preamble_bottom, d)
460
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500461 print_deps(splitrrecommends, "Recommends", spec_preamble_bottom, d)
462 print_deps(splitrsuggests, "Suggests", spec_preamble_bottom, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500463 print_deps(splitrprovides, "Provides", spec_preamble_bottom, d)
464 print_deps(splitrobsoletes, "Obsoletes", spec_preamble_bottom, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500465 print_deps(splitrconflicts, "Conflicts", spec_preamble_bottom, d)
466
467 spec_preamble_bottom.append('')
468
469 spec_preamble_bottom.append('%%description -n %s' % splitname)
470 append_description(spec_preamble_bottom, splitdescription)
471
472 spec_preamble_bottom.append('')
473
474 # Now process scriptlets
475 if splitrpreinst:
476 spec_scriptlets_bottom.append('%%pre -n %s' % splitname)
477 spec_scriptlets_bottom.append('# %s - preinst' % splitname)
478 spec_scriptlets_bottom.append(splitrpreinst)
479 spec_scriptlets_bottom.append('')
480 if splitrpostinst:
481 spec_scriptlets_bottom.append('%%post -n %s' % splitname)
482 spec_scriptlets_bottom.append('# %s - postinst' % splitname)
483 spec_scriptlets_bottom.append(splitrpostinst)
484 spec_scriptlets_bottom.append('')
485 if splitrprerm:
486 spec_scriptlets_bottom.append('%%preun -n %s' % splitname)
487 spec_scriptlets_bottom.append('# %s - prerm' % splitname)
488 scriptvar = wrap_uninstall(splitrprerm)
489 spec_scriptlets_bottom.append(scriptvar)
490 spec_scriptlets_bottom.append('')
491 if splitrpostrm:
492 spec_scriptlets_bottom.append('%%postun -n %s' % splitname)
493 spec_scriptlets_bottom.append('# %s - postrm' % splitname)
494 scriptvar = wrap_uninstall(splitrpostrm)
495 spec_scriptlets_bottom.append(scriptvar)
496 spec_scriptlets_bottom.append('')
497
498 # Now process files
499 file_list = []
500 walk_files(root, file_list, conffiles, dirfiles)
501 if not file_list and localdata.getVar('ALLOW_EMPTY', False) != "1":
502 bb.note("Not creating empty RPM package for %s" % splitname)
503 else:
504 spec_files_bottom.append('%%files -n %s' % splitname)
505 if extra_pkgdata:
506 package_rpm_extra_pkgdata(splitname, spec_files_bottom, localdata)
507 spec_files_bottom.append('%defattr(-,-,-,-)')
508 if file_list:
509 bb.note("Creating RPM package for %s" % splitname)
510 spec_files_bottom.extend(file_list)
511 else:
Brad Bishopa34c0302019-09-23 22:34:48 -0400512 bb.note("Creating empty RPM package for %s" % splitname)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500513 spec_files_bottom.append('')
514
515 del localdata
516
517 add_prep(d,spec_files_bottom)
518 spec_preamble_top.append('Summary: %s' % srcsummary)
519 spec_preamble_top.append('Name: %s' % srcname)
520 spec_preamble_top.append('Version: %s' % srcversion)
521 spec_preamble_top.append('Release: %s' % srcrelease)
522 if srcepoch and srcepoch.strip() != "":
523 spec_preamble_top.append('Epoch: %s' % srcepoch)
524 spec_preamble_top.append('License: %s' % srclicense)
525 spec_preamble_top.append('Group: %s' % srcsection)
526 spec_preamble_top.append('Packager: %s' % srcmaintainer)
527 if srchomepage:
528 spec_preamble_top.append('URL: %s' % srchomepage)
529 if srccustomtagschunk:
530 spec_preamble_top.append(srccustomtagschunk)
531 tail_source(d)
532
533 # Replaces == Obsoletes && Provides
534 robsoletes = bb.utils.explode_dep_versions2(srcrobsoletes or "")
535 rprovides = bb.utils.explode_dep_versions2(srcrprovides or "")
536 rreplaces = bb.utils.explode_dep_versions2(srcrreplaces or "")
537 for dep in rreplaces:
538 if not dep in robsoletes:
539 robsoletes[dep] = rreplaces[dep]
540 if not dep in rprovides:
541 rprovides[dep] = rreplaces[dep]
542 srcrobsoletes = bb.utils.join_deps(robsoletes, commasep=False)
543 srcrprovides = bb.utils.join_deps(rprovides, commasep=False)
544
545 print_deps(srcdepends, "BuildRequires", spec_preamble_top, d)
546 print_deps(srcrdepends, "Requires", spec_preamble_top, d)
547 if srcrpreinst:
548 print_deps(srcrdepends, "Requires(pre)", spec_preamble_top, d)
549 if srcrpostinst:
550 print_deps(srcrdepends, "Requires(post)", spec_preamble_top, d)
551 if srcrprerm:
552 print_deps(srcrdepends, "Requires(preun)", spec_preamble_top, d)
553 if srcrpostrm:
554 print_deps(srcrdepends, "Requires(postun)", spec_preamble_top, d)
555
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500556 print_deps(srcrrecommends, "Recommends", spec_preamble_top, d)
557 print_deps(srcrsuggests, "Suggests", spec_preamble_top, d)
558 print_deps(srcrprovides + (" /bin/sh" if srcname.startswith("nativesdk-") else ""), "Provides", spec_preamble_top, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500559 print_deps(srcrobsoletes, "Obsoletes", spec_preamble_top, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500560 print_deps(srcrconflicts, "Conflicts", spec_preamble_top, d)
561
562 spec_preamble_top.append('')
563
564 spec_preamble_top.append('%description')
565 append_description(spec_preamble_top, srcdescription)
566
567 spec_preamble_top.append('')
568
569 if srcrpreinst:
570 spec_scriptlets_top.append('%pre')
571 spec_scriptlets_top.append('# %s - preinst' % srcname)
572 spec_scriptlets_top.append(srcrpreinst)
573 spec_scriptlets_top.append('')
574 if srcrpostinst:
575 spec_scriptlets_top.append('%post')
576 spec_scriptlets_top.append('# %s - postinst' % srcname)
577 spec_scriptlets_top.append(srcrpostinst)
578 spec_scriptlets_top.append('')
579 if srcrprerm:
580 spec_scriptlets_top.append('%preun')
581 spec_scriptlets_top.append('# %s - prerm' % srcname)
582 scriptvar = wrap_uninstall(srcrprerm)
583 spec_scriptlets_top.append(scriptvar)
584 spec_scriptlets_top.append('')
585 if srcrpostrm:
586 spec_scriptlets_top.append('%postun')
587 spec_scriptlets_top.append('# %s - postrm' % srcname)
588 scriptvar = wrap_uninstall(srcrpostrm)
589 spec_scriptlets_top.append(scriptvar)
590 spec_scriptlets_top.append('')
591
592 # Write the SPEC file
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500593 specfile = open(outspecfile, 'w')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500594
595 # RPMSPEC_PREAMBLE is a way to add arbitrary text to the top
596 # of the generated spec file
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500597 external_preamble = d.getVar("RPMSPEC_PREAMBLE")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500598 if external_preamble:
599 specfile.write(external_preamble + "\n")
600
601 for line in spec_preamble_top:
602 specfile.write(line + "\n")
603
604 for line in spec_preamble_bottom:
605 specfile.write(line + "\n")
606
607 for line in spec_scriptlets_top:
608 specfile.write(line + "\n")
609
610 for line in spec_scriptlets_bottom:
611 specfile.write(line + "\n")
612
613 for line in spec_files_top:
614 specfile.write(line + "\n")
615
616 for line in spec_files_bottom:
617 specfile.write(line + "\n")
618
619 specfile.close()
620}
621# Otherwise allarch packages may change depending on override configuration
622write_specfile[vardepsexclude] = "OVERRIDES"
623
624python do_package_rpm () {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500625 workdir = d.getVar('WORKDIR')
626 tmpdir = d.getVar('TMPDIR')
627 pkgd = d.getVar('PKGD')
628 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500629 if not workdir or not pkgd or not tmpdir:
630 bb.error("Variables incorrectly set, unable to package")
631 return
632
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500633 packages = d.getVar('PACKAGES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500634 if not packages or packages == '':
635 bb.debug(1, "No packages; nothing to do")
636 return
637
638 # Construct the spec file...
639 # If the spec file already exist, and has not been stored into
640 # pseudo's files.db, it maybe cause rpmbuild src.rpm fail,
641 # so remove it before doing rpmbuild src.rpm.
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500642 srcname = d.getVar('PN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500643 outspecfile = workdir + "/" + srcname + ".spec"
644 if os.path.isfile(outspecfile):
645 os.remove(outspecfile)
646 d.setVar('OUTSPECFILE', outspecfile)
647 bb.build.exec_func('write_specfile', d)
648
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500649 perfiledeps = (d.getVar("MERGEPERFILEDEPS") or "0") == "0"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500650 if perfiledeps:
651 outdepends, outprovides = write_rpm_perfiledata(srcname, d)
652
653 # Setup the rpmbuild arguments...
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500654 rpmbuild = d.getVar('RPMBUILD')
655 targetsys = d.getVar('TARGET_SYS')
656 targetvendor = d.getVar('HOST_VENDOR')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500657
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500658 # Too many places in dnf stack assume that arch-independent packages are "noarch".
659 # Let's not fight against this.
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500660 package_arch = (d.getVar('PACKAGE_ARCH') or "").replace("-", "_")
661 if package_arch == "all":
662 package_arch = "noarch"
663
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500664 sdkpkgsuffix = (d.getVar('SDKPKGSUFFIX') or "nativesdk").replace("-", "_")
665 d.setVar('PACKAGE_ARCH_EXTEND', package_arch)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500666 pkgwritedir = d.expand('${PKGWRITEDIRRPM}/${PACKAGE_ARCH_EXTEND}')
667 d.setVar('RPM_PKGWRITEDIR', pkgwritedir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500668 bb.debug(1, 'PKGWRITEDIR: %s' % d.getVar('RPM_PKGWRITEDIR'))
669 pkgarch = d.expand('${PACKAGE_ARCH_EXTEND}${HOST_VENDOR}-linux')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500670 bb.utils.mkdirhier(pkgwritedir)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600671 os.chmod(pkgwritedir, 0o755)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500672
673 cmd = rpmbuild
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500674 cmd = cmd + " --noclean --nodeps --short-circuit --target " + pkgarch + " --buildroot " + pkgd
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500675 cmd = cmd + " --define '_topdir " + workdir + "' --define '_rpmdir " + pkgwritedir + "'"
Brad Bishop316dfdd2018-06-25 12:45:53 -0400676 cmd = cmd + " --define '_builddir " + d.getVar('B') + "'"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500677 cmd = cmd + " --define '_build_name_fmt %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm'"
678 cmd = cmd + " --define '_use_internal_dependency_generator 0'"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500679 cmd = cmd + " --define '_binaries_in_noarch_packages_terminate_build 0'"
680 cmd = cmd + " --define '_build_id_links none'"
681 cmd = cmd + " --define '_binary_payload w6T.xzdio'"
682 cmd = cmd + " --define '_source_payload w6T.xzdio'"
Brad Bishop316dfdd2018-06-25 12:45:53 -0400683 cmd = cmd + " --define 'clamp_mtime_to_source_date_epoch 1'"
684 cmd = cmd + " --define '_buildhost reproducible'"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500685 if perfiledeps:
686 cmd = cmd + " --define '__find_requires " + outdepends + "'"
687 cmd = cmd + " --define '__find_provides " + outprovides + "'"
688 else:
689 cmd = cmd + " --define '__find_requires %{nil}'"
690 cmd = cmd + " --define '__find_provides %{nil}'"
691 cmd = cmd + " --define '_unpackaged_files_terminate_build 0'"
692 cmd = cmd + " --define 'debug_package %{nil}'"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500693 cmd = cmd + " --define '_tmppath " + workdir + "'"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500694 if d.getVarFlag('ARCHIVER_MODE', 'srpm') == '1' and bb.data.inherits_class('archiver', d):
695 cmd = cmd + " --define '_sourcedir " + d.getVar('ARCHIVER_OUTDIR') + "'"
Brad Bishop19323692019-04-05 15:28:33 -0400696 cmdsrpm = cmd + " --define '_srcrpmdir " + d.getVar('ARCHIVER_RPMOUTDIR') + "'"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500697 cmdsrpm = cmdsrpm + " -bs " + outspecfile
698 # Build the .src.rpm
699 d.setVar('SBUILDSPEC', cmdsrpm + "\n")
700 d.setVarFlag('SBUILDSPEC', 'func', '1')
701 bb.build.exec_func('SBUILDSPEC', d)
702 cmd = cmd + " -bb " + outspecfile
703
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500704 # rpm 4 creates various empty directories in _topdir, let's clean them up
705 cleanupcmd = "rm -rf %s/BUILDROOT %s/SOURCES %s/SPECS %s/SRPMS" % (workdir, workdir, workdir, workdir)
706
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500707 # Build the rpm package!
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500708 d.setVar('BUILDSPEC', cmd + "\n" + cleanupcmd + "\n")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500709 d.setVarFlag('BUILDSPEC', 'func', '1')
710 bb.build.exec_func('BUILDSPEC', d)
711
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500712 if d.getVar('RPM_SIGN_PACKAGES') == '1':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500713 bb.build.exec_func("sign_rpm", d)
714}
715
716python () {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500717 if d.getVar('PACKAGES') != '':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500718 deps = ' rpm-native:do_populate_sysroot virtual/fakeroot-native:do_populate_sysroot'
719 d.appendVarFlag('do_package_write_rpm', 'depends', deps)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500720 d.setVarFlag('do_package_write_rpm', 'fakeroot', '1')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500721}
722
723SSTATETASKS += "do_package_write_rpm"
724do_package_write_rpm[sstate-inputdirs] = "${PKGWRITEDIRRPM}"
725do_package_write_rpm[sstate-outputdirs] = "${DEPLOY_DIR_RPM}"
726# Take a shared lock, we can write multiple packages at the same time...
727# but we need to stop the rootfs/solver from running while we do...
728do_package_write_rpm[sstate-lockfile-shared] += "${DEPLOY_DIR_RPM}/rpm.lock"
729
730python do_package_write_rpm_setscene () {
731 sstate_setscene(d)
732}
733addtask do_package_write_rpm_setscene
734
735python do_package_write_rpm () {
736 bb.build.exec_func("read_subpackage_metadata", d)
737 bb.build.exec_func("do_package_rpm", d)
738}
739
740do_package_write_rpm[dirs] = "${PKGWRITEDIRRPM}"
741do_package_write_rpm[cleandirs] = "${PKGWRITEDIRRPM}"
742do_package_write_rpm[umask] = "022"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500743do_package_write_rpm[depends] += "${@oe.utils.build_depends_string(d.getVar('PACKAGE_WRITE_DEPS'), 'do_populate_sysroot')}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500744addtask package_write_rpm after do_packagedata do_package
745
746PACKAGEINDEXDEPS += "rpm-native:do_populate_sysroot"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500747PACKAGEINDEXDEPS += "createrepo-c-native:do_populate_sysroot"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500748
749do_build[recrdeptask] += "do_package_write_rpm"