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