Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 1 | # |
| 2 | # Copyright OpenEmbedded Contributors |
| 3 | # |
| 4 | # SPDX-License-Identifier: MIT |
| 5 | # |
| 6 | |
| 7 | # |
| 8 | # Packaging process |
| 9 | # |
| 10 | # Executive summary: This class iterates over the functions listed in PACKAGEFUNCS |
| 11 | # Taking D and splitting it up into the packages listed in PACKAGES, placing the |
| 12 | # resulting output in PKGDEST. |
| 13 | # |
| 14 | # There are the following default steps but PACKAGEFUNCS can be extended: |
| 15 | # |
| 16 | # a) package_convert_pr_autoinc - convert AUTOINC in PKGV to ${PRSERV_PV_AUTOINC} |
| 17 | # |
| 18 | # b) perform_packagecopy - Copy D into PKGD |
| 19 | # |
| 20 | # c) package_do_split_locales - Split out the locale files, updates FILES and PACKAGES |
| 21 | # |
| 22 | # d) split_and_strip_files - split the files into runtime and debug and strip them. |
| 23 | # Debug files include debug info split, and associated sources that end up in -dbg packages |
| 24 | # |
| 25 | # e) fixup_perms - Fix up permissions in the package before we split it. |
| 26 | # |
| 27 | # f) populate_packages - Split the files in PKGD into separate packages in PKGDEST/<pkgname> |
| 28 | # Also triggers the binary stripping code to put files in -dbg packages. |
| 29 | # |
| 30 | # g) package_do_filedeps - Collect perfile run-time dependency metadata |
| 31 | # The data is stores in FILER{PROVIDES,DEPENDS}_file_pkg variables with |
| 32 | # a list of affected files in FILER{PROVIDES,DEPENDS}FLIST_pkg |
| 33 | # |
| 34 | # h) package_do_shlibs - Look at the shared libraries generated and autotmatically add any |
| 35 | # dependencies found. Also stores the package name so anyone else using this library |
| 36 | # knows which package to depend on. |
| 37 | # |
| 38 | # i) package_do_pkgconfig - Keep track of which packages need and provide which .pc files |
| 39 | # |
| 40 | # j) read_shlibdeps - Reads the stored shlibs information into the metadata |
| 41 | # |
| 42 | # k) package_depchains - Adds automatic dependencies to -dbg and -dev packages |
| 43 | # |
| 44 | # l) emit_pkgdata - saves the packaging data into PKGDATA_DIR for use in later |
| 45 | # packaging steps |
| 46 | |
| 47 | inherit packagedata |
| 48 | inherit chrpath |
| 49 | inherit package_pkgdata |
| 50 | inherit insane |
| 51 | |
| 52 | PKGD = "${WORKDIR}/package" |
| 53 | PKGDEST = "${WORKDIR}/packages-split" |
| 54 | |
| 55 | LOCALE_SECTION ?= '' |
| 56 | |
| 57 | ALL_MULTILIB_PACKAGE_ARCHS = "${@all_multilib_tune_values(d, 'PACKAGE_ARCHS')}" |
| 58 | |
| 59 | # rpm is used for the per-file dependency identification |
| 60 | # dwarfsrcfiles is used to determine the list of debug source files |
| 61 | PACKAGE_DEPENDS += "rpm-native dwarfsrcfiles-native" |
| 62 | |
| 63 | |
| 64 | # If your postinstall can execute at rootfs creation time rather than on |
| 65 | # target but depends on a native/cross tool in order to execute, you need to |
| 66 | # list that tool in PACKAGE_WRITE_DEPS. Target package dependencies belong |
| 67 | # in the package dependencies as normal, this is just for native/cross support |
| 68 | # tools at rootfs build time. |
| 69 | PACKAGE_WRITE_DEPS ??= "" |
| 70 | |
| 71 | def legitimize_package_name(s): |
Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame] | 72 | return oe.package.legitimize_package_name(s) |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 73 | |
| 74 | def do_split_packages(d, root, file_regex, output_pattern, description, postinst=None, recursive=False, hook=None, extra_depends=None, aux_files_pattern=None, postrm=None, allow_dirs=False, prepend=False, match_path=False, aux_files_pattern_verbatim=None, allow_links=False, summary=None): |
| 75 | """ |
| 76 | Used in .bb files to split up dynamically generated subpackages of a |
| 77 | given package, usually plugins or modules. |
| 78 | |
| 79 | Arguments: |
| 80 | root -- the path in which to search |
| 81 | file_regex -- regular expression to match searched files. Use |
| 82 | parentheses () to mark the part of this expression |
| 83 | that should be used to derive the module name (to be |
| 84 | substituted where %s is used in other function |
| 85 | arguments as noted below) |
| 86 | output_pattern -- pattern to use for the package names. Must include %s. |
| 87 | description -- description to set for each package. Must include %s. |
| 88 | postinst -- postinstall script to use for all packages (as a |
| 89 | string) |
| 90 | recursive -- True to perform a recursive search - default False |
| 91 | hook -- a hook function to be called for every match. The |
| 92 | function will be called with the following arguments |
| 93 | (in the order listed): |
| 94 | f: full path to the file/directory match |
| 95 | pkg: the package name |
| 96 | file_regex: as above |
| 97 | output_pattern: as above |
| 98 | modulename: the module name derived using file_regex |
| 99 | extra_depends -- extra runtime dependencies (RDEPENDS) to be set for |
| 100 | all packages. The default value of None causes a |
| 101 | dependency on the main package (${PN}) - if you do |
| 102 | not want this, pass '' for this parameter. |
| 103 | aux_files_pattern -- extra item(s) to be added to FILES for each |
| 104 | package. Can be a single string item or a list of |
| 105 | strings for multiple items. Must include %s. |
| 106 | postrm -- postrm script to use for all packages (as a string) |
| 107 | allow_dirs -- True allow directories to be matched - default False |
| 108 | prepend -- if True, prepend created packages to PACKAGES instead |
| 109 | of the default False which appends them |
| 110 | match_path -- match file_regex on the whole relative path to the |
| 111 | root rather than just the file name |
| 112 | aux_files_pattern_verbatim -- extra item(s) to be added to FILES for |
| 113 | each package, using the actual derived module name |
| 114 | rather than converting it to something legal for a |
| 115 | package name. Can be a single string item or a list |
| 116 | of strings for multiple items. Must include %s. |
| 117 | allow_links -- True to allow symlinks to be matched - default False |
| 118 | summary -- Summary to set for each package. Must include %s; |
| 119 | defaults to description if not set. |
| 120 | |
| 121 | """ |
| 122 | |
| 123 | dvar = d.getVar('PKGD') |
| 124 | root = d.expand(root) |
| 125 | output_pattern = d.expand(output_pattern) |
| 126 | extra_depends = d.expand(extra_depends) |
| 127 | |
| 128 | # If the root directory doesn't exist, don't error out later but silently do |
| 129 | # no splitting. |
| 130 | if not os.path.exists(dvar + root): |
| 131 | return [] |
| 132 | |
| 133 | ml = d.getVar("MLPREFIX") |
| 134 | if ml: |
| 135 | if not output_pattern.startswith(ml): |
| 136 | output_pattern = ml + output_pattern |
| 137 | |
| 138 | newdeps = [] |
| 139 | for dep in (extra_depends or "").split(): |
| 140 | if dep.startswith(ml): |
| 141 | newdeps.append(dep) |
| 142 | else: |
| 143 | newdeps.append(ml + dep) |
| 144 | if newdeps: |
| 145 | extra_depends = " ".join(newdeps) |
| 146 | |
| 147 | |
| 148 | packages = d.getVar('PACKAGES').split() |
| 149 | split_packages = set() |
| 150 | |
| 151 | if postinst: |
| 152 | postinst = '#!/bin/sh\n' + postinst + '\n' |
| 153 | if postrm: |
| 154 | postrm = '#!/bin/sh\n' + postrm + '\n' |
| 155 | if not recursive: |
| 156 | objs = os.listdir(dvar + root) |
| 157 | else: |
| 158 | objs = [] |
| 159 | for walkroot, dirs, files in os.walk(dvar + root): |
| 160 | for file in files: |
| 161 | relpath = os.path.join(walkroot, file).replace(dvar + root + '/', '', 1) |
| 162 | if relpath: |
| 163 | objs.append(relpath) |
| 164 | |
| 165 | if extra_depends == None: |
| 166 | extra_depends = d.getVar("PN") |
| 167 | |
| 168 | if not summary: |
| 169 | summary = description |
| 170 | |
| 171 | for o in sorted(objs): |
| 172 | import re, stat |
| 173 | if match_path: |
| 174 | m = re.match(file_regex, o) |
| 175 | else: |
| 176 | m = re.match(file_regex, os.path.basename(o)) |
| 177 | |
| 178 | if not m: |
| 179 | continue |
| 180 | f = os.path.join(dvar + root, o) |
| 181 | mode = os.lstat(f).st_mode |
| 182 | if not (stat.S_ISREG(mode) or (allow_links and stat.S_ISLNK(mode)) or (allow_dirs and stat.S_ISDIR(mode))): |
| 183 | continue |
Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame] | 184 | on = oe.package.legitimize_package_name(m.group(1)) |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 185 | pkg = output_pattern % on |
| 186 | split_packages.add(pkg) |
| 187 | if not pkg in packages: |
| 188 | if prepend: |
| 189 | packages = [pkg] + packages |
| 190 | else: |
| 191 | packages.append(pkg) |
| 192 | oldfiles = d.getVar('FILES:' + pkg) |
| 193 | newfile = os.path.join(root, o) |
| 194 | # These names will be passed through glob() so if the filename actually |
| 195 | # contains * or ? (rare, but possible) we need to handle that specially |
| 196 | newfile = newfile.replace('*', '[*]') |
| 197 | newfile = newfile.replace('?', '[?]') |
| 198 | if not oldfiles: |
| 199 | the_files = [newfile] |
| 200 | if aux_files_pattern: |
| 201 | if type(aux_files_pattern) is list: |
| 202 | for fp in aux_files_pattern: |
| 203 | the_files.append(fp % on) |
| 204 | else: |
| 205 | the_files.append(aux_files_pattern % on) |
| 206 | if aux_files_pattern_verbatim: |
| 207 | if type(aux_files_pattern_verbatim) is list: |
| 208 | for fp in aux_files_pattern_verbatim: |
| 209 | the_files.append(fp % m.group(1)) |
| 210 | else: |
| 211 | the_files.append(aux_files_pattern_verbatim % m.group(1)) |
| 212 | d.setVar('FILES:' + pkg, " ".join(the_files)) |
| 213 | else: |
| 214 | d.setVar('FILES:' + pkg, oldfiles + " " + newfile) |
| 215 | if extra_depends != '': |
| 216 | d.appendVar('RDEPENDS:' + pkg, ' ' + extra_depends) |
| 217 | if not d.getVar('DESCRIPTION:' + pkg): |
| 218 | d.setVar('DESCRIPTION:' + pkg, description % on) |
| 219 | if not d.getVar('SUMMARY:' + pkg): |
| 220 | d.setVar('SUMMARY:' + pkg, summary % on) |
| 221 | if postinst: |
| 222 | d.setVar('pkg_postinst:' + pkg, postinst) |
| 223 | if postrm: |
| 224 | d.setVar('pkg_postrm:' + pkg, postrm) |
| 225 | if callable(hook): |
| 226 | hook(f, pkg, file_regex, output_pattern, m.group(1)) |
| 227 | |
| 228 | d.setVar('PACKAGES', ' '.join(packages)) |
| 229 | return list(split_packages) |
| 230 | |
| 231 | PACKAGE_DEPENDS += "file-native" |
| 232 | |
| 233 | python () { |
| 234 | if d.getVar('PACKAGES') != '': |
| 235 | deps = "" |
| 236 | for dep in (d.getVar('PACKAGE_DEPENDS') or "").split(): |
| 237 | deps += " %s:do_populate_sysroot" % dep |
| 238 | if d.getVar('PACKAGE_MINIDEBUGINFO') == '1': |
| 239 | deps += ' xz-native:do_populate_sysroot' |
| 240 | d.appendVarFlag('do_package', 'depends', deps) |
| 241 | |
| 242 | # shlibs requires any DEPENDS to have already packaged for the *.list files |
| 243 | d.appendVarFlag('do_package', 'deptask', " do_packagedata") |
| 244 | } |
| 245 | |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 246 | |
| 247 | PRSERV_ACTIVE = "${@bool(d.getVar("PRSERV_HOST"))}" |
| 248 | PRSERV_ACTIVE[vardepvalue] = "${PRSERV_ACTIVE}" |
| 249 | package_get_auto_pr[vardepsexclude] = "BB_TASKDEPDATA" |
| 250 | package_get_auto_pr[vardeps] += "PRSERV_ACTIVE" |
| 251 | python package_get_auto_pr() { |
| 252 | import oe.prservice |
| 253 | |
| 254 | def get_do_package_hash(pn): |
| 255 | if d.getVar("BB_RUNTASK") != "do_package": |
| 256 | taskdepdata = d.getVar("BB_TASKDEPDATA", False) |
| 257 | for dep in taskdepdata: |
| 258 | if taskdepdata[dep][1] == "do_package" and taskdepdata[dep][0] == pn: |
| 259 | return taskdepdata[dep][6] |
| 260 | return None |
| 261 | |
| 262 | # Support per recipe PRSERV_HOST |
| 263 | pn = d.getVar('PN') |
| 264 | host = d.getVar("PRSERV_HOST_" + pn) |
| 265 | if not (host is None): |
| 266 | d.setVar("PRSERV_HOST", host) |
| 267 | |
| 268 | pkgv = d.getVar("PKGV") |
| 269 | |
| 270 | # PR Server not active, handle AUTOINC |
| 271 | if not d.getVar('PRSERV_HOST'): |
| 272 | d.setVar("PRSERV_PV_AUTOINC", "0") |
| 273 | return |
| 274 | |
| 275 | auto_pr = None |
| 276 | pv = d.getVar("PV") |
| 277 | version = d.getVar("PRAUTOINX") |
| 278 | pkgarch = d.getVar("PACKAGE_ARCH") |
| 279 | checksum = get_do_package_hash(pn) |
| 280 | |
| 281 | # If do_package isn't in the dependencies, we can't get the checksum... |
| 282 | if not checksum: |
| 283 | bb.warn('Task %s requested do_package unihash, but it was not available.' % d.getVar('BB_RUNTASK')) |
| 284 | #taskdepdata = d.getVar("BB_TASKDEPDATA", False) |
| 285 | #for dep in taskdepdata: |
| 286 | # bb.warn('%s:%s = %s' % (taskdepdata[dep][0], taskdepdata[dep][1], taskdepdata[dep][6])) |
| 287 | return |
| 288 | |
| 289 | if d.getVar('PRSERV_LOCKDOWN'): |
| 290 | auto_pr = d.getVar('PRAUTO_' + version + '_' + pkgarch) or d.getVar('PRAUTO_' + version) or None |
| 291 | if auto_pr is None: |
| 292 | bb.fatal("Can NOT get PRAUTO from lockdown exported file") |
| 293 | d.setVar('PRAUTO',str(auto_pr)) |
| 294 | return |
| 295 | |
| 296 | try: |
| 297 | conn = oe.prservice.prserv_make_conn(d) |
| 298 | if conn is not None: |
| 299 | if "AUTOINC" in pkgv: |
| 300 | srcpv = bb.fetch2.get_srcrev(d) |
| 301 | base_ver = "AUTOINC-%s" % version[:version.find(srcpv)] |
| 302 | value = conn.getPR(base_ver, pkgarch, srcpv) |
| 303 | d.setVar("PRSERV_PV_AUTOINC", str(value)) |
| 304 | |
| 305 | auto_pr = conn.getPR(version, pkgarch, checksum) |
| 306 | conn.close() |
| 307 | except Exception as e: |
| 308 | bb.fatal("Can NOT get PRAUTO, exception %s" % str(e)) |
| 309 | if auto_pr is None: |
| 310 | bb.fatal("Can NOT get PRAUTO from remote PR service") |
| 311 | d.setVar('PRAUTO',str(auto_pr)) |
| 312 | } |
| 313 | |
| 314 | # |
| 315 | # Package functions suitable for inclusion in PACKAGEFUNCS |
| 316 | # |
| 317 | |
| 318 | python package_convert_pr_autoinc() { |
| 319 | pkgv = d.getVar("PKGV") |
| 320 | |
| 321 | # Adjust pkgv as necessary... |
| 322 | if 'AUTOINC' in pkgv: |
| 323 | d.setVar("PKGV", pkgv.replace("AUTOINC", "${PRSERV_PV_AUTOINC}")) |
| 324 | |
| 325 | # Change PRSERV_PV_AUTOINC and EXTENDPRAUTO usage to special values |
| 326 | d.setVar('PRSERV_PV_AUTOINC', '@PRSERV_PV_AUTOINC@') |
| 327 | d.setVar('EXTENDPRAUTO', '@EXTENDPRAUTO@') |
| 328 | } |
| 329 | |
| 330 | LOCALEBASEPN ??= "${PN}" |
| 331 | |
| 332 | python package_do_split_locales() { |
Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame] | 333 | oe.package.split_locales(d) |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 334 | } |
| 335 | |
| 336 | python perform_packagecopy () { |
| 337 | import subprocess |
| 338 | import shutil |
| 339 | |
| 340 | dest = d.getVar('D') |
| 341 | dvar = d.getVar('PKGD') |
| 342 | |
| 343 | # Start by package population by taking a copy of the installed |
| 344 | # files to operate on |
| 345 | # Preserve sparse files and hard links |
| 346 | cmd = 'tar --exclude=./sysroot-only -cf - -C %s -p -S . | tar -xf - -C %s' % (dest, dvar) |
| 347 | subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) |
| 348 | |
| 349 | # replace RPATHs for the nativesdk binaries, to make them relocatable |
| 350 | if bb.data.inherits_class('nativesdk', d) or bb.data.inherits_class('cross-canadian', d): |
| 351 | rpath_replace (dvar, d) |
| 352 | } |
| 353 | perform_packagecopy[cleandirs] = "${PKGD}" |
| 354 | perform_packagecopy[dirs] = "${PKGD}" |
| 355 | |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 356 | python populate_packages () { |
Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame] | 357 | oe.package.populate_packages(d) |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 358 | } |
| 359 | populate_packages[dirs] = "${D}" |
| 360 | |
| 361 | python package_fixsymlinks () { |
Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame] | 362 | oe.package.process_fixsymlinks(pkgfiles, d) |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 363 | } |
| 364 | |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 365 | python package_package_name_hook() { |
| 366 | """ |
| 367 | A package_name_hook function can be used to rewrite the package names by |
| 368 | changing PKG. For an example, see debian.bbclass. |
| 369 | """ |
| 370 | pass |
| 371 | } |
| 372 | |
| 373 | EXPORT_FUNCTIONS package_name_hook |
| 374 | |
| 375 | |
| 376 | PKGDESTWORK = "${WORKDIR}/pkgdata" |
| 377 | |
| 378 | PKGDATA_VARS = "PN PE PV PR PKGE PKGV PKGR LICENSE DESCRIPTION SUMMARY RDEPENDS RPROVIDES RRECOMMENDS RSUGGESTS RREPLACES RCONFLICTS SECTION PKG ALLOW_EMPTY FILES CONFFILES FILES_INFO PACKAGE_ADD_METADATA pkg_postinst pkg_postrm pkg_preinst pkg_prerm" |
| 379 | |
| 380 | python emit_pkgdata() { |
Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame] | 381 | import oe.packagedata |
| 382 | oe.packagedata.emit_pkgdata(pkgfiles, d) |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 383 | } |
| 384 | emit_pkgdata[dirs] = "${PKGDESTWORK}/runtime ${PKGDESTWORK}/runtime-reverse ${PKGDESTWORK}/runtime-rprovides ${PKGDESTWORK}/extended" |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 385 | |
| 386 | ldconfig_postinst_fragment() { |
| 387 | if [ x"$D" = "x" ]; then |
| 388 | if [ -x /sbin/ldconfig ]; then /sbin/ldconfig ; fi |
| 389 | fi |
| 390 | } |
| 391 | |
| 392 | RPMDEPS = "${STAGING_LIBDIR_NATIVE}/rpm/rpmdeps --alldeps --define '__font_provides %{nil}'" |
| 393 | |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 394 | python package_do_filedeps() { |
Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame] | 395 | oe.package.process_filedeps(pkgfiles, d) |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 396 | } |
| 397 | |
| 398 | SHLIBSDIRS = "${WORKDIR_PKGDATA}/${MLPREFIX}shlibs2" |
| 399 | SHLIBSWORKDIR = "${PKGDESTWORK}/${MLPREFIX}shlibs2" |
| 400 | |
| 401 | python package_do_shlibs() { |
Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame] | 402 | oe.package.process_shlibs(pkgfiles, d) |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 403 | } |
| 404 | |
| 405 | python package_do_pkgconfig () { |
Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame] | 406 | oe.package.process_pkgconfig(pkgfiles, d) |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 407 | } |
| 408 | |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 409 | python read_shlibdeps () { |
Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame] | 410 | pkglibdeps = oe.package.read_libdep_files(d) |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 411 | |
| 412 | packages = d.getVar('PACKAGES').split() |
| 413 | for pkg in packages: |
| 414 | rdepends = bb.utils.explode_dep_versions2(d.getVar('RDEPENDS:' + pkg) or "") |
| 415 | for dep in sorted(pkglibdeps[pkg]): |
| 416 | # Add the dep if it's not already there, or if no comparison is set |
| 417 | if dep not in rdepends: |
| 418 | rdepends[dep] = [] |
| 419 | for v in pkglibdeps[pkg][dep]: |
| 420 | if v not in rdepends[dep]: |
| 421 | rdepends[dep].append(v) |
| 422 | d.setVar('RDEPENDS:' + pkg, bb.utils.join_deps(rdepends, commasep=False)) |
| 423 | } |
| 424 | |
| 425 | python package_depchains() { |
Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame] | 426 | oe.package.process_depchains(pkgfiles, d) |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 427 | } |
| 428 | |
| 429 | # Since bitbake can't determine which variables are accessed during package |
| 430 | # iteration, we need to list them here: |
| 431 | PACKAGEVARS = "FILES RDEPENDS RRECOMMENDS SUMMARY DESCRIPTION RSUGGESTS RPROVIDES RCONFLICTS PKG ALLOW_EMPTY pkg_postinst pkg_postrm pkg_postinst_ontarget INITSCRIPT_NAME INITSCRIPT_PARAMS DEBIAN_NOAUTONAME ALTERNATIVE PKGE PKGV PKGR USERADD_PARAM GROUPADD_PARAM CONFFILES SYSTEMD_SERVICE LICENSE SECTION pkg_preinst pkg_prerm RREPLACES GROUPMEMS_PARAM SYSTEMD_AUTO_ENABLE SKIP_FILEDEPS PRIVATE_LIBS PACKAGE_ADD_METADATA" |
| 432 | |
| 433 | def gen_packagevar(d, pkgvars="PACKAGEVARS"): |
| 434 | ret = [] |
| 435 | pkgs = (d.getVar("PACKAGES") or "").split() |
| 436 | vars = (d.getVar(pkgvars) or "").split() |
| 437 | for v in vars: |
| 438 | ret.append(v) |
| 439 | for p in pkgs: |
| 440 | for v in vars: |
| 441 | ret.append(v + ":" + p) |
| 442 | |
| 443 | # Ensure that changes to INCOMPATIBLE_LICENSE re-run do_package for |
| 444 | # affected recipes. |
| 445 | ret.append('_exclude_incompatible-%s' % p) |
| 446 | return " ".join(ret) |
| 447 | |
Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame] | 448 | |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 449 | # Functions for setting up PKGD |
Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame] | 450 | PACKAGE_PREPROCESS_FUNCS ?= "" |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 451 | # Functions which split PKGD up into separate packages |
| 452 | PACKAGESPLITFUNCS ?= " \ |
| 453 | package_do_split_locales \ |
| 454 | populate_packages" |
| 455 | # Functions which process metadata based on split packages |
| 456 | PACKAGEFUNCS += " \ |
| 457 | package_fixsymlinks \ |
| 458 | package_name_hook \ |
| 459 | package_do_filedeps \ |
| 460 | package_do_shlibs \ |
| 461 | package_do_pkgconfig \ |
| 462 | read_shlibdeps \ |
| 463 | package_depchains \ |
| 464 | emit_pkgdata" |
| 465 | |
| 466 | python do_package () { |
| 467 | # Change the following version to cause sstate to invalidate the package |
| 468 | # cache. This is useful if an item this class depends on changes in a |
| 469 | # way that the output of this class changes. rpmdeps is a good example |
| 470 | # as any change to rpmdeps requires this to be rerun. |
| 471 | # PACKAGE_BBCLASS_VERSION = "4" |
| 472 | |
| 473 | # Init cachedpath |
| 474 | global cpath |
| 475 | cpath = oe.cachedpath.CachedPath() |
| 476 | |
| 477 | ########################################################################### |
| 478 | # Sanity test the setup |
| 479 | ########################################################################### |
| 480 | |
| 481 | packages = (d.getVar('PACKAGES') or "").split() |
| 482 | if len(packages) < 1: |
| 483 | bb.debug(1, "No packages to build, skipping do_package") |
| 484 | return |
| 485 | |
| 486 | workdir = d.getVar('WORKDIR') |
| 487 | outdir = d.getVar('DEPLOY_DIR') |
| 488 | dest = d.getVar('D') |
| 489 | dvar = d.getVar('PKGD') |
| 490 | pn = d.getVar('PN') |
| 491 | |
| 492 | if not workdir or not outdir or not dest or not dvar or not pn: |
| 493 | msg = "WORKDIR, DEPLOY_DIR, D, PN and PKGD all must be defined, unable to package" |
| 494 | oe.qa.handle_error("var-undefined", msg, d) |
| 495 | return |
| 496 | |
| 497 | bb.build.exec_func("package_convert_pr_autoinc", d) |
| 498 | |
| 499 | ########################################################################### |
| 500 | # Optimisations |
| 501 | ########################################################################### |
| 502 | |
| 503 | # Continually expanding complex expressions is inefficient, particularly |
| 504 | # when we write to the datastore and invalidate the expansion cache. This |
| 505 | # code pre-expands some frequently used variables |
| 506 | |
| 507 | def expandVar(x, d): |
| 508 | d.setVar(x, d.getVar(x)) |
| 509 | |
| 510 | for x in 'PN', 'PV', 'BPN', 'TARGET_SYS', 'EXTENDPRAUTO': |
| 511 | expandVar(x, d) |
| 512 | |
| 513 | ########################################################################### |
| 514 | # Setup PKGD (from D) |
| 515 | ########################################################################### |
| 516 | |
Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame] | 517 | bb.build.exec_func("package_prepare_pkgdata", d) |
| 518 | bb.build.exec_func("perform_packagecopy", d) |
| 519 | for f in (d.getVar('PACKAGE_PREPROCESS_FUNCS') or '').split(): |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 520 | bb.build.exec_func(f, d) |
Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame] | 521 | oe.package.process_split_and_strip_files(d) |
| 522 | oe.package.fixup_perms(d) |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 523 | |
| 524 | ########################################################################### |
| 525 | # Split up PKGD into PKGDEST |
| 526 | ########################################################################### |
| 527 | |
| 528 | cpath = oe.cachedpath.CachedPath() |
| 529 | |
| 530 | for f in (d.getVar('PACKAGESPLITFUNCS') or '').split(): |
| 531 | bb.build.exec_func(f, d) |
| 532 | |
| 533 | ########################################################################### |
| 534 | # Process PKGDEST |
| 535 | ########################################################################### |
| 536 | |
| 537 | # Build global list of files in each split package |
| 538 | global pkgfiles |
| 539 | pkgfiles = {} |
| 540 | packages = d.getVar('PACKAGES').split() |
| 541 | pkgdest = d.getVar('PKGDEST') |
| 542 | for pkg in packages: |
| 543 | pkgfiles[pkg] = [] |
| 544 | for walkroot, dirs, files in cpath.walk(pkgdest + "/" + pkg): |
| 545 | for file in files: |
| 546 | pkgfiles[pkg].append(walkroot + os.sep + file) |
| 547 | |
| 548 | for f in (d.getVar('PACKAGEFUNCS') or '').split(): |
| 549 | bb.build.exec_func(f, d) |
| 550 | |
| 551 | oe.qa.exit_if_errors(d) |
| 552 | } |
| 553 | |
| 554 | do_package[dirs] = "${SHLIBSWORKDIR} ${D}" |
Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame] | 555 | do_package[vardeps] += "${PACKAGE_PREPROCESS_FUNCS} ${PACKAGESPLITFUNCS} ${PACKAGEFUNCS} ${@gen_packagevar(d)}" |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 556 | addtask package after do_install |
| 557 | |
| 558 | SSTATETASKS += "do_package" |
| 559 | do_package[cleandirs] = "${PKGDEST} ${PKGDESTWORK}" |
| 560 | do_package[sstate-plaindirs] = "${PKGD} ${PKGDEST} ${PKGDESTWORK}" |
| 561 | do_package_setscene[dirs] = "${STAGING_DIR}" |
| 562 | |
| 563 | python do_package_setscene () { |
| 564 | sstate_setscene(d) |
| 565 | } |
| 566 | addtask do_package_setscene |
| 567 | |
| 568 | # Copy from PKGDESTWORK to tempdirectory as tempdirectory can be cleaned at both |
| 569 | # do_package_setscene and do_packagedata_setscene leading to races |
| 570 | python do_packagedata () { |
| 571 | bb.build.exec_func("package_get_auto_pr", d) |
| 572 | |
| 573 | src = d.expand("${PKGDESTWORK}") |
| 574 | dest = d.expand("${WORKDIR}/pkgdata-pdata-input") |
| 575 | oe.path.copyhardlinktree(src, dest) |
| 576 | |
| 577 | bb.build.exec_func("packagedata_translate_pr_autoinc", d) |
| 578 | } |
| 579 | do_packagedata[cleandirs] += "${WORKDIR}/pkgdata-pdata-input" |
| 580 | |
| 581 | # Translate the EXTENDPRAUTO and AUTOINC to the final values |
| 582 | packagedata_translate_pr_autoinc() { |
| 583 | find ${WORKDIR}/pkgdata-pdata-input -type f | xargs --no-run-if-empty \ |
| 584 | sed -e 's,@PRSERV_PV_AUTOINC@,${PRSERV_PV_AUTOINC},g' \ |
| 585 | -e 's,@EXTENDPRAUTO@,${EXTENDPRAUTO},g' -i |
| 586 | } |
| 587 | |
| 588 | addtask packagedata before do_build after do_package |
| 589 | |
| 590 | SSTATETASKS += "do_packagedata" |
| 591 | do_packagedata[sstate-inputdirs] = "${WORKDIR}/pkgdata-pdata-input" |
| 592 | do_packagedata[sstate-outputdirs] = "${PKGDATA_DIR}" |
| 593 | do_packagedata[stamp-extra-info] = "${MACHINE_ARCH}" |
| 594 | |
| 595 | python do_packagedata_setscene () { |
| 596 | sstate_setscene(d) |
| 597 | } |
| 598 | addtask do_packagedata_setscene |
| 599 | |