blob: 984051d6aa2809ba28110a5f5c4fb6f19f40b002 [file] [log] [blame]
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001# These directories will be staged in the sysroot
2SYSROOT_DIRS = " \
3 ${includedir} \
4 ${libdir} \
5 ${base_libdir} \
6 ${nonarch_base_libdir} \
7 ${datadir} \
8"
9
10# These directories are also staged in the sysroot when they contain files that
11# are usable on the build system
12SYSROOT_DIRS_NATIVE = " \
13 ${bindir} \
14 ${sbindir} \
15 ${base_bindir} \
16 ${base_sbindir} \
17 ${libexecdir} \
18 ${sysconfdir} \
19 ${localstatedir} \
20"
21SYSROOT_DIRS_append_class-native = " ${SYSROOT_DIRS_NATIVE}"
22SYSROOT_DIRS_append_class-cross = " ${SYSROOT_DIRS_NATIVE}"
23SYSROOT_DIRS_append_class-crosssdk = " ${SYSROOT_DIRS_NATIVE}"
24
25# These directories will not be staged in the sysroot
26SYSROOT_DIRS_BLACKLIST = " \
27 ${mandir} \
28 ${docdir} \
29 ${infodir} \
30 ${datadir}/locale \
31 ${datadir}/applications \
32 ${datadir}/fonts \
33 ${datadir}/pixmaps \
Brad Bishop6e60e8b2018-02-01 10:27:11 -050034 ${libdir}/${PN}/ptest \
Patrick Williamsc0f7c042017-02-23 20:41:17 -060035"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050036
37sysroot_stage_dir() {
38 src="$1"
39 dest="$2"
40 # if the src doesn't exist don't do anything
41 if [ ! -d "$src" ]; then
42 return
43 fi
44
45 mkdir -p "$dest"
46 (
47 cd $src
48 find . -print0 | cpio --null -pdlu $dest
49 )
50}
51
Patrick Williamsc124f4f2015-09-15 14:41:29 -050052sysroot_stage_dirs() {
53 from="$1"
54 to="$2"
55
Patrick Williamsc0f7c042017-02-23 20:41:17 -060056 for dir in ${SYSROOT_DIRS}; do
57 sysroot_stage_dir "$from$dir" "$to$dir"
58 done
59
60 # Remove directories we do not care about
61 for dir in ${SYSROOT_DIRS_BLACKLIST}; do
62 rm -rf "$to$dir"
63 done
Patrick Williamsc124f4f2015-09-15 14:41:29 -050064}
65
66sysroot_stage_all() {
67 sysroot_stage_dirs ${D} ${SYSROOT_DESTDIR}
68}
69
70python sysroot_strip () {
71 import stat, errno
72
Brad Bishop6e60e8b2018-02-01 10:27:11 -050073 dvar = d.getVar('SYSROOT_DESTDIR')
74 pn = d.getVar('PN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050075
76 os.chdir(dvar)
77
78 # Return type (bits):
79 # 0 - not elf
80 # 1 - ELF
81 # 2 - stripped
82 # 4 - executable
83 # 8 - shared library
84 # 16 - kernel module
85 def isELF(path):
86 type = 0
87 ret, result = oe.utils.getstatusoutput("file \"%s\"" % path.replace("\"", "\\\""))
88
89 if ret:
90 bb.error("split_and_strip_files: 'file %s' failed" % path)
91 return type
92
93 # Not stripped
94 if "ELF" in result:
95 type |= 1
96 if "not stripped" not in result:
97 type |= 2
98 if "executable" in result:
99 type |= 4
100 if "shared" in result:
101 type |= 8
102 return type
103
104
105 elffiles = {}
106 inodes = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500107 libdir = os.path.abspath(dvar + os.sep + d.getVar("libdir"))
108 baselibdir = os.path.abspath(dvar + os.sep + d.getVar("base_libdir"))
109 if (d.getVar('INHIBIT_SYSROOT_STRIP') != '1'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500110 #
111 # First lets figure out all of the files we may have to process
112 #
113 for root, dirs, files in os.walk(dvar):
114 for f in files:
115 file = os.path.join(root, f)
116
117 try:
118 ltarget = oe.path.realpath(file, dvar, False)
119 s = os.lstat(ltarget)
120 except OSError as e:
121 (err, strerror) = e.args
122 if err != errno.ENOENT:
123 raise
124 # Skip broken symlinks
125 continue
126 if not s:
127 continue
128 # Check its an excutable
129 if (s[stat.ST_MODE] & stat.S_IXUSR) or (s[stat.ST_MODE] & stat.S_IXGRP) or (s[stat.ST_MODE] & stat.S_IXOTH) \
130 or ((file.startswith(libdir) or file.startswith(baselibdir)) and ".so" in f):
131 # If it's a symlink, and points to an ELF file, we capture the readlink target
132 if os.path.islink(file):
133 continue
134
135 # It's a file (or hardlink), not a link
136 # ...but is it ELF, and is it already stripped?
137 elf_file = isELF(file)
138 if elf_file & 1:
139 if elf_file & 2:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500140 if 'already-stripped' in (d.getVar('INSANE_SKIP_' + pn) or "").split():
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500141 bb.note("Skipping file %s from %s for already-stripped QA test" % (file[len(dvar):], pn))
142 else:
143 bb.warn("File '%s' from %s was already stripped, this will prevent future debugging!" % (file[len(dvar):], pn))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500144 continue
145
146 if s.st_ino in inodes:
147 os.unlink(file)
148 os.link(inodes[s.st_ino], file)
149 else:
150 inodes[s.st_ino] = file
151 # break hardlink
152 bb.utils.copyfile(file, file)
153 elffiles[file] = elf_file
154
155 #
156 # Now strip them (in parallel)
157 #
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500158 strip = d.getVar("STRIP")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500159 sfiles = []
160 for file in elffiles:
161 elf_file = int(elffiles[file])
162 #bb.note("Strip %s" % file)
163 sfiles.append((file, elf_file, strip))
164
165 oe.utils.multiprocess_exec(sfiles, oe.package.runstrip)
166}
167
168do_populate_sysroot[dirs] = "${SYSROOT_DESTDIR}"
169do_populate_sysroot[umask] = "022"
170
171addtask populate_sysroot after do_install
172
173SYSROOT_PREPROCESS_FUNCS ?= ""
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500174SYSROOT_DESTDIR = "${WORKDIR}/sysroot-destdir"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500175
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500176python do_populate_sysroot () {
177 bb.build.exec_func("sysroot_stage_all", d)
178 bb.build.exec_func("sysroot_strip", d)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500179 for f in (d.getVar('SYSROOT_PREPROCESS_FUNCS') or '').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500180 bb.build.exec_func(f, d)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500181 pn = d.getVar("PN")
182 multiprov = d.getVar("MULTI_PROVIDER_WHITELIST").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500183 provdir = d.expand("${SYSROOT_DESTDIR}${base_prefix}/sysroot-providers/")
184 bb.utils.mkdirhier(provdir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500185 for p in d.getVar("PROVIDES").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500186 if p in multiprov:
187 continue
188 p = p.replace("/", "_")
189 with open(provdir + p, "w") as f:
190 f.write(pn)
191}
192
193do_populate_sysroot[vardeps] += "${SYSROOT_PREPROCESS_FUNCS}"
194do_populate_sysroot[vardepsexclude] += "MULTI_PROVIDER_WHITELIST"
195
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500196POPULATESYSROOTDEPS = ""
197POPULATESYSROOTDEPS_class-target = "virtual/${MLPREFIX}${TARGET_PREFIX}binutils:do_populate_sysroot"
198POPULATESYSROOTDEPS_class-nativesdk = "virtual/${TARGET_PREFIX}binutils-crosssdk:do_populate_sysroot"
199do_populate_sysroot[depends] += "${POPULATESYSROOTDEPS}"
200
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500201SSTATETASKS += "do_populate_sysroot"
202do_populate_sysroot[cleandirs] = "${SYSROOT_DESTDIR}"
203do_populate_sysroot[sstate-inputdirs] = "${SYSROOT_DESTDIR}"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500204do_populate_sysroot[sstate-outputdirs] = "${COMPONENTS_DIR}/${PACKAGE_ARCH}/${PN}"
205do_populate_sysroot[sstate-fixmedir] = "${COMPONENTS_DIR}/${PACKAGE_ARCH}/${PN}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500206
207python do_populate_sysroot_setscene () {
208 sstate_setscene(d)
209}
210addtask do_populate_sysroot_setscene
211
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500212def staging_copyfile(c, target, dest, postinsts, seendirs):
213 import errno
214
215 destdir = os.path.dirname(dest)
216 if destdir not in seendirs:
217 bb.utils.mkdirhier(destdir)
218 seendirs.add(destdir)
219 if "/usr/bin/postinst-" in c:
220 postinsts.append(dest)
221 if os.path.islink(c):
222 linkto = os.readlink(c)
223 if os.path.lexists(dest):
224 if not os.path.islink(dest):
225 raise OSError(errno.EEXIST, "Link %s already exists as a file" % dest, dest)
226 if os.readlink(dest) == linkto:
227 return dest
228 raise OSError(errno.EEXIST, "Link %s already exists to a different location? (%s vs %s)" % (dest, os.readlink(dest), linkto), dest)
229 os.symlink(linkto, dest)
230 #bb.warn(c)
231 else:
232 try:
233 os.link(c, dest)
234 except OSError as err:
235 if err.errno == errno.EXDEV:
236 bb.utils.copyfile(c, dest)
237 else:
238 raise
239 return dest
240
241def staging_copydir(c, target, dest, seendirs):
242 if dest not in seendirs:
243 bb.utils.mkdirhier(dest)
244 seendirs.add(dest)
245
246def staging_processfixme(fixme, target, recipesysroot, recipesysrootnative, d):
247 import subprocess
248
249 if not fixme:
250 return
251 cmd = "sed -e 's:^[^/]*/:%s/:g' %s | xargs sed -i -e 's:FIXMESTAGINGDIRTARGET:%s:g; s:FIXMESTAGINGDIRHOST:%s:g'" % (target, " ".join(fixme), recipesysroot, recipesysrootnative)
252 for fixmevar in ['COMPONENTS_DIR', 'HOSTTOOLS_DIR', 'PKGDATA_DIR', 'PSEUDO_LOCALSTATEDIR', 'LOGFIFO']:
253 fixme_path = d.getVar(fixmevar)
254 cmd += " -e 's:FIXME_%s:%s:g'" % (fixmevar, fixme_path)
255 bb.debug(2, cmd)
256 subprocess.check_output(cmd, shell=True)
257
258
259def staging_populate_sysroot_dir(targetsysroot, nativesysroot, native, d):
260 import glob
261 import subprocess
262
263 fixme = []
264 postinsts = []
265 seendirs = set()
266 stagingdir = d.getVar("STAGING_DIR")
267 if native:
268 pkgarchs = ['${BUILD_ARCH}', '${BUILD_ARCH}_*']
269 targetdir = nativesysroot
270 else:
271 pkgarchs = ['${MACHINE_ARCH}']
272 pkgarchs = pkgarchs + list(reversed(d.getVar("PACKAGE_EXTRA_ARCHS").split()))
273 pkgarchs.append('allarch')
274 targetdir = targetsysroot
275
276 bb.utils.mkdirhier(targetdir)
277 for pkgarch in pkgarchs:
278 for manifest in glob.glob(d.expand("${SSTATE_MANIFESTS}/manifest-%s-*.populate_sysroot" % pkgarch)):
279 if manifest.endswith("-initial.populate_sysroot"):
280 # skip glibc-initial and libgcc-initial due to file overlap
281 continue
282 tmanifest = targetdir + "/" + os.path.basename(manifest)
283 if os.path.exists(tmanifest):
284 continue
285 try:
286 os.link(manifest, tmanifest)
287 except OSError as err:
288 if err.errno == errno.EXDEV:
289 bb.utils.copyfile(manifest, tmanifest)
290 else:
291 raise
292 with open(manifest, "r") as f:
293 for l in f:
294 l = l.strip()
295 if l.endswith("/fixmepath"):
296 fixme.append(l)
297 continue
298 if l.endswith("/fixmepath.cmd"):
299 continue
300 dest = l.replace(stagingdir, "")
301 dest = targetdir + "/" + "/".join(dest.split("/")[3:])
302 if l.endswith("/"):
303 staging_copydir(l, targetdir, dest, seendirs)
304 continue
305 try:
306 staging_copyfile(l, targetdir, dest, postinsts, seendirs)
307 except FileExistsError:
308 continue
309
310 staging_processfixme(fixme, targetdir, targetsysroot, nativesysroot, d)
311 for p in postinsts:
312 subprocess.check_output(p, shell=True)
313
314#
315# Manifests here are complicated. The main sysroot area has the unpacked sstate
316# which us unrelocated and tracked by the main sstate manifests. Each recipe
317# specific sysroot has manifests for each dependency that is installed there.
318# The task hash is used to tell whether the data needs to be reinstalled. We
319# use a symlink to point to the currently installed hash. There is also a
320# "complete" stamp file which is used to mark if installation completed. If
321# something fails (e.g. a postinst), this won't get written and we would
322# remove and reinstall the dependency. This also means partially installed
323# dependencies should get cleaned up correctly.
324#
325
326python extend_recipe_sysroot() {
327 import copy
328 import subprocess
329 import errno
330 import collections
331 import glob
332
333 taskdepdata = d.getVar("BB_TASKDEPDATA", False)
334 mytaskname = d.getVar("BB_RUNTASK")
335 if mytaskname.endswith("_setscene"):
336 mytaskname = mytaskname.replace("_setscene", "")
337 workdir = d.getVar("WORKDIR")
338 #bb.warn(str(taskdepdata))
339 pn = d.getVar("PN")
340
341 stagingdir = d.getVar("STAGING_DIR")
342 sharedmanifests = d.getVar("COMPONENTS_DIR") + "/manifests"
343 recipesysroot = d.getVar("RECIPE_SYSROOT")
344 recipesysrootnative = d.getVar("RECIPE_SYSROOT_NATIVE")
345 current_variant = d.getVar("BBEXTENDVARIANT")
346
347 # Detect bitbake -b usage
348 nodeps = d.getVar("BB_LIMITEDDEPS") or False
349 if nodeps:
350 lock = bb.utils.lockfile(recipesysroot + "/sysroot.lock")
351 staging_populate_sysroot_dir(recipesysroot, recipesysrootnative, True, d)
352 staging_populate_sysroot_dir(recipesysroot, recipesysrootnative, False, d)
353 bb.utils.unlockfile(lock)
354 return
355
356 start = None
357 configuredeps = []
358 for dep in taskdepdata:
359 data = taskdepdata[dep]
360 if data[1] == mytaskname and data[0] == pn:
361 start = dep
362 break
363 if start is None:
364 bb.fatal("Couldn't find ourself in BB_TASKDEPDATA?")
365
366 # We need to figure out which sysroot files we need to expose to this task.
367 # This needs to match what would get restored from sstate, which is controlled
368 # ultimately by calls from bitbake to setscene_depvalid().
369 # That function expects a setscene dependency tree. We build a dependency tree
370 # condensed to inter-sstate task dependencies, similar to that used by setscene
371 # tasks. We can then call into setscene_depvalid() and decide
372 # which dependencies we can "see" and should expose in the recipe specific sysroot.
373 setscenedeps = copy.deepcopy(taskdepdata)
374
375 start = set([start])
376
377 sstatetasks = d.getVar("SSTATETASKS").split()
378
379 def print_dep_tree(deptree):
380 data = ""
381 for dep in deptree:
382 deps = " " + "\n ".join(deptree[dep][3]) + "\n"
383 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])
384 return data
385
386 #bb.note("Full dep tree is:\n%s" % print_dep_tree(taskdepdata))
387
388 #bb.note(" start2 is %s" % str(start))
389
390 # If start is an sstate task (like do_package) we need to add in its direct dependencies
391 # else the code below won't recurse into them.
392 for dep in set(start):
393 for dep2 in setscenedeps[dep][3]:
394 start.add(dep2)
395 start.remove(dep)
396
397 #bb.note(" start3 is %s" % str(start))
398
399 # Create collapsed do_populate_sysroot -> do_populate_sysroot tree
400 for dep in taskdepdata:
401 data = setscenedeps[dep]
402 if data[1] not in sstatetasks:
403 for dep2 in setscenedeps:
404 data2 = setscenedeps[dep2]
405 if dep in data2[3]:
406 data2[3].update(setscenedeps[dep][3])
407 data2[3].remove(dep)
408 if dep in start:
409 start.update(setscenedeps[dep][3])
410 start.remove(dep)
411 del setscenedeps[dep]
412
413 # Remove circular references
414 for dep in setscenedeps:
415 if dep in setscenedeps[dep][3]:
416 setscenedeps[dep][3].remove(dep)
417
418 #bb.note("Computed dep tree is:\n%s" % print_dep_tree(setscenedeps))
419 #bb.note(" start is %s" % str(start))
420
421 # Direct dependencies should be present and can be depended upon
422 for dep in set(start):
423 if setscenedeps[dep][1] == "do_populate_sysroot":
424 if dep not in configuredeps:
425 configuredeps.append(dep)
426 bb.note("Direct dependencies are %s" % str(configuredeps))
427 #bb.note(" or %s" % str(start))
428
429 msgbuf = []
430 # Call into setscene_depvalid for each sub-dependency and only copy sysroot files
431 # for ones that would be restored from sstate.
432 done = list(start)
433 next = list(start)
434 while next:
435 new = []
436 for dep in next:
437 data = setscenedeps[dep]
438 for datadep in data[3]:
439 if datadep in done:
440 continue
441 taskdeps = {}
442 taskdeps[dep] = setscenedeps[dep][:2]
443 taskdeps[datadep] = setscenedeps[datadep][:2]
444 retval = setscene_depvalid(datadep, taskdeps, [], d, msgbuf)
445 if retval:
446 msgbuf.append("Skipping setscene dependency %s for installation into the sysroot" % datadep)
447 continue
448 done.append(datadep)
449 new.append(datadep)
450 if datadep not in configuredeps and setscenedeps[datadep][1] == "do_populate_sysroot":
451 configuredeps.append(datadep)
452 msgbuf.append("Adding dependency on %s" % setscenedeps[datadep][0])
453 else:
454 msgbuf.append("Following dependency on %s" % setscenedeps[datadep][0])
455 next = new
456
457 bb.note("\n".join(msgbuf))
458
459 depdir = recipesysrootnative + "/installeddeps"
460 bb.utils.mkdirhier(depdir)
461 bb.utils.mkdirhier(sharedmanifests)
462
463 lock = bb.utils.lockfile(recipesysroot + "/sysroot.lock")
464
465 fixme = {}
466 fixme[''] = []
467 fixme['native'] = []
468 seendirs = set()
469 postinsts = []
470 multilibs = {}
471 manifests = {}
472
473 for f in os.listdir(depdir):
474 if not f.endswith(".complete"):
475 continue
476 f = depdir + "/" + f
477 if os.path.islink(f) and not os.path.exists(f):
478 bb.note("%s no longer exists, removing from sysroot" % f)
479 lnk = os.readlink(f.replace(".complete", ""))
480 sstate_clean_manifest(depdir + "/" + lnk, d, workdir)
481 os.unlink(f)
482 os.unlink(f.replace(".complete", ""))
483
484 installed = []
485 for dep in configuredeps:
486 c = setscenedeps[dep][0]
487 if mytaskname in ["do_sdk_depends", "do_populate_sdk_ext"] and c.endswith("-initial"):
488 bb.note("Skipping initial setscene dependency %s for installation into the sysroot" % c)
489 continue
490 installed.append(c)
491
492 # We want to remove anything which this task previously installed but is no longer a dependency
493 taskindex = depdir + "/" + "index." + mytaskname
494 if os.path.exists(taskindex):
495 potential = []
496 with open(taskindex, "r") as f:
497 for l in f:
498 l = l.strip()
499 if l not in installed:
500 fl = depdir + "/" + l
501 if not os.path.exists(fl):
502 # Was likely already uninstalled
503 continue
504 potential.append(l)
505 # We need to ensure not other task needs this dependency. We hold the sysroot
506 # lock so we ca search the indexes to check
507 if potential:
508 for i in glob.glob(depdir + "/index.*"):
509 if i.endswith("." + mytaskname):
510 continue
511 with open(i, "r") as f:
512 for l in f:
513 l = l.strip()
514 if l in potential:
515 potential.remove(l)
516 for l in potential:
517 fl = depdir + "/" + l
518 bb.note("Task %s no longer depends on %s, removing from sysroot" % (mytaskname, l))
519 lnk = os.readlink(fl)
520 sstate_clean_manifest(depdir + "/" + lnk, d, workdir)
521 os.unlink(fl)
522 os.unlink(fl + ".complete")
523
524 for dep in configuredeps:
525 c = setscenedeps[dep][0]
526 if c not in installed:
527 continue
528 taskhash = setscenedeps[dep][5]
529 taskmanifest = depdir + "/" + c + "." + taskhash
530
531 if os.path.exists(depdir + "/" + c):
532 lnk = os.readlink(depdir + "/" + c)
533 if lnk == c + "." + taskhash and os.path.exists(depdir + "/" + c + ".complete"):
534 bb.note("%s exists in sysroot, skipping" % c)
535 continue
536 else:
537 bb.note("%s exists in sysroot, but is stale (%s vs. %s), removing." % (c, lnk, c + "." + taskhash))
538 sstate_clean_manifest(depdir + "/" + lnk, d, workdir)
539 os.unlink(depdir + "/" + c)
540 if os.path.lexists(depdir + "/" + c + ".complete"):
541 os.unlink(depdir + "/" + c + ".complete")
542 elif os.path.lexists(depdir + "/" + c):
543 os.unlink(depdir + "/" + c)
544
545 os.symlink(c + "." + taskhash, depdir + "/" + c)
546
547 d2 = d
548 destsysroot = recipesysroot
549 variant = ''
550 if setscenedeps[dep][2].startswith("virtual:multilib"):
551 variant = setscenedeps[dep][2].split(":")[2]
552 if variant != current_variant:
553 if variant not in multilibs:
554 multilibs[variant] = get_multilib_datastore(variant, d)
555 d2 = multilibs[variant]
556 destsysroot = d2.getVar("RECIPE_SYSROOT")
557
558 native = False
559 if c.endswith("-native"):
560 manifest = d2.expand("${SSTATE_MANIFESTS}/manifest-${BUILD_ARCH}-%s.populate_sysroot" % c)
561 native = True
562 elif c.startswith("nativesdk-"):
563 manifest = d2.expand("${SSTATE_MANIFESTS}/manifest-${SDK_ARCH}_${SDK_OS}-%s.populate_sysroot" % c)
564 elif "-cross-" in c:
565 manifest = d2.expand("${SSTATE_MANIFESTS}/manifest-${BUILD_ARCH}_${TARGET_ARCH}-%s.populate_sysroot" % c)
566 native = True
567 elif "-crosssdk" in c:
568 manifest = d2.expand("${SSTATE_MANIFESTS}/manifest-${BUILD_ARCH}_${SDK_ARCH}_${SDK_OS}-%s.populate_sysroot" % c)
569 native = True
570 else:
571 pkgarchs = ['${MACHINE_ARCH}']
572 pkgarchs = pkgarchs + list(reversed(d2.getVar("PACKAGE_EXTRA_ARCHS").split()))
573 pkgarchs.append('allarch')
574 for pkgarch in pkgarchs:
575 manifest = d2.expand("${SSTATE_MANIFESTS}/manifest-%s-%s.populate_sysroot" % (pkgarch, c))
576 if os.path.exists(manifest):
577 break
578 if not os.path.exists(manifest):
579 bb.warn("Manifest %s not found?" % manifest)
580 else:
581 newmanifest = collections.OrderedDict()
582 if native:
583 fm = fixme['native']
584 targetdir = recipesysrootnative
585 else:
586 fm = fixme['']
587 targetdir = destsysroot
588 with open(manifest, "r") as f:
589 manifests[dep] = manifest
590 for l in f:
591 l = l.strip()
592 if l.endswith("/fixmepath"):
593 fm.append(l)
594 continue
595 if l.endswith("/fixmepath.cmd"):
596 continue
597 dest = l.replace(stagingdir, "")
598 dest = targetdir + "/" + "/".join(dest.split("/")[3:])
599 newmanifest[l] = dest
600 # Having multiple identical manifests in each sysroot eats diskspace so
601 # create a shared pool of them and hardlink if we can.
602 # We create the manifest in advance so that if something fails during installation,
603 # or the build is interrupted, subsequent exeuction can cleanup.
604 sharedm = sharedmanifests + "/" + os.path.basename(taskmanifest)
605 if not os.path.exists(sharedm):
606 smlock = bb.utils.lockfile(sharedm + ".lock")
607 # Can race here. You'd think it just means we may not end up with all copies hardlinked to each other
608 # but python can lose file handles so we need to do this under a lock.
609 if not os.path.exists(sharedm):
610 with open(sharedm, 'w') as m:
611 for l in newmanifest:
612 dest = newmanifest[l]
613 m.write(dest.replace(workdir + "/", "") + "\n")
614 bb.utils.unlockfile(smlock)
615 try:
616 os.link(sharedm, taskmanifest)
617 except OSError as err:
618 if err.errno == errno.EXDEV:
619 bb.utils.copyfile(sharedm, taskmanifest)
620 else:
621 raise
622 # Finally actually install the files
623 for l in newmanifest:
624 dest = newmanifest[l]
625 if l.endswith("/"):
626 staging_copydir(l, targetdir, dest, seendirs)
627 continue
628 staging_copyfile(l, targetdir, dest, postinsts, seendirs)
629
630 for f in fixme:
631 if f == '':
632 staging_processfixme(fixme[f], recipesysroot, recipesysroot, recipesysrootnative, d)
633 elif f == 'native':
634 staging_processfixme(fixme[f], recipesysrootnative, recipesysroot, recipesysrootnative, d)
635 else:
636 staging_processfixme(fixme[f], multilibs[f].getVar("RECIPE_SYSROOT"), recipesysroot, recipesysrootnative, d)
637
638 for p in postinsts:
639 subprocess.check_output(p, shell=True)
640
641 for dep in manifests:
642 c = setscenedeps[dep][0]
643 os.symlink(manifests[dep], depdir + "/" + c + ".complete")
644
645 with open(taskindex, "w") as f:
646 for l in sorted(installed):
647 f.write(l + "\n")
648
649 bb.utils.unlockfile(lock)
650}
651extend_recipe_sysroot[vardepsexclude] += "MACHINE_ARCH PACKAGE_EXTRA_ARCHS SDK_ARCH BUILD_ARCH SDK_OS BB_TASKDEPDATA"
652
653python do_prepare_recipe_sysroot () {
654 bb.build.exec_func("extend_recipe_sysroot", d)
655}
656addtask do_prepare_recipe_sysroot before do_configure after do_fetch
657
658# Clean out the recipe specific sysroots before do_fetch
659# (use a prefunc so we can order before extend_recipe_sysroot if it gets added)
660python clean_recipe_sysroot() {
661 return
662}
663clean_recipe_sysroot[cleandirs] += "${RECIPE_SYSROOT} ${RECIPE_SYSROOT_NATIVE}"
664do_fetch[prefuncs] += "clean_recipe_sysroot"
665
666python staging_taskhandler() {
667 bbtasks = e.tasklist
668 for task in bbtasks:
669 deps = d.getVarFlag(task, "depends")
670 if deps and "populate_sysroot" in deps:
671 d.appendVarFlag(task, "prefuncs", " extend_recipe_sysroot")
672}
673staging_taskhandler[eventmask] = "bb.event.RecipeTaskPreProcess"
674addhandler staging_taskhandler
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500675