blob: 172384b37636956aa9e6c912f260e73539d25a86 [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}"
Patrick Williamsc0f7c042017-02-23 20:41:17 -060033# Ignore overlapping README
34SSTATE_DUPWHITELIST += "${DEPLOY_DIR}/sdk/README_-_DO_NOT_DELETE_FILES_IN_THIS_DIRECTORY.txt"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050035
36SSTATE_SCAN_FILES ?= "*.la *-config *_config"
37SSTATE_SCAN_CMD ?= 'find ${SSTATE_BUILDDIR} \( -name "${@"\" -o -name \"".join(d.getVar("SSTATE_SCAN_FILES", True).split())}" \) -type f'
38
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050039BB_HASHFILENAME = "False ${SSTATE_PKGSPEC} ${SSTATE_SWSPEC}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050040
41SSTATE_ARCHS = " \
42 ${BUILD_ARCH} \
43 ${BUILD_ARCH}_${SDK_ARCH}_${SDK_OS} \
44 ${BUILD_ARCH}_${TARGET_ARCH} \
45 ${SDK_ARCH}_${SDK_OS} \
46 ${SDK_ARCH}_${PACKAGE_ARCH} \
47 allarch \
48 ${PACKAGE_ARCH} \
49 ${MACHINE}"
50
51SSTATE_MANMACH ?= "${SSTATE_PKGARCH}"
52
53SSTATECREATEFUNCS = "sstate_hardcode_path"
54SSTATEPOSTCREATEFUNCS = ""
55SSTATEPREINSTFUNCS = ""
56SSTATEPOSTUNPACKFUNCS = "sstate_hardcode_path_unpack"
57SSTATEPOSTINSTFUNCS = ""
58EXTRA_STAGING_FIXMES ?= ""
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050059SSTATECLEANFUNCS = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -050060
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050061# Check whether sstate exists for tasks that support sstate and are in the
62# locked signatures file.
63SIGGEN_LOCKEDSIGS_SSTATE_EXISTS_CHECK ?= 'error'
64
65# Check whether the task's computed hash matches the task's hash in the
66# locked signatures file.
67SIGGEN_LOCKEDSIGS_TASKSIG_CHECK ?= "error"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050068
69# The GnuPG key ID and passphrase to use to sign sstate archives (or unset to
70# not sign)
71SSTATE_SIG_KEY ?= ""
72SSTATE_SIG_PASSPHRASE ?= ""
73# Whether to verify the GnUPG signatures when extracting sstate archives
74SSTATE_VERIFY_SIG ?= "0"
75
Patrick Williamsc124f4f2015-09-15 14:41:29 -050076python () {
77 if bb.data.inherits_class('native', d):
78 d.setVar('SSTATE_PKGARCH', d.getVar('BUILD_ARCH', False))
79 elif bb.data.inherits_class('crosssdk', d):
80 d.setVar('SSTATE_PKGARCH', d.expand("${BUILD_ARCH}_${SDK_ARCH}_${SDK_OS}"))
81 elif bb.data.inherits_class('cross', d):
82 d.setVar('SSTATE_PKGARCH', d.expand("${BUILD_ARCH}_${TARGET_ARCH}"))
83 elif bb.data.inherits_class('nativesdk', d):
84 d.setVar('SSTATE_PKGARCH', d.expand("${SDK_ARCH}_${SDK_OS}"))
85 elif bb.data.inherits_class('cross-canadian', d):
86 d.setVar('SSTATE_PKGARCH', d.expand("${SDK_ARCH}_${PACKAGE_ARCH}"))
87 elif bb.data.inherits_class('allarch', d) and d.getVar("PACKAGE_ARCH", True) == "all":
88 d.setVar('SSTATE_PKGARCH', "allarch")
89 else:
90 d.setVar('SSTATE_MANMACH', d.expand("${PACKAGE_ARCH}"))
91
92 if bb.data.inherits_class('native', d) or bb.data.inherits_class('crosssdk', d) or bb.data.inherits_class('cross', d):
93 d.setVar('SSTATE_EXTRAPATH', "${NATIVELSBSTRING}/")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050094 d.setVar('BB_HASHFILENAME', "True ${SSTATE_PKGSPEC} ${SSTATE_SWSPEC}")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050095 d.setVar('SSTATE_EXTRAPATHWILDCARD', "*/")
96
97 # These classes encode staging paths into their scripts data so can only be
98 # reused if we manipulate the paths
99 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):
100 scan_cmd = "grep -Irl ${STAGING_DIR} ${SSTATE_BUILDDIR}"
101 d.setVar('SSTATE_SCAN_CMD', scan_cmd)
102
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600103 unique_tasks = sorted(set((d.getVar('SSTATETASKS', True) or "").split()))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500104 d.setVar('SSTATETASKS', " ".join(unique_tasks))
105 for task in unique_tasks:
106 d.prependVarFlag(task, 'prefuncs', "sstate_task_prefunc ")
107 d.appendVarFlag(task, 'postfuncs', " sstate_task_postfunc")
108}
109
110def sstate_init(task, d):
111 ss = {}
112 ss['task'] = task
113 ss['dirs'] = []
114 ss['plaindirs'] = []
115 ss['lockfiles'] = []
116 ss['lockfiles-shared'] = []
117 return ss
118
119def sstate_state_fromvars(d, task = None):
120 if task is None:
121 task = d.getVar('BB_CURRENTTASK', True)
122 if not task:
123 bb.fatal("sstate code running without task context?!")
124 task = task.replace("_setscene", "")
125
126 if task.startswith("do_"):
127 task = task[3:]
128 inputs = (d.getVarFlag("do_" + task, 'sstate-inputdirs', True) or "").split()
129 outputs = (d.getVarFlag("do_" + task, 'sstate-outputdirs', True) or "").split()
130 plaindirs = (d.getVarFlag("do_" + task, 'sstate-plaindirs', True) or "").split()
131 lockfiles = (d.getVarFlag("do_" + task, 'sstate-lockfile', True) or "").split()
132 lockfilesshared = (d.getVarFlag("do_" + task, 'sstate-lockfile-shared', True) or "").split()
133 interceptfuncs = (d.getVarFlag("do_" + task, 'sstate-interceptfuncs', True) or "").split()
134 if not task or len(inputs) != len(outputs):
135 bb.fatal("sstate variables not setup correctly?!")
136
137 if task == "populate_lic":
138 d.setVar("SSTATE_PKGSPEC", "${SSTATE_SWSPEC}")
139 d.setVar("SSTATE_EXTRAPATH", "")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500140 d.setVar('SSTATE_EXTRAPATHWILDCARD', "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500141
142 ss = sstate_init(task, d)
143 for i in range(len(inputs)):
144 sstate_add(ss, inputs[i], outputs[i], d)
145 ss['lockfiles'] = lockfiles
146 ss['lockfiles-shared'] = lockfilesshared
147 ss['plaindirs'] = plaindirs
148 ss['interceptfuncs'] = interceptfuncs
149 return ss
150
151def sstate_add(ss, source, dest, d):
152 if not source.endswith("/"):
153 source = source + "/"
154 if not dest.endswith("/"):
155 dest = dest + "/"
156 source = os.path.normpath(source)
157 dest = os.path.normpath(dest)
158 srcbase = os.path.basename(source)
159 ss['dirs'].append([srcbase, source, dest])
160 return ss
161
162def sstate_install(ss, d):
163 import oe.path
164 import oe.sstatesig
165 import subprocess
166
167 sharedfiles = []
168 shareddirs = []
169 bb.utils.mkdirhier(d.expand("${SSTATE_MANIFESTS}"))
170
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500171 sstateinst = d.expand("${WORKDIR}/sstate-install-%s/" % ss['task'])
172
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500173 manifest, d2 = oe.sstatesig.sstate_get_manifest_filename(ss['task'], d)
174
175 if os.access(manifest, os.R_OK):
176 bb.fatal("Package already staged (%s)?!" % manifest)
177
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600178 d.setVar("SSTATE_INST_POSTRM", manifest + ".postrm")
179
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500180 locks = []
181 for lock in ss['lockfiles-shared']:
182 locks.append(bb.utils.lockfile(lock, True))
183 for lock in ss['lockfiles']:
184 locks.append(bb.utils.lockfile(lock))
185
186 for state in ss['dirs']:
187 bb.debug(2, "Staging files from %s to %s" % (state[1], state[2]))
188 for walkroot, dirs, files in os.walk(state[1]):
189 for file in files:
190 srcpath = os.path.join(walkroot, file)
191 dstpath = srcpath.replace(state[1], state[2])
192 #bb.debug(2, "Staging %s to %s" % (srcpath, dstpath))
193 sharedfiles.append(dstpath)
194 for dir in dirs:
195 srcdir = os.path.join(walkroot, dir)
196 dstdir = srcdir.replace(state[1], state[2])
197 #bb.debug(2, "Staging %s to %s" % (srcdir, dstdir))
198 if not dstdir.endswith("/"):
199 dstdir = dstdir + "/"
200 shareddirs.append(dstdir)
201
202 # Check the file list for conflicts against files which already exist
203 whitelist = (d.getVar("SSTATE_DUPWHITELIST", True) or "").split()
204 match = []
205 for f in sharedfiles:
206 if os.path.exists(f):
207 f = os.path.normpath(f)
208 realmatch = True
209 for w in whitelist:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600210 w = os.path.normpath(w)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500211 if f.startswith(w):
212 realmatch = False
213 break
214 if realmatch:
215 match.append(f)
216 sstate_search_cmd = "grep -rl '%s' %s --exclude=master.list | sed -e 's:^.*/::' -e 's:\.populate-sysroot::'" % (f, d.expand("${SSTATE_MANIFESTS}"))
217 search_output = subprocess.Popen(sstate_search_cmd, shell=True, stdout=subprocess.PIPE).communicate()[0]
218 if search_output != "":
219 match.append("Matched in %s" % search_output.rstrip())
220 if match:
221 bb.error("The recipe %s is trying to install files into a shared " \
222 "area when those files already exist. Those files and their manifest " \
223 "location are:\n %s\nPlease verify which recipe should provide the " \
224 "above files.\nThe build has stopped as continuing in this scenario WILL " \
225 "break things, if not now, possibly in the future (we've seen builds fail " \
226 "several months later). If the system knew how to recover from this " \
227 "automatically it would however there are several different scenarios " \
228 "which can result in this and we don't know which one this is. It may be " \
229 "you have switched providers of something like virtual/kernel (e.g. from " \
230 "linux-yocto to linux-yocto-dev), in that case you need to execute the " \
231 "clean task for both recipes and it will resolve this error. It may be " \
232 "you changed DISTRO_FEATURES from systemd to udev or vice versa. Cleaning " \
233 "those recipes should again resolve this error however switching " \
234 "DISTRO_FEATURES on an existing build directory is not supported, you " \
235 "should really clean out tmp and rebuild (reusing sstate should be safe). " \
236 "It could be the overlapping files detected are harmless in which case " \
237 "adding them to SSTATE_DUPWHITELIST may be the correct solution. It could " \
238 "also be your build is including two different conflicting versions of " \
239 "things (e.g. bluez 4 and bluez 5 and the correct solution for that would " \
240 "be to resolve the conflict. If in doubt, please ask on the mailing list, " \
241 "sharing the error and filelist above." % \
242 (d.getVar('PN', True), "\n ".join(match)))
243 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.")
244
245 # Write out the manifest
246 f = open(manifest, "w")
247 for file in sharedfiles:
248 f.write(file + "\n")
249
250 # We want to ensure that directories appear at the end of the manifest
251 # so that when we test to see if they should be deleted any contents
252 # added by the task will have been removed first.
253 dirs = sorted(shareddirs, key=len)
254 # Must remove children first, which will have a longer path than the parent
255 for di in reversed(dirs):
256 f.write(di + "\n")
257 f.close()
258
259 # Append to the list of manifests for this PACKAGE_ARCH
260
261 i = d2.expand("${SSTATE_MANIFESTS}/index-${SSTATE_MANMACH}")
262 l = bb.utils.lockfile(i + ".lock")
263 filedata = d.getVar("STAMP", True) + " " + d2.getVar("SSTATE_MANFILEPREFIX", True) + " " + d.getVar("WORKDIR", True) + "\n"
264 manifests = []
265 if os.path.exists(i):
266 with open(i, "r") as f:
267 manifests = f.readlines()
268 if filedata not in manifests:
269 with open(i, "a+") as f:
270 f.write(filedata)
271 bb.utils.unlockfile(l)
272
273 # Run the actual file install
274 for state in ss['dirs']:
275 if os.path.exists(state[1]):
276 oe.path.copyhardlinktree(state[1], state[2])
277
278 for postinst in (d.getVar('SSTATEPOSTINSTFUNCS', True) or '').split():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500279 # All hooks should run in the SSTATE_INSTDIR
280 bb.build.exec_func(postinst, d, (sstateinst,))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500281
282 for lock in locks:
283 bb.utils.unlockfile(lock)
284
285sstate_install[vardepsexclude] += "SSTATE_DUPWHITELIST STATE_MANMACH SSTATE_MANFILEPREFIX"
286sstate_install[vardeps] += "${SSTATEPOSTINSTFUNCS}"
287
288def sstate_installpkg(ss, d):
289 import oe.path
290 import subprocess
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500291 from oe.gpg_sign import get_signer
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500292
293 def prepdir(dir):
294 # remove dir if it exists, ensure any parent directories do exist
295 if os.path.exists(dir):
296 oe.path.remove(dir)
297 bb.utils.mkdirhier(dir)
298 oe.path.remove(dir)
299
300 sstateinst = d.expand("${WORKDIR}/sstate-install-%s/" % ss['task'])
301 sstatefetch = d.getVar('SSTATE_PKGNAME', True) + '_' + ss['task'] + ".tgz"
302 sstatepkg = d.getVar('SSTATE_PKG', True) + '_' + ss['task'] + ".tgz"
303
304 if not os.path.exists(sstatepkg):
305 pstaging_fetch(sstatefetch, sstatepkg, d)
306
307 if not os.path.isfile(sstatepkg):
308 bb.note("Staging package %s does not exist" % sstatepkg)
309 return False
310
311 sstate_clean(ss, d)
312
313 d.setVar('SSTATE_INSTDIR', sstateinst)
314 d.setVar('SSTATE_PKG', sstatepkg)
315
316 if bb.utils.to_boolean(d.getVar("SSTATE_VERIFY_SIG", True), False):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500317 signer = get_signer(d, 'local')
318 if not signer.verify(sstatepkg + '.sig'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500319 bb.warn("Cannot verify signature on sstate package %s" % sstatepkg)
320
321 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 -0500322 # All hooks should run in the SSTATE_INSTDIR
323 bb.build.exec_func(f, d, (sstateinst,))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500324
325 for state in ss['dirs']:
326 prepdir(state[1])
327 os.rename(sstateinst + state[0], state[1])
328 sstate_install(ss, d)
329
330 for plain in ss['plaindirs']:
331 workdir = d.getVar('WORKDIR', True)
332 src = sstateinst + "/" + plain.replace(workdir, '')
333 dest = plain
334 bb.utils.mkdirhier(src)
335 prepdir(dest)
336 os.rename(src, dest)
337
338 return True
339
340python sstate_hardcode_path_unpack () {
341 # Fixup hardcoded paths
342 #
343 # Note: The logic below must match the reverse logic in
344 # sstate_hardcode_path(d)
345 import subprocess
346
347 sstateinst = d.getVar('SSTATE_INSTDIR', True)
348 fixmefn = sstateinst + "fixmepath"
349 if os.path.isfile(fixmefn):
350 staging = d.getVar('STAGING_DIR', True)
351 staging_target = d.getVar('STAGING_DIR_TARGET', True)
352 staging_host = d.getVar('STAGING_DIR_HOST', True)
353
354 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):
355 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIR:%s:g'" % (staging)
356 elif bb.data.inherits_class('cross', d):
357 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRTARGET:%s:g; s:FIXMESTAGINGDIR:%s:g'" % (staging_target, staging)
358 else:
359 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRHOST:%s:g'" % (staging_host)
360
361 extra_staging_fixmes = d.getVar('EXTRA_STAGING_FIXMES', True) or ''
362 for fixmevar in extra_staging_fixmes.split():
363 fixme_path = d.getVar(fixmevar, True)
364 sstate_sed_cmd += " -e 's:FIXME_%s:%s:g'" % (fixmevar, fixme_path)
365
366 # Add sstateinst to each filename in fixmepath, use xargs to efficiently call sed
367 sstate_hardcode_cmd = "sed -e 's:^:%s:g' %s | xargs %s" % (sstateinst, fixmefn, sstate_sed_cmd)
368
369 bb.note("Replacing fixme paths in sstate package: %s" % (sstate_hardcode_cmd))
370 subprocess.call(sstate_hardcode_cmd, shell=True)
371
372 # Need to remove this or we'd copy it into the target directory and may
373 # conflict with another writer
374 os.remove(fixmefn)
375}
376
377def sstate_clean_cachefile(ss, d):
378 import oe.path
379
380 sstatepkgfile = d.getVar('SSTATE_PATHSPEC', True) + "*_" + ss['task'] + ".tgz*"
381 bb.note("Removing %s" % sstatepkgfile)
382 oe.path.remove(sstatepkgfile)
383
384def sstate_clean_cachefiles(d):
385 for task in (d.getVar('SSTATETASKS', True) or "").split():
386 ld = d.createCopy()
387 ss = sstate_state_fromvars(ld, task)
388 sstate_clean_cachefile(ss, ld)
389
390def sstate_clean_manifest(manifest, d):
391 import oe.path
392
393 mfile = open(manifest)
394 entries = mfile.readlines()
395 mfile.close()
396
397 for entry in entries:
398 entry = entry.strip()
399 bb.debug(2, "Removing manifest: %s" % entry)
400 # We can race against another package populating directories as we're removing them
401 # so we ignore errors here.
402 try:
403 if entry.endswith("/"):
404 if os.path.islink(entry[:-1]):
405 os.remove(entry[:-1])
406 elif os.path.exists(entry) and len(os.listdir(entry)) == 0:
407 os.rmdir(entry[:-1])
408 else:
409 oe.path.remove(entry)
410 except OSError:
411 pass
412
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600413 postrm = manifest + ".postrm"
414 if os.path.exists(manifest + ".postrm"):
415 import subprocess
416 os.chmod(postrm, 0o755)
417 subprocess.call(postrm, shell=True)
418 oe.path.remove(postrm)
419
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500420 oe.path.remove(manifest)
421
422def sstate_clean(ss, d):
423 import oe.path
424 import glob
425
426 d2 = d.createCopy()
427 stamp_clean = d.getVar("STAMPCLEAN", True)
428 extrainf = d.getVarFlag("do_" + ss['task'], 'stamp-extra-info', True)
429 if extrainf:
430 d2.setVar("SSTATE_MANMACH", extrainf)
431 wildcard_stfile = "%s.do_%s*.%s" % (stamp_clean, ss['task'], extrainf)
432 else:
433 wildcard_stfile = "%s.do_%s*" % (stamp_clean, ss['task'])
434
435 manifest = d2.expand("${SSTATE_MANFILEPREFIX}.%s" % ss['task'])
436
437 if os.path.exists(manifest):
438 locks = []
439 for lock in ss['lockfiles-shared']:
440 locks.append(bb.utils.lockfile(lock))
441 for lock in ss['lockfiles']:
442 locks.append(bb.utils.lockfile(lock))
443
444 sstate_clean_manifest(manifest, d)
445
446 for lock in locks:
447 bb.utils.unlockfile(lock)
448
449 # Remove the current and previous stamps, but keep the sigdata.
450 #
451 # The glob() matches do_task* which may match multiple tasks, for
452 # example: do_package and do_package_write_ipk, so we need to
453 # exactly match *.do_task.* and *.do_task_setscene.*
454 rm_stamp = '.do_%s.' % ss['task']
455 rm_setscene = '.do_%s_setscene.' % ss['task']
456 # For BB_SIGNATURE_HANDLER = "noop"
457 rm_nohash = ".do_%s" % ss['task']
458 for stfile in glob.glob(wildcard_stfile):
459 # Keep the sigdata
460 if ".sigdata." in stfile:
461 continue
462 # Preserve taint files in the stamps directory
463 if stfile.endswith('.taint'):
464 continue
465 if rm_stamp in stfile or rm_setscene in stfile or \
466 stfile.endswith(rm_nohash):
467 oe.path.remove(stfile)
468
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500469 # Removes the users/groups created by the package
470 for cleanfunc in (d.getVar('SSTATECLEANFUNCS', True) or '').split():
471 bb.build.exec_func(cleanfunc, d)
472
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500473sstate_clean[vardepsexclude] = "SSTATE_MANFILEPREFIX"
474
475CLEANFUNCS += "sstate_cleanall"
476
477python sstate_cleanall() {
478 bb.note("Removing shared state for package %s" % d.getVar('PN', True))
479
480 manifest_dir = d.getVar('SSTATE_MANIFESTS', True)
481 if not os.path.exists(manifest_dir):
482 return
483
484 tasks = d.getVar('SSTATETASKS', True).split()
485 for name in tasks:
486 ld = d.createCopy()
487 shared_state = sstate_state_fromvars(ld, name)
488 sstate_clean(shared_state, ld)
489}
490
491python sstate_hardcode_path () {
492 import subprocess, platform
493
494 # Need to remove hardcoded paths and fix these when we install the
495 # staging packages.
496 #
497 # Note: the logic in this function needs to match the reverse logic
498 # in sstate_installpkg(ss, d)
499
500 staging = d.getVar('STAGING_DIR', True)
501 staging_target = d.getVar('STAGING_DIR_TARGET', True)
502 staging_host = d.getVar('STAGING_DIR_HOST', True)
503 sstate_builddir = d.getVar('SSTATE_BUILDDIR', True)
504
505 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):
506 sstate_grep_cmd = "grep -l -e '%s'" % (staging)
507 sstate_sed_cmd = "sed -i -e 's:%s:FIXMESTAGINGDIR:g'" % (staging)
508 elif bb.data.inherits_class('cross', d):
509 sstate_grep_cmd = "grep -l -e '%s' -e '%s'" % (staging_target, staging)
510 sstate_sed_cmd = "sed -i -e 's:%s:FIXMESTAGINGDIRTARGET:g; s:%s:FIXMESTAGINGDIR:g'" % (staging_target, staging)
511 else:
512 sstate_grep_cmd = "grep -l -e '%s'" % (staging_host)
513 sstate_sed_cmd = "sed -i -e 's:%s:FIXMESTAGINGDIRHOST:g'" % (staging_host)
514
515 extra_staging_fixmes = d.getVar('EXTRA_STAGING_FIXMES', True) or ''
516 for fixmevar in extra_staging_fixmes.split():
517 fixme_path = d.getVar(fixmevar, True)
518 sstate_sed_cmd += " -e 's:%s:FIXME_%s:g'" % (fixme_path, fixmevar)
519
520 fixmefn = sstate_builddir + "fixmepath"
521
522 sstate_scan_cmd = d.getVar('SSTATE_SCAN_CMD', True)
523 sstate_filelist_cmd = "tee %s" % (fixmefn)
524
525 # fixmepath file needs relative paths, drop sstate_builddir prefix
526 sstate_filelist_relative_cmd = "sed -i -e 's:^%s::g' %s" % (sstate_builddir, fixmefn)
527
528 xargs_no_empty_run_cmd = '--no-run-if-empty'
529 if platform.system() == 'Darwin':
530 xargs_no_empty_run_cmd = ''
531
532 # Limit the fixpaths and sed operations based on the initial grep search
533 # This has the side effect of making sure the vfs cache is hot
534 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)
535
536 bb.note("Removing hardcoded paths from sstate package: '%s'" % (sstate_hardcode_cmd))
537 subprocess.call(sstate_hardcode_cmd, shell=True)
538
539 # If the fixmefn is empty, remove it..
540 if os.stat(fixmefn).st_size == 0:
541 os.remove(fixmefn)
542 else:
543 bb.note("Replacing absolute paths in fixmepath file: '%s'" % (sstate_filelist_relative_cmd))
544 subprocess.call(sstate_filelist_relative_cmd, shell=True)
545}
546
547def sstate_package(ss, d):
548 import oe.path
549
550 def make_relative_symlink(path, outputpath, d):
551 # Replace out absolute TMPDIR paths in symlinks with relative ones
552 if not os.path.islink(path):
553 return
554 link = os.readlink(path)
555 if not os.path.isabs(link):
556 return
557 if not link.startswith(tmpdir):
558 return
559
560 depth = outputpath.rpartition(tmpdir)[2].count('/')
561 base = link.partition(tmpdir)[2].strip()
562 while depth > 1:
563 base = "/.." + base
564 depth -= 1
565 base = "." + base
566
567 bb.debug(2, "Replacing absolute path %s with relative path %s for %s" % (link, base, outputpath))
568 os.remove(path)
569 os.symlink(base, path)
570
571 tmpdir = d.getVar('TMPDIR', True)
572
573 sstatebuild = d.expand("${WORKDIR}/sstate-build-%s/" % ss['task'])
574 sstatepkg = d.getVar('SSTATE_PKG', True) + '_'+ ss['task'] + ".tgz"
575 bb.utils.remove(sstatebuild, recurse=True)
576 bb.utils.mkdirhier(sstatebuild)
577 bb.utils.mkdirhier(os.path.dirname(sstatepkg))
578 for state in ss['dirs']:
579 if not os.path.exists(state[1]):
580 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600581 if d.getVar('SSTATE_SKIP_CREATION', True) == '1':
582 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500583 srcbase = state[0].rstrip("/").rsplit('/', 1)[0]
584 for walkroot, dirs, files in os.walk(state[1]):
585 for file in files:
586 srcpath = os.path.join(walkroot, file)
587 dstpath = srcpath.replace(state[1], state[2])
588 make_relative_symlink(srcpath, dstpath, d)
589 for dir in dirs:
590 srcpath = os.path.join(walkroot, dir)
591 dstpath = srcpath.replace(state[1], state[2])
592 make_relative_symlink(srcpath, dstpath, d)
593 bb.debug(2, "Preparing tree %s for packaging at %s" % (state[1], sstatebuild + state[0]))
594 oe.path.copyhardlinktree(state[1], sstatebuild + state[0])
595
596 workdir = d.getVar('WORKDIR', True)
597 for plain in ss['plaindirs']:
598 pdir = plain.replace(workdir, sstatebuild)
599 bb.utils.mkdirhier(plain)
600 bb.utils.mkdirhier(pdir)
601 oe.path.copyhardlinktree(plain, pdir)
602
603 d.setVar('SSTATE_BUILDDIR', sstatebuild)
604 d.setVar('SSTATE_PKG', sstatepkg)
605
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500606 for f in (d.getVar('SSTATECREATEFUNCS', True) or '').split() + \
607 ['sstate_create_package', 'sstate_sign_package'] + \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500608 (d.getVar('SSTATEPOSTCREATEFUNCS', True) or '').split():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500609 # All hooks should run in SSTATE_BUILDDIR.
610 bb.build.exec_func(f, d, (sstatebuild,))
611
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500612 bb.siggen.dump_this_task(sstatepkg + ".siginfo", d)
613
614 return
615
616def pstaging_fetch(sstatefetch, sstatepkg, d):
617 import bb.fetch2
618
619 # Only try and fetch if the user has configured a mirror
620 mirrors = d.getVar('SSTATE_MIRRORS', True)
621 if not mirrors:
622 return
623
624 # Copy the data object and override DL_DIR and SRC_URI
625 localdata = bb.data.createCopy(d)
626 bb.data.update_data(localdata)
627
628 dldir = localdata.expand("${SSTATE_DIR}")
629 bb.utils.mkdirhier(dldir)
630
631 localdata.delVar('MIRRORS')
632 localdata.setVar('FILESPATH', dldir)
633 localdata.setVar('DL_DIR', dldir)
634 localdata.setVar('PREMIRRORS', mirrors)
635
636 # if BB_NO_NETWORK is set but we also have SSTATE_MIRROR_ALLOW_NETWORK,
637 # we'll want to allow network access for the current set of fetches.
638 if localdata.getVar('BB_NO_NETWORK', True) == "1" and localdata.getVar('SSTATE_MIRROR_ALLOW_NETWORK', True) == "1":
639 localdata.delVar('BB_NO_NETWORK')
640
641 # Try a fetch from the sstate mirror, if it fails just return and
642 # we will build the package
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600643 uris = ['file://{0};downloadfilename={0}'.format(sstatefetch),
644 'file://{0}.siginfo;downloadfilename={0}.siginfo'.format(sstatefetch)]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500645 if bb.utils.to_boolean(d.getVar("SSTATE_VERIFY_SIG", True), False):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600646 uris += ['file://{0}.sig;downloadfilename={0}.sig'.format(sstatefetch)]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500647
648 for srcuri in uris:
649 localdata.setVar('SRC_URI', srcuri)
650 try:
651 fetcher = bb.fetch2.Fetch([srcuri], localdata, cache=False)
652 fetcher.download()
653
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500654 except bb.fetch2.BBFetchException:
655 break
656
657def sstate_setscene(d):
658 shared_state = sstate_state_fromvars(d)
659 accelerate = sstate_installpkg(shared_state, d)
660 if not accelerate:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600661 bb.fatal("No suitable staging package found")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500662
663python sstate_task_prefunc () {
664 shared_state = sstate_state_fromvars(d)
665 sstate_clean(shared_state, d)
666}
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500667sstate_task_prefunc[dirs] = "${WORKDIR}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500668
669python sstate_task_postfunc () {
670 shared_state = sstate_state_fromvars(d)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500671
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500672 sstate_install(shared_state, d)
673 for intercept in shared_state['interceptfuncs']:
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500674 bb.build.exec_func(intercept, d, (d.getVar("WORKDIR", True),))
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600675 omask = os.umask(0o002)
676 if omask != 0o002:
677 bb.note("Using umask 0o002 (not %0o) for sstate packaging" % omask)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500678 sstate_package(shared_state, d)
679 os.umask(omask)
680}
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500681sstate_task_postfunc[dirs] = "${WORKDIR}"
682
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500683
684#
685# Shell function to generate a sstate package from a directory
686# set as SSTATE_BUILDDIR. Will be run from within SSTATE_BUILDDIR.
687#
688sstate_create_package () {
689 TFILE=`mktemp ${SSTATE_PKG}.XXXXXXXX`
690 # Need to handle empty directories
691 if [ "$(ls -A)" ]; then
692 set +e
693 tar -czf $TFILE *
694 ret=$?
695 if [ $ret -ne 0 ] && [ $ret -ne 1 ]; then
696 exit 1
697 fi
698 set -e
699 else
700 tar -cz --file=$TFILE --files-from=/dev/null
701 fi
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500702 chmod 0664 $TFILE
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500703 mv -f $TFILE ${SSTATE_PKG}
704
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500705 cd ${WORKDIR}
706 rm -rf ${SSTATE_BUILDDIR}
707}
708
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500709python sstate_sign_package () {
710 from oe.gpg_sign import get_signer
711
712 if d.getVar('SSTATE_SIG_KEY', True):
713 signer = get_signer(d, 'local')
714 sstate_pkg = d.getVar('SSTATE_PKG', True)
715 if os.path.exists(sstate_pkg + '.sig'):
716 os.unlink(sstate_pkg + '.sig')
717 signer.detach_sign(sstate_pkg, d.getVar('SSTATE_SIG_KEY', False), None,
718 d.getVar('SSTATE_SIG_PASSPHRASE', True), armor=False)
719}
720
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500721#
722# Shell function to decompress and prepare a package for installation
723# Will be run from within SSTATE_INSTDIR.
724#
725sstate_unpack_package () {
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500726 tar -xvzf ${SSTATE_PKG}
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}