blob: 062b2817c886b49e8c62e7ae5c662564fce8cd00 [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 () {
Brad Bishopd7bf8c12018-02-25 22:55:05 -050071 inhibit_sysroot = d.getVar('INHIBIT_SYSROOT_STRIP')
72 if inhibit_sysroot and oe.types.boolean(inhibit_sysroot):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080073 return
Patrick Williamsc124f4f2015-09-15 14:41:29 -050074
Brad Bishopd7bf8c12018-02-25 22:55:05 -050075 dstdir = d.getVar('SYSROOT_DESTDIR')
Brad Bishop6e60e8b2018-02-01 10:27:11 -050076 pn = d.getVar('PN')
Brad Bishopd7bf8c12018-02-25 22:55:05 -050077 libdir = os.path.abspath(dstdir + os.sep + d.getVar("libdir"))
78 base_libdir = os.path.abspath(dstdir + os.sep + d.getVar("base_libdir"))
79 qa_already_stripped = 'already-stripped' in (d.getVar('INSANE_SKIP_' + pn) or "").split()
80 strip_cmd = d.getVar("STRIP")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050081
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080082 oe.package.strip_execs(pn, dstdir, strip_cmd, libdir, base_libdir, d,
Brad Bishopd7bf8c12018-02-25 22:55:05 -050083 qa_already_stripped=qa_already_stripped)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050084}
85
86do_populate_sysroot[dirs] = "${SYSROOT_DESTDIR}"
87do_populate_sysroot[umask] = "022"
88
89addtask populate_sysroot after do_install
90
91SYSROOT_PREPROCESS_FUNCS ?= ""
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050092SYSROOT_DESTDIR = "${WORKDIR}/sysroot-destdir"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050093
Patrick Williamsc124f4f2015-09-15 14:41:29 -050094python do_populate_sysroot () {
95 bb.build.exec_func("sysroot_stage_all", d)
96 bb.build.exec_func("sysroot_strip", d)
Brad Bishop6e60e8b2018-02-01 10:27:11 -050097 for f in (d.getVar('SYSROOT_PREPROCESS_FUNCS') or '').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -050098 bb.build.exec_func(f, d)
Brad Bishop6e60e8b2018-02-01 10:27:11 -050099 pn = d.getVar("PN")
100 multiprov = d.getVar("MULTI_PROVIDER_WHITELIST").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500101 provdir = d.expand("${SYSROOT_DESTDIR}${base_prefix}/sysroot-providers/")
102 bb.utils.mkdirhier(provdir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500103 for p in d.getVar("PROVIDES").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500104 if p in multiprov:
105 continue
106 p = p.replace("/", "_")
107 with open(provdir + p, "w") as f:
108 f.write(pn)
109}
110
111do_populate_sysroot[vardeps] += "${SYSROOT_PREPROCESS_FUNCS}"
112do_populate_sysroot[vardepsexclude] += "MULTI_PROVIDER_WHITELIST"
113
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500114POPULATESYSROOTDEPS = ""
115POPULATESYSROOTDEPS_class-target = "virtual/${MLPREFIX}${TARGET_PREFIX}binutils:do_populate_sysroot"
116POPULATESYSROOTDEPS_class-nativesdk = "virtual/${TARGET_PREFIX}binutils-crosssdk:do_populate_sysroot"
117do_populate_sysroot[depends] += "${POPULATESYSROOTDEPS}"
118
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500119SSTATETASKS += "do_populate_sysroot"
120do_populate_sysroot[cleandirs] = "${SYSROOT_DESTDIR}"
121do_populate_sysroot[sstate-inputdirs] = "${SYSROOT_DESTDIR}"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500122do_populate_sysroot[sstate-outputdirs] = "${COMPONENTS_DIR}/${PACKAGE_ARCH}/${PN}"
123do_populate_sysroot[sstate-fixmedir] = "${COMPONENTS_DIR}/${PACKAGE_ARCH}/${PN}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500124
125python do_populate_sysroot_setscene () {
126 sstate_setscene(d)
127}
128addtask do_populate_sysroot_setscene
129
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500130def staging_copyfile(c, target, dest, postinsts, seendirs):
131 import errno
132
133 destdir = os.path.dirname(dest)
134 if destdir not in seendirs:
135 bb.utils.mkdirhier(destdir)
136 seendirs.add(destdir)
137 if "/usr/bin/postinst-" in c:
138 postinsts.append(dest)
139 if os.path.islink(c):
140 linkto = os.readlink(c)
141 if os.path.lexists(dest):
142 if not os.path.islink(dest):
143 raise OSError(errno.EEXIST, "Link %s already exists as a file" % dest, dest)
144 if os.readlink(dest) == linkto:
145 return dest
146 raise OSError(errno.EEXIST, "Link %s already exists to a different location? (%s vs %s)" % (dest, os.readlink(dest), linkto), dest)
147 os.symlink(linkto, dest)
148 #bb.warn(c)
149 else:
150 try:
151 os.link(c, dest)
152 except OSError as err:
153 if err.errno == errno.EXDEV:
154 bb.utils.copyfile(c, dest)
155 else:
156 raise
157 return dest
158
159def staging_copydir(c, target, dest, seendirs):
160 if dest not in seendirs:
161 bb.utils.mkdirhier(dest)
162 seendirs.add(dest)
163
164def staging_processfixme(fixme, target, recipesysroot, recipesysrootnative, d):
165 import subprocess
166
167 if not fixme:
168 return
169 cmd = "sed -e 's:^[^/]*/:%s/:g' %s | xargs sed -i -e 's:FIXMESTAGINGDIRTARGET:%s:g; s:FIXMESTAGINGDIRHOST:%s:g'" % (target, " ".join(fixme), recipesysroot, recipesysrootnative)
170 for fixmevar in ['COMPONENTS_DIR', 'HOSTTOOLS_DIR', 'PKGDATA_DIR', 'PSEUDO_LOCALSTATEDIR', 'LOGFIFO']:
171 fixme_path = d.getVar(fixmevar)
172 cmd += " -e 's:FIXME_%s:%s:g'" % (fixmevar, fixme_path)
173 bb.debug(2, cmd)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400174 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500175
176
177def staging_populate_sysroot_dir(targetsysroot, nativesysroot, native, d):
178 import glob
179 import subprocess
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500180 import errno
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500181
182 fixme = []
183 postinsts = []
184 seendirs = set()
185 stagingdir = d.getVar("STAGING_DIR")
186 if native:
187 pkgarchs = ['${BUILD_ARCH}', '${BUILD_ARCH}_*']
188 targetdir = nativesysroot
189 else:
190 pkgarchs = ['${MACHINE_ARCH}']
191 pkgarchs = pkgarchs + list(reversed(d.getVar("PACKAGE_EXTRA_ARCHS").split()))
192 pkgarchs.append('allarch')
193 targetdir = targetsysroot
194
195 bb.utils.mkdirhier(targetdir)
196 for pkgarch in pkgarchs:
197 for manifest in glob.glob(d.expand("${SSTATE_MANIFESTS}/manifest-%s-*.populate_sysroot" % pkgarch)):
198 if manifest.endswith("-initial.populate_sysroot"):
199 # skip glibc-initial and libgcc-initial due to file overlap
200 continue
Brad Bishop19323692019-04-05 15:28:33 -0400201 if not native and (manifest.endswith("-native.populate_sysroot") or "nativesdk-" in manifest):
202 continue
203 if native and not (manifest.endswith("-native.populate_sysroot") or manifest.endswith("-cross.populate_sysroot") or "-cross-" in manifest):
204 continue
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500205 tmanifest = targetdir + "/" + os.path.basename(manifest)
206 if os.path.exists(tmanifest):
207 continue
208 try:
209 os.link(manifest, tmanifest)
210 except OSError as err:
211 if err.errno == errno.EXDEV:
212 bb.utils.copyfile(manifest, tmanifest)
213 else:
214 raise
215 with open(manifest, "r") as f:
216 for l in f:
217 l = l.strip()
218 if l.endswith("/fixmepath"):
219 fixme.append(l)
220 continue
221 if l.endswith("/fixmepath.cmd"):
222 continue
223 dest = l.replace(stagingdir, "")
224 dest = targetdir + "/" + "/".join(dest.split("/")[3:])
225 if l.endswith("/"):
226 staging_copydir(l, targetdir, dest, seendirs)
227 continue
228 try:
229 staging_copyfile(l, targetdir, dest, postinsts, seendirs)
230 except FileExistsError:
231 continue
232
233 staging_processfixme(fixme, targetdir, targetsysroot, nativesysroot, d)
234 for p in postinsts:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400235 subprocess.check_output(p, shell=True, stderr=subprocess.STDOUT)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500236
237#
238# Manifests here are complicated. The main sysroot area has the unpacked sstate
239# which us unrelocated and tracked by the main sstate manifests. Each recipe
240# specific sysroot has manifests for each dependency that is installed there.
241# The task hash is used to tell whether the data needs to be reinstalled. We
242# use a symlink to point to the currently installed hash. There is also a
243# "complete" stamp file which is used to mark if installation completed. If
244# something fails (e.g. a postinst), this won't get written and we would
245# remove and reinstall the dependency. This also means partially installed
246# dependencies should get cleaned up correctly.
247#
248
249python extend_recipe_sysroot() {
250 import copy
251 import subprocess
252 import errno
253 import collections
254 import glob
255
256 taskdepdata = d.getVar("BB_TASKDEPDATA", False)
257 mytaskname = d.getVar("BB_RUNTASK")
258 if mytaskname.endswith("_setscene"):
259 mytaskname = mytaskname.replace("_setscene", "")
260 workdir = d.getVar("WORKDIR")
261 #bb.warn(str(taskdepdata))
262 pn = d.getVar("PN")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800263 mc = d.getVar("BB_CURRENT_MC")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500264 stagingdir = d.getVar("STAGING_DIR")
265 sharedmanifests = d.getVar("COMPONENTS_DIR") + "/manifests"
266 recipesysroot = d.getVar("RECIPE_SYSROOT")
267 recipesysrootnative = d.getVar("RECIPE_SYSROOT_NATIVE")
268 current_variant = d.getVar("BBEXTENDVARIANT")
269
270 # Detect bitbake -b usage
271 nodeps = d.getVar("BB_LIMITEDDEPS") or False
272 if nodeps:
273 lock = bb.utils.lockfile(recipesysroot + "/sysroot.lock")
274 staging_populate_sysroot_dir(recipesysroot, recipesysrootnative, True, d)
275 staging_populate_sysroot_dir(recipesysroot, recipesysrootnative, False, d)
276 bb.utils.unlockfile(lock)
277 return
278
279 start = None
280 configuredeps = []
281 for dep in taskdepdata:
282 data = taskdepdata[dep]
283 if data[1] == mytaskname and data[0] == pn:
284 start = dep
285 break
286 if start is None:
287 bb.fatal("Couldn't find ourself in BB_TASKDEPDATA?")
288
289 # We need to figure out which sysroot files we need to expose to this task.
290 # This needs to match what would get restored from sstate, which is controlled
291 # ultimately by calls from bitbake to setscene_depvalid().
292 # That function expects a setscene dependency tree. We build a dependency tree
293 # condensed to inter-sstate task dependencies, similar to that used by setscene
294 # tasks. We can then call into setscene_depvalid() and decide
295 # which dependencies we can "see" and should expose in the recipe specific sysroot.
296 setscenedeps = copy.deepcopy(taskdepdata)
297
298 start = set([start])
299
300 sstatetasks = d.getVar("SSTATETASKS").split()
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800301 # Add recipe specific tasks referenced by setscene_depvalid()
302 sstatetasks.append("do_stash_locale")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500303
304 def print_dep_tree(deptree):
305 data = ""
306 for dep in deptree:
307 deps = " " + "\n ".join(deptree[dep][3]) + "\n"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800308 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])
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500309 return data
310
311 #bb.note("Full dep tree is:\n%s" % print_dep_tree(taskdepdata))
312
313 #bb.note(" start2 is %s" % str(start))
314
315 # If start is an sstate task (like do_package) we need to add in its direct dependencies
316 # else the code below won't recurse into them.
317 for dep in set(start):
318 for dep2 in setscenedeps[dep][3]:
319 start.add(dep2)
320 start.remove(dep)
321
322 #bb.note(" start3 is %s" % str(start))
323
324 # Create collapsed do_populate_sysroot -> do_populate_sysroot tree
325 for dep in taskdepdata:
326 data = setscenedeps[dep]
327 if data[1] not in sstatetasks:
328 for dep2 in setscenedeps:
329 data2 = setscenedeps[dep2]
330 if dep in data2[3]:
331 data2[3].update(setscenedeps[dep][3])
332 data2[3].remove(dep)
333 if dep in start:
334 start.update(setscenedeps[dep][3])
335 start.remove(dep)
336 del setscenedeps[dep]
337
338 # Remove circular references
339 for dep in setscenedeps:
340 if dep in setscenedeps[dep][3]:
341 setscenedeps[dep][3].remove(dep)
342
343 #bb.note("Computed dep tree is:\n%s" % print_dep_tree(setscenedeps))
344 #bb.note(" start is %s" % str(start))
345
346 # Direct dependencies should be present and can be depended upon
347 for dep in set(start):
348 if setscenedeps[dep][1] == "do_populate_sysroot":
349 if dep not in configuredeps:
350 configuredeps.append(dep)
351 bb.note("Direct dependencies are %s" % str(configuredeps))
352 #bb.note(" or %s" % str(start))
353
354 msgbuf = []
355 # Call into setscene_depvalid for each sub-dependency and only copy sysroot files
356 # for ones that would be restored from sstate.
357 done = list(start)
358 next = list(start)
359 while next:
360 new = []
361 for dep in next:
362 data = setscenedeps[dep]
363 for datadep in data[3]:
364 if datadep in done:
365 continue
366 taskdeps = {}
367 taskdeps[dep] = setscenedeps[dep][:2]
368 taskdeps[datadep] = setscenedeps[datadep][:2]
369 retval = setscene_depvalid(datadep, taskdeps, [], d, msgbuf)
370 if retval:
371 msgbuf.append("Skipping setscene dependency %s for installation into the sysroot" % datadep)
372 continue
373 done.append(datadep)
374 new.append(datadep)
375 if datadep not in configuredeps and setscenedeps[datadep][1] == "do_populate_sysroot":
376 configuredeps.append(datadep)
377 msgbuf.append("Adding dependency on %s" % setscenedeps[datadep][0])
378 else:
379 msgbuf.append("Following dependency on %s" % setscenedeps[datadep][0])
380 next = new
381
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500382 # This logging is too verbose for day to day use sadly
383 #bb.debug(2, "\n".join(msgbuf))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500384
385 depdir = recipesysrootnative + "/installeddeps"
386 bb.utils.mkdirhier(depdir)
387 bb.utils.mkdirhier(sharedmanifests)
388
389 lock = bb.utils.lockfile(recipesysroot + "/sysroot.lock")
390
391 fixme = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500392 seendirs = set()
393 postinsts = []
394 multilibs = {}
395 manifests = {}
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500396 # All files that we're going to be installing, to find conflicts.
397 fileset = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500398
399 for f in os.listdir(depdir):
400 if not f.endswith(".complete"):
401 continue
402 f = depdir + "/" + f
403 if os.path.islink(f) and not os.path.exists(f):
404 bb.note("%s no longer exists, removing from sysroot" % f)
405 lnk = os.readlink(f.replace(".complete", ""))
406 sstate_clean_manifest(depdir + "/" + lnk, d, workdir)
407 os.unlink(f)
408 os.unlink(f.replace(".complete", ""))
409
410 installed = []
411 for dep in configuredeps:
412 c = setscenedeps[dep][0]
413 if mytaskname in ["do_sdk_depends", "do_populate_sdk_ext"] and c.endswith("-initial"):
414 bb.note("Skipping initial setscene dependency %s for installation into the sysroot" % c)
415 continue
416 installed.append(c)
417
418 # We want to remove anything which this task previously installed but is no longer a dependency
419 taskindex = depdir + "/" + "index." + mytaskname
420 if os.path.exists(taskindex):
421 potential = []
422 with open(taskindex, "r") as f:
423 for l in f:
424 l = l.strip()
425 if l not in installed:
426 fl = depdir + "/" + l
427 if not os.path.exists(fl):
428 # Was likely already uninstalled
429 continue
430 potential.append(l)
431 # We need to ensure not other task needs this dependency. We hold the sysroot
432 # lock so we ca search the indexes to check
433 if potential:
434 for i in glob.glob(depdir + "/index.*"):
435 if i.endswith("." + mytaskname):
436 continue
437 with open(i, "r") as f:
438 for l in f:
439 l = l.strip()
440 if l in potential:
441 potential.remove(l)
442 for l in potential:
443 fl = depdir + "/" + l
444 bb.note("Task %s no longer depends on %s, removing from sysroot" % (mytaskname, l))
445 lnk = os.readlink(fl)
446 sstate_clean_manifest(depdir + "/" + lnk, d, workdir)
447 os.unlink(fl)
448 os.unlink(fl + ".complete")
449
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500450 msg_exists = []
451 msg_adding = []
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800452
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500453 for dep in configuredeps:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800454 if mc != 'default':
455 # We should not care about other multiconfigs
456 depmc = dep.split(':')[1]
457 if depmc != mc:
458 continue
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500459 c = setscenedeps[dep][0]
460 if c not in installed:
461 continue
462 taskhash = setscenedeps[dep][5]
463 taskmanifest = depdir + "/" + c + "." + taskhash
464
465 if os.path.exists(depdir + "/" + c):
466 lnk = os.readlink(depdir + "/" + c)
467 if lnk == c + "." + taskhash and os.path.exists(depdir + "/" + c + ".complete"):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500468 msg_exists.append(c)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500469 continue
470 else:
471 bb.note("%s exists in sysroot, but is stale (%s vs. %s), removing." % (c, lnk, c + "." + taskhash))
472 sstate_clean_manifest(depdir + "/" + lnk, d, workdir)
473 os.unlink(depdir + "/" + c)
474 if os.path.lexists(depdir + "/" + c + ".complete"):
475 os.unlink(depdir + "/" + c + ".complete")
476 elif os.path.lexists(depdir + "/" + c):
477 os.unlink(depdir + "/" + c)
478
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500479 msg_adding.append(c)
480
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500481 os.symlink(c + "." + taskhash, depdir + "/" + c)
482
Brad Bishop316dfdd2018-06-25 12:45:53 -0400483 manifest, d2 = oe.sstatesig.find_sstate_manifest(c, setscenedeps[dep][2], "populate_sysroot", d, multilibs)
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700484 if d2 is not d:
485 # If we don't do this, the recipe sysroot will be placed in the wrong WORKDIR for multilibs
486 # We need a consistent WORKDIR for the image
487 d2.setVar("WORKDIR", d.getVar("WORKDIR"))
Brad Bishop316dfdd2018-06-25 12:45:53 -0400488 destsysroot = d2.getVar("RECIPE_SYSROOT")
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700489 # We put allarch recipes into the default sysroot
490 if manifest and "allarch" in manifest:
491 destsysroot = d.getVar("RECIPE_SYSROOT")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500492
493 native = False
Brad Bishop316dfdd2018-06-25 12:45:53 -0400494 if c.endswith("-native") or "-cross-" in c or "-crosssdk" in c:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500495 native = True
Brad Bishop316dfdd2018-06-25 12:45:53 -0400496
497 if manifest:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500498 newmanifest = collections.OrderedDict()
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700499 targetdir = destsysroot
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500500 if native:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500501 targetdir = recipesysrootnative
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700502 if targetdir not in fixme:
503 fixme[targetdir] = []
504 fm = fixme[targetdir]
505
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500506 with open(manifest, "r") as f:
507 manifests[dep] = manifest
508 for l in f:
509 l = l.strip()
510 if l.endswith("/fixmepath"):
511 fm.append(l)
512 continue
513 if l.endswith("/fixmepath.cmd"):
514 continue
515 dest = l.replace(stagingdir, "")
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500516 dest = "/" + "/".join(dest.split("/")[3:])
517 newmanifest[l] = targetdir + dest
518
519 # Check if files have already been installed by another
520 # recipe and abort if they have, explaining what recipes are
521 # conflicting.
522 hashname = targetdir + dest
523 if not hashname.endswith("/"):
524 if hashname in fileset:
525 bb.fatal("The file %s is installed by both %s and %s, aborting" % (dest, c, fileset[hashname]))
526 else:
527 fileset[hashname] = c
528
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500529 # Having multiple identical manifests in each sysroot eats diskspace so
530 # create a shared pool of them and hardlink if we can.
531 # We create the manifest in advance so that if something fails during installation,
532 # or the build is interrupted, subsequent exeuction can cleanup.
533 sharedm = sharedmanifests + "/" + os.path.basename(taskmanifest)
534 if not os.path.exists(sharedm):
535 smlock = bb.utils.lockfile(sharedm + ".lock")
536 # Can race here. You'd think it just means we may not end up with all copies hardlinked to each other
537 # but python can lose file handles so we need to do this under a lock.
538 if not os.path.exists(sharedm):
539 with open(sharedm, 'w') as m:
540 for l in newmanifest:
541 dest = newmanifest[l]
542 m.write(dest.replace(workdir + "/", "") + "\n")
543 bb.utils.unlockfile(smlock)
544 try:
545 os.link(sharedm, taskmanifest)
546 except OSError as err:
547 if err.errno == errno.EXDEV:
548 bb.utils.copyfile(sharedm, taskmanifest)
549 else:
550 raise
551 # Finally actually install the files
552 for l in newmanifest:
553 dest = newmanifest[l]
554 if l.endswith("/"):
555 staging_copydir(l, targetdir, dest, seendirs)
556 continue
557 staging_copyfile(l, targetdir, dest, postinsts, seendirs)
558
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500559 bb.note("Installed into sysroot: %s" % str(msg_adding))
560 bb.note("Skipping as already exists in sysroot: %s" % str(msg_exists))
561
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500562 for f in fixme:
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700563 staging_processfixme(fixme[f], f, recipesysroot, recipesysrootnative, d)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500564
565 for p in postinsts:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400566 subprocess.check_output(p, shell=True, stderr=subprocess.STDOUT)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500567
568 for dep in manifests:
569 c = setscenedeps[dep][0]
570 os.symlink(manifests[dep], depdir + "/" + c + ".complete")
571
572 with open(taskindex, "w") as f:
573 for l in sorted(installed):
574 f.write(l + "\n")
575
576 bb.utils.unlockfile(lock)
577}
578extend_recipe_sysroot[vardepsexclude] += "MACHINE_ARCH PACKAGE_EXTRA_ARCHS SDK_ARCH BUILD_ARCH SDK_OS BB_TASKDEPDATA"
579
Brad Bishop19323692019-04-05 15:28:33 -0400580do_prepare_recipe_sysroot[deptask] = "do_populate_sysroot"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500581python do_prepare_recipe_sysroot () {
582 bb.build.exec_func("extend_recipe_sysroot", d)
583}
584addtask do_prepare_recipe_sysroot before do_configure after do_fetch
585
586# Clean out the recipe specific sysroots before do_fetch
587# (use a prefunc so we can order before extend_recipe_sysroot if it gets added)
588python clean_recipe_sysroot() {
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500589 # We remove these stamps since we're removing any content they'd have added with
590 # cleandirs. This removes the sigdata too, likely not a big deal,
591 oe.path.remove(d.getVar("STAMP") + "*addto_recipe_sysroot*")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500592 return
593}
594clean_recipe_sysroot[cleandirs] += "${RECIPE_SYSROOT} ${RECIPE_SYSROOT_NATIVE}"
595do_fetch[prefuncs] += "clean_recipe_sysroot"
596
597python staging_taskhandler() {
598 bbtasks = e.tasklist
599 for task in bbtasks:
600 deps = d.getVarFlag(task, "depends")
601 if deps and "populate_sysroot" in deps:
602 d.appendVarFlag(task, "prefuncs", " extend_recipe_sysroot")
603}
604staging_taskhandler[eventmask] = "bb.event.RecipeTaskPreProcess"
605addhandler staging_taskhandler