staging.bbclass 23 KB

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