1inherit 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# 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 32# Construct per file dependencies file 33def write_rpm_perfiledata(srcname, d): 34 workdir = d.getVar('WORKDIR') 35 packages = d.getVar('PACKAGES') 36 pkgd = d.getVar('PKGD') 37 38 def dump_filerdeps(varname, outfile, d): 39 outfile.write("#!/usr/bin/env python3\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 44 dependsflist = (d.getVar(dependsflist_key) or "") 45 for dfile in dependsflist.split(): 46 key = "FILE" + varname + ":" + dfile + ":" + pkg 47 deps = filter_nativesdk_deps(srcname, d.getVar(key) or "") 48 depends_dict = bb.utils.explode_dep_versions(deps) 49 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 77 dependsfile = open(outdepends, 'w') 78 79 dump_filerdeps('RDEPENDS', dependsfile, d) 80 81 dependsfile.close() 82 os.chmod(outdepends, 0o755) 83 84 # OE-core / RPM Provides 85 outprovides = workdir + "/" + srcname + ".provides" 86 87 providesfile = open(outprovides, 'w') 88 89 dump_filerdeps('RPROVIDES', providesfile, d) 90 91 providesfile.close() 92 os.chmod(outprovides, 0o755) 93 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): 102 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') ) 104 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): 109 if d.getVarFlag('ARCHIVER_MODE', 'srpm') == '1' and bb.data.inherits_class('archiver', d): 110 ar_outdir = d.getVar('ARCHIVER_OUTDIR') 111 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: 116 # 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 120 # 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 127 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): 143 depends = d.getVar(varname) 144 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("%", "%%%%%%%%") 196 197 # Treat all symlinks to directories as normal files. 198 # os.walk() lists them as directories. 199 def move_to_files(dir): 200 if os.path.islink(os.path.join(rootpath, dir)): 201 files.append(dir) 202 return True 203 else: 204 return False 205 dirs[:] = [dir for dir in dirs if not move_to_files(dir)] 206 207 # Directory handling can happen in two ways, either DIRFILES is not set at all 208 # in which case we fall back to the older behaviour of packages owning all their 209 # directories 210 if dirfiles is None: 211 for dir in dirs: 212 if dir == "CONTROL" or dir == "DEBIAN": 213 continue 214 dir = dir.replace("%", "%%%%%%%%") 215 # All packages own the directories their files are in... 216 target.append('%dir "' + path + '/' + dir + '"') 217 else: 218 # packages own only empty directories or explict directory. 219 # This will prevent the overlapping of security permission. 220 if path and not files and not dirs: 221 target.append('%dir "' + path + '"') 222 elif path and path in dirfiles: 223 target.append('%dir "' + path + '"') 224 225 for file in files: 226 if file == "CONTROL" or file == "DEBIAN": 227 continue 228 file = file.replace("%", "%%%%%%%%") 229 if conffiles.count(path + '/' + file): 230 target.append('%config "' + path + '/' + file + '"') 231 else: 232 target.append('"' + path + '/' + file + '"') 233 234 # Prevent the prerm/postrm scripts from being run during an upgrade 235 def wrap_uninstall(scriptvar): 236 scr = scriptvar.strip() 237 if scr.startswith("#!"): 238 pos = scr.find("\n") + 1 239 else: 240 pos = 0 241 scr = scr[:pos] + 'if [ "$1" = "0" ] ; then\n' + scr[pos:] + '\nfi' 242 return scr 243 244 def get_perfile(varname, pkg, d): 245 deps = [] 246 dependsflist_key = 'FILE' + varname + 'FLIST' + ":" + pkg 247 dependsflist = (d.getVar(dependsflist_key) or "") 248 for dfile in dependsflist.split(): 249 key = "FILE" + varname + ":" + dfile + ":" + pkg 250 depends = d.getVar(key) 251 if depends: 252 deps.append(depends) 253 return " ".join(deps) 254 255 def append_description(spec_preamble, text): 256 """ 257 Add the description to the spec file. 258 """ 259 import textwrap 260 dedent_text = textwrap.dedent(text).strip() 261 # Bitbake saves "\n" as "\\n" 262 if '\\n' in dedent_text: 263 for t in dedent_text.split('\\n'): 264 spec_preamble.append(t.strip()) 265 else: 266 spec_preamble.append('%s' % textwrap.fill(dedent_text, width=75)) 267 268 packages = d.getVar('PACKAGES') 269 if not packages or packages == '': 270 bb.debug(1, "No packages; nothing to do") 271 return 272 273 pkgdest = d.getVar('PKGDEST') 274 if not pkgdest: 275 bb.fatal("No PKGDEST") 276 277 outspecfile = d.getVar('OUTSPECFILE') 278 if not outspecfile: 279 bb.fatal("No OUTSPECFILE") 280 281 # Construct the SPEC file... 282 srcname = d.getVar('PN') 283 localdata = bb.data.createCopy(d) 284 localdata.setVar('OVERRIDES', d.getVar("OVERRIDES", False) + ":" + srcname) 285 srcsummary = (localdata.getVar('SUMMARY') or localdata.getVar('DESCRIPTION') or ".") 286 srcversion = localdata.getVar('PKGV').replace('-', '+') 287 srcrelease = localdata.getVar('PKGR') 288 srcepoch = (localdata.getVar('PKGE') or "") 289 srclicense = localdata.getVar('LICENSE') 290 srcsection = localdata.getVar('SECTION') 291 srcmaintainer = localdata.getVar('MAINTAINER') 292 srchomepage = localdata.getVar('HOMEPAGE') 293 srcdescription = localdata.getVar('DESCRIPTION') or "." 294 srccustomtagschunk = get_package_additional_metadata("rpm", localdata) 295 296 srcdepends = d.getVar('DEPENDS') 297 srcrdepends = "" 298 srcrrecommends = "" 299 srcrsuggests = "" 300 srcrprovides = "" 301 srcrreplaces = "" 302 srcrconflicts = "" 303 srcrobsoletes = "" 304 305 srcrpreinst = [] 306 srcrpostinst = [] 307 srcrprerm = [] 308 srcrpostrm = [] 309 310 spec_preamble_top = [] 311 spec_preamble_bottom = [] 312 313 spec_scriptlets_top = [] 314 spec_scriptlets_bottom = [] 315 316 spec_files_top = [] 317 spec_files_bottom = [] 318 319 perfiledeps = (d.getVar("MERGEPERFILEDEPS") or "0") == "0" 320 extra_pkgdata = (d.getVar("RPM_EXTRA_PKGDATA") or "0") == "1" 321 322 for pkg in packages.split(): 323 localdata = bb.data.createCopy(d) 324 325 root = "%s/%s" % (pkgdest, pkg) 326 327 localdata.setVar('ROOT', '') 328 localdata.setVar('ROOT_%s' % pkg, root) 329 pkgname = localdata.getVar('PKG:%s' % pkg) 330 if not pkgname: 331 pkgname = pkg 332 localdata.setVar('PKG', pkgname) 333 334 localdata.setVar('OVERRIDES', d.getVar("OVERRIDES", False) + ":" + pkg) 335 336 conffiles = get_conffiles(pkg, d) 337 dirfiles = localdata.getVar('DIRFILES') 338 if dirfiles is not None: 339 dirfiles = dirfiles.split() 340 341 splitname = pkgname 342 343 splitsummary = (localdata.getVar('SUMMARY') or localdata.getVar('DESCRIPTION') or ".") 344 splitversion = (localdata.getVar('PKGV') or "").replace('-', '+') 345 splitrelease = (localdata.getVar('PKGR') or "") 346 splitepoch = (localdata.getVar('PKGE') or "") 347 splitlicense = (localdata.getVar('LICENSE') or "") 348 splitsection = (localdata.getVar('SECTION') or "") 349 splitdescription = (localdata.getVar('DESCRIPTION') or ".") 350 splitcustomtagschunk = get_package_additional_metadata("rpm", localdata) 351 352 translate_vers('RDEPENDS', localdata) 353 translate_vers('RRECOMMENDS', localdata) 354 translate_vers('RSUGGESTS', localdata) 355 translate_vers('RPROVIDES', localdata) 356 translate_vers('RREPLACES', localdata) 357 translate_vers('RCONFLICTS', localdata) 358 359 # Map the dependencies into their final form 360 mapping_rename_hook(localdata) 361 362 splitrdepends = localdata.getVar('RDEPENDS') or "" 363 splitrrecommends = localdata.getVar('RRECOMMENDS') or "" 364 splitrsuggests = localdata.getVar('RSUGGESTS') or "" 365 splitrprovides = localdata.getVar('RPROVIDES') or "" 366 splitrreplaces = localdata.getVar('RREPLACES') or "" 367 splitrconflicts = localdata.getVar('RCONFLICTS') or "" 368 splitrobsoletes = "" 369 370 splitrpreinst = localdata.getVar('pkg_preinst') 371 splitrpostinst = localdata.getVar('pkg_postinst') 372 splitrprerm = localdata.getVar('pkg_prerm') 373 splitrpostrm = localdata.getVar('pkg_postrm') 374 375 376 if not perfiledeps: 377 # Add in summary of per file dependencies 378 splitrdepends = splitrdepends + " " + get_perfile('RDEPENDS', pkg, d) 379 splitrprovides = splitrprovides + " " + get_perfile('RPROVIDES', pkg, d) 380 381 splitrdepends = filter_nativesdk_deps(srcname, splitrdepends) 382 383 # Gather special src/first package data 384 if srcname == splitname: 385 archiving = d.getVarFlag('ARCHIVER_MODE', 'srpm') == '1' and \ 386 bb.data.inherits_class('archiver', d) 387 if archiving and srclicense != splitlicense: 388 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.") 389 390 srclicense = splitlicense 391 srcrdepends = splitrdepends 392 srcrrecommends = splitrrecommends 393 srcrsuggests = splitrsuggests 394 srcrprovides = splitrprovides 395 srcrreplaces = splitrreplaces 396 srcrconflicts = splitrconflicts 397 398 srcrpreinst = splitrpreinst 399 srcrpostinst = splitrpostinst 400 srcrprerm = splitrprerm 401 srcrpostrm = splitrpostrm 402 403 file_list = [] 404 walk_files(root, file_list, conffiles, dirfiles) 405 if not file_list and localdata.getVar('ALLOW_EMPTY', False) != "1": 406 bb.note("Not creating empty RPM package for %s" % splitname) 407 else: 408 spec_files_top.append('%files') 409 if extra_pkgdata: 410 package_rpm_extra_pkgdata(splitname, spec_files_top, localdata) 411 spec_files_top.append('%defattr(-,-,-,-)') 412 if file_list: 413 bb.note("Creating RPM package for %s" % splitname) 414 spec_files_top.extend(file_list) 415 else: 416 bb.note("Creating empty RPM package for %s" % splitname) 417 spec_files_top.append('') 418 continue 419 420 # Process subpackage data 421 spec_preamble_bottom.append('%%package -n %s' % splitname) 422 spec_preamble_bottom.append('Summary: %s' % splitsummary) 423 if srcversion != splitversion: 424 spec_preamble_bottom.append('Version: %s' % splitversion) 425 if srcrelease != splitrelease: 426 spec_preamble_bottom.append('Release: %s' % splitrelease) 427 if srcepoch != splitepoch: 428 spec_preamble_bottom.append('Epoch: %s' % splitepoch) 429 spec_preamble_bottom.append('License: %s' % splitlicense) 430 spec_preamble_bottom.append('Group: %s' % splitsection) 431 432 if srccustomtagschunk != splitcustomtagschunk: 433 spec_preamble_bottom.append(splitcustomtagschunk) 434 435 # Replaces == Obsoletes && Provides 436 robsoletes = bb.utils.explode_dep_versions2(splitrobsoletes) 437 rprovides = bb.utils.explode_dep_versions2(splitrprovides) 438 rreplaces = bb.utils.explode_dep_versions2(splitrreplaces) 439 for dep in rreplaces: 440 if not dep in robsoletes: 441 robsoletes[dep] = rreplaces[dep] 442 if not dep in rprovides: 443 rprovides[dep] = rreplaces[dep] 444 splitrobsoletes = bb.utils.join_deps(robsoletes, commasep=False) 445 splitrprovides = bb.utils.join_deps(rprovides, commasep=False) 446 447 print_deps(splitrdepends, "Requires", spec_preamble_bottom, d) 448 if splitrpreinst: 449 print_deps(splitrdepends, "Requires(pre)", spec_preamble_bottom, d) 450 if splitrpostinst: 451 print_deps(splitrdepends, "Requires(post)", spec_preamble_bottom, d) 452 if splitrprerm: 453 print_deps(splitrdepends, "Requires(preun)", spec_preamble_bottom, d) 454 if splitrpostrm: 455 print_deps(splitrdepends, "Requires(postun)", spec_preamble_bottom, d) 456 457 print_deps(splitrrecommends, "Recommends", spec_preamble_bottom, d) 458 print_deps(splitrsuggests, "Suggests", spec_preamble_bottom, d) 459 print_deps(splitrprovides, "Provides", spec_preamble_bottom, d) 460 print_deps(splitrobsoletes, "Obsoletes", spec_preamble_bottom, d) 461 print_deps(splitrconflicts, "Conflicts", spec_preamble_bottom, d) 462 463 spec_preamble_bottom.append('') 464 465 spec_preamble_bottom.append('%%description -n %s' % splitname) 466 append_description(spec_preamble_bottom, splitdescription) 467 468 spec_preamble_bottom.append('') 469 470 # Now process scriptlets 471 if splitrpreinst: 472 spec_scriptlets_bottom.append('%%pre -n %s' % splitname) 473 spec_scriptlets_bottom.append('# %s - preinst' % splitname) 474 spec_scriptlets_bottom.append(splitrpreinst) 475 spec_scriptlets_bottom.append('') 476 if splitrpostinst: 477 spec_scriptlets_bottom.append('%%post -n %s' % splitname) 478 spec_scriptlets_bottom.append('# %s - postinst' % splitname) 479 spec_scriptlets_bottom.append(splitrpostinst) 480 spec_scriptlets_bottom.append('') 481 if splitrprerm: 482 spec_scriptlets_bottom.append('%%preun -n %s' % splitname) 483 spec_scriptlets_bottom.append('# %s - prerm' % splitname) 484 scriptvar = wrap_uninstall(splitrprerm) 485 spec_scriptlets_bottom.append(scriptvar) 486 spec_scriptlets_bottom.append('') 487 if splitrpostrm: 488 spec_scriptlets_bottom.append('%%postun -n %s' % splitname) 489 spec_scriptlets_bottom.append('# %s - postrm' % splitname) 490 scriptvar = wrap_uninstall(splitrpostrm) 491 spec_scriptlets_bottom.append(scriptvar) 492 spec_scriptlets_bottom.append('') 493 494 # Now process files 495 file_list = [] 496 walk_files(root, file_list, conffiles, dirfiles) 497 if not file_list and localdata.getVar('ALLOW_EMPTY', False) != "1": 498 bb.note("Not creating empty RPM package for %s" % splitname) 499 else: 500 spec_files_bottom.append('%%files -n %s' % splitname) 501 if extra_pkgdata: 502 package_rpm_extra_pkgdata(splitname, spec_files_bottom, localdata) 503 spec_files_bottom.append('%defattr(-,-,-,-)') 504 if file_list: 505 bb.note("Creating RPM package for %s" % splitname) 506 spec_files_bottom.extend(file_list) 507 else: 508 bb.note("Creating empty RPM package for %s" % splitname) 509 spec_files_bottom.append('') 510 511 del localdata 512 513 add_prep(d,spec_files_bottom) 514 spec_preamble_top.append('Summary: %s' % srcsummary) 515 spec_preamble_top.append('Name: %s' % srcname) 516 spec_preamble_top.append('Version: %s' % srcversion) 517 spec_preamble_top.append('Release: %s' % srcrelease) 518 if srcepoch and srcepoch.strip() != "": 519 spec_preamble_top.append('Epoch: %s' % srcepoch) 520 spec_preamble_top.append('License: %s' % srclicense) 521 spec_preamble_top.append('Group: %s' % srcsection) 522 spec_preamble_top.append('Packager: %s' % srcmaintainer) 523 if srchomepage: 524 spec_preamble_top.append('URL: %s' % srchomepage) 525 if srccustomtagschunk: 526 spec_preamble_top.append(srccustomtagschunk) 527 tail_source(d) 528 529 # Replaces == Obsoletes && Provides 530 robsoletes = bb.utils.explode_dep_versions2(srcrobsoletes) 531 rprovides = bb.utils.explode_dep_versions2(srcrprovides) 532 rreplaces = bb.utils.explode_dep_versions2(srcrreplaces) 533 for dep in rreplaces: 534 if not dep in robsoletes: 535 robsoletes[dep] = rreplaces[dep] 536 if not dep in rprovides: 537 rprovides[dep] = rreplaces[dep] 538 srcrobsoletes = bb.utils.join_deps(robsoletes, commasep=False) 539 srcrprovides = bb.utils.join_deps(rprovides, commasep=False) 540 541 print_deps(srcdepends, "BuildRequires", spec_preamble_top, d) 542 print_deps(srcrdepends, "Requires", spec_preamble_top, d) 543 if srcrpreinst: 544 print_deps(srcrdepends, "Requires(pre)", spec_preamble_top, d) 545 if srcrpostinst: 546 print_deps(srcrdepends, "Requires(post)", spec_preamble_top, d) 547 if srcrprerm: 548 print_deps(srcrdepends, "Requires(preun)", spec_preamble_top, d) 549 if srcrpostrm: 550 print_deps(srcrdepends, "Requires(postun)", spec_preamble_top, d) 551 552 print_deps(srcrrecommends, "Recommends", spec_preamble_top, d) 553 print_deps(srcrsuggests, "Suggests", spec_preamble_top, d) 554 print_deps(srcrprovides, "Provides", spec_preamble_top, d) 555 print_deps(srcrobsoletes, "Obsoletes", spec_preamble_top, d) 556 print_deps(srcrconflicts, "Conflicts", spec_preamble_top, d) 557 558 spec_preamble_top.append('') 559 560 spec_preamble_top.append('%description') 561 append_description(spec_preamble_top, srcdescription) 562 563 spec_preamble_top.append('') 564 565 if srcrpreinst: 566 spec_scriptlets_top.append('%pre') 567 spec_scriptlets_top.append('# %s - preinst' % srcname) 568 spec_scriptlets_top.append(srcrpreinst) 569 spec_scriptlets_top.append('') 570 if srcrpostinst: 571 spec_scriptlets_top.append('%post') 572 spec_scriptlets_top.append('# %s - postinst' % srcname) 573 spec_scriptlets_top.append(srcrpostinst) 574 spec_scriptlets_top.append('') 575 if srcrprerm: 576 spec_scriptlets_top.append('%preun') 577 spec_scriptlets_top.append('# %s - prerm' % srcname) 578 scriptvar = wrap_uninstall(srcrprerm) 579 spec_scriptlets_top.append(scriptvar) 580 spec_scriptlets_top.append('') 581 if srcrpostrm: 582 spec_scriptlets_top.append('%postun') 583 spec_scriptlets_top.append('# %s - postrm' % srcname) 584 scriptvar = wrap_uninstall(srcrpostrm) 585 spec_scriptlets_top.append(scriptvar) 586 spec_scriptlets_top.append('') 587 588 # Write the SPEC file 589 specfile = open(outspecfile, 'w') 590 591 # RPMSPEC_PREAMBLE is a way to add arbitrary text to the top 592 # of the generated spec file 593 external_preamble = d.getVar("RPMSPEC_PREAMBLE") 594 if external_preamble: 595 specfile.write(external_preamble + "\n") 596 597 for line in spec_preamble_top: 598 specfile.write(line + "\n") 599 600 for line in spec_preamble_bottom: 601 specfile.write(line + "\n") 602 603 for line in spec_scriptlets_top: 604 specfile.write(line + "\n") 605 606 for line in spec_scriptlets_bottom: 607 specfile.write(line + "\n") 608 609 for line in spec_files_top: 610 specfile.write(line + "\n") 611 612 for line in spec_files_bottom: 613 specfile.write(line + "\n") 614 615 specfile.close() 616} 617# Otherwise allarch packages may change depending on override configuration 618write_specfile[vardepsexclude] = "OVERRIDES" 619 620# Have to list any variables referenced as X_<pkg> that aren't in pkgdata here 621RPMEXTRAVARS = "PACKAGE_ADD_METADATA_RPM" 622write_specfile[vardeps] += "${@gen_packagevar(d, 'RPMEXTRAVARS')}" 623 624python do_package_rpm () { 625 workdir = d.getVar('WORKDIR') 626 tmpdir = d.getVar('TMPDIR') 627 pkgd = d.getVar('PKGD') 628 pkgdest = d.getVar('PKGDEST') 629 if not workdir or not pkgd or not tmpdir: 630 bb.error("Variables incorrectly set, unable to package") 631 return 632 633 packages = d.getVar('PACKAGES') 634 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. 642 srcname = d.getVar('PN') 643 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 649 perfiledeps = (d.getVar("MERGEPERFILEDEPS") or "0") == "0" 650 if perfiledeps: 651 outdepends, outprovides = write_rpm_perfiledata(srcname, d) 652 653 # Setup the rpmbuild arguments... 654 rpmbuild = d.getVar('RPMBUILD') 655 targetsys = d.getVar('TARGET_SYS') 656 targetvendor = d.getVar('HOST_VENDOR') 657 658 # Too many places in dnf stack assume that arch-independent packages are "noarch". 659 # Let's not fight against this. 660 package_arch = (d.getVar('PACKAGE_ARCH') or "").replace("-", "_") 661 if package_arch == "all": 662 package_arch = "noarch" 663 664 sdkpkgsuffix = (d.getVar('SDKPKGSUFFIX') or "nativesdk").replace("-", "_") 665 d.setVar('PACKAGE_ARCH_EXTEND', package_arch) 666 pkgwritedir = d.expand('${PKGWRITEDIRRPM}/${PACKAGE_ARCH_EXTEND}') 667 d.setVar('RPM_PKGWRITEDIR', pkgwritedir) 668 bb.debug(1, 'PKGWRITEDIR: %s' % d.getVar('RPM_PKGWRITEDIR')) 669 pkgarch = d.expand('${PACKAGE_ARCH_EXTEND}${HOST_VENDOR}-linux') 670 bb.utils.mkdirhier(pkgwritedir) 671 os.chmod(pkgwritedir, 0o755) 672 673 cmd = rpmbuild 674 cmd = cmd + " --noclean --nodeps --short-circuit --target " + pkgarch + " --buildroot " + pkgd 675 cmd = cmd + " --define '_topdir " + workdir + "' --define '_rpmdir " + pkgwritedir + "'" 676 cmd = cmd + " --define '_builddir " + d.getVar('B') + "'" 677 cmd = cmd + " --define '_build_name_fmt %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm'" 678 cmd = cmd + " --define '_use_internal_dependency_generator 0'" 679 cmd = cmd + " --define '_binaries_in_noarch_packages_terminate_build 0'" 680 cmd = cmd + " --define '_build_id_links none'" 681 cmd = cmd + " --define '_binary_payload w19T%d.zstdio'" % int(d.getVar("ZSTD_THREADS")) 682 cmd = cmd + " --define '_source_payload w19T%d.zstdio'" % int(d.getVar("ZSTD_THREADS")) 683 cmd = cmd + " --define 'clamp_mtime_to_source_date_epoch 1'" 684 cmd = cmd + " --define 'use_source_date_epoch_as_buildtime 1'" 685 cmd = cmd + " --define '_buildhost reproducible'" 686 cmd = cmd + " --define '__font_provides %{nil}'" 687 if perfiledeps: 688 cmd = cmd + " --define '__find_requires " + outdepends + "'" 689 cmd = cmd + " --define '__find_provides " + outprovides + "'" 690 else: 691 cmd = cmd + " --define '__find_requires %{nil}'" 692 cmd = cmd + " --define '__find_provides %{nil}'" 693 cmd = cmd + " --define '_unpackaged_files_terminate_build 0'" 694 cmd = cmd + " --define 'debug_package %{nil}'" 695 cmd = cmd + " --define '_tmppath " + workdir + "'" 696 if d.getVarFlag('ARCHIVER_MODE', 'srpm') == '1' and bb.data.inherits_class('archiver', d): 697 cmd = cmd + " --define '_sourcedir " + d.getVar('ARCHIVER_OUTDIR') + "'" 698 cmdsrpm = cmd + " --define '_srcrpmdir " + d.getVar('ARCHIVER_RPMOUTDIR') + "'" 699 cmdsrpm = cmdsrpm + " -bs " + outspecfile 700 # Build the .src.rpm 701 d.setVar('SBUILDSPEC', cmdsrpm + "\n") 702 d.setVarFlag('SBUILDSPEC', 'func', '1') 703 bb.build.exec_func('SBUILDSPEC', d) 704 cmd = cmd + " -bb " + outspecfile 705 706 # rpm 4 creates various empty directories in _topdir, let's clean them up 707 cleanupcmd = "rm -rf %s/BUILDROOT %s/SOURCES %s/SPECS %s/SRPMS" % (workdir, workdir, workdir, workdir) 708 709 # Build the rpm package! 710 d.setVar('BUILDSPEC', cmd + "\n" + cleanupcmd + "\n") 711 d.setVarFlag('BUILDSPEC', 'func', '1') 712 bb.build.exec_func('BUILDSPEC', d) 713 714 if d.getVar('RPM_SIGN_PACKAGES') == '1': 715 bb.build.exec_func("sign_rpm", d) 716} 717 718python () { 719 if d.getVar('PACKAGES') != '': 720 deps = ' rpm-native:do_populate_sysroot virtual/fakeroot-native:do_populate_sysroot' 721 d.appendVarFlag('do_package_write_rpm', 'depends', deps) 722 d.setVarFlag('do_package_write_rpm', 'fakeroot', '1') 723} 724 725SSTATETASKS += "do_package_write_rpm" 726do_package_write_rpm[sstate-inputdirs] = "${PKGWRITEDIRRPM}" 727do_package_write_rpm[sstate-outputdirs] = "${DEPLOY_DIR_RPM}" 728# Take a shared lock, we can write multiple packages at the same time... 729# but we need to stop the rootfs/solver from running while we do... 730do_package_write_rpm[sstate-lockfile-shared] += "${DEPLOY_DIR_RPM}/rpm.lock" 731 732python do_package_write_rpm_setscene () { 733 sstate_setscene(d) 734} 735addtask do_package_write_rpm_setscene 736 737python do_package_write_rpm () { 738 bb.build.exec_func("read_subpackage_metadata", d) 739 bb.build.exec_func("do_package_rpm", d) 740} 741 742do_package_write_rpm[dirs] = "${PKGWRITEDIRRPM}" 743do_package_write_rpm[cleandirs] = "${PKGWRITEDIRRPM}" 744do_package_write_rpm[depends] += "${@oe.utils.build_depends_string(d.getVar('PACKAGE_WRITE_DEPS'), 'do_populate_sysroot')}" 745addtask package_write_rpm after do_packagedata do_package do_deploy_source_date_epoch before do_build 746do_build[rdeptask] += "do_package_write_rpm" 747 748PACKAGEINDEXDEPS += "rpm-native:do_populate_sysroot" 749PACKAGEINDEXDEPS += "createrepo-c-native:do_populate_sysroot" 750