1# These directories will be staged in the sysroot 2SYSROOT_DIRS = " \ 3 ${includedir} \ 4 ${libdir} \ 5 ${base_libdir} \ 6 ${nonarch_base_libdir} \ 7 ${datadir} \ 8 /sysroot-only \ 9" 10 11# These directories are also staged in the sysroot when they contain files that 12# are usable on the build system 13SYSROOT_DIRS_NATIVE = " \ 14 ${bindir} \ 15 ${sbindir} \ 16 ${base_bindir} \ 17 ${base_sbindir} \ 18 ${libexecdir} \ 19 ${sysconfdir} \ 20 ${localstatedir} \ 21" 22SYSROOT_DIRS:append:class-native = " ${SYSROOT_DIRS_NATIVE}" 23SYSROOT_DIRS:append:class-cross = " ${SYSROOT_DIRS_NATIVE}" 24SYSROOT_DIRS:append:class-crosssdk = " ${SYSROOT_DIRS_NATIVE}" 25 26# These directories will not be staged in the sysroot 27SYSROOT_DIRS_IGNORE = " \ 28 ${mandir} \ 29 ${docdir} \ 30 ${infodir} \ 31 ${datadir}/X11/locale \ 32 ${datadir}/applications \ 33 ${datadir}/bash-completion \ 34 ${datadir}/fonts \ 35 ${datadir}/gtk-doc/html \ 36 ${datadir}/installed-tests \ 37 ${datadir}/locale \ 38 ${datadir}/pixmaps \ 39 ${datadir}/terminfo \ 40 ${libdir}/${BPN}/ptest \ 41" 42 43sysroot_stage_dir() { 44 src="$1" 45 dest="$2" 46 # if the src doesn't exist don't do anything 47 if [ ! -d "$src" ]; then 48 return 49 fi 50 51 mkdir -p "$dest" 52 rdest=$(realpath --relative-to="$src" "$dest") 53 ( 54 cd $src 55 find . -print0 | cpio --null -pdlu $rdest 56 ) 57} 58 59sysroot_stage_dirs() { 60 from="$1" 61 to="$2" 62 63 for dir in ${SYSROOT_DIRS}; do 64 sysroot_stage_dir "$from$dir" "$to$dir" 65 done 66 67 # Remove directories we do not care about 68 for dir in ${SYSROOT_DIRS_IGNORE}; do 69 rm -rf "$to$dir" 70 done 71} 72 73sysroot_stage_all() { 74 sysroot_stage_dirs ${D} ${SYSROOT_DESTDIR} 75} 76 77python sysroot_strip () { 78 inhibit_sysroot = d.getVar('INHIBIT_SYSROOT_STRIP') 79 if inhibit_sysroot and oe.types.boolean(inhibit_sysroot): 80 return 81 82 dstdir = d.getVar('SYSROOT_DESTDIR') 83 pn = d.getVar('PN') 84 libdir = d.getVar("libdir") 85 base_libdir = d.getVar("base_libdir") 86 qa_already_stripped = 'already-stripped' in (d.getVar('INSANE_SKIP:' + pn) or "").split() 87 strip_cmd = d.getVar("STRIP") 88 89 oe.package.strip_execs(pn, dstdir, strip_cmd, libdir, base_libdir, d, 90 qa_already_stripped=qa_already_stripped) 91} 92 93do_populate_sysroot[dirs] = "${SYSROOT_DESTDIR}" 94 95addtask populate_sysroot after do_install 96 97SYSROOT_PREPROCESS_FUNCS ?= "" 98SYSROOT_DESTDIR = "${WORKDIR}/sysroot-destdir" 99 100python do_populate_sysroot () { 101 # SYSROOT 'version' 2 102 bb.build.exec_func("sysroot_stage_all", d) 103 bb.build.exec_func("sysroot_strip", d) 104 for f in (d.getVar('SYSROOT_PREPROCESS_FUNCS') or '').split(): 105 bb.build.exec_func(f, d) 106 pn = d.getVar("PN") 107 multiprov = d.getVar("BB_MULTI_PROVIDER_ALLOWED").split() 108 provdir = d.expand("${SYSROOT_DESTDIR}${base_prefix}/sysroot-providers/") 109 bb.utils.mkdirhier(provdir) 110 for p in d.getVar("PROVIDES").split(): 111 if p in multiprov: 112 continue 113 p = p.replace("/", "_") 114 with open(provdir + p, "w") as f: 115 f.write(pn) 116} 117 118do_populate_sysroot[vardeps] += "${SYSROOT_PREPROCESS_FUNCS}" 119do_populate_sysroot[vardepsexclude] += "BB_MULTI_PROVIDER_ALLOWED" 120 121POPULATESYSROOTDEPS = "" 122POPULATESYSROOTDEPS:class-target = "virtual/${MLPREFIX}${HOST_PREFIX}binutils:do_populate_sysroot" 123POPULATESYSROOTDEPS:class-nativesdk = "virtual/${HOST_PREFIX}binutils-crosssdk:do_populate_sysroot" 124do_populate_sysroot[depends] += "${POPULATESYSROOTDEPS}" 125 126SSTATETASKS += "do_populate_sysroot" 127do_populate_sysroot[cleandirs] = "${SYSROOT_DESTDIR}" 128do_populate_sysroot[sstate-inputdirs] = "${SYSROOT_DESTDIR}" 129do_populate_sysroot[sstate-outputdirs] = "${COMPONENTS_DIR}/${PACKAGE_ARCH}/${PN}" 130do_populate_sysroot[sstate-fixmedir] = "${COMPONENTS_DIR}/${PACKAGE_ARCH}/${PN}" 131 132python do_populate_sysroot_setscene () { 133 sstate_setscene(d) 134} 135addtask do_populate_sysroot_setscene 136 137def staging_copyfile(c, target, dest, postinsts, seendirs): 138 import errno 139 140 destdir = os.path.dirname(dest) 141 if destdir not in seendirs: 142 bb.utils.mkdirhier(destdir) 143 seendirs.add(destdir) 144 if "/usr/bin/postinst-" in c: 145 postinsts.append(dest) 146 if os.path.islink(c): 147 linkto = os.readlink(c) 148 if os.path.lexists(dest): 149 if not os.path.islink(dest): 150 raise OSError(errno.EEXIST, "Link %s already exists as a file" % dest, dest) 151 if os.readlink(dest) == linkto: 152 return dest 153 raise OSError(errno.EEXIST, "Link %s already exists to a different location? (%s vs %s)" % (dest, os.readlink(dest), linkto), dest) 154 os.symlink(linkto, dest) 155 #bb.warn(c) 156 else: 157 try: 158 os.link(c, dest) 159 except OSError as err: 160 if err.errno == errno.EXDEV: 161 bb.utils.copyfile(c, dest) 162 else: 163 raise 164 return dest 165 166def staging_copydir(c, target, dest, seendirs): 167 if dest not in seendirs: 168 bb.utils.mkdirhier(dest) 169 seendirs.add(dest) 170 171def staging_processfixme(fixme, target, recipesysroot, recipesysrootnative, d): 172 import subprocess 173 174 if not fixme: 175 return 176 cmd = "sed -e 's:^[^/]*/:%s/:g' %s | xargs sed -i -e 's:FIXMESTAGINGDIRTARGET:%s:g; s:FIXMESTAGINGDIRHOST:%s:g'" % (target, " ".join(fixme), recipesysroot, recipesysrootnative) 177 for fixmevar in ['PSEUDO_SYSROOT', 'HOSTTOOLS_DIR', 'PKGDATA_DIR', 'PSEUDO_LOCALSTATEDIR', 'LOGFIFO']: 178 fixme_path = d.getVar(fixmevar) 179 cmd += " -e 's:FIXME_%s:%s:g'" % (fixmevar, fixme_path) 180 bb.debug(2, cmd) 181 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) 182 183 184def staging_populate_sysroot_dir(targetsysroot, nativesysroot, native, d): 185 import glob 186 import subprocess 187 import errno 188 189 fixme = [] 190 postinsts = [] 191 seendirs = set() 192 stagingdir = d.getVar("STAGING_DIR") 193 if native: 194 pkgarchs = ['${BUILD_ARCH}', '${BUILD_ARCH}_*'] 195 targetdir = nativesysroot 196 else: 197 pkgarchs = ['${MACHINE_ARCH}'] 198 pkgarchs = pkgarchs + list(reversed(d.getVar("PACKAGE_EXTRA_ARCHS").split())) 199 pkgarchs.append('allarch') 200 targetdir = targetsysroot 201 202 bb.utils.mkdirhier(targetdir) 203 for pkgarch in pkgarchs: 204 for manifest in glob.glob(d.expand("${SSTATE_MANIFESTS}/manifest-%s-*.populate_sysroot" % pkgarch)): 205 if manifest.endswith("-initial.populate_sysroot"): 206 # skip libgcc-initial due to file overlap 207 continue 208 if not native and (manifest.endswith("-native.populate_sysroot") or "nativesdk-" in manifest): 209 continue 210 if native and not (manifest.endswith("-native.populate_sysroot") or manifest.endswith("-cross.populate_sysroot") or "-cross-" in manifest): 211 continue 212 tmanifest = targetdir + "/" + os.path.basename(manifest) 213 if os.path.exists(tmanifest): 214 continue 215 try: 216 os.link(manifest, tmanifest) 217 except OSError as err: 218 if err.errno == errno.EXDEV: 219 bb.utils.copyfile(manifest, tmanifest) 220 else: 221 raise 222 with open(manifest, "r") as f: 223 for l in f: 224 l = l.strip() 225 if l.endswith("/fixmepath"): 226 fixme.append(l) 227 continue 228 if l.endswith("/fixmepath.cmd"): 229 continue 230 dest = l.replace(stagingdir, "") 231 dest = targetdir + "/" + "/".join(dest.split("/")[3:]) 232 if l.endswith("/"): 233 staging_copydir(l, targetdir, dest, seendirs) 234 continue 235 try: 236 staging_copyfile(l, targetdir, dest, postinsts, seendirs) 237 except FileExistsError: 238 continue 239 240 staging_processfixme(fixme, targetdir, targetsysroot, nativesysroot, d) 241 for p in postinsts: 242 subprocess.check_output(p, shell=True, stderr=subprocess.STDOUT) 243 244# 245# Manifests here are complicated. The main sysroot area has the unpacked sstate 246# which us unrelocated and tracked by the main sstate manifests. Each recipe 247# specific sysroot has manifests for each dependency that is installed there. 248# The task hash is used to tell whether the data needs to be reinstalled. We 249# use a symlink to point to the currently installed hash. There is also a 250# "complete" stamp file which is used to mark if installation completed. If 251# something fails (e.g. a postinst), this won't get written and we would 252# remove and reinstall the dependency. This also means partially installed 253# dependencies should get cleaned up correctly. 254# 255 256python extend_recipe_sysroot() { 257 import copy 258 import subprocess 259 import errno 260 import collections 261 import glob 262 263 taskdepdata = d.getVar("BB_TASKDEPDATA", False) 264 mytaskname = d.getVar("BB_RUNTASK") 265 if mytaskname.endswith("_setscene"): 266 mytaskname = mytaskname.replace("_setscene", "") 267 workdir = d.getVar("WORKDIR") 268 #bb.warn(str(taskdepdata)) 269 pn = d.getVar("PN") 270 stagingdir = d.getVar("STAGING_DIR") 271 sharedmanifests = d.getVar("COMPONENTS_DIR") + "/manifests" 272 # only needed by multilib cross-canadian since it redefines RECIPE_SYSROOT 273 manifestprefix = d.getVar("RECIPE_SYSROOT_MANIFEST_SUBDIR") 274 if manifestprefix: 275 sharedmanifests = sharedmanifests + "/" + manifestprefix 276 recipesysroot = d.getVar("RECIPE_SYSROOT") 277 recipesysrootnative = d.getVar("RECIPE_SYSROOT_NATIVE") 278 279 # Detect bitbake -b usage 280 nodeps = d.getVar("BB_LIMITEDDEPS") or False 281 if nodeps: 282 lock = bb.utils.lockfile(recipesysroot + "/sysroot.lock") 283 staging_populate_sysroot_dir(recipesysroot, recipesysrootnative, True, d) 284 staging_populate_sysroot_dir(recipesysroot, recipesysrootnative, False, d) 285 bb.utils.unlockfile(lock) 286 return 287 288 start = None 289 configuredeps = [] 290 owntaskdeps = [] 291 for dep in taskdepdata: 292 data = taskdepdata[dep] 293 if data[1] == mytaskname and data[0] == pn: 294 start = dep 295 elif data[0] == pn: 296 owntaskdeps.append(data[1]) 297 if start is None: 298 bb.fatal("Couldn't find ourself in BB_TASKDEPDATA?") 299 300 # We need to figure out which sysroot files we need to expose to this task. 301 # This needs to match what would get restored from sstate, which is controlled 302 # ultimately by calls from bitbake to setscene_depvalid(). 303 # That function expects a setscene dependency tree. We build a dependency tree 304 # condensed to inter-sstate task dependencies, similar to that used by setscene 305 # tasks. We can then call into setscene_depvalid() and decide 306 # which dependencies we can "see" and should expose in the recipe specific sysroot. 307 setscenedeps = copy.deepcopy(taskdepdata) 308 309 start = set([start]) 310 311 sstatetasks = d.getVar("SSTATETASKS").split() 312 # Add recipe specific tasks referenced by setscene_depvalid() 313 sstatetasks.append("do_stash_locale") 314 sstatetasks.append("do_deploy") 315 316 def print_dep_tree(deptree): 317 data = "" 318 for dep in deptree: 319 deps = " " + "\n ".join(deptree[dep][3]) + "\n" 320 data = data + "%s:\n %s\n %s\n%s %s\n %s\n" % (deptree[dep][0], deptree[dep][1], deptree[dep][2], deps, deptree[dep][4], deptree[dep][5]) 321 return data 322 323 #bb.note("Full dep tree is:\n%s" % print_dep_tree(taskdepdata)) 324 325 #bb.note(" start2 is %s" % str(start)) 326 327 # If start is an sstate task (like do_package) we need to add in its direct dependencies 328 # else the code below won't recurse into them. 329 for dep in set(start): 330 for dep2 in setscenedeps[dep][3]: 331 start.add(dep2) 332 start.remove(dep) 333 334 #bb.note(" start3 is %s" % str(start)) 335 336 # Create collapsed do_populate_sysroot -> do_populate_sysroot tree 337 for dep in taskdepdata: 338 data = setscenedeps[dep] 339 if data[1] not in sstatetasks: 340 for dep2 in setscenedeps: 341 data2 = setscenedeps[dep2] 342 if dep in data2[3]: 343 data2[3].update(setscenedeps[dep][3]) 344 data2[3].remove(dep) 345 if dep in start: 346 start.update(setscenedeps[dep][3]) 347 start.remove(dep) 348 del setscenedeps[dep] 349 350 # Remove circular references 351 for dep in setscenedeps: 352 if dep in setscenedeps[dep][3]: 353 setscenedeps[dep][3].remove(dep) 354 355 #bb.note("Computed dep tree is:\n%s" % print_dep_tree(setscenedeps)) 356 #bb.note(" start is %s" % str(start)) 357 358 # Direct dependencies should be present and can be depended upon 359 for dep in sorted(set(start)): 360 if setscenedeps[dep][1] == "do_populate_sysroot": 361 if dep not in configuredeps: 362 configuredeps.append(dep) 363 bb.note("Direct dependencies are %s" % str(configuredeps)) 364 #bb.note(" or %s" % str(start)) 365 366 msgbuf = [] 367 # Call into setscene_depvalid for each sub-dependency and only copy sysroot files 368 # for ones that would be restored from sstate. 369 done = list(start) 370 next = list(start) 371 while next: 372 new = [] 373 for dep in next: 374 data = setscenedeps[dep] 375 for datadep in data[3]: 376 if datadep in done: 377 continue 378 taskdeps = {} 379 taskdeps[dep] = setscenedeps[dep][:2] 380 taskdeps[datadep] = setscenedeps[datadep][:2] 381 retval = setscene_depvalid(datadep, taskdeps, [], d, msgbuf) 382 if retval: 383 msgbuf.append("Skipping setscene dependency %s for installation into the sysroot" % datadep) 384 continue 385 done.append(datadep) 386 new.append(datadep) 387 if datadep not in configuredeps and setscenedeps[datadep][1] == "do_populate_sysroot": 388 configuredeps.append(datadep) 389 msgbuf.append("Adding dependency on %s" % setscenedeps[datadep][0]) 390 else: 391 msgbuf.append("Following dependency on %s" % setscenedeps[datadep][0]) 392 next = new 393 394 # This logging is too verbose for day to day use sadly 395 #bb.debug(2, "\n".join(msgbuf)) 396 397 depdir = recipesysrootnative + "/installeddeps" 398 bb.utils.mkdirhier(depdir) 399 bb.utils.mkdirhier(sharedmanifests) 400 401 lock = bb.utils.lockfile(recipesysroot + "/sysroot.lock") 402 403 fixme = {} 404 seendirs = set() 405 postinsts = [] 406 multilibs = {} 407 manifests = {} 408 # All files that we're going to be installing, to find conflicts. 409 fileset = {} 410 411 invalidate_tasks = set() 412 for f in os.listdir(depdir): 413 removed = [] 414 if not f.endswith(".complete"): 415 continue 416 f = depdir + "/" + f 417 if os.path.islink(f) and not os.path.exists(f): 418 bb.note("%s no longer exists, removing from sysroot" % f) 419 lnk = os.readlink(f.replace(".complete", "")) 420 sstate_clean_manifest(depdir + "/" + lnk, d, canrace=True, prefix=workdir) 421 os.unlink(f) 422 os.unlink(f.replace(".complete", "")) 423 removed.append(os.path.basename(f.replace(".complete", ""))) 424 425 # If we've removed files from the sysroot above, the task that installed them may still 426 # have a stamp file present for the task. This is probably invalid right now but may become 427 # valid again if the user were to change configuration back for example. Since we've removed 428 # the files a task might need, remove the stamp file too to force it to rerun. 429 # YOCTO #14790 430 if removed: 431 for i in glob.glob(depdir + "/index.*"): 432 if i.endswith("." + mytaskname): 433 continue 434 with open(i, "r") as f: 435 for l in f: 436 if l.startswith("TaskDeps:"): 437 continue 438 l = l.strip() 439 if l in removed: 440 invalidate_tasks.add(i.rsplit(".", 1)[1]) 441 break 442 for t in invalidate_tasks: 443 bb.note("Invalidating stamps for task %s" % t) 444 bb.build.clean_stamp(t, d) 445 446 installed = [] 447 for dep in configuredeps: 448 c = setscenedeps[dep][0] 449 if mytaskname in ["do_sdk_depends", "do_populate_sdk_ext"] and c.endswith("-initial"): 450 bb.note("Skipping initial setscene dependency %s for installation into the sysroot" % c) 451 continue 452 installed.append(c) 453 454 # We want to remove anything which this task previously installed but is no longer a dependency 455 taskindex = depdir + "/" + "index." + mytaskname 456 if os.path.exists(taskindex): 457 potential = [] 458 with open(taskindex, "r") as f: 459 for l in f: 460 l = l.strip() 461 if l not in installed: 462 fl = depdir + "/" + l 463 if not os.path.exists(fl): 464 # Was likely already uninstalled 465 continue 466 potential.append(l) 467 # We need to ensure no other task needs this dependency. We hold the sysroot 468 # lock so we ca search the indexes to check 469 if potential: 470 for i in glob.glob(depdir + "/index.*"): 471 if i.endswith("." + mytaskname): 472 continue 473 with open(i, "r") as f: 474 for l in f: 475 if l.startswith("TaskDeps:"): 476 prevtasks = l.split()[1:] 477 if mytaskname in prevtasks: 478 # We're a dependency of this task so we can clear items out the sysroot 479 break 480 l = l.strip() 481 if l in potential: 482 potential.remove(l) 483 for l in potential: 484 fl = depdir + "/" + l 485 bb.note("Task %s no longer depends on %s, removing from sysroot" % (mytaskname, l)) 486 lnk = os.readlink(fl) 487 sstate_clean_manifest(depdir + "/" + lnk, d, canrace=True, prefix=workdir) 488 os.unlink(fl) 489 os.unlink(fl + ".complete") 490 491 msg_exists = [] 492 msg_adding = [] 493 494 # Handle all removals first since files may move between recipes 495 for dep in configuredeps: 496 c = setscenedeps[dep][0] 497 if c not in installed: 498 continue 499 taskhash = setscenedeps[dep][5] 500 taskmanifest = depdir + "/" + c + "." + taskhash 501 502 if os.path.exists(depdir + "/" + c): 503 lnk = os.readlink(depdir + "/" + c) 504 if lnk == c + "." + taskhash and os.path.exists(depdir + "/" + c + ".complete"): 505 continue 506 else: 507 bb.note("%s exists in sysroot, but is stale (%s vs. %s), removing." % (c, lnk, c + "." + taskhash)) 508 sstate_clean_manifest(depdir + "/" + lnk, d, canrace=True, prefix=workdir) 509 os.unlink(depdir + "/" + c) 510 if os.path.lexists(depdir + "/" + c + ".complete"): 511 os.unlink(depdir + "/" + c + ".complete") 512 elif os.path.lexists(depdir + "/" + c): 513 os.unlink(depdir + "/" + c) 514 515 binfiles = {} 516 # Now handle installs 517 for dep in configuredeps: 518 c = setscenedeps[dep][0] 519 if c not in installed: 520 continue 521 taskhash = setscenedeps[dep][5] 522 taskmanifest = depdir + "/" + c + "." + taskhash 523 524 if os.path.exists(depdir + "/" + c): 525 lnk = os.readlink(depdir + "/" + c) 526 if lnk == c + "." + taskhash and os.path.exists(depdir + "/" + c + ".complete"): 527 msg_exists.append(c) 528 continue 529 530 msg_adding.append(c) 531 532 os.symlink(c + "." + taskhash, depdir + "/" + c) 533 534 manifest, d2 = oe.sstatesig.find_sstate_manifest(c, setscenedeps[dep][2], "populate_sysroot", d, multilibs) 535 if d2 is not d: 536 # If we don't do this, the recipe sysroot will be placed in the wrong WORKDIR for multilibs 537 # We need a consistent WORKDIR for the image 538 d2.setVar("WORKDIR", d.getVar("WORKDIR")) 539 destsysroot = d2.getVar("RECIPE_SYSROOT") 540 # We put allarch recipes into the default sysroot 541 if manifest and "allarch" in manifest: 542 destsysroot = d.getVar("RECIPE_SYSROOT") 543 544 native = False 545 if c.endswith("-native") or "-cross-" in c or "-crosssdk" in c: 546 native = True 547 548 if manifest: 549 newmanifest = collections.OrderedDict() 550 targetdir = destsysroot 551 if native: 552 targetdir = recipesysrootnative 553 if targetdir not in fixme: 554 fixme[targetdir] = [] 555 fm = fixme[targetdir] 556 557 with open(manifest, "r") as f: 558 manifests[dep] = manifest 559 for l in f: 560 l = l.strip() 561 if l.endswith("/fixmepath"): 562 fm.append(l) 563 continue 564 if l.endswith("/fixmepath.cmd"): 565 continue 566 dest = l.replace(stagingdir, "") 567 dest = "/" + "/".join(dest.split("/")[3:]) 568 newmanifest[l] = targetdir + dest 569 570 # Check if files have already been installed by another 571 # recipe and abort if they have, explaining what recipes are 572 # conflicting. 573 hashname = targetdir + dest 574 if not hashname.endswith("/"): 575 if hashname in fileset: 576 bb.fatal("The file %s is installed by both %s and %s, aborting" % (dest, c, fileset[hashname])) 577 else: 578 fileset[hashname] = c 579 580 # Having multiple identical manifests in each sysroot eats diskspace so 581 # create a shared pool of them and hardlink if we can. 582 # We create the manifest in advance so that if something fails during installation, 583 # or the build is interrupted, subsequent exeuction can cleanup. 584 sharedm = sharedmanifests + "/" + os.path.basename(taskmanifest) 585 if not os.path.exists(sharedm): 586 smlock = bb.utils.lockfile(sharedm + ".lock") 587 # Can race here. You'd think it just means we may not end up with all copies hardlinked to each other 588 # but python can lose file handles so we need to do this under a lock. 589 if not os.path.exists(sharedm): 590 with open(sharedm, 'w') as m: 591 for l in newmanifest: 592 dest = newmanifest[l] 593 m.write(dest.replace(workdir + "/", "") + "\n") 594 bb.utils.unlockfile(smlock) 595 try: 596 os.link(sharedm, taskmanifest) 597 except OSError as err: 598 if err.errno == errno.EXDEV: 599 bb.utils.copyfile(sharedm, taskmanifest) 600 else: 601 raise 602 # Finally actually install the files 603 for l in newmanifest: 604 dest = newmanifest[l] 605 if l.endswith("/"): 606 staging_copydir(l, targetdir, dest, seendirs) 607 continue 608 if "/bin/" in l or "/sbin/" in l: 609 # defer /*bin/* files until last in case they need libs 610 binfiles[l] = (targetdir, dest) 611 else: 612 staging_copyfile(l, targetdir, dest, postinsts, seendirs) 613 614 # Handle deferred binfiles 615 for l in binfiles: 616 (targetdir, dest) = binfiles[l] 617 staging_copyfile(l, targetdir, dest, postinsts, seendirs) 618 619 bb.note("Installed into sysroot: %s" % str(msg_adding)) 620 bb.note("Skipping as already exists in sysroot: %s" % str(msg_exists)) 621 622 for f in fixme: 623 staging_processfixme(fixme[f], f, recipesysroot, recipesysrootnative, d) 624 625 for p in postinsts: 626 subprocess.check_output(p, shell=True, stderr=subprocess.STDOUT) 627 628 for dep in manifests: 629 c = setscenedeps[dep][0] 630 os.symlink(manifests[dep], depdir + "/" + c + ".complete") 631 632 with open(taskindex, "w") as f: 633 f.write("TaskDeps: " + " ".join(owntaskdeps) + "\n") 634 for l in sorted(installed): 635 f.write(l + "\n") 636 637 bb.utils.unlockfile(lock) 638} 639extend_recipe_sysroot[vardepsexclude] += "MACHINE_ARCH PACKAGE_EXTRA_ARCHS SDK_ARCH BUILD_ARCH SDK_OS BB_TASKDEPDATA" 640 641do_prepare_recipe_sysroot[deptask] = "do_populate_sysroot" 642python do_prepare_recipe_sysroot () { 643 bb.build.exec_func("extend_recipe_sysroot", d) 644} 645addtask do_prepare_recipe_sysroot before do_configure after do_fetch 646 647python staging_taskhandler() { 648 bbtasks = e.tasklist 649 for task in bbtasks: 650 deps = d.getVarFlag(task, "depends") 651 if task == "do_configure" or (deps and "populate_sysroot" in deps): 652 d.prependVarFlag(task, "prefuncs", "extend_recipe_sysroot ") 653} 654staging_taskhandler[eventmask] = "bb.event.RecipeTaskPreProcess" 655addhandler staging_taskhandler 656 657 658# 659# Target build output, stored in do_populate_sysroot or do_package can depend 660# not only upon direct dependencies but also indirect ones. A good example is 661# linux-libc-headers. The toolchain depends on this but most target recipes do 662# not. There are some headers which are not used by the toolchain build and do 663# not change the toolchain task output, hence the task hashes can change without 664# changing the sysroot output of that recipe yet they can influence others. 665# 666# A specific example is rtc.h which can change rtcwake.c in util-linux but is not 667# used in the glibc or gcc build. To account for this, we need to account for the 668# populate_sysroot hashes in the task output hashes. 669# 670python target_add_sysroot_deps () { 671 current_task = "do_" + d.getVar("BB_CURRENTTASK") 672 if current_task not in ["do_populate_sysroot", "do_package"]: 673 return 674 675 pn = d.getVar("PN") 676 if pn.endswith("-native"): 677 return 678 679 taskdepdata = d.getVar("BB_TASKDEPDATA", False) 680 deps = {} 681 for dep in taskdepdata.values(): 682 if dep[1] == "do_populate_sysroot" and not dep[0].endswith(("-native", "-initial")) and "-cross-" not in dep[0] and dep[0] != pn: 683 deps[dep[0]] = dep[6] 684 685 d.setVar("HASHEQUIV_EXTRA_SIGDATA", "\n".join("%s: %s" % (k, deps[k]) for k in sorted(deps.keys()))) 686} 687SSTATECREATEFUNCS += "target_add_sysroot_deps" 688 689