blob: 1a64cb271ace70da3576ee8c27a6937a058a938a [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):
39 outfile.write("#!/usr/bin/env python\n\n")
40 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:
412 bb.note("Creating RPM package for %s" % splitname)
413 spec_files_top.append('%files')
414 if extra_pkgdata:
415 package_rpm_extra_pkgdata(splitname, spec_files_top, localdata)
416 spec_files_top.append('%defattr(-,-,-,-)')
417 if file_list:
418 bb.note("Creating RPM package for %s" % splitname)
419 spec_files_top.extend(file_list)
420 else:
421 bb.note("Creating EMPTY RPM Package for %s" % splitname)
422 spec_files_top.append('')
423 continue
424
425 # Process subpackage data
426 spec_preamble_bottom.append('%%package -n %s' % splitname)
427 spec_preamble_bottom.append('Summary: %s' % splitsummary)
428 if srcversion != splitversion:
429 spec_preamble_bottom.append('Version: %s' % splitversion)
430 if srcrelease != splitrelease:
431 spec_preamble_bottom.append('Release: %s' % splitrelease)
432 if srcepoch != splitepoch:
433 spec_preamble_bottom.append('Epoch: %s' % splitepoch)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400434 spec_preamble_bottom.append('License: %s' % splitlicense)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500435 spec_preamble_bottom.append('Group: %s' % splitsection)
436
437 if srccustomtagschunk != splitcustomtagschunk:
438 spec_preamble_bottom.append(splitcustomtagschunk)
439
440 # Replaces == Obsoletes && Provides
441 robsoletes = bb.utils.explode_dep_versions2(splitrobsoletes or "")
442 rprovides = bb.utils.explode_dep_versions2(splitrprovides or "")
443 rreplaces = bb.utils.explode_dep_versions2(splitrreplaces or "")
444 for dep in rreplaces:
445 if not dep in robsoletes:
446 robsoletes[dep] = rreplaces[dep]
447 if not dep in rprovides:
448 rprovides[dep] = rreplaces[dep]
449 splitrobsoletes = bb.utils.join_deps(robsoletes, commasep=False)
450 splitrprovides = bb.utils.join_deps(rprovides, commasep=False)
451
452 print_deps(splitrdepends, "Requires", spec_preamble_bottom, d)
453 if splitrpreinst:
454 print_deps(splitrdepends, "Requires(pre)", spec_preamble_bottom, d)
455 if splitrpostinst:
456 print_deps(splitrdepends, "Requires(post)", spec_preamble_bottom, d)
457 if splitrprerm:
458 print_deps(splitrdepends, "Requires(preun)", spec_preamble_bottom, d)
459 if splitrpostrm:
460 print_deps(splitrdepends, "Requires(postun)", spec_preamble_bottom, d)
461
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500462 print_deps(splitrrecommends, "Recommends", spec_preamble_bottom, d)
463 print_deps(splitrsuggests, "Suggests", spec_preamble_bottom, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500464 print_deps(splitrprovides, "Provides", spec_preamble_bottom, d)
465 print_deps(splitrobsoletes, "Obsoletes", spec_preamble_bottom, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500466 print_deps(splitrconflicts, "Conflicts", spec_preamble_bottom, d)
467
468 spec_preamble_bottom.append('')
469
470 spec_preamble_bottom.append('%%description -n %s' % splitname)
471 append_description(spec_preamble_bottom, splitdescription)
472
473 spec_preamble_bottom.append('')
474
475 # Now process scriptlets
476 if splitrpreinst:
477 spec_scriptlets_bottom.append('%%pre -n %s' % splitname)
478 spec_scriptlets_bottom.append('# %s - preinst' % splitname)
479 spec_scriptlets_bottom.append(splitrpreinst)
480 spec_scriptlets_bottom.append('')
481 if splitrpostinst:
482 spec_scriptlets_bottom.append('%%post -n %s' % splitname)
483 spec_scriptlets_bottom.append('# %s - postinst' % splitname)
484 spec_scriptlets_bottom.append(splitrpostinst)
485 spec_scriptlets_bottom.append('')
486 if splitrprerm:
487 spec_scriptlets_bottom.append('%%preun -n %s' % splitname)
488 spec_scriptlets_bottom.append('# %s - prerm' % splitname)
489 scriptvar = wrap_uninstall(splitrprerm)
490 spec_scriptlets_bottom.append(scriptvar)
491 spec_scriptlets_bottom.append('')
492 if splitrpostrm:
493 spec_scriptlets_bottom.append('%%postun -n %s' % splitname)
494 spec_scriptlets_bottom.append('# %s - postrm' % splitname)
495 scriptvar = wrap_uninstall(splitrpostrm)
496 spec_scriptlets_bottom.append(scriptvar)
497 spec_scriptlets_bottom.append('')
498
499 # Now process files
500 file_list = []
501 walk_files(root, file_list, conffiles, dirfiles)
502 if not file_list and localdata.getVar('ALLOW_EMPTY', False) != "1":
503 bb.note("Not creating empty RPM package for %s" % splitname)
504 else:
505 spec_files_bottom.append('%%files -n %s' % splitname)
506 if extra_pkgdata:
507 package_rpm_extra_pkgdata(splitname, spec_files_bottom, localdata)
508 spec_files_bottom.append('%defattr(-,-,-,-)')
509 if file_list:
510 bb.note("Creating RPM package for %s" % splitname)
511 spec_files_bottom.extend(file_list)
512 else:
513 bb.note("Creating EMPTY RPM Package for %s" % splitname)
514 spec_files_bottom.append('')
515
516 del localdata
517
518 add_prep(d,spec_files_bottom)
519 spec_preamble_top.append('Summary: %s' % srcsummary)
520 spec_preamble_top.append('Name: %s' % srcname)
521 spec_preamble_top.append('Version: %s' % srcversion)
522 spec_preamble_top.append('Release: %s' % srcrelease)
523 if srcepoch and srcepoch.strip() != "":
524 spec_preamble_top.append('Epoch: %s' % srcepoch)
525 spec_preamble_top.append('License: %s' % srclicense)
526 spec_preamble_top.append('Group: %s' % srcsection)
527 spec_preamble_top.append('Packager: %s' % srcmaintainer)
528 if srchomepage:
529 spec_preamble_top.append('URL: %s' % srchomepage)
530 if srccustomtagschunk:
531 spec_preamble_top.append(srccustomtagschunk)
532 tail_source(d)
533
534 # Replaces == Obsoletes && Provides
535 robsoletes = bb.utils.explode_dep_versions2(srcrobsoletes or "")
536 rprovides = bb.utils.explode_dep_versions2(srcrprovides or "")
537 rreplaces = bb.utils.explode_dep_versions2(srcrreplaces or "")
538 for dep in rreplaces:
539 if not dep in robsoletes:
540 robsoletes[dep] = rreplaces[dep]
541 if not dep in rprovides:
542 rprovides[dep] = rreplaces[dep]
543 srcrobsoletes = bb.utils.join_deps(robsoletes, commasep=False)
544 srcrprovides = bb.utils.join_deps(rprovides, commasep=False)
545
546 print_deps(srcdepends, "BuildRequires", spec_preamble_top, d)
547 print_deps(srcrdepends, "Requires", spec_preamble_top, d)
548 if srcrpreinst:
549 print_deps(srcrdepends, "Requires(pre)", spec_preamble_top, d)
550 if srcrpostinst:
551 print_deps(srcrdepends, "Requires(post)", spec_preamble_top, d)
552 if srcrprerm:
553 print_deps(srcrdepends, "Requires(preun)", spec_preamble_top, d)
554 if srcrpostrm:
555 print_deps(srcrdepends, "Requires(postun)", spec_preamble_top, d)
556
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500557 print_deps(srcrrecommends, "Recommends", spec_preamble_top, d)
558 print_deps(srcrsuggests, "Suggests", spec_preamble_top, d)
559 print_deps(srcrprovides + (" /bin/sh" if srcname.startswith("nativesdk-") else ""), "Provides", spec_preamble_top, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500560 print_deps(srcrobsoletes, "Obsoletes", spec_preamble_top, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500561 print_deps(srcrconflicts, "Conflicts", spec_preamble_top, d)
562
563 spec_preamble_top.append('')
564
565 spec_preamble_top.append('%description')
566 append_description(spec_preamble_top, srcdescription)
567
568 spec_preamble_top.append('')
569
570 if srcrpreinst:
571 spec_scriptlets_top.append('%pre')
572 spec_scriptlets_top.append('# %s - preinst' % srcname)
573 spec_scriptlets_top.append(srcrpreinst)
574 spec_scriptlets_top.append('')
575 if srcrpostinst:
576 spec_scriptlets_top.append('%post')
577 spec_scriptlets_top.append('# %s - postinst' % srcname)
578 spec_scriptlets_top.append(srcrpostinst)
579 spec_scriptlets_top.append('')
580 if srcrprerm:
581 spec_scriptlets_top.append('%preun')
582 spec_scriptlets_top.append('# %s - prerm' % srcname)
583 scriptvar = wrap_uninstall(srcrprerm)
584 spec_scriptlets_top.append(scriptvar)
585 spec_scriptlets_top.append('')
586 if srcrpostrm:
587 spec_scriptlets_top.append('%postun')
588 spec_scriptlets_top.append('# %s - postrm' % srcname)
589 scriptvar = wrap_uninstall(srcrpostrm)
590 spec_scriptlets_top.append(scriptvar)
591 spec_scriptlets_top.append('')
592
593 # Write the SPEC file
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500594 specfile = open(outspecfile, 'w')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500595
596 # RPMSPEC_PREAMBLE is a way to add arbitrary text to the top
597 # of the generated spec file
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500598 external_preamble = d.getVar("RPMSPEC_PREAMBLE")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500599 if external_preamble:
600 specfile.write(external_preamble + "\n")
601
602 for line in spec_preamble_top:
603 specfile.write(line + "\n")
604
605 for line in spec_preamble_bottom:
606 specfile.write(line + "\n")
607
608 for line in spec_scriptlets_top:
609 specfile.write(line + "\n")
610
611 for line in spec_scriptlets_bottom:
612 specfile.write(line + "\n")
613
614 for line in spec_files_top:
615 specfile.write(line + "\n")
616
617 for line in spec_files_bottom:
618 specfile.write(line + "\n")
619
620 specfile.close()
621}
622# Otherwise allarch packages may change depending on override configuration
623write_specfile[vardepsexclude] = "OVERRIDES"
624
625python do_package_rpm () {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500626 workdir = d.getVar('WORKDIR')
627 tmpdir = d.getVar('TMPDIR')
628 pkgd = d.getVar('PKGD')
629 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500630 if not workdir or not pkgd or not tmpdir:
631 bb.error("Variables incorrectly set, unable to package")
632 return
633
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500634 packages = d.getVar('PACKAGES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500635 if not packages or packages == '':
636 bb.debug(1, "No packages; nothing to do")
637 return
638
639 # Construct the spec file...
640 # If the spec file already exist, and has not been stored into
641 # pseudo's files.db, it maybe cause rpmbuild src.rpm fail,
642 # so remove it before doing rpmbuild src.rpm.
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500643 srcname = d.getVar('PN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500644 outspecfile = workdir + "/" + srcname + ".spec"
645 if os.path.isfile(outspecfile):
646 os.remove(outspecfile)
647 d.setVar('OUTSPECFILE', outspecfile)
648 bb.build.exec_func('write_specfile', d)
649
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500650 perfiledeps = (d.getVar("MERGEPERFILEDEPS") or "0") == "0"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500651 if perfiledeps:
652 outdepends, outprovides = write_rpm_perfiledata(srcname, d)
653
654 # Setup the rpmbuild arguments...
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500655 rpmbuild = d.getVar('RPMBUILD')
656 targetsys = d.getVar('TARGET_SYS')
657 targetvendor = d.getVar('HOST_VENDOR')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500658
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500659 # Too many places in dnf stack assume that arch-independent packages are "noarch".
660 # Let's not fight against this.
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500661 package_arch = (d.getVar('PACKAGE_ARCH') or "").replace("-", "_")
662 if package_arch == "all":
663 package_arch = "noarch"
664
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500665 sdkpkgsuffix = (d.getVar('SDKPKGSUFFIX') or "nativesdk").replace("-", "_")
666 d.setVar('PACKAGE_ARCH_EXTEND', package_arch)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500667 pkgwritedir = d.expand('${PKGWRITEDIRRPM}/${PACKAGE_ARCH_EXTEND}')
668 d.setVar('RPM_PKGWRITEDIR', pkgwritedir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500669 bb.debug(1, 'PKGWRITEDIR: %s' % d.getVar('RPM_PKGWRITEDIR'))
670 pkgarch = d.expand('${PACKAGE_ARCH_EXTEND}${HOST_VENDOR}-linux')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500671 bb.utils.mkdirhier(pkgwritedir)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600672 os.chmod(pkgwritedir, 0o755)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500673
674 cmd = rpmbuild
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500675 cmd = cmd + " --noclean --nodeps --short-circuit --target " + pkgarch + " --buildroot " + pkgd
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500676 cmd = cmd + " --define '_topdir " + workdir + "' --define '_rpmdir " + pkgwritedir + "'"
Brad Bishop316dfdd2018-06-25 12:45:53 -0400677 cmd = cmd + " --define '_builddir " + d.getVar('B') + "'"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500678 cmd = cmd + " --define '_build_name_fmt %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm'"
679 cmd = cmd + " --define '_use_internal_dependency_generator 0'"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500680 cmd = cmd + " --define '_binaries_in_noarch_packages_terminate_build 0'"
681 cmd = cmd + " --define '_build_id_links none'"
682 cmd = cmd + " --define '_binary_payload w6T.xzdio'"
683 cmd = cmd + " --define '_source_payload w6T.xzdio'"
Brad Bishop316dfdd2018-06-25 12:45:53 -0400684 cmd = cmd + " --define 'clamp_mtime_to_source_date_epoch 1'"
685 cmd = cmd + " --define '_buildhost reproducible'"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500686 if perfiledeps:
687 cmd = cmd + " --define '__find_requires " + outdepends + "'"
688 cmd = cmd + " --define '__find_provides " + outprovides + "'"
689 else:
690 cmd = cmd + " --define '__find_requires %{nil}'"
691 cmd = cmd + " --define '__find_provides %{nil}'"
692 cmd = cmd + " --define '_unpackaged_files_terminate_build 0'"
693 cmd = cmd + " --define 'debug_package %{nil}'"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500694 cmd = cmd + " --define '_tmppath " + workdir + "'"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500695 if d.getVarFlag('ARCHIVER_MODE', 'srpm') == '1' and bb.data.inherits_class('archiver', d):
696 cmd = cmd + " --define '_sourcedir " + d.getVar('ARCHIVER_OUTDIR') + "'"
Brad Bishop19323692019-04-05 15:28:33 -0400697 cmdsrpm = cmd + " --define '_srcrpmdir " + d.getVar('ARCHIVER_RPMOUTDIR') + "'"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500698 cmdsrpm = cmdsrpm + " -bs " + outspecfile
699 # Build the .src.rpm
700 d.setVar('SBUILDSPEC', cmdsrpm + "\n")
701 d.setVarFlag('SBUILDSPEC', 'func', '1')
702 bb.build.exec_func('SBUILDSPEC', d)
703 cmd = cmd + " -bb " + outspecfile
704
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500705 # rpm 4 creates various empty directories in _topdir, let's clean them up
706 cleanupcmd = "rm -rf %s/BUILDROOT %s/SOURCES %s/SPECS %s/SRPMS" % (workdir, workdir, workdir, workdir)
707
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500708 # Build the rpm package!
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500709 d.setVar('BUILDSPEC', cmd + "\n" + cleanupcmd + "\n")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500710 d.setVarFlag('BUILDSPEC', 'func', '1')
711 bb.build.exec_func('BUILDSPEC', d)
712
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500713 if d.getVar('RPM_SIGN_PACKAGES') == '1':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500714 bb.build.exec_func("sign_rpm", d)
715}
716
717python () {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500718 if d.getVar('PACKAGES') != '':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500719 deps = ' rpm-native:do_populate_sysroot virtual/fakeroot-native:do_populate_sysroot'
720 d.appendVarFlag('do_package_write_rpm', 'depends', deps)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500721 d.setVarFlag('do_package_write_rpm', 'fakeroot', '1')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500722}
723
724SSTATETASKS += "do_package_write_rpm"
725do_package_write_rpm[sstate-inputdirs] = "${PKGWRITEDIRRPM}"
726do_package_write_rpm[sstate-outputdirs] = "${DEPLOY_DIR_RPM}"
727# Take a shared lock, we can write multiple packages at the same time...
728# but we need to stop the rootfs/solver from running while we do...
729do_package_write_rpm[sstate-lockfile-shared] += "${DEPLOY_DIR_RPM}/rpm.lock"
730
731python do_package_write_rpm_setscene () {
732 sstate_setscene(d)
733}
734addtask do_package_write_rpm_setscene
735
736python do_package_write_rpm () {
737 bb.build.exec_func("read_subpackage_metadata", d)
738 bb.build.exec_func("do_package_rpm", d)
739}
740
741do_package_write_rpm[dirs] = "${PKGWRITEDIRRPM}"
742do_package_write_rpm[cleandirs] = "${PKGWRITEDIRRPM}"
743do_package_write_rpm[umask] = "022"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500744do_package_write_rpm[depends] += "${@oe.utils.build_depends_string(d.getVar('PACKAGE_WRITE_DEPS'), 'do_populate_sysroot')}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500745addtask package_write_rpm after do_packagedata do_package
746
747PACKAGEINDEXDEPS += "rpm-native:do_populate_sysroot"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500748PACKAGEINDEXDEPS += "createrepo-c-native:do_populate_sysroot"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500749
750do_build[recrdeptask] += "do_package_write_rpm"