blob: 5b92c5485a28136f1df0e3397092009cfdd61bcd [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001SSTATE_VERSION = "3"
2
3SSTATE_MANIFESTS ?= "${TMPDIR}/sstate-control"
4SSTATE_MANFILEPREFIX = "${SSTATE_MANIFESTS}/manifest-${SSTATE_MANMACH}-${PN}"
5
6def generate_sstatefn(spec, hash, d):
7 if not hash:
8 hash = "INVALID"
9 return hash[:2] + "/" + spec + hash
10
11SSTATE_PKGARCH = "${PACKAGE_ARCH}"
12SSTATE_PKGSPEC = "sstate:${PN}:${PACKAGE_ARCH}${TARGET_VENDOR}-${TARGET_OS}:${PV}:${PR}:${SSTATE_PKGARCH}:${SSTATE_VERSION}:"
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050013SSTATE_SWSPEC = "sstate:${PN}::${PV}:${PR}::${SSTATE_VERSION}:"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050014SSTATE_PKGNAME = "${SSTATE_EXTRAPATH}${@generate_sstatefn(d.getVar('SSTATE_PKGSPEC', True), d.getVar('BB_TASKHASH', True), d)}"
15SSTATE_PKG = "${SSTATE_DIR}/${SSTATE_PKGNAME}"
16SSTATE_EXTRAPATH = ""
17SSTATE_EXTRAPATHWILDCARD = ""
18SSTATE_PATHSPEC = "${SSTATE_DIR}/${SSTATE_EXTRAPATHWILDCARD}*/${SSTATE_PKGSPEC}"
19
Patrick Williamsc0f7c042017-02-23 20:41:17 -060020# explicitly make PV to depend on evaluated value of PV variable
21PV[vardepvalue] = "${PV}"
22
Patrick Williamsc124f4f2015-09-15 14:41:29 -050023# We don't want the sstate to depend on things like the distro string
24# of the system, we let the sstate paths take care of this.
25SSTATE_EXTRAPATH[vardepvalue] = ""
26
27# For multilib rpm the allarch packagegroup files can overwrite (in theory they're identical)
28SSTATE_DUPWHITELIST = "${DEPLOY_DIR_IMAGE}/ ${DEPLOY_DIR}/licenses/ ${DEPLOY_DIR_RPM}/all/"
29# Avoid docbook/sgml catalog warnings for now
30SSTATE_DUPWHITELIST += "${STAGING_ETCDIR_NATIVE}/sgml ${STAGING_DATADIR_NATIVE}/sgml"
31# Archive the sources for many architectures in one deploy folder
32SSTATE_DUPWHITELIST += "${DEPLOY_DIR_SRC}"
33
34SSTATE_SCAN_FILES ?= "*.la *-config *_config"
35SSTATE_SCAN_CMD ?= 'find ${SSTATE_BUILDDIR} \( -name "${@"\" -o -name \"".join(d.getVar("SSTATE_SCAN_FILES", True).split())}" \) -type f'
36
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050037BB_HASHFILENAME = "False ${SSTATE_PKGSPEC} ${SSTATE_SWSPEC}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050038
39SSTATE_ARCHS = " \
40 ${BUILD_ARCH} \
41 ${BUILD_ARCH}_${SDK_ARCH}_${SDK_OS} \
42 ${BUILD_ARCH}_${TARGET_ARCH} \
43 ${SDK_ARCH}_${SDK_OS} \
44 ${SDK_ARCH}_${PACKAGE_ARCH} \
45 allarch \
46 ${PACKAGE_ARCH} \
47 ${MACHINE}"
48
49SSTATE_MANMACH ?= "${SSTATE_PKGARCH}"
50
51SSTATECREATEFUNCS = "sstate_hardcode_path"
52SSTATEPOSTCREATEFUNCS = ""
53SSTATEPREINSTFUNCS = ""
54SSTATEPOSTUNPACKFUNCS = "sstate_hardcode_path_unpack"
55SSTATEPOSTINSTFUNCS = ""
56EXTRA_STAGING_FIXMES ?= ""
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050057SSTATECLEANFUNCS = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -050058
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050059# Check whether sstate exists for tasks that support sstate and are in the
60# locked signatures file.
61SIGGEN_LOCKEDSIGS_SSTATE_EXISTS_CHECK ?= 'error'
62
63# Check whether the task's computed hash matches the task's hash in the
64# locked signatures file.
65SIGGEN_LOCKEDSIGS_TASKSIG_CHECK ?= "error"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050066
67# The GnuPG key ID and passphrase to use to sign sstate archives (or unset to
68# not sign)
69SSTATE_SIG_KEY ?= ""
70SSTATE_SIG_PASSPHRASE ?= ""
71# Whether to verify the GnUPG signatures when extracting sstate archives
72SSTATE_VERIFY_SIG ?= "0"
73
Patrick Williamsc124f4f2015-09-15 14:41:29 -050074python () {
75 if bb.data.inherits_class('native', d):
76 d.setVar('SSTATE_PKGARCH', d.getVar('BUILD_ARCH', False))
77 elif bb.data.inherits_class('crosssdk', d):
78 d.setVar('SSTATE_PKGARCH', d.expand("${BUILD_ARCH}_${SDK_ARCH}_${SDK_OS}"))
79 elif bb.data.inherits_class('cross', d):
80 d.setVar('SSTATE_PKGARCH', d.expand("${BUILD_ARCH}_${TARGET_ARCH}"))
81 elif bb.data.inherits_class('nativesdk', d):
82 d.setVar('SSTATE_PKGARCH', d.expand("${SDK_ARCH}_${SDK_OS}"))
83 elif bb.data.inherits_class('cross-canadian', d):
84 d.setVar('SSTATE_PKGARCH', d.expand("${SDK_ARCH}_${PACKAGE_ARCH}"))
85 elif bb.data.inherits_class('allarch', d) and d.getVar("PACKAGE_ARCH", True) == "all":
86 d.setVar('SSTATE_PKGARCH', "allarch")
87 else:
88 d.setVar('SSTATE_MANMACH', d.expand("${PACKAGE_ARCH}"))
89
90 if bb.data.inherits_class('native', d) or bb.data.inherits_class('crosssdk', d) or bb.data.inherits_class('cross', d):
91 d.setVar('SSTATE_EXTRAPATH', "${NATIVELSBSTRING}/")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050092 d.setVar('BB_HASHFILENAME', "True ${SSTATE_PKGSPEC} ${SSTATE_SWSPEC}")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050093 d.setVar('SSTATE_EXTRAPATHWILDCARD', "*/")
94
95 # These classes encode staging paths into their scripts data so can only be
96 # reused if we manipulate the paths
97 if bb.data.inherits_class('native', d) or bb.data.inherits_class('cross', d) or bb.data.inherits_class('sdk', d) or bb.data.inherits_class('crosssdk', d):
98 scan_cmd = "grep -Irl ${STAGING_DIR} ${SSTATE_BUILDDIR}"
99 d.setVar('SSTATE_SCAN_CMD', scan_cmd)
100
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600101 unique_tasks = sorted(set((d.getVar('SSTATETASKS', True) or "").split()))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500102 d.setVar('SSTATETASKS', " ".join(unique_tasks))
103 for task in unique_tasks:
104 d.prependVarFlag(task, 'prefuncs', "sstate_task_prefunc ")
105 d.appendVarFlag(task, 'postfuncs', " sstate_task_postfunc")
106}
107
108def sstate_init(task, d):
109 ss = {}
110 ss['task'] = task
111 ss['dirs'] = []
112 ss['plaindirs'] = []
113 ss['lockfiles'] = []
114 ss['lockfiles-shared'] = []
115 return ss
116
117def sstate_state_fromvars(d, task = None):
118 if task is None:
119 task = d.getVar('BB_CURRENTTASK', True)
120 if not task:
121 bb.fatal("sstate code running without task context?!")
122 task = task.replace("_setscene", "")
123
124 if task.startswith("do_"):
125 task = task[3:]
126 inputs = (d.getVarFlag("do_" + task, 'sstate-inputdirs', True) or "").split()
127 outputs = (d.getVarFlag("do_" + task, 'sstate-outputdirs', True) or "").split()
128 plaindirs = (d.getVarFlag("do_" + task, 'sstate-plaindirs', True) or "").split()
129 lockfiles = (d.getVarFlag("do_" + task, 'sstate-lockfile', True) or "").split()
130 lockfilesshared = (d.getVarFlag("do_" + task, 'sstate-lockfile-shared', True) or "").split()
131 interceptfuncs = (d.getVarFlag("do_" + task, 'sstate-interceptfuncs', True) or "").split()
132 if not task or len(inputs) != len(outputs):
133 bb.fatal("sstate variables not setup correctly?!")
134
135 if task == "populate_lic":
136 d.setVar("SSTATE_PKGSPEC", "${SSTATE_SWSPEC}")
137 d.setVar("SSTATE_EXTRAPATH", "")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500138 d.setVar('SSTATE_EXTRAPATHWILDCARD', "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500139
140 ss = sstate_init(task, d)
141 for i in range(len(inputs)):
142 sstate_add(ss, inputs[i], outputs[i], d)
143 ss['lockfiles'] = lockfiles
144 ss['lockfiles-shared'] = lockfilesshared
145 ss['plaindirs'] = plaindirs
146 ss['interceptfuncs'] = interceptfuncs
147 return ss
148
149def sstate_add(ss, source, dest, d):
150 if not source.endswith("/"):
151 source = source + "/"
152 if not dest.endswith("/"):
153 dest = dest + "/"
154 source = os.path.normpath(source)
155 dest = os.path.normpath(dest)
156 srcbase = os.path.basename(source)
157 ss['dirs'].append([srcbase, source, dest])
158 return ss
159
160def sstate_install(ss, d):
161 import oe.path
162 import oe.sstatesig
163 import subprocess
164
165 sharedfiles = []
166 shareddirs = []
167 bb.utils.mkdirhier(d.expand("${SSTATE_MANIFESTS}"))
168
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500169 sstateinst = d.expand("${WORKDIR}/sstate-install-%s/" % ss['task'])
170
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500171 manifest, d2 = oe.sstatesig.sstate_get_manifest_filename(ss['task'], d)
172
173 if os.access(manifest, os.R_OK):
174 bb.fatal("Package already staged (%s)?!" % manifest)
175
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600176 d.setVar("SSTATE_INST_POSTRM", manifest + ".postrm")
177
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500178 locks = []
179 for lock in ss['lockfiles-shared']:
180 locks.append(bb.utils.lockfile(lock, True))
181 for lock in ss['lockfiles']:
182 locks.append(bb.utils.lockfile(lock))
183
184 for state in ss['dirs']:
185 bb.debug(2, "Staging files from %s to %s" % (state[1], state[2]))
186 for walkroot, dirs, files in os.walk(state[1]):
187 for file in files:
188 srcpath = os.path.join(walkroot, file)
189 dstpath = srcpath.replace(state[1], state[2])
190 #bb.debug(2, "Staging %s to %s" % (srcpath, dstpath))
191 sharedfiles.append(dstpath)
192 for dir in dirs:
193 srcdir = os.path.join(walkroot, dir)
194 dstdir = srcdir.replace(state[1], state[2])
195 #bb.debug(2, "Staging %s to %s" % (srcdir, dstdir))
196 if not dstdir.endswith("/"):
197 dstdir = dstdir + "/"
198 shareddirs.append(dstdir)
199
200 # Check the file list for conflicts against files which already exist
201 whitelist = (d.getVar("SSTATE_DUPWHITELIST", True) or "").split()
202 match = []
203 for f in sharedfiles:
204 if os.path.exists(f):
205 f = os.path.normpath(f)
206 realmatch = True
207 for w in whitelist:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600208 w = os.path.normpath(w)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500209 if f.startswith(w):
210 realmatch = False
211 break
212 if realmatch:
213 match.append(f)
214 sstate_search_cmd = "grep -rl '%s' %s --exclude=master.list | sed -e 's:^.*/::' -e 's:\.populate-sysroot::'" % (f, d.expand("${SSTATE_MANIFESTS}"))
215 search_output = subprocess.Popen(sstate_search_cmd, shell=True, stdout=subprocess.PIPE).communicate()[0]
216 if search_output != "":
217 match.append("Matched in %s" % search_output.rstrip())
218 if match:
219 bb.error("The recipe %s is trying to install files into a shared " \
220 "area when those files already exist. Those files and their manifest " \
221 "location are:\n %s\nPlease verify which recipe should provide the " \
222 "above files.\nThe build has stopped as continuing in this scenario WILL " \
223 "break things, if not now, possibly in the future (we've seen builds fail " \
224 "several months later). If the system knew how to recover from this " \
225 "automatically it would however there are several different scenarios " \
226 "which can result in this and we don't know which one this is. It may be " \
227 "you have switched providers of something like virtual/kernel (e.g. from " \
228 "linux-yocto to linux-yocto-dev), in that case you need to execute the " \
229 "clean task for both recipes and it will resolve this error. It may be " \
230 "you changed DISTRO_FEATURES from systemd to udev or vice versa. Cleaning " \
231 "those recipes should again resolve this error however switching " \
232 "DISTRO_FEATURES on an existing build directory is not supported, you " \
233 "should really clean out tmp and rebuild (reusing sstate should be safe). " \
234 "It could be the overlapping files detected are harmless in which case " \
235 "adding them to SSTATE_DUPWHITELIST may be the correct solution. It could " \
236 "also be your build is including two different conflicting versions of " \
237 "things (e.g. bluez 4 and bluez 5 and the correct solution for that would " \
238 "be to resolve the conflict. If in doubt, please ask on the mailing list, " \
239 "sharing the error and filelist above." % \
240 (d.getVar('PN', True), "\n ".join(match)))
241 bb.fatal("If the above message is too much, the simpler version is you're advised to wipe out tmp and rebuild (reusing sstate is fine). That will likely fix things in most (but not all) cases.")
242
243 # Write out the manifest
244 f = open(manifest, "w")
245 for file in sharedfiles:
246 f.write(file + "\n")
247
248 # We want to ensure that directories appear at the end of the manifest
249 # so that when we test to see if they should be deleted any contents
250 # added by the task will have been removed first.
251 dirs = sorted(shareddirs, key=len)
252 # Must remove children first, which will have a longer path than the parent
253 for di in reversed(dirs):
254 f.write(di + "\n")
255 f.close()
256
257 # Append to the list of manifests for this PACKAGE_ARCH
258
259 i = d2.expand("${SSTATE_MANIFESTS}/index-${SSTATE_MANMACH}")
260 l = bb.utils.lockfile(i + ".lock")
261 filedata = d.getVar("STAMP", True) + " " + d2.getVar("SSTATE_MANFILEPREFIX", True) + " " + d.getVar("WORKDIR", True) + "\n"
262 manifests = []
263 if os.path.exists(i):
264 with open(i, "r") as f:
265 manifests = f.readlines()
266 if filedata not in manifests:
267 with open(i, "a+") as f:
268 f.write(filedata)
269 bb.utils.unlockfile(l)
270
271 # Run the actual file install
272 for state in ss['dirs']:
273 if os.path.exists(state[1]):
274 oe.path.copyhardlinktree(state[1], state[2])
275
276 for postinst in (d.getVar('SSTATEPOSTINSTFUNCS', True) or '').split():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500277 # All hooks should run in the SSTATE_INSTDIR
278 bb.build.exec_func(postinst, d, (sstateinst,))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500279
280 for lock in locks:
281 bb.utils.unlockfile(lock)
282
283sstate_install[vardepsexclude] += "SSTATE_DUPWHITELIST STATE_MANMACH SSTATE_MANFILEPREFIX"
284sstate_install[vardeps] += "${SSTATEPOSTINSTFUNCS}"
285
286def sstate_installpkg(ss, d):
287 import oe.path
288 import subprocess
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500289 from oe.gpg_sign import get_signer
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500290
291 def prepdir(dir):
292 # remove dir if it exists, ensure any parent directories do exist
293 if os.path.exists(dir):
294 oe.path.remove(dir)
295 bb.utils.mkdirhier(dir)
296 oe.path.remove(dir)
297
298 sstateinst = d.expand("${WORKDIR}/sstate-install-%s/" % ss['task'])
299 sstatefetch = d.getVar('SSTATE_PKGNAME', True) + '_' + ss['task'] + ".tgz"
300 sstatepkg = d.getVar('SSTATE_PKG', True) + '_' + ss['task'] + ".tgz"
301
302 if not os.path.exists(sstatepkg):
303 pstaging_fetch(sstatefetch, sstatepkg, d)
304
305 if not os.path.isfile(sstatepkg):
306 bb.note("Staging package %s does not exist" % sstatepkg)
307 return False
308
309 sstate_clean(ss, d)
310
311 d.setVar('SSTATE_INSTDIR', sstateinst)
312 d.setVar('SSTATE_PKG', sstatepkg)
313
314 if bb.utils.to_boolean(d.getVar("SSTATE_VERIFY_SIG", True), False):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500315 signer = get_signer(d, 'local')
316 if not signer.verify(sstatepkg + '.sig'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500317 bb.warn("Cannot verify signature on sstate package %s" % sstatepkg)
318
319 for f in (d.getVar('SSTATEPREINSTFUNCS', True) or '').split() + ['sstate_unpack_package'] + (d.getVar('SSTATEPOSTUNPACKFUNCS', True) or '').split():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500320 # All hooks should run in the SSTATE_INSTDIR
321 bb.build.exec_func(f, d, (sstateinst,))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500322
323 for state in ss['dirs']:
324 prepdir(state[1])
325 os.rename(sstateinst + state[0], state[1])
326 sstate_install(ss, d)
327
328 for plain in ss['plaindirs']:
329 workdir = d.getVar('WORKDIR', True)
330 src = sstateinst + "/" + plain.replace(workdir, '')
331 dest = plain
332 bb.utils.mkdirhier(src)
333 prepdir(dest)
334 os.rename(src, dest)
335
336 return True
337
338python sstate_hardcode_path_unpack () {
339 # Fixup hardcoded paths
340 #
341 # Note: The logic below must match the reverse logic in
342 # sstate_hardcode_path(d)
343 import subprocess
344
345 sstateinst = d.getVar('SSTATE_INSTDIR', True)
346 fixmefn = sstateinst + "fixmepath"
347 if os.path.isfile(fixmefn):
348 staging = d.getVar('STAGING_DIR', True)
349 staging_target = d.getVar('STAGING_DIR_TARGET', True)
350 staging_host = d.getVar('STAGING_DIR_HOST', True)
351
352 if bb.data.inherits_class('native', d) or bb.data.inherits_class('nativesdk', d) or bb.data.inherits_class('crosssdk', d) or bb.data.inherits_class('cross-canadian', d):
353 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIR:%s:g'" % (staging)
354 elif bb.data.inherits_class('cross', d):
355 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRTARGET:%s:g; s:FIXMESTAGINGDIR:%s:g'" % (staging_target, staging)
356 else:
357 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRHOST:%s:g'" % (staging_host)
358
359 extra_staging_fixmes = d.getVar('EXTRA_STAGING_FIXMES', True) or ''
360 for fixmevar in extra_staging_fixmes.split():
361 fixme_path = d.getVar(fixmevar, True)
362 sstate_sed_cmd += " -e 's:FIXME_%s:%s:g'" % (fixmevar, fixme_path)
363
364 # Add sstateinst to each filename in fixmepath, use xargs to efficiently call sed
365 sstate_hardcode_cmd = "sed -e 's:^:%s:g' %s | xargs %s" % (sstateinst, fixmefn, sstate_sed_cmd)
366
367 bb.note("Replacing fixme paths in sstate package: %s" % (sstate_hardcode_cmd))
368 subprocess.call(sstate_hardcode_cmd, shell=True)
369
370 # Need to remove this or we'd copy it into the target directory and may
371 # conflict with another writer
372 os.remove(fixmefn)
373}
374
375def sstate_clean_cachefile(ss, d):
376 import oe.path
377
378 sstatepkgfile = d.getVar('SSTATE_PATHSPEC', True) + "*_" + ss['task'] + ".tgz*"
379 bb.note("Removing %s" % sstatepkgfile)
380 oe.path.remove(sstatepkgfile)
381
382def sstate_clean_cachefiles(d):
383 for task in (d.getVar('SSTATETASKS', True) or "").split():
384 ld = d.createCopy()
385 ss = sstate_state_fromvars(ld, task)
386 sstate_clean_cachefile(ss, ld)
387
388def sstate_clean_manifest(manifest, d):
389 import oe.path
390
391 mfile = open(manifest)
392 entries = mfile.readlines()
393 mfile.close()
394
395 for entry in entries:
396 entry = entry.strip()
397 bb.debug(2, "Removing manifest: %s" % entry)
398 # We can race against another package populating directories as we're removing them
399 # so we ignore errors here.
400 try:
401 if entry.endswith("/"):
402 if os.path.islink(entry[:-1]):
403 os.remove(entry[:-1])
404 elif os.path.exists(entry) and len(os.listdir(entry)) == 0:
405 os.rmdir(entry[:-1])
406 else:
407 oe.path.remove(entry)
408 except OSError:
409 pass
410
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600411 postrm = manifest + ".postrm"
412 if os.path.exists(manifest + ".postrm"):
413 import subprocess
414 os.chmod(postrm, 0o755)
415 subprocess.call(postrm, shell=True)
416 oe.path.remove(postrm)
417
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500418 oe.path.remove(manifest)
419
420def sstate_clean(ss, d):
421 import oe.path
422 import glob
423
424 d2 = d.createCopy()
425 stamp_clean = d.getVar("STAMPCLEAN", True)
426 extrainf = d.getVarFlag("do_" + ss['task'], 'stamp-extra-info', True)
427 if extrainf:
428 d2.setVar("SSTATE_MANMACH", extrainf)
429 wildcard_stfile = "%s.do_%s*.%s" % (stamp_clean, ss['task'], extrainf)
430 else:
431 wildcard_stfile = "%s.do_%s*" % (stamp_clean, ss['task'])
432
433 manifest = d2.expand("${SSTATE_MANFILEPREFIX}.%s" % ss['task'])
434
435 if os.path.exists(manifest):
436 locks = []
437 for lock in ss['lockfiles-shared']:
438 locks.append(bb.utils.lockfile(lock))
439 for lock in ss['lockfiles']:
440 locks.append(bb.utils.lockfile(lock))
441
442 sstate_clean_manifest(manifest, d)
443
444 for lock in locks:
445 bb.utils.unlockfile(lock)
446
447 # Remove the current and previous stamps, but keep the sigdata.
448 #
449 # The glob() matches do_task* which may match multiple tasks, for
450 # example: do_package and do_package_write_ipk, so we need to
451 # exactly match *.do_task.* and *.do_task_setscene.*
452 rm_stamp = '.do_%s.' % ss['task']
453 rm_setscene = '.do_%s_setscene.' % ss['task']
454 # For BB_SIGNATURE_HANDLER = "noop"
455 rm_nohash = ".do_%s" % ss['task']
456 for stfile in glob.glob(wildcard_stfile):
457 # Keep the sigdata
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500458 if ".sigdata." in stfile or ".sigbasedata." in stfile:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500459 continue
460 # Preserve taint files in the stamps directory
461 if stfile.endswith('.taint'):
462 continue
463 if rm_stamp in stfile or rm_setscene in stfile or \
464 stfile.endswith(rm_nohash):
465 oe.path.remove(stfile)
466
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500467 # Removes the users/groups created by the package
468 for cleanfunc in (d.getVar('SSTATECLEANFUNCS', True) or '').split():
469 bb.build.exec_func(cleanfunc, d)
470
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500471sstate_clean[vardepsexclude] = "SSTATE_MANFILEPREFIX"
472
473CLEANFUNCS += "sstate_cleanall"
474
475python sstate_cleanall() {
476 bb.note("Removing shared state for package %s" % d.getVar('PN', True))
477
478 manifest_dir = d.getVar('SSTATE_MANIFESTS', True)
479 if not os.path.exists(manifest_dir):
480 return
481
482 tasks = d.getVar('SSTATETASKS', True).split()
483 for name in tasks:
484 ld = d.createCopy()
485 shared_state = sstate_state_fromvars(ld, name)
486 sstate_clean(shared_state, ld)
487}
488
489python sstate_hardcode_path () {
490 import subprocess, platform
491
492 # Need to remove hardcoded paths and fix these when we install the
493 # staging packages.
494 #
495 # Note: the logic in this function needs to match the reverse logic
496 # in sstate_installpkg(ss, d)
497
498 staging = d.getVar('STAGING_DIR', True)
499 staging_target = d.getVar('STAGING_DIR_TARGET', True)
500 staging_host = d.getVar('STAGING_DIR_HOST', True)
501 sstate_builddir = d.getVar('SSTATE_BUILDDIR', True)
502
503 if bb.data.inherits_class('native', d) or bb.data.inherits_class('nativesdk', d) or bb.data.inherits_class('crosssdk', d) or bb.data.inherits_class('cross-canadian', d):
504 sstate_grep_cmd = "grep -l -e '%s'" % (staging)
505 sstate_sed_cmd = "sed -i -e 's:%s:FIXMESTAGINGDIR:g'" % (staging)
506 elif bb.data.inherits_class('cross', d):
507 sstate_grep_cmd = "grep -l -e '%s' -e '%s'" % (staging_target, staging)
508 sstate_sed_cmd = "sed -i -e 's:%s:FIXMESTAGINGDIRTARGET:g; s:%s:FIXMESTAGINGDIR:g'" % (staging_target, staging)
509 else:
510 sstate_grep_cmd = "grep -l -e '%s'" % (staging_host)
511 sstate_sed_cmd = "sed -i -e 's:%s:FIXMESTAGINGDIRHOST:g'" % (staging_host)
512
513 extra_staging_fixmes = d.getVar('EXTRA_STAGING_FIXMES', True) or ''
514 for fixmevar in extra_staging_fixmes.split():
515 fixme_path = d.getVar(fixmevar, True)
516 sstate_sed_cmd += " -e 's:%s:FIXME_%s:g'" % (fixme_path, fixmevar)
517
518 fixmefn = sstate_builddir + "fixmepath"
519
520 sstate_scan_cmd = d.getVar('SSTATE_SCAN_CMD', True)
521 sstate_filelist_cmd = "tee %s" % (fixmefn)
522
523 # fixmepath file needs relative paths, drop sstate_builddir prefix
524 sstate_filelist_relative_cmd = "sed -i -e 's:^%s::g' %s" % (sstate_builddir, fixmefn)
525
526 xargs_no_empty_run_cmd = '--no-run-if-empty'
527 if platform.system() == 'Darwin':
528 xargs_no_empty_run_cmd = ''
529
530 # Limit the fixpaths and sed operations based on the initial grep search
531 # This has the side effect of making sure the vfs cache is hot
532 sstate_hardcode_cmd = "%s | xargs %s | %s | xargs %s %s" % (sstate_scan_cmd, sstate_grep_cmd, sstate_filelist_cmd, xargs_no_empty_run_cmd, sstate_sed_cmd)
533
534 bb.note("Removing hardcoded paths from sstate package: '%s'" % (sstate_hardcode_cmd))
535 subprocess.call(sstate_hardcode_cmd, shell=True)
536
537 # If the fixmefn is empty, remove it..
538 if os.stat(fixmefn).st_size == 0:
539 os.remove(fixmefn)
540 else:
541 bb.note("Replacing absolute paths in fixmepath file: '%s'" % (sstate_filelist_relative_cmd))
542 subprocess.call(sstate_filelist_relative_cmd, shell=True)
543}
544
545def sstate_package(ss, d):
546 import oe.path
547
548 def make_relative_symlink(path, outputpath, d):
549 # Replace out absolute TMPDIR paths in symlinks with relative ones
550 if not os.path.islink(path):
551 return
552 link = os.readlink(path)
553 if not os.path.isabs(link):
554 return
555 if not link.startswith(tmpdir):
556 return
557
558 depth = outputpath.rpartition(tmpdir)[2].count('/')
559 base = link.partition(tmpdir)[2].strip()
560 while depth > 1:
561 base = "/.." + base
562 depth -= 1
563 base = "." + base
564
565 bb.debug(2, "Replacing absolute path %s with relative path %s for %s" % (link, base, outputpath))
566 os.remove(path)
567 os.symlink(base, path)
568
569 tmpdir = d.getVar('TMPDIR', True)
570
571 sstatebuild = d.expand("${WORKDIR}/sstate-build-%s/" % ss['task'])
572 sstatepkg = d.getVar('SSTATE_PKG', True) + '_'+ ss['task'] + ".tgz"
573 bb.utils.remove(sstatebuild, recurse=True)
574 bb.utils.mkdirhier(sstatebuild)
575 bb.utils.mkdirhier(os.path.dirname(sstatepkg))
576 for state in ss['dirs']:
577 if not os.path.exists(state[1]):
578 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600579 if d.getVar('SSTATE_SKIP_CREATION', True) == '1':
580 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500581 srcbase = state[0].rstrip("/").rsplit('/', 1)[0]
582 for walkroot, dirs, files in os.walk(state[1]):
583 for file in files:
584 srcpath = os.path.join(walkroot, file)
585 dstpath = srcpath.replace(state[1], state[2])
586 make_relative_symlink(srcpath, dstpath, d)
587 for dir in dirs:
588 srcpath = os.path.join(walkroot, dir)
589 dstpath = srcpath.replace(state[1], state[2])
590 make_relative_symlink(srcpath, dstpath, d)
591 bb.debug(2, "Preparing tree %s for packaging at %s" % (state[1], sstatebuild + state[0]))
592 oe.path.copyhardlinktree(state[1], sstatebuild + state[0])
593
594 workdir = d.getVar('WORKDIR', True)
595 for plain in ss['plaindirs']:
596 pdir = plain.replace(workdir, sstatebuild)
597 bb.utils.mkdirhier(plain)
598 bb.utils.mkdirhier(pdir)
599 oe.path.copyhardlinktree(plain, pdir)
600
601 d.setVar('SSTATE_BUILDDIR', sstatebuild)
602 d.setVar('SSTATE_PKG', sstatepkg)
603
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500604 for f in (d.getVar('SSTATECREATEFUNCS', True) or '').split() + \
605 ['sstate_create_package', 'sstate_sign_package'] + \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500606 (d.getVar('SSTATEPOSTCREATEFUNCS', True) or '').split():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500607 # All hooks should run in SSTATE_BUILDDIR.
608 bb.build.exec_func(f, d, (sstatebuild,))
609
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500610 bb.siggen.dump_this_task(sstatepkg + ".siginfo", d)
611
612 return
613
614def pstaging_fetch(sstatefetch, sstatepkg, d):
615 import bb.fetch2
616
617 # Only try and fetch if the user has configured a mirror
618 mirrors = d.getVar('SSTATE_MIRRORS', True)
619 if not mirrors:
620 return
621
622 # Copy the data object and override DL_DIR and SRC_URI
623 localdata = bb.data.createCopy(d)
624 bb.data.update_data(localdata)
625
626 dldir = localdata.expand("${SSTATE_DIR}")
627 bb.utils.mkdirhier(dldir)
628
629 localdata.delVar('MIRRORS')
630 localdata.setVar('FILESPATH', dldir)
631 localdata.setVar('DL_DIR', dldir)
632 localdata.setVar('PREMIRRORS', mirrors)
633
634 # if BB_NO_NETWORK is set but we also have SSTATE_MIRROR_ALLOW_NETWORK,
635 # we'll want to allow network access for the current set of fetches.
636 if localdata.getVar('BB_NO_NETWORK', True) == "1" and localdata.getVar('SSTATE_MIRROR_ALLOW_NETWORK', True) == "1":
637 localdata.delVar('BB_NO_NETWORK')
638
639 # Try a fetch from the sstate mirror, if it fails just return and
640 # we will build the package
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600641 uris = ['file://{0};downloadfilename={0}'.format(sstatefetch),
642 'file://{0}.siginfo;downloadfilename={0}.siginfo'.format(sstatefetch)]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500643 if bb.utils.to_boolean(d.getVar("SSTATE_VERIFY_SIG", True), False):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600644 uris += ['file://{0}.sig;downloadfilename={0}.sig'.format(sstatefetch)]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500645
646 for srcuri in uris:
647 localdata.setVar('SRC_URI', srcuri)
648 try:
649 fetcher = bb.fetch2.Fetch([srcuri], localdata, cache=False)
650 fetcher.download()
651
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500652 except bb.fetch2.BBFetchException:
653 break
654
655def sstate_setscene(d):
656 shared_state = sstate_state_fromvars(d)
657 accelerate = sstate_installpkg(shared_state, d)
658 if not accelerate:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600659 bb.fatal("No suitable staging package found")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500660
661python sstate_task_prefunc () {
662 shared_state = sstate_state_fromvars(d)
663 sstate_clean(shared_state, d)
664}
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500665sstate_task_prefunc[dirs] = "${WORKDIR}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500666
667python sstate_task_postfunc () {
668 shared_state = sstate_state_fromvars(d)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500669
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500670 sstate_install(shared_state, d)
671 for intercept in shared_state['interceptfuncs']:
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500672 bb.build.exec_func(intercept, d, (d.getVar("WORKDIR", True),))
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600673 omask = os.umask(0o002)
674 if omask != 0o002:
675 bb.note("Using umask 0o002 (not %0o) for sstate packaging" % omask)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500676 sstate_package(shared_state, d)
677 os.umask(omask)
678}
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500679sstate_task_postfunc[dirs] = "${WORKDIR}"
680
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500681
682#
683# Shell function to generate a sstate package from a directory
684# set as SSTATE_BUILDDIR. Will be run from within SSTATE_BUILDDIR.
685#
686sstate_create_package () {
687 TFILE=`mktemp ${SSTATE_PKG}.XXXXXXXX`
688 # Need to handle empty directories
689 if [ "$(ls -A)" ]; then
690 set +e
691 tar -czf $TFILE *
692 ret=$?
693 if [ $ret -ne 0 ] && [ $ret -ne 1 ]; then
694 exit 1
695 fi
696 set -e
697 else
698 tar -cz --file=$TFILE --files-from=/dev/null
699 fi
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500700 chmod 0664 $TFILE
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500701 mv -f $TFILE ${SSTATE_PKG}
702
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500703 cd ${WORKDIR}
704 rm -rf ${SSTATE_BUILDDIR}
705}
706
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500707python sstate_sign_package () {
708 from oe.gpg_sign import get_signer
709
710 if d.getVar('SSTATE_SIG_KEY', True):
711 signer = get_signer(d, 'local')
712 sstate_pkg = d.getVar('SSTATE_PKG', True)
713 if os.path.exists(sstate_pkg + '.sig'):
714 os.unlink(sstate_pkg + '.sig')
715 signer.detach_sign(sstate_pkg, d.getVar('SSTATE_SIG_KEY', False), None,
716 d.getVar('SSTATE_SIG_PASSPHRASE', True), armor=False)
717}
718
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500719#
720# Shell function to decompress and prepare a package for installation
721# Will be run from within SSTATE_INSTDIR.
722#
723sstate_unpack_package () {
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500724 tar -xvzf ${SSTATE_PKG}
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500725 # update .siginfo atime on local/NFS mirror
726 [ -w ${SSTATE_PKG}.siginfo ] && [ -h ${SSTATE_PKG}.siginfo ] && touch -a ${SSTATE_PKG}.siginfo
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500727 # Use "! -w ||" to return true for read only files
728 [ ! -w ${SSTATE_PKG} ] || touch --no-dereference ${SSTATE_PKG}
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500729 [ ! -w ${SSTATE_PKG}.sig ] || [ ! -e ${SSTATE_PKG}.sig ] || touch --no-dereference ${SSTATE_PKG}.sig
730 [ ! -w ${SSTATE_PKG}.siginfo ] || [ ! -e ${SSTATE_PKG}.siginfo ] || touch --no-dereference ${SSTATE_PKG}.siginfo
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500731}
732
733BB_HASHCHECK_FUNCTION = "sstate_checkhashes"
734
735def sstate_checkhashes(sq_fn, sq_task, sq_hash, sq_hashfn, d, siginfo=False):
736
737 ret = []
738 missed = []
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600739 missing = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500740 extension = ".tgz"
741 if siginfo:
742 extension = extension + ".siginfo"
743
744 def getpathcomponents(task, d):
745 # Magic data from BB_HASHFILENAME
746 splithashfn = sq_hashfn[task].split(" ")
747 spec = splithashfn[1]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500748 if splithashfn[0] == "True":
749 extrapath = d.getVar("NATIVELSBSTRING", True) + "/"
750 else:
751 extrapath = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500752
753 tname = sq_task[task][3:]
754
755 if tname in ["fetch", "unpack", "patch", "populate_lic", "preconfigure"] and splithashfn[2]:
756 spec = splithashfn[2]
757 extrapath = ""
758
759 return spec, extrapath, tname
760
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600761 def sstate_pkg_to_pn(pkg, d):
762 """
763 Translate an sstate filename to a PN value by way of SSTATE_PKGSPEC. This is slightly hacky but
764 we don't have access to everything in this context.
765 """
766 pkgspec = d.getVar('SSTATE_PKGSPEC', False)
767 try:
768 idx = pkgspec.split(':').index('${PN}')
769 except ValueError:
770 bb.fatal('Unable to find ${PN} in SSTATE_PKGSPEC')
771 return pkg.split(':')[idx]
772
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500773
774 for task in range(len(sq_fn)):
775
776 spec, extrapath, tname = getpathcomponents(task, d)
777
778 sstatefile = d.expand("${SSTATE_DIR}/" + extrapath + generate_sstatefn(spec, sq_hash[task], d) + "_" + tname + extension)
779
780 if os.path.exists(sstatefile):
781 bb.debug(2, "SState: Found valid sstate file %s" % sstatefile)
782 ret.append(task)
783 continue
784 else:
785 missed.append(task)
786 bb.debug(2, "SState: Looked for but didn't find file %s" % sstatefile)
787
788 mirrors = d.getVar("SSTATE_MIRRORS", True)
789 if mirrors:
790 # Copy the data object and override DL_DIR and SRC_URI
791 localdata = bb.data.createCopy(d)
792 bb.data.update_data(localdata)
793
794 dldir = localdata.expand("${SSTATE_DIR}")
795 localdata.delVar('MIRRORS')
796 localdata.setVar('FILESPATH', dldir)
797 localdata.setVar('DL_DIR', dldir)
798 localdata.setVar('PREMIRRORS', mirrors)
799
800 bb.debug(2, "SState using premirror of: %s" % mirrors)
801
802 # if BB_NO_NETWORK is set but we also have SSTATE_MIRROR_ALLOW_NETWORK,
803 # we'll want to allow network access for the current set of fetches.
804 if localdata.getVar('BB_NO_NETWORK', True) == "1" and localdata.getVar('SSTATE_MIRROR_ALLOW_NETWORK', True) == "1":
805 localdata.delVar('BB_NO_NETWORK')
806
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600807 whitelist = bb.runqueue.get_setscene_enforce_whitelist(d)
808
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500809 from bb.fetch2 import FetchConnectionCache
810 def checkstatus_init(thread_worker):
811 thread_worker.connection_cache = FetchConnectionCache()
812
813 def checkstatus_end(thread_worker):
814 thread_worker.connection_cache.close_connections()
815
816 def checkstatus(thread_worker, arg):
817 (task, sstatefile) = arg
818
819 localdata2 = bb.data.createCopy(localdata)
820 srcuri = "file://" + sstatefile
821 localdata.setVar('SRC_URI', srcuri)
822 bb.debug(2, "SState: Attempting to fetch %s" % srcuri)
823
824 try:
825 fetcher = bb.fetch2.Fetch(srcuri.split(), localdata2,
826 connection_cache=thread_worker.connection_cache)
827 fetcher.checkstatus()
828 bb.debug(2, "SState: Successful fetch test for %s" % srcuri)
829 ret.append(task)
830 if task in missed:
831 missed.remove(task)
832 except:
833 missed.append(task)
834 bb.debug(2, "SState: Unsuccessful fetch test for %s" % srcuri)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600835 if whitelist:
836 pn = sstate_pkg_to_pn(sstatefile, d)
837 taskname = sq_task[task]
838 if not bb.runqueue.check_setscene_enforce_whitelist(pn, taskname, whitelist):
839 missing.append(task)
840 bb.error('Sstate artifact unavailable for %s.%s' % (pn, taskname))
841 pass
842 bb.event.fire(bb.event.ProcessProgress("Checking sstate mirror object availability", len(tasklist) - thread_worker.tasks.qsize()), d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500843
844 tasklist = []
845 for task in range(len(sq_fn)):
846 if task in ret:
847 continue
848 spec, extrapath, tname = getpathcomponents(task, d)
849 sstatefile = d.expand(extrapath + generate_sstatefn(spec, sq_hash[task], d) + "_" + tname + extension)
850 tasklist.append((task, sstatefile))
851
852 if tasklist:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600853 bb.event.fire(bb.event.ProcessStarted("Checking sstate mirror object availability", len(tasklist)), d)
854
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500855 import multiprocessing
856 nproc = min(multiprocessing.cpu_count(), len(tasklist))
857
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600858 bb.event.enable_threadlock()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500859 pool = oe.utils.ThreadedPool(nproc, len(tasklist),
860 worker_init=checkstatus_init, worker_end=checkstatus_end)
861 for t in tasklist:
862 pool.add_task(checkstatus, t)
863 pool.start()
864 pool.wait_completion()
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600865 bb.event.disable_threadlock()
866
867 bb.event.fire(bb.event.ProcessFinished("Checking sstate mirror object availability"), d)
868 if whitelist and missing:
869 bb.fatal('Required artifacts were unavailable - exiting')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500870
871 inheritlist = d.getVar("INHERIT", True)
872 if "toaster" in inheritlist:
873 evdata = {'missed': [], 'found': []};
874 for task in missed:
875 spec, extrapath, tname = getpathcomponents(task, d)
876 sstatefile = d.expand(extrapath + generate_sstatefn(spec, sq_hash[task], d) + "_" + tname + ".tgz")
877 evdata['missed'].append( (sq_fn[task], sq_task[task], sq_hash[task], sstatefile ) )
878 for task in ret:
879 spec, extrapath, tname = getpathcomponents(task, d)
880 sstatefile = d.expand(extrapath + generate_sstatefn(spec, sq_hash[task], d) + "_" + tname + ".tgz")
881 evdata['found'].append( (sq_fn[task], sq_task[task], sq_hash[task], sstatefile ) )
882 bb.event.fire(bb.event.MetadataEvent("MissedSstate", evdata), d)
883
884 if hasattr(bb.parse.siggen, "checkhashes"):
885 bb.parse.siggen.checkhashes(missed, ret, sq_fn, sq_task, sq_hash, sq_hashfn, d)
886
887 return ret
888
889BB_SETSCENE_DEPVALID = "setscene_depvalid"
890
891def setscene_depvalid(task, taskdependees, notneeded, d):
892 # taskdependees is a dict of tasks which depend on task, each being a 3 item list of [PN, TASKNAME, FILENAME]
893 # task is included in taskdependees too
894
895 bb.debug(2, "Considering setscene task: %s" % (str(taskdependees[task])))
896
897 def isNativeCross(x):
898 return x.endswith("-native") or "-cross-" in x or "-crosssdk" in x
899
900 def isPostInstDep(x):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500901 if x in ["qemu-native", "gdk-pixbuf-native", "qemuwrapper-cross", "depmodwrapper-cross", "systemd-systemctl-native", "gtk-icon-utils-native", "ca-certificates-native"]:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500902 return True
903 return False
904
905 # We only need to trigger populate_lic through direct dependencies
906 if taskdependees[task][1] == "do_populate_lic":
907 return True
908
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500909 # We only need to trigger packagedata through direct dependencies
910 # but need to preserve packagedata on packagedata links
911 if taskdependees[task][1] == "do_packagedata":
912 for dep in taskdependees:
913 if taskdependees[dep][1] == "do_packagedata":
914 return False
915 return True
916
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500917 for dep in taskdependees:
918 bb.debug(2, " considering dependency: %s" % (str(taskdependees[dep])))
919 if task == dep:
920 continue
921 if dep in notneeded:
922 continue
923 # do_package_write_* and do_package doesn't need do_package
924 if taskdependees[task][1] == "do_package" and taskdependees[dep][1] in ['do_package', 'do_package_write_deb', 'do_package_write_ipk', 'do_package_write_rpm', 'do_packagedata', 'do_package_qa']:
925 continue
926 # do_package_write_* and do_package doesn't need do_populate_sysroot, unless is a postinstall dependency
927 if taskdependees[task][1] == "do_populate_sysroot" and taskdependees[dep][1] in ['do_package', 'do_package_write_deb', 'do_package_write_ipk', 'do_package_write_rpm', 'do_packagedata', 'do_package_qa']:
928 if isPostInstDep(taskdependees[task][0]) and taskdependees[dep][1] in ['do_package_write_deb', 'do_package_write_ipk', 'do_package_write_rpm']:
929 return False
930 continue
931 # Native/Cross packages don't exist and are noexec anyway
932 if isNativeCross(taskdependees[dep][0]) and taskdependees[dep][1] in ['do_package_write_deb', 'do_package_write_ipk', 'do_package_write_rpm', 'do_packagedata', 'do_package', 'do_package_qa']:
933 continue
934
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500935 # This is due to the [depends] in useradd.bbclass complicating matters
936 # The logic *is* reversed here due to the way hard setscene dependencies are injected
937 if (taskdependees[task][1] == 'do_package' or taskdependees[task][1] == 'do_populate_sysroot') and taskdependees[dep][0].endswith(('shadow-native', 'shadow-sysroot', 'base-passwd', 'pseudo-native')) and taskdependees[dep][1] == 'do_populate_sysroot':
938 continue
939
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500940 # Consider sysroot depending on sysroot tasks
941 if taskdependees[task][1] == 'do_populate_sysroot' and taskdependees[dep][1] == 'do_populate_sysroot':
942 # base-passwd/shadow-sysroot don't need their dependencies
943 if taskdependees[dep][0].endswith(("base-passwd", "shadow-sysroot")):
944 continue
945 # Nothing need depend on libc-initial/gcc-cross-initial
946 if "-initial" in taskdependees[task][0]:
947 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600948 # For meta-extsdk-toolchain we want all sysroot dependencies
949 if taskdependees[dep][0] == 'meta-extsdk-toolchain':
950 return False
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500951 # Native/Cross populate_sysroot need their dependencies
952 if isNativeCross(taskdependees[task][0]) and isNativeCross(taskdependees[dep][0]):
953 return False
954 # Target populate_sysroot depended on by cross tools need to be installed
955 if isNativeCross(taskdependees[dep][0]):
956 return False
957 # Native/cross tools depended upon by target sysroot are not needed
958 if isNativeCross(taskdependees[task][0]):
959 continue
960 # Target populate_sysroot need their dependencies
961 return False
962
963 if taskdependees[task][1] == 'do_shared_workdir':
964 continue
965
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500966 if taskdependees[dep][1] == "do_populate_lic":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500967 continue
968
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500969
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500970 # Safe fallthrough default
971 bb.debug(2, " Default setscene dependency fall through due to dependency: %s" % (str(taskdependees[dep])))
972 return False
973 return True
974
975addhandler sstate_eventhandler
976sstate_eventhandler[eventmask] = "bb.build.TaskSucceeded"
977python sstate_eventhandler() {
978 d = e.data
979 # When we write an sstate package we rewrite the SSTATE_PKG
980 spkg = d.getVar('SSTATE_PKG', True)
981 if not spkg.endswith(".tgz"):
982 taskname = d.getVar("BB_RUNTASK", True)[3:]
983 spec = d.getVar('SSTATE_PKGSPEC', True)
984 swspec = d.getVar('SSTATE_SWSPEC', True)
985 if taskname in ["fetch", "unpack", "patch", "populate_lic", "preconfigure"] and swspec:
986 d.setVar("SSTATE_PKGSPEC", "${SSTATE_SWSPEC}")
987 d.setVar("SSTATE_EXTRAPATH", "")
988 sstatepkg = d.getVar('SSTATE_PKG', True)
989 bb.siggen.dump_this_task(sstatepkg + '_' + taskname + ".tgz" ".siginfo", d)
990}
991
992SSTATE_PRUNE_OBSOLETEWORKDIR = "1"
993
994# Event handler which removes manifests and stamps file for
995# recipes which are no longer reachable in a build where they
996# once were.
997# Also optionally removes the workdir of those tasks/recipes
998#
999addhandler sstate_eventhandler2
1000sstate_eventhandler2[eventmask] = "bb.event.ReachableStamps"
1001python sstate_eventhandler2() {
1002 import glob
1003 d = e.data
1004 stamps = e.stamps.values()
1005 removeworkdir = (d.getVar("SSTATE_PRUNE_OBSOLETEWORKDIR", False) == "1")
1006 seen = []
1007 for a in d.getVar("SSTATE_ARCHS", True).split():
1008 toremove = []
1009 i = d.expand("${SSTATE_MANIFESTS}/index-" + a)
1010 if not os.path.exists(i):
1011 continue
1012 with open(i, "r") as f:
1013 lines = f.readlines()
1014 for l in lines:
1015 (stamp, manifest, workdir) = l.split()
1016 if stamp not in stamps:
1017 toremove.append(l)
1018 if stamp not in seen:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001019 bb.debug(2, "Stamp %s is not reachable, removing related manifests" % stamp)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001020 seen.append(stamp)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001021
1022 if toremove:
1023 bb.note("There are %d recipes to be removed from sysroot %s, removing..." % (len(toremove), a))
1024
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001025 for r in toremove:
1026 (stamp, manifest, workdir) = r.split()
1027 for m in glob.glob(manifest + ".*"):
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001028 if m.endswith(".postrm"):
1029 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001030 sstate_clean_manifest(m, d)
1031 bb.utils.remove(stamp + "*")
1032 if removeworkdir:
1033 bb.utils.remove(workdir, recurse = True)
1034 lines.remove(r)
1035 with open(i, "w") as f:
1036 for l in lines:
1037 f.write(l)
1038}