blob: 25f77c77350fc6f7660277a3e98942fcac5344ac [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} \
Andrew Geisslerd1e89492021-02-12 15:35:20 -06008 /sysroot-only \
Patrick Williamsc0f7c042017-02-23 20:41:17 -06009"
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"
Patrick Williams213cb262021-08-07 19:21:33 -050022SYSROOT_DIRS:append:class-native = " ${SYSROOT_DIRS_NATIVE}"
23SYSROOT_DIRS:append:class-cross = " ${SYSROOT_DIRS_NATIVE}"
24SYSROOT_DIRS:append:class-crosssdk = " ${SYSROOT_DIRS_NATIVE}"
Patrick Williamsc0f7c042017-02-23 20:41:17 -060025
26# These directories will not be staged in the sysroot
27SYSROOT_DIRS_BLACKLIST = " \
28 ${mandir} \
29 ${docdir} \
30 ${infodir} \
Andrew Geisslerd1e89492021-02-12 15:35:20 -060031 ${datadir}/X11/locale \
Patrick Williamsc0f7c042017-02-23 20:41:17 -060032 ${datadir}/applications \
Andrew Geisslerd1e89492021-02-12 15:35:20 -060033 ${datadir}/bash-completion \
Patrick Williamsc0f7c042017-02-23 20:41:17 -060034 ${datadir}/fonts \
Brad Bishopc342db32019-05-15 21:57:59 -040035 ${datadir}/gtk-doc/html \
Andrew Geisslerd1e89492021-02-12 15:35:20 -060036 ${datadir}/installed-tests \
Brad Bishopc342db32019-05-15 21:57:59 -040037 ${datadir}/locale \
Patrick Williamsc0f7c042017-02-23 20:41:17 -060038 ${datadir}/pixmaps \
Andrew Geisslerd1e89492021-02-12 15:35:20 -060039 ${datadir}/terminfo \
Andrew Geissler82c905d2020-04-13 13:39:40 -050040 ${libdir}/${BPN}/ptest \
Patrick Williamsc0f7c042017-02-23 20:41:17 -060041"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050042
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 (
53 cd $src
54 find . -print0 | cpio --null -pdlu $dest
55 )
56}
57
Patrick Williamsc124f4f2015-09-15 14:41:29 -050058sysroot_stage_dirs() {
59 from="$1"
60 to="$2"
61
Patrick Williamsc0f7c042017-02-23 20:41:17 -060062 for dir in ${SYSROOT_DIRS}; do
63 sysroot_stage_dir "$from$dir" "$to$dir"
64 done
65
66 # Remove directories we do not care about
67 for dir in ${SYSROOT_DIRS_BLACKLIST}; do
68 rm -rf "$to$dir"
69 done
Patrick Williamsc124f4f2015-09-15 14:41:29 -050070}
71
72sysroot_stage_all() {
73 sysroot_stage_dirs ${D} ${SYSROOT_DESTDIR}
74}
75
76python sysroot_strip () {
Brad Bishopd7bf8c12018-02-25 22:55:05 -050077 inhibit_sysroot = d.getVar('INHIBIT_SYSROOT_STRIP')
78 if inhibit_sysroot and oe.types.boolean(inhibit_sysroot):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080079 return
Patrick Williamsc124f4f2015-09-15 14:41:29 -050080
Brad Bishopd7bf8c12018-02-25 22:55:05 -050081 dstdir = d.getVar('SYSROOT_DESTDIR')
Brad Bishop6e60e8b2018-02-01 10:27:11 -050082 pn = d.getVar('PN')
Andrew Geissler82c905d2020-04-13 13:39:40 -050083 libdir = d.getVar("libdir")
84 base_libdir = d.getVar("base_libdir")
Patrick Williams213cb262021-08-07 19:21:33 -050085 qa_already_stripped = 'already-stripped' in (d.getVar('INSANE_SKIP:' + pn) or "").split()
Brad Bishopd7bf8c12018-02-25 22:55:05 -050086 strip_cmd = d.getVar("STRIP")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050087
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080088 oe.package.strip_execs(pn, dstdir, strip_cmd, libdir, base_libdir, d,
Brad Bishopd7bf8c12018-02-25 22:55:05 -050089 qa_already_stripped=qa_already_stripped)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050090}
91
92do_populate_sysroot[dirs] = "${SYSROOT_DESTDIR}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050093
94addtask populate_sysroot after do_install
95
96SYSROOT_PREPROCESS_FUNCS ?= ""
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050097SYSROOT_DESTDIR = "${WORKDIR}/sysroot-destdir"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050098
Patrick Williamsc124f4f2015-09-15 14:41:29 -050099python do_populate_sysroot () {
Andrew Geissler4b740dc2020-05-05 08:54:39 -0500100 # SYSROOT 'version' 2
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500101 bb.build.exec_func("sysroot_stage_all", d)
102 bb.build.exec_func("sysroot_strip", d)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500103 for f in (d.getVar('SYSROOT_PREPROCESS_FUNCS') or '').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500104 bb.build.exec_func(f, d)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500105 pn = d.getVar("PN")
106 multiprov = d.getVar("MULTI_PROVIDER_WHITELIST").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500107 provdir = d.expand("${SYSROOT_DESTDIR}${base_prefix}/sysroot-providers/")
108 bb.utils.mkdirhier(provdir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500109 for p in d.getVar("PROVIDES").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500110 if p in multiprov:
111 continue
112 p = p.replace("/", "_")
113 with open(provdir + p, "w") as f:
114 f.write(pn)
115}
116
117do_populate_sysroot[vardeps] += "${SYSROOT_PREPROCESS_FUNCS}"
118do_populate_sysroot[vardepsexclude] += "MULTI_PROVIDER_WHITELIST"
119
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500120POPULATESYSROOTDEPS = ""
Patrick Williams213cb262021-08-07 19:21:33 -0500121POPULATESYSROOTDEPS:class-target = "virtual/${MLPREFIX}${TARGET_PREFIX}binutils:do_populate_sysroot"
122POPULATESYSROOTDEPS:class-nativesdk = "virtual/${TARGET_PREFIX}binutils-crosssdk:do_populate_sysroot"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500123do_populate_sysroot[depends] += "${POPULATESYSROOTDEPS}"
124
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500125SSTATETASKS += "do_populate_sysroot"
126do_populate_sysroot[cleandirs] = "${SYSROOT_DESTDIR}"
127do_populate_sysroot[sstate-inputdirs] = "${SYSROOT_DESTDIR}"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500128do_populate_sysroot[sstate-outputdirs] = "${COMPONENTS_DIR}/${PACKAGE_ARCH}/${PN}"
129do_populate_sysroot[sstate-fixmedir] = "${COMPONENTS_DIR}/${PACKAGE_ARCH}/${PN}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500130
131python do_populate_sysroot_setscene () {
132 sstate_setscene(d)
133}
134addtask do_populate_sysroot_setscene
135
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500136def staging_copyfile(c, target, dest, postinsts, seendirs):
137 import errno
138
139 destdir = os.path.dirname(dest)
140 if destdir not in seendirs:
141 bb.utils.mkdirhier(destdir)
142 seendirs.add(destdir)
143 if "/usr/bin/postinst-" in c:
144 postinsts.append(dest)
145 if os.path.islink(c):
146 linkto = os.readlink(c)
147 if os.path.lexists(dest):
148 if not os.path.islink(dest):
149 raise OSError(errno.EEXIST, "Link %s already exists as a file" % dest, dest)
150 if os.readlink(dest) == linkto:
151 return dest
152 raise OSError(errno.EEXIST, "Link %s already exists to a different location? (%s vs %s)" % (dest, os.readlink(dest), linkto), dest)
153 os.symlink(linkto, dest)
154 #bb.warn(c)
155 else:
156 try:
157 os.link(c, dest)
158 except OSError as err:
159 if err.errno == errno.EXDEV:
160 bb.utils.copyfile(c, dest)
161 else:
162 raise
163 return dest
164
165def staging_copydir(c, target, dest, seendirs):
166 if dest not in seendirs:
167 bb.utils.mkdirhier(dest)
168 seendirs.add(dest)
169
170def staging_processfixme(fixme, target, recipesysroot, recipesysrootnative, d):
171 import subprocess
172
173 if not fixme:
174 return
175 cmd = "sed -e 's:^[^/]*/:%s/:g' %s | xargs sed -i -e 's:FIXMESTAGINGDIRTARGET:%s:g; s:FIXMESTAGINGDIRHOST:%s:g'" % (target, " ".join(fixme), recipesysroot, recipesysrootnative)
Brad Bishop15ae2502019-06-18 21:44:24 -0400176 for fixmevar in ['PSEUDO_SYSROOT', 'HOSTTOOLS_DIR', 'PKGDATA_DIR', 'PSEUDO_LOCALSTATEDIR', 'LOGFIFO']:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500177 fixme_path = d.getVar(fixmevar)
178 cmd += " -e 's:FIXME_%s:%s:g'" % (fixmevar, fixme_path)
179 bb.debug(2, cmd)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400180 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500181
182
183def staging_populate_sysroot_dir(targetsysroot, nativesysroot, native, d):
184 import glob
185 import subprocess
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500186 import errno
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500187
188 fixme = []
189 postinsts = []
190 seendirs = set()
191 stagingdir = d.getVar("STAGING_DIR")
192 if native:
193 pkgarchs = ['${BUILD_ARCH}', '${BUILD_ARCH}_*']
194 targetdir = nativesysroot
195 else:
196 pkgarchs = ['${MACHINE_ARCH}']
197 pkgarchs = pkgarchs + list(reversed(d.getVar("PACKAGE_EXTRA_ARCHS").split()))
198 pkgarchs.append('allarch')
199 targetdir = targetsysroot
200
201 bb.utils.mkdirhier(targetdir)
202 for pkgarch in pkgarchs:
203 for manifest in glob.glob(d.expand("${SSTATE_MANIFESTS}/manifest-%s-*.populate_sysroot" % pkgarch)):
204 if manifest.endswith("-initial.populate_sysroot"):
Brad Bishop79641f22019-09-10 07:20:22 -0400205 # skip libgcc-initial due to file overlap
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500206 continue
Brad Bishop19323692019-04-05 15:28:33 -0400207 if not native and (manifest.endswith("-native.populate_sysroot") or "nativesdk-" in manifest):
208 continue
209 if native and not (manifest.endswith("-native.populate_sysroot") or manifest.endswith("-cross.populate_sysroot") or "-cross-" in manifest):
210 continue
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500211 tmanifest = targetdir + "/" + os.path.basename(manifest)
212 if os.path.exists(tmanifest):
213 continue
214 try:
215 os.link(manifest, tmanifest)
216 except OSError as err:
217 if err.errno == errno.EXDEV:
218 bb.utils.copyfile(manifest, tmanifest)
219 else:
220 raise
221 with open(manifest, "r") as f:
222 for l in f:
223 l = l.strip()
224 if l.endswith("/fixmepath"):
225 fixme.append(l)
226 continue
227 if l.endswith("/fixmepath.cmd"):
228 continue
229 dest = l.replace(stagingdir, "")
230 dest = targetdir + "/" + "/".join(dest.split("/")[3:])
231 if l.endswith("/"):
232 staging_copydir(l, targetdir, dest, seendirs)
233 continue
234 try:
235 staging_copyfile(l, targetdir, dest, postinsts, seendirs)
236 except FileExistsError:
237 continue
238
239 staging_processfixme(fixme, targetdir, targetsysroot, nativesysroot, d)
240 for p in postinsts:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400241 subprocess.check_output(p, shell=True, stderr=subprocess.STDOUT)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500242
243#
244# Manifests here are complicated. The main sysroot area has the unpacked sstate
245# which us unrelocated and tracked by the main sstate manifests. Each recipe
246# specific sysroot has manifests for each dependency that is installed there.
247# The task hash is used to tell whether the data needs to be reinstalled. We
248# use a symlink to point to the currently installed hash. There is also a
249# "complete" stamp file which is used to mark if installation completed. If
250# something fails (e.g. a postinst), this won't get written and we would
251# remove and reinstall the dependency. This also means partially installed
252# dependencies should get cleaned up correctly.
253#
254
255python extend_recipe_sysroot() {
256 import copy
257 import subprocess
258 import errno
259 import collections
260 import glob
261
262 taskdepdata = d.getVar("BB_TASKDEPDATA", False)
263 mytaskname = d.getVar("BB_RUNTASK")
264 if mytaskname.endswith("_setscene"):
265 mytaskname = mytaskname.replace("_setscene", "")
266 workdir = d.getVar("WORKDIR")
267 #bb.warn(str(taskdepdata))
268 pn = d.getVar("PN")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500269 stagingdir = d.getVar("STAGING_DIR")
270 sharedmanifests = d.getVar("COMPONENTS_DIR") + "/manifests"
271 recipesysroot = d.getVar("RECIPE_SYSROOT")
272 recipesysrootnative = d.getVar("RECIPE_SYSROOT_NATIVE")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500273
274 # Detect bitbake -b usage
275 nodeps = d.getVar("BB_LIMITEDDEPS") or False
276 if nodeps:
277 lock = bb.utils.lockfile(recipesysroot + "/sysroot.lock")
278 staging_populate_sysroot_dir(recipesysroot, recipesysrootnative, True, d)
279 staging_populate_sysroot_dir(recipesysroot, recipesysrootnative, False, d)
280 bb.utils.unlockfile(lock)
281 return
282
283 start = None
284 configuredeps = []
Andrew Geissler82c905d2020-04-13 13:39:40 -0500285 owntaskdeps = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500286 for dep in taskdepdata:
287 data = taskdepdata[dep]
288 if data[1] == mytaskname and data[0] == pn:
289 start = dep
Andrew Geissler82c905d2020-04-13 13:39:40 -0500290 elif data[0] == pn:
291 owntaskdeps.append(data[1])
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500292 if start is None:
293 bb.fatal("Couldn't find ourself in BB_TASKDEPDATA?")
294
295 # We need to figure out which sysroot files we need to expose to this task.
296 # This needs to match what would get restored from sstate, which is controlled
297 # ultimately by calls from bitbake to setscene_depvalid().
298 # That function expects a setscene dependency tree. We build a dependency tree
299 # condensed to inter-sstate task dependencies, similar to that used by setscene
300 # tasks. We can then call into setscene_depvalid() and decide
301 # which dependencies we can "see" and should expose in the recipe specific sysroot.
302 setscenedeps = copy.deepcopy(taskdepdata)
303
304 start = set([start])
305
306 sstatetasks = d.getVar("SSTATETASKS").split()
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800307 # Add recipe specific tasks referenced by setscene_depvalid()
308 sstatetasks.append("do_stash_locale")
Andrew Geissler5199d832021-09-24 16:47:35 -0500309 sstatetasks.append("do_deploy")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500310
311 def print_dep_tree(deptree):
312 data = ""
313 for dep in deptree:
314 deps = " " + "\n ".join(deptree[dep][3]) + "\n"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800315 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 -0500316 return data
317
318 #bb.note("Full dep tree is:\n%s" % print_dep_tree(taskdepdata))
319
320 #bb.note(" start2 is %s" % str(start))
321
322 # If start is an sstate task (like do_package) we need to add in its direct dependencies
323 # else the code below won't recurse into them.
324 for dep in set(start):
325 for dep2 in setscenedeps[dep][3]:
326 start.add(dep2)
327 start.remove(dep)
328
329 #bb.note(" start3 is %s" % str(start))
330
331 # Create collapsed do_populate_sysroot -> do_populate_sysroot tree
332 for dep in taskdepdata:
333 data = setscenedeps[dep]
334 if data[1] not in sstatetasks:
335 for dep2 in setscenedeps:
336 data2 = setscenedeps[dep2]
337 if dep in data2[3]:
338 data2[3].update(setscenedeps[dep][3])
339 data2[3].remove(dep)
340 if dep in start:
341 start.update(setscenedeps[dep][3])
342 start.remove(dep)
343 del setscenedeps[dep]
344
345 # Remove circular references
346 for dep in setscenedeps:
347 if dep in setscenedeps[dep][3]:
348 setscenedeps[dep][3].remove(dep)
349
350 #bb.note("Computed dep tree is:\n%s" % print_dep_tree(setscenedeps))
351 #bb.note(" start is %s" % str(start))
352
353 # Direct dependencies should be present and can be depended upon
354 for dep in set(start):
355 if setscenedeps[dep][1] == "do_populate_sysroot":
356 if dep not in configuredeps:
357 configuredeps.append(dep)
358 bb.note("Direct dependencies are %s" % str(configuredeps))
359 #bb.note(" or %s" % str(start))
360
361 msgbuf = []
362 # Call into setscene_depvalid for each sub-dependency and only copy sysroot files
363 # for ones that would be restored from sstate.
364 done = list(start)
365 next = list(start)
366 while next:
367 new = []
368 for dep in next:
369 data = setscenedeps[dep]
370 for datadep in data[3]:
371 if datadep in done:
372 continue
373 taskdeps = {}
374 taskdeps[dep] = setscenedeps[dep][:2]
375 taskdeps[datadep] = setscenedeps[datadep][:2]
376 retval = setscene_depvalid(datadep, taskdeps, [], d, msgbuf)
377 if retval:
378 msgbuf.append("Skipping setscene dependency %s for installation into the sysroot" % datadep)
379 continue
380 done.append(datadep)
381 new.append(datadep)
382 if datadep not in configuredeps and setscenedeps[datadep][1] == "do_populate_sysroot":
383 configuredeps.append(datadep)
384 msgbuf.append("Adding dependency on %s" % setscenedeps[datadep][0])
385 else:
386 msgbuf.append("Following dependency on %s" % setscenedeps[datadep][0])
387 next = new
388
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500389 # This logging is too verbose for day to day use sadly
390 #bb.debug(2, "\n".join(msgbuf))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500391
392 depdir = recipesysrootnative + "/installeddeps"
393 bb.utils.mkdirhier(depdir)
394 bb.utils.mkdirhier(sharedmanifests)
395
396 lock = bb.utils.lockfile(recipesysroot + "/sysroot.lock")
397
398 fixme = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500399 seendirs = set()
400 postinsts = []
401 multilibs = {}
402 manifests = {}
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500403 # All files that we're going to be installing, to find conflicts.
404 fileset = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500405
406 for f in os.listdir(depdir):
407 if not f.endswith(".complete"):
408 continue
409 f = depdir + "/" + f
410 if os.path.islink(f) and not os.path.exists(f):
411 bb.note("%s no longer exists, removing from sysroot" % f)
412 lnk = os.readlink(f.replace(".complete", ""))
Andrew Geissler5f350902021-07-23 13:09:54 -0400413 sstate_clean_manifest(depdir + "/" + lnk, d, canrace=True, prefix=workdir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500414 os.unlink(f)
415 os.unlink(f.replace(".complete", ""))
416
417 installed = []
418 for dep in configuredeps:
419 c = setscenedeps[dep][0]
420 if mytaskname in ["do_sdk_depends", "do_populate_sdk_ext"] and c.endswith("-initial"):
421 bb.note("Skipping initial setscene dependency %s for installation into the sysroot" % c)
422 continue
423 installed.append(c)
424
425 # We want to remove anything which this task previously installed but is no longer a dependency
426 taskindex = depdir + "/" + "index." + mytaskname
427 if os.path.exists(taskindex):
428 potential = []
429 with open(taskindex, "r") as f:
430 for l in f:
431 l = l.strip()
432 if l not in installed:
433 fl = depdir + "/" + l
434 if not os.path.exists(fl):
435 # Was likely already uninstalled
436 continue
437 potential.append(l)
Andrew Geissler82c905d2020-04-13 13:39:40 -0500438 # We need to ensure no other task needs this dependency. We hold the sysroot
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500439 # lock so we ca search the indexes to check
440 if potential:
441 for i in glob.glob(depdir + "/index.*"):
442 if i.endswith("." + mytaskname):
443 continue
444 with open(i, "r") as f:
445 for l in f:
Andrew Geissler82c905d2020-04-13 13:39:40 -0500446 if l.startswith("TaskDeps:"):
447 prevtasks = l.split()[1:]
448 if mytaskname in prevtasks:
449 # We're a dependency of this task so we can clear items out the sysroot
450 break
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500451 l = l.strip()
452 if l in potential:
453 potential.remove(l)
454 for l in potential:
455 fl = depdir + "/" + l
456 bb.note("Task %s no longer depends on %s, removing from sysroot" % (mytaskname, l))
457 lnk = os.readlink(fl)
Andrew Geissler5f350902021-07-23 13:09:54 -0400458 sstate_clean_manifest(depdir + "/" + lnk, d, canrace=True, prefix=workdir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500459 os.unlink(fl)
460 os.unlink(fl + ".complete")
461
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500462 msg_exists = []
463 msg_adding = []
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800464
Brad Bishop1d80a2e2019-11-15 16:35:03 -0500465 # Handle all removals first since files may move between recipes
466 for dep in configuredeps:
467 c = setscenedeps[dep][0]
468 if c not in installed:
469 continue
470 taskhash = setscenedeps[dep][5]
471 taskmanifest = depdir + "/" + c + "." + taskhash
472
473 if os.path.exists(depdir + "/" + c):
474 lnk = os.readlink(depdir + "/" + c)
475 if lnk == c + "." + taskhash and os.path.exists(depdir + "/" + c + ".complete"):
476 continue
477 else:
478 bb.note("%s exists in sysroot, but is stale (%s vs. %s), removing." % (c, lnk, c + "." + taskhash))
Andrew Geissler5f350902021-07-23 13:09:54 -0400479 sstate_clean_manifest(depdir + "/" + lnk, d, canrace=True, prefix=workdir)
Brad Bishop1d80a2e2019-11-15 16:35:03 -0500480 os.unlink(depdir + "/" + c)
481 if os.path.lexists(depdir + "/" + c + ".complete"):
482 os.unlink(depdir + "/" + c + ".complete")
483 elif os.path.lexists(depdir + "/" + c):
484 os.unlink(depdir + "/" + c)
485
Andrew Geissler82c905d2020-04-13 13:39:40 -0500486 binfiles = {}
Brad Bishop1d80a2e2019-11-15 16:35:03 -0500487 # Now handle installs
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500488 for dep in configuredeps:
489 c = setscenedeps[dep][0]
490 if c not in installed:
491 continue
492 taskhash = setscenedeps[dep][5]
493 taskmanifest = depdir + "/" + c + "." + taskhash
494
495 if os.path.exists(depdir + "/" + c):
496 lnk = os.readlink(depdir + "/" + c)
497 if lnk == c + "." + taskhash and os.path.exists(depdir + "/" + c + ".complete"):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500498 msg_exists.append(c)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500499 continue
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500500
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500501 msg_adding.append(c)
502
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500503 os.symlink(c + "." + taskhash, depdir + "/" + c)
504
Brad Bishop316dfdd2018-06-25 12:45:53 -0400505 manifest, d2 = oe.sstatesig.find_sstate_manifest(c, setscenedeps[dep][2], "populate_sysroot", d, multilibs)
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700506 if d2 is not d:
507 # If we don't do this, the recipe sysroot will be placed in the wrong WORKDIR for multilibs
508 # We need a consistent WORKDIR for the image
509 d2.setVar("WORKDIR", d.getVar("WORKDIR"))
Brad Bishop316dfdd2018-06-25 12:45:53 -0400510 destsysroot = d2.getVar("RECIPE_SYSROOT")
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700511 # We put allarch recipes into the default sysroot
512 if manifest and "allarch" in manifest:
513 destsysroot = d.getVar("RECIPE_SYSROOT")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500514
515 native = False
Brad Bishop316dfdd2018-06-25 12:45:53 -0400516 if c.endswith("-native") or "-cross-" in c or "-crosssdk" in c:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500517 native = True
Brad Bishop316dfdd2018-06-25 12:45:53 -0400518
519 if manifest:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500520 newmanifest = collections.OrderedDict()
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700521 targetdir = destsysroot
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500522 if native:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500523 targetdir = recipesysrootnative
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700524 if targetdir not in fixme:
525 fixme[targetdir] = []
526 fm = fixme[targetdir]
527
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500528 with open(manifest, "r") as f:
529 manifests[dep] = manifest
530 for l in f:
531 l = l.strip()
532 if l.endswith("/fixmepath"):
533 fm.append(l)
534 continue
535 if l.endswith("/fixmepath.cmd"):
536 continue
537 dest = l.replace(stagingdir, "")
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500538 dest = "/" + "/".join(dest.split("/")[3:])
539 newmanifest[l] = targetdir + dest
540
541 # Check if files have already been installed by another
542 # recipe and abort if they have, explaining what recipes are
543 # conflicting.
544 hashname = targetdir + dest
545 if not hashname.endswith("/"):
546 if hashname in fileset:
547 bb.fatal("The file %s is installed by both %s and %s, aborting" % (dest, c, fileset[hashname]))
548 else:
549 fileset[hashname] = c
550
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500551 # Having multiple identical manifests in each sysroot eats diskspace so
552 # create a shared pool of them and hardlink if we can.
553 # We create the manifest in advance so that if something fails during installation,
554 # or the build is interrupted, subsequent exeuction can cleanup.
555 sharedm = sharedmanifests + "/" + os.path.basename(taskmanifest)
556 if not os.path.exists(sharedm):
557 smlock = bb.utils.lockfile(sharedm + ".lock")
558 # Can race here. You'd think it just means we may not end up with all copies hardlinked to each other
559 # but python can lose file handles so we need to do this under a lock.
560 if not os.path.exists(sharedm):
561 with open(sharedm, 'w') as m:
562 for l in newmanifest:
563 dest = newmanifest[l]
564 m.write(dest.replace(workdir + "/", "") + "\n")
565 bb.utils.unlockfile(smlock)
566 try:
567 os.link(sharedm, taskmanifest)
568 except OSError as err:
569 if err.errno == errno.EXDEV:
570 bb.utils.copyfile(sharedm, taskmanifest)
571 else:
572 raise
573 # Finally actually install the files
574 for l in newmanifest:
575 dest = newmanifest[l]
576 if l.endswith("/"):
577 staging_copydir(l, targetdir, dest, seendirs)
578 continue
Andrew Geissler82c905d2020-04-13 13:39:40 -0500579 if "/bin/" in l or "/sbin/" in l:
580 # defer /*bin/* files until last in case they need libs
581 binfiles[l] = (targetdir, dest)
582 else:
583 staging_copyfile(l, targetdir, dest, postinsts, seendirs)
584
585 # Handle deferred binfiles
586 for l in binfiles:
587 (targetdir, dest) = binfiles[l]
588 staging_copyfile(l, targetdir, dest, postinsts, seendirs)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500589
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500590 bb.note("Installed into sysroot: %s" % str(msg_adding))
591 bb.note("Skipping as already exists in sysroot: %s" % str(msg_exists))
592
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500593 for f in fixme:
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700594 staging_processfixme(fixme[f], f, recipesysroot, recipesysrootnative, d)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500595
596 for p in postinsts:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400597 subprocess.check_output(p, shell=True, stderr=subprocess.STDOUT)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500598
599 for dep in manifests:
600 c = setscenedeps[dep][0]
601 os.symlink(manifests[dep], depdir + "/" + c + ".complete")
602
603 with open(taskindex, "w") as f:
Andrew Geissler82c905d2020-04-13 13:39:40 -0500604 f.write("TaskDeps: " + " ".join(owntaskdeps) + "\n")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500605 for l in sorted(installed):
606 f.write(l + "\n")
607
608 bb.utils.unlockfile(lock)
609}
610extend_recipe_sysroot[vardepsexclude] += "MACHINE_ARCH PACKAGE_EXTRA_ARCHS SDK_ARCH BUILD_ARCH SDK_OS BB_TASKDEPDATA"
611
Brad Bishop19323692019-04-05 15:28:33 -0400612do_prepare_recipe_sysroot[deptask] = "do_populate_sysroot"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500613python do_prepare_recipe_sysroot () {
614 bb.build.exec_func("extend_recipe_sysroot", d)
615}
616addtask do_prepare_recipe_sysroot before do_configure after do_fetch
617
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500618python staging_taskhandler() {
619 bbtasks = e.tasklist
620 for task in bbtasks:
621 deps = d.getVarFlag(task, "depends")
Andrew Geisslerc3d88e42020-10-02 09:45:00 -0500622 if task == "do_configure" or (deps and "populate_sysroot" in deps):
Andrew Geisslereff27472021-10-29 15:35:00 -0500623 d.prependVarFlag(task, "prefuncs", "extend_recipe_sysroot ")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500624}
625staging_taskhandler[eventmask] = "bb.event.RecipeTaskPreProcess"
626addhandler staging_taskhandler