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