blob: 3a3f7cc24b3e73ecb6fa8b5532f3951aefcf48e1 [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
Andrew Geissler82c905d2020-04-13 13:39:40 -05006def generate_sstatefn(spec, hash, taskname, siginfo, d):
7 if taskname is None:
8 return ""
9 extension = ".tgz"
10 # 8 chars reserved for siginfo
11 limit = 254 - 8
12 if siginfo:
13 limit = 254
14 extension = ".tgz.siginfo"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050015 if not hash:
16 hash = "INVALID"
Andrew Geissler82c905d2020-04-13 13:39:40 -050017 fn = spec + hash + "_" + taskname + extension
18 # If the filename is too long, attempt to reduce it
19 if len(fn) > limit:
20 components = spec.split(":")
21 # Fields 0,5,6 are mandatory, 1 is most useful, 2,3,4 are just for information
22 # 7 is for the separators
23 avail = (254 - len(hash + "_" + taskname + extension) - len(components[0]) - len(components[1]) - len(components[5]) - len(components[6]) - 7) // 3
24 components[2] = components[2][:avail]
25 components[3] = components[3][:avail]
26 components[4] = components[4][:avail]
27 spec = ":".join(components)
28 fn = spec + hash + "_" + taskname + extension
29 if len(fn) > limit:
30 bb.fatal("Unable to reduce sstate name to less than 255 chararacters")
31 return hash[:2] + "/" + hash[2:4] + "/" + fn
Patrick Williamsc124f4f2015-09-15 14:41:29 -050032
33SSTATE_PKGARCH = "${PACKAGE_ARCH}"
34SSTATE_PKGSPEC = "sstate:${PN}:${PACKAGE_ARCH}${TARGET_VENDOR}-${TARGET_OS}:${PV}:${PR}:${SSTATE_PKGARCH}:${SSTATE_VERSION}:"
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050035SSTATE_SWSPEC = "sstate:${PN}::${PV}:${PR}::${SSTATE_VERSION}:"
Andrew Geissler82c905d2020-04-13 13:39:40 -050036SSTATE_PKGNAME = "${SSTATE_EXTRAPATH}${@generate_sstatefn(d.getVar('SSTATE_PKGSPEC'), d.getVar('BB_UNIHASH'), d.getVar('SSTATE_CURRTASK'), False, d)}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050037SSTATE_PKG = "${SSTATE_DIR}/${SSTATE_PKGNAME}"
38SSTATE_EXTRAPATH = ""
39SSTATE_EXTRAPATHWILDCARD = ""
Andrew Geissler82c905d2020-04-13 13:39:40 -050040SSTATE_PATHSPEC = "${SSTATE_DIR}/${SSTATE_EXTRAPATHWILDCARD}*/*/${SSTATE_PKGSPEC}*_${SSTATE_PATH_CURRTASK}.tgz*"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050041
Patrick Williamsc0f7c042017-02-23 20:41:17 -060042# explicitly make PV to depend on evaluated value of PV variable
43PV[vardepvalue] = "${PV}"
44
Patrick Williamsc124f4f2015-09-15 14:41:29 -050045# We don't want the sstate to depend on things like the distro string
46# of the system, we let the sstate paths take care of this.
47SSTATE_EXTRAPATH[vardepvalue] = ""
Brad Bishop19323692019-04-05 15:28:33 -040048SSTATE_EXTRAPATHWILDCARD[vardepvalue] = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -050049
50# For multilib rpm the allarch packagegroup files can overwrite (in theory they're identical)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080051SSTATE_DUPWHITELIST = "${DEPLOY_DIR}/licenses/"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050052# Avoid docbook/sgml catalog warnings for now
53SSTATE_DUPWHITELIST += "${STAGING_ETCDIR_NATIVE}/sgml ${STAGING_DATADIR_NATIVE}/sgml"
Brad Bishop316dfdd2018-06-25 12:45:53 -040054# sdk-provides-dummy-nativesdk and nativesdk-buildtools-perl-dummy overlap for different SDKMACHINE
55SSTATE_DUPWHITELIST += "${DEPLOY_DIR_RPM}/sdk_provides_dummy_nativesdk/ ${DEPLOY_DIR_IPK}/sdk-provides-dummy-nativesdk/"
56SSTATE_DUPWHITELIST += "${DEPLOY_DIR_RPM}/buildtools_dummy_nativesdk/ ${DEPLOY_DIR_IPK}/buildtools-dummy-nativesdk/"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080057# target-sdk-provides-dummy overlaps that allarch is disabled when multilib is used
58SSTATE_DUPWHITELIST += "${COMPONENTS_DIR}/sdk-provides-dummy-target/ ${DEPLOY_DIR_RPM}/sdk_provides_dummy_target/ ${DEPLOY_DIR_IPK}/sdk-provides-dummy-target/"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050059# Archive the sources for many architectures in one deploy folder
60SSTATE_DUPWHITELIST += "${DEPLOY_DIR_SRC}"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080061# ovmf/grub-efi/systemd-boot/intel-microcode multilib recipes can generate identical overlapping files
62SSTATE_DUPWHITELIST += "${DEPLOY_DIR_IMAGE}/ovmf"
63SSTATE_DUPWHITELIST += "${DEPLOY_DIR_IMAGE}/grub-efi"
64SSTATE_DUPWHITELIST += "${DEPLOY_DIR_IMAGE}/systemd-boot"
65SSTATE_DUPWHITELIST += "${DEPLOY_DIR_IMAGE}/microcode"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050066
Brad Bishop6e60e8b2018-02-01 10:27:11 -050067SSTATE_SCAN_FILES ?= "*.la *-config *_config postinst-*"
68SSTATE_SCAN_CMD ??= 'find ${SSTATE_BUILDDIR} \( -name "${@"\" -o -name \"".join(d.getVar("SSTATE_SCAN_FILES").split())}" \) -type f'
69SSTATE_SCAN_CMD_NATIVE ??= 'grep -Irl -e ${RECIPE_SYSROOT} -e ${RECIPE_SYSROOT_NATIVE} -e ${HOSTTOOLS_DIR} ${SSTATE_BUILDDIR}'
Patrick Williamsc124f4f2015-09-15 14:41:29 -050070
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050071BB_HASHFILENAME = "False ${SSTATE_PKGSPEC} ${SSTATE_SWSPEC}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050072
73SSTATE_ARCHS = " \
74 ${BUILD_ARCH} \
Andrew Geissler6ce62a22020-11-30 19:58:47 -060075 ${BUILD_ARCH}_${ORIGNATIVELSBSTRING} \
Patrick Williamsc124f4f2015-09-15 14:41:29 -050076 ${BUILD_ARCH}_${SDK_ARCH}_${SDK_OS} \
77 ${BUILD_ARCH}_${TARGET_ARCH} \
78 ${SDK_ARCH}_${SDK_OS} \
79 ${SDK_ARCH}_${PACKAGE_ARCH} \
80 allarch \
81 ${PACKAGE_ARCH} \
Brad Bishop316dfdd2018-06-25 12:45:53 -040082 ${PACKAGE_EXTRA_ARCHS} \
83 ${MACHINE_ARCH}"
Andrew Geissler6ce62a22020-11-30 19:58:47 -060084SSTATE_ARCHS[vardepsexclude] = "ORIGNATIVELSBSTRING"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050085
86SSTATE_MANMACH ?= "${SSTATE_PKGARCH}"
87
88SSTATECREATEFUNCS = "sstate_hardcode_path"
Brad Bishop19323692019-04-05 15:28:33 -040089SSTATECREATEFUNCS[vardeps] = "SSTATE_SCAN_FILES"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050090SSTATEPOSTCREATEFUNCS = ""
91SSTATEPREINSTFUNCS = ""
92SSTATEPOSTUNPACKFUNCS = "sstate_hardcode_path_unpack"
93SSTATEPOSTINSTFUNCS = ""
Brad Bishop6e60e8b2018-02-01 10:27:11 -050094EXTRA_STAGING_FIXMES ?= "HOSTTOOLS_DIR"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050095
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050096# Check whether sstate exists for tasks that support sstate and are in the
97# locked signatures file.
98SIGGEN_LOCKEDSIGS_SSTATE_EXISTS_CHECK ?= 'error'
99
100# Check whether the task's computed hash matches the task's hash in the
101# locked signatures file.
102SIGGEN_LOCKEDSIGS_TASKSIG_CHECK ?= "error"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500103
104# The GnuPG key ID and passphrase to use to sign sstate archives (or unset to
105# not sign)
106SSTATE_SIG_KEY ?= ""
107SSTATE_SIG_PASSPHRASE ?= ""
108# Whether to verify the GnUPG signatures when extracting sstate archives
109SSTATE_VERIFY_SIG ?= "0"
110
Brad Bishop19323692019-04-05 15:28:33 -0400111SSTATE_HASHEQUIV_METHOD ?= "oe.sstatesig.OEOuthashBasic"
112SSTATE_HASHEQUIV_METHOD[doc] = "The fully-qualified function used to calculate \
113 the output hash for a task, which in turn is used to determine equivalency. \
114 "
115
Brad Bishop19323692019-04-05 15:28:33 -0400116SSTATE_HASHEQUIV_REPORT_TASKDATA ?= "0"
117SSTATE_HASHEQUIV_REPORT_TASKDATA[doc] = "Report additional useful data to the \
118 hash equivalency server, such as PN, PV, taskname, etc. This information \
119 is very useful for developers looking at task data, but may leak sensitive \
120 data if the equivalence server is public. \
121 "
122
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500123python () {
124 if bb.data.inherits_class('native', d):
125 d.setVar('SSTATE_PKGARCH', d.getVar('BUILD_ARCH', False))
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600126 if d.getVar("PN") == "pseudo-native":
127 d.appendVar('SSTATE_PKGARCH', '_${ORIGNATIVELSBSTRING}')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500128 elif bb.data.inherits_class('crosssdk', d):
129 d.setVar('SSTATE_PKGARCH', d.expand("${BUILD_ARCH}_${SDK_ARCH}_${SDK_OS}"))
130 elif bb.data.inherits_class('cross', d):
131 d.setVar('SSTATE_PKGARCH', d.expand("${BUILD_ARCH}_${TARGET_ARCH}"))
132 elif bb.data.inherits_class('nativesdk', d):
133 d.setVar('SSTATE_PKGARCH', d.expand("${SDK_ARCH}_${SDK_OS}"))
134 elif bb.data.inherits_class('cross-canadian', d):
135 d.setVar('SSTATE_PKGARCH', d.expand("${SDK_ARCH}_${PACKAGE_ARCH}"))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500136 elif bb.data.inherits_class('allarch', d) and d.getVar("PACKAGE_ARCH") == "all":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500137 d.setVar('SSTATE_PKGARCH', "allarch")
138 else:
139 d.setVar('SSTATE_MANMACH', d.expand("${PACKAGE_ARCH}"))
140
141 if bb.data.inherits_class('native', d) or bb.data.inherits_class('crosssdk', d) or bb.data.inherits_class('cross', d):
142 d.setVar('SSTATE_EXTRAPATH', "${NATIVELSBSTRING}/")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500143 d.setVar('BB_HASHFILENAME', "True ${SSTATE_PKGSPEC} ${SSTATE_SWSPEC}")
Brad Bishop19323692019-04-05 15:28:33 -0400144 d.setVar('SSTATE_EXTRAPATHWILDCARD', "${NATIVELSBSTRING}/")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500145
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500146 unique_tasks = sorted(set((d.getVar('SSTATETASKS') or "").split()))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500147 d.setVar('SSTATETASKS', " ".join(unique_tasks))
148 for task in unique_tasks:
149 d.prependVarFlag(task, 'prefuncs', "sstate_task_prefunc ")
150 d.appendVarFlag(task, 'postfuncs', " sstate_task_postfunc")
151}
152
153def sstate_init(task, d):
154 ss = {}
155 ss['task'] = task
156 ss['dirs'] = []
157 ss['plaindirs'] = []
158 ss['lockfiles'] = []
159 ss['lockfiles-shared'] = []
160 return ss
161
162def sstate_state_fromvars(d, task = None):
163 if task is None:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500164 task = d.getVar('BB_CURRENTTASK')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500165 if not task:
166 bb.fatal("sstate code running without task context?!")
167 task = task.replace("_setscene", "")
168
169 if task.startswith("do_"):
170 task = task[3:]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500171 inputs = (d.getVarFlag("do_" + task, 'sstate-inputdirs') or "").split()
172 outputs = (d.getVarFlag("do_" + task, 'sstate-outputdirs') or "").split()
173 plaindirs = (d.getVarFlag("do_" + task, 'sstate-plaindirs') or "").split()
174 lockfiles = (d.getVarFlag("do_" + task, 'sstate-lockfile') or "").split()
175 lockfilesshared = (d.getVarFlag("do_" + task, 'sstate-lockfile-shared') or "").split()
176 interceptfuncs = (d.getVarFlag("do_" + task, 'sstate-interceptfuncs') or "").split()
177 fixmedir = d.getVarFlag("do_" + task, 'sstate-fixmedir') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500178 if not task or len(inputs) != len(outputs):
179 bb.fatal("sstate variables not setup correctly?!")
180
181 if task == "populate_lic":
182 d.setVar("SSTATE_PKGSPEC", "${SSTATE_SWSPEC}")
183 d.setVar("SSTATE_EXTRAPATH", "")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500184 d.setVar('SSTATE_EXTRAPATHWILDCARD', "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500185
186 ss = sstate_init(task, d)
187 for i in range(len(inputs)):
188 sstate_add(ss, inputs[i], outputs[i], d)
189 ss['lockfiles'] = lockfiles
190 ss['lockfiles-shared'] = lockfilesshared
191 ss['plaindirs'] = plaindirs
192 ss['interceptfuncs'] = interceptfuncs
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500193 ss['fixmedir'] = fixmedir
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500194 return ss
195
196def sstate_add(ss, source, dest, d):
197 if not source.endswith("/"):
198 source = source + "/"
199 if not dest.endswith("/"):
200 dest = dest + "/"
201 source = os.path.normpath(source)
202 dest = os.path.normpath(dest)
203 srcbase = os.path.basename(source)
204 ss['dirs'].append([srcbase, source, dest])
205 return ss
206
207def sstate_install(ss, d):
208 import oe.path
209 import oe.sstatesig
210 import subprocess
211
212 sharedfiles = []
213 shareddirs = []
214 bb.utils.mkdirhier(d.expand("${SSTATE_MANIFESTS}"))
215
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500216 sstateinst = d.expand("${WORKDIR}/sstate-install-%s/" % ss['task'])
217
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500218 manifest, d2 = oe.sstatesig.sstate_get_manifest_filename(ss['task'], d)
219
220 if os.access(manifest, os.R_OK):
221 bb.fatal("Package already staged (%s)?!" % manifest)
222
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600223 d.setVar("SSTATE_INST_POSTRM", manifest + ".postrm")
224
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500225 locks = []
226 for lock in ss['lockfiles-shared']:
227 locks.append(bb.utils.lockfile(lock, True))
228 for lock in ss['lockfiles']:
229 locks.append(bb.utils.lockfile(lock))
230
231 for state in ss['dirs']:
232 bb.debug(2, "Staging files from %s to %s" % (state[1], state[2]))
233 for walkroot, dirs, files in os.walk(state[1]):
234 for file in files:
235 srcpath = os.path.join(walkroot, file)
236 dstpath = srcpath.replace(state[1], state[2])
237 #bb.debug(2, "Staging %s to %s" % (srcpath, dstpath))
238 sharedfiles.append(dstpath)
239 for dir in dirs:
240 srcdir = os.path.join(walkroot, dir)
241 dstdir = srcdir.replace(state[1], state[2])
242 #bb.debug(2, "Staging %s to %s" % (srcdir, dstdir))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500243 if os.path.islink(srcdir):
244 sharedfiles.append(dstdir)
245 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500246 if not dstdir.endswith("/"):
247 dstdir = dstdir + "/"
248 shareddirs.append(dstdir)
249
250 # Check the file list for conflicts against files which already exist
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500251 whitelist = (d.getVar("SSTATE_DUPWHITELIST") or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500252 match = []
253 for f in sharedfiles:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500254 if os.path.exists(f) and not os.path.islink(f):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500255 f = os.path.normpath(f)
256 realmatch = True
257 for w in whitelist:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600258 w = os.path.normpath(w)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500259 if f.startswith(w):
260 realmatch = False
261 break
262 if realmatch:
263 match.append(f)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500264 sstate_search_cmd = "grep -rlF '%s' %s --exclude=master.list | sed -e 's:^.*/::'" % (f, d.expand("${SSTATE_MANIFESTS}"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500265 search_output = subprocess.Popen(sstate_search_cmd, shell=True, stdout=subprocess.PIPE).communicate()[0]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500266 if search_output:
267 match.append(" (matched in %s)" % search_output.decode('utf-8').rstrip())
268 else:
269 match.append(" (not matched to any task)")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500270 if match:
271 bb.error("The recipe %s is trying to install files into a shared " \
272 "area when those files already exist. Those files and their manifest " \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500273 "location are:\n %s\nPlease verify which recipe should provide the " \
274 "above files.\n\nThe build has stopped, as continuing in this scenario WILL " \
275 "break things - if not now, possibly in the future (we've seen builds fail " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500276 "several months later). If the system knew how to recover from this " \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500277 "automatically it would, however there are several different scenarios " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500278 "which can result in this and we don't know which one this is. It may be " \
279 "you have switched providers of something like virtual/kernel (e.g. from " \
280 "linux-yocto to linux-yocto-dev), in that case you need to execute the " \
281 "clean task for both recipes and it will resolve this error. It may be " \
282 "you changed DISTRO_FEATURES from systemd to udev or vice versa. Cleaning " \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500283 "those recipes should again resolve this error, however switching " \
284 "DISTRO_FEATURES on an existing build directory is not supported - you " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500285 "should really clean out tmp and rebuild (reusing sstate should be safe). " \
286 "It could be the overlapping files detected are harmless in which case " \
287 "adding them to SSTATE_DUPWHITELIST may be the correct solution. It could " \
288 "also be your build is including two different conflicting versions of " \
289 "things (e.g. bluez 4 and bluez 5 and the correct solution for that would " \
290 "be to resolve the conflict. If in doubt, please ask on the mailing list, " \
291 "sharing the error and filelist above." % \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500292 (d.getVar('PN'), "\n ".join(match)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500293 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.")
294
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500295 if ss['fixmedir'] and os.path.exists(ss['fixmedir'] + "/fixmepath.cmd"):
296 sharedfiles.append(ss['fixmedir'] + "/fixmepath.cmd")
297 sharedfiles.append(ss['fixmedir'] + "/fixmepath")
298
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500299 # Write out the manifest
300 f = open(manifest, "w")
301 for file in sharedfiles:
302 f.write(file + "\n")
303
304 # We want to ensure that directories appear at the end of the manifest
305 # so that when we test to see if they should be deleted any contents
306 # added by the task will have been removed first.
307 dirs = sorted(shareddirs, key=len)
308 # Must remove children first, which will have a longer path than the parent
309 for di in reversed(dirs):
310 f.write(di + "\n")
311 f.close()
312
313 # Append to the list of manifests for this PACKAGE_ARCH
314
315 i = d2.expand("${SSTATE_MANIFESTS}/index-${SSTATE_MANMACH}")
316 l = bb.utils.lockfile(i + ".lock")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500317 filedata = d.getVar("STAMP") + " " + d2.getVar("SSTATE_MANFILEPREFIX") + " " + d.getVar("WORKDIR") + "\n"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500318 manifests = []
319 if os.path.exists(i):
320 with open(i, "r") as f:
321 manifests = f.readlines()
William A. Kennington IIIac69b482021-06-02 12:28:27 -0700322 # We append new entries, we don't remove older entries which may have the same
323 # manifest name but different versions from stamp/workdir. See below.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500324 if filedata not in manifests:
325 with open(i, "a+") as f:
326 f.write(filedata)
327 bb.utils.unlockfile(l)
328
329 # Run the actual file install
330 for state in ss['dirs']:
331 if os.path.exists(state[1]):
332 oe.path.copyhardlinktree(state[1], state[2])
333
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500334 for postinst in (d.getVar('SSTATEPOSTINSTFUNCS') or '').split():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500335 # All hooks should run in the SSTATE_INSTDIR
336 bb.build.exec_func(postinst, d, (sstateinst,))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500337
338 for lock in locks:
339 bb.utils.unlockfile(lock)
340
341sstate_install[vardepsexclude] += "SSTATE_DUPWHITELIST STATE_MANMACH SSTATE_MANFILEPREFIX"
342sstate_install[vardeps] += "${SSTATEPOSTINSTFUNCS}"
343
344def sstate_installpkg(ss, d):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500345 from oe.gpg_sign import get_signer
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500346
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500347 sstateinst = d.expand("${WORKDIR}/sstate-install-%s/" % ss['task'])
Andrew Geissler82c905d2020-04-13 13:39:40 -0500348 d.setVar("SSTATE_CURRTASK", ss['task'])
349 sstatefetch = d.getVar('SSTATE_PKGNAME')
350 sstatepkg = d.getVar('SSTATE_PKG')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500351
352 if not os.path.exists(sstatepkg):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800353 pstaging_fetch(sstatefetch, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500354
355 if not os.path.isfile(sstatepkg):
Brad Bishop08902b02019-08-20 09:16:51 -0400356 bb.note("Sstate package %s does not exist" % sstatepkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500357 return False
358
359 sstate_clean(ss, d)
360
361 d.setVar('SSTATE_INSTDIR', sstateinst)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500362
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500363 if bb.utils.to_boolean(d.getVar("SSTATE_VERIFY_SIG"), False):
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500364 if not os.path.isfile(sstatepkg + '.sig'):
365 bb.warn("No signature file for sstate package %s, skipping acceleration..." % sstatepkg)
366 return False
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500367 signer = get_signer(d, 'local')
368 if not signer.verify(sstatepkg + '.sig'):
Brad Bishop08902b02019-08-20 09:16:51 -0400369 bb.warn("Cannot verify signature on sstate package %s, skipping acceleration..." % sstatepkg)
370 return False
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500371
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500372 # Empty sstateinst directory, ensure its clean
373 if os.path.exists(sstateinst):
374 oe.path.remove(sstateinst)
375 bb.utils.mkdirhier(sstateinst)
376
377 sstateinst = d.getVar("SSTATE_INSTDIR")
378 d.setVar('SSTATE_FIXMEDIR', ss['fixmedir'])
379
380 for f in (d.getVar('SSTATEPREINSTFUNCS') or '').split() + ['sstate_unpack_package']:
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500381 # All hooks should run in the SSTATE_INSTDIR
382 bb.build.exec_func(f, d, (sstateinst,))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500383
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500384 return sstate_installpkgdir(ss, d)
385
386def sstate_installpkgdir(ss, d):
387 import oe.path
388 import subprocess
389
390 sstateinst = d.getVar("SSTATE_INSTDIR")
391 d.setVar('SSTATE_FIXMEDIR', ss['fixmedir'])
392
393 for f in (d.getVar('SSTATEPOSTUNPACKFUNCS') or '').split():
394 # All hooks should run in the SSTATE_INSTDIR
395 bb.build.exec_func(f, d, (sstateinst,))
396
397 def prepdir(dir):
398 # remove dir if it exists, ensure any parent directories do exist
399 if os.path.exists(dir):
400 oe.path.remove(dir)
401 bb.utils.mkdirhier(dir)
402 oe.path.remove(dir)
403
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500404 for state in ss['dirs']:
405 prepdir(state[1])
Andrew Geisslerc926e172021-05-07 16:11:35 -0500406 bb.utils.rename(sstateinst + state[0], state[1])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500407 sstate_install(ss, d)
408
409 for plain in ss['plaindirs']:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500410 workdir = d.getVar('WORKDIR')
Brad Bishop977dc1a2019-02-06 16:01:43 -0500411 sharedworkdir = os.path.join(d.getVar('TMPDIR'), "work-shared")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500412 src = sstateinst + "/" + plain.replace(workdir, '')
Brad Bishop977dc1a2019-02-06 16:01:43 -0500413 if sharedworkdir in plain:
414 src = sstateinst + "/" + plain.replace(sharedworkdir, '')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500415 dest = plain
416 bb.utils.mkdirhier(src)
417 prepdir(dest)
Andrew Geisslerc926e172021-05-07 16:11:35 -0500418 bb.utils.rename(src, dest)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500419
420 return True
421
422python sstate_hardcode_path_unpack () {
423 # Fixup hardcoded paths
424 #
425 # Note: The logic below must match the reverse logic in
426 # sstate_hardcode_path(d)
427 import subprocess
428
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500429 sstateinst = d.getVar('SSTATE_INSTDIR')
430 sstatefixmedir = d.getVar('SSTATE_FIXMEDIR')
431 fixmefn = sstateinst + "fixmepath"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500432 if os.path.isfile(fixmefn):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500433 staging_target = d.getVar('RECIPE_SYSROOT')
434 staging_host = d.getVar('RECIPE_SYSROOT_NATIVE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500435
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500436 if bb.data.inherits_class('native', d) or bb.data.inherits_class('cross-canadian', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500437 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRHOST:%s:g'" % (staging_host)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500438 elif bb.data.inherits_class('cross', d) or bb.data.inherits_class('crosssdk', d):
439 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRTARGET:%s:g; s:FIXMESTAGINGDIRHOST:%s:g'" % (staging_target, staging_host)
440 else:
441 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRTARGET:%s:g'" % (staging_target)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500442
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500443 extra_staging_fixmes = d.getVar('EXTRA_STAGING_FIXMES') or ''
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500444 for fixmevar in extra_staging_fixmes.split():
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500445 fixme_path = d.getVar(fixmevar)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500446 sstate_sed_cmd += " -e 's:FIXME_%s:%s:g'" % (fixmevar, fixme_path)
447
448 # Add sstateinst to each filename in fixmepath, use xargs to efficiently call sed
449 sstate_hardcode_cmd = "sed -e 's:^:%s:g' %s | xargs %s" % (sstateinst, fixmefn, sstate_sed_cmd)
450
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500451 # Defer do_populate_sysroot relocation command
452 if sstatefixmedir:
453 bb.utils.mkdirhier(sstatefixmedir)
454 with open(sstatefixmedir + "/fixmepath.cmd", "w") as f:
455 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(fixmefn, sstatefixmedir + "/fixmepath")
456 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(sstateinst, "FIXMEFINALSSTATEINST")
457 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(staging_host, "FIXMEFINALSSTATEHOST")
458 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(staging_target, "FIXMEFINALSSTATETARGET")
459 f.write(sstate_hardcode_cmd)
460 bb.utils.copyfile(fixmefn, sstatefixmedir + "/fixmepath")
461 return
462
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500463 bb.note("Replacing fixme paths in sstate package: %s" % (sstate_hardcode_cmd))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500464 subprocess.check_call(sstate_hardcode_cmd, shell=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500465
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800466 # Need to remove this or we'd copy it into the target directory and may
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500467 # conflict with another writer
468 os.remove(fixmefn)
469}
470
471def sstate_clean_cachefile(ss, d):
472 import oe.path
473
Brad Bishopa5c52ff2018-11-23 10:55:50 +1300474 if d.getVarFlag('do_%s' % ss['task'], 'task'):
Andrew Geissler82c905d2020-04-13 13:39:40 -0500475 d.setVar("SSTATE_PATH_CURRTASK", ss['task'])
476 sstatepkgfile = d.getVar('SSTATE_PATHSPEC')
Brad Bishopa5c52ff2018-11-23 10:55:50 +1300477 bb.note("Removing %s" % sstatepkgfile)
478 oe.path.remove(sstatepkgfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500479
480def sstate_clean_cachefiles(d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500481 for task in (d.getVar('SSTATETASKS') or "").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500482 ld = d.createCopy()
483 ss = sstate_state_fromvars(ld, task)
484 sstate_clean_cachefile(ss, ld)
485
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500486def sstate_clean_manifest(manifest, d, prefix=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500487 import oe.path
488
489 mfile = open(manifest)
490 entries = mfile.readlines()
491 mfile.close()
492
493 for entry in entries:
494 entry = entry.strip()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500495 if prefix and not entry.startswith("/"):
496 entry = prefix + "/" + entry
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500497 bb.debug(2, "Removing manifest: %s" % entry)
498 # We can race against another package populating directories as we're removing them
499 # so we ignore errors here.
500 try:
501 if entry.endswith("/"):
502 if os.path.islink(entry[:-1]):
503 os.remove(entry[:-1])
504 elif os.path.exists(entry) and len(os.listdir(entry)) == 0:
505 os.rmdir(entry[:-1])
506 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500507 os.remove(entry)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500508 except OSError:
509 pass
510
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600511 postrm = manifest + ".postrm"
512 if os.path.exists(manifest + ".postrm"):
513 import subprocess
514 os.chmod(postrm, 0o755)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500515 subprocess.check_call(postrm, shell=True)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600516 oe.path.remove(postrm)
517
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500518 oe.path.remove(manifest)
519
520def sstate_clean(ss, d):
521 import oe.path
522 import glob
523
524 d2 = d.createCopy()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500525 stamp_clean = d.getVar("STAMPCLEAN")
526 extrainf = d.getVarFlag("do_" + ss['task'], 'stamp-extra-info')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500527 if extrainf:
528 d2.setVar("SSTATE_MANMACH", extrainf)
529 wildcard_stfile = "%s.do_%s*.%s" % (stamp_clean, ss['task'], extrainf)
530 else:
531 wildcard_stfile = "%s.do_%s*" % (stamp_clean, ss['task'])
532
533 manifest = d2.expand("${SSTATE_MANFILEPREFIX}.%s" % ss['task'])
534
535 if os.path.exists(manifest):
536 locks = []
537 for lock in ss['lockfiles-shared']:
538 locks.append(bb.utils.lockfile(lock))
539 for lock in ss['lockfiles']:
540 locks.append(bb.utils.lockfile(lock))
541
542 sstate_clean_manifest(manifest, d)
543
544 for lock in locks:
545 bb.utils.unlockfile(lock)
546
547 # Remove the current and previous stamps, but keep the sigdata.
548 #
549 # The glob() matches do_task* which may match multiple tasks, for
550 # example: do_package and do_package_write_ipk, so we need to
551 # exactly match *.do_task.* and *.do_task_setscene.*
552 rm_stamp = '.do_%s.' % ss['task']
553 rm_setscene = '.do_%s_setscene.' % ss['task']
554 # For BB_SIGNATURE_HANDLER = "noop"
555 rm_nohash = ".do_%s" % ss['task']
556 for stfile in glob.glob(wildcard_stfile):
557 # Keep the sigdata
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500558 if ".sigdata." in stfile or ".sigbasedata." in stfile:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500559 continue
560 # Preserve taint files in the stamps directory
561 if stfile.endswith('.taint'):
562 continue
563 if rm_stamp in stfile or rm_setscene in stfile or \
564 stfile.endswith(rm_nohash):
565 oe.path.remove(stfile)
566
567sstate_clean[vardepsexclude] = "SSTATE_MANFILEPREFIX"
568
569CLEANFUNCS += "sstate_cleanall"
570
571python sstate_cleanall() {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500572 bb.note("Removing shared state for package %s" % d.getVar('PN'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500573
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500574 manifest_dir = d.getVar('SSTATE_MANIFESTS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500575 if not os.path.exists(manifest_dir):
576 return
577
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500578 tasks = d.getVar('SSTATETASKS').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500579 for name in tasks:
580 ld = d.createCopy()
581 shared_state = sstate_state_fromvars(ld, name)
582 sstate_clean(shared_state, ld)
583}
584
585python sstate_hardcode_path () {
586 import subprocess, platform
587
588 # Need to remove hardcoded paths and fix these when we install the
589 # staging packages.
590 #
591 # Note: the logic in this function needs to match the reverse logic
592 # in sstate_installpkg(ss, d)
593
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500594 staging_target = d.getVar('RECIPE_SYSROOT')
595 staging_host = d.getVar('RECIPE_SYSROOT_NATIVE')
596 sstate_builddir = d.getVar('SSTATE_BUILDDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500597
Brad Bishop316dfdd2018-06-25 12:45:53 -0400598 sstate_sed_cmd = "sed -i -e 's:%s:FIXMESTAGINGDIRHOST:g'" % staging_host
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500599 if bb.data.inherits_class('native', d) or bb.data.inherits_class('cross-canadian', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500600 sstate_grep_cmd = "grep -l -e '%s'" % (staging_host)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500601 elif bb.data.inherits_class('cross', d) or bb.data.inherits_class('crosssdk', d):
602 sstate_grep_cmd = "grep -l -e '%s' -e '%s'" % (staging_target, staging_host)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400603 sstate_sed_cmd += " -e 's:%s:FIXMESTAGINGDIRTARGET:g'" % staging_target
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500604 else:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400605 sstate_grep_cmd = "grep -l -e '%s' -e '%s'" % (staging_target, staging_host)
606 sstate_sed_cmd += " -e 's:%s:FIXMESTAGINGDIRTARGET:g'" % staging_target
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500607
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500608 extra_staging_fixmes = d.getVar('EXTRA_STAGING_FIXMES') or ''
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500609 for fixmevar in extra_staging_fixmes.split():
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500610 fixme_path = d.getVar(fixmevar)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500611 sstate_sed_cmd += " -e 's:%s:FIXME_%s:g'" % (fixme_path, fixmevar)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500612 sstate_grep_cmd += " -e '%s'" % (fixme_path)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500613
614 fixmefn = sstate_builddir + "fixmepath"
615
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500616 sstate_scan_cmd = d.getVar('SSTATE_SCAN_CMD')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500617 sstate_filelist_cmd = "tee %s" % (fixmefn)
618
619 # fixmepath file needs relative paths, drop sstate_builddir prefix
620 sstate_filelist_relative_cmd = "sed -i -e 's:^%s::g' %s" % (sstate_builddir, fixmefn)
621
622 xargs_no_empty_run_cmd = '--no-run-if-empty'
623 if platform.system() == 'Darwin':
624 xargs_no_empty_run_cmd = ''
625
626 # Limit the fixpaths and sed operations based on the initial grep search
627 # This has the side effect of making sure the vfs cache is hot
628 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)
629
630 bb.note("Removing hardcoded paths from sstate package: '%s'" % (sstate_hardcode_cmd))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500631 subprocess.check_output(sstate_hardcode_cmd, shell=True, cwd=sstate_builddir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500632
633 # If the fixmefn is empty, remove it..
634 if os.stat(fixmefn).st_size == 0:
635 os.remove(fixmefn)
636 else:
637 bb.note("Replacing absolute paths in fixmepath file: '%s'" % (sstate_filelist_relative_cmd))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500638 subprocess.check_output(sstate_filelist_relative_cmd, shell=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500639}
640
641def sstate_package(ss, d):
642 import oe.path
643
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500644 tmpdir = d.getVar('TMPDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500645
646 sstatebuild = d.expand("${WORKDIR}/sstate-build-%s/" % ss['task'])
Andrew Geissler82c905d2020-04-13 13:39:40 -0500647 d.setVar("SSTATE_CURRTASK", ss['task'])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500648 bb.utils.remove(sstatebuild, recurse=True)
649 bb.utils.mkdirhier(sstatebuild)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500650 for state in ss['dirs']:
651 if not os.path.exists(state[1]):
652 continue
653 srcbase = state[0].rstrip("/").rsplit('/', 1)[0]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500654 # Find and error for absolute symlinks. We could attempt to relocate but its not
655 # clear where the symlink is relative to in this context. We could add that markup
656 # to sstate tasks but there aren't many of these so better just avoid them entirely.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500657 for walkroot, dirs, files in os.walk(state[1]):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500658 for file in files + dirs:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500659 srcpath = os.path.join(walkroot, file)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500660 if not os.path.islink(srcpath):
661 continue
662 link = os.readlink(srcpath)
663 if not os.path.isabs(link):
664 continue
665 if not link.startswith(tmpdir):
666 continue
667 bb.error("sstate found an absolute path symlink %s pointing at %s. Please replace this with a relative link." % (srcpath, link))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500668 bb.debug(2, "Preparing tree %s for packaging at %s" % (state[1], sstatebuild + state[0]))
Andrew Geisslerc926e172021-05-07 16:11:35 -0500669 bb.utils.rename(state[1], sstatebuild + state[0])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500670
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500671 workdir = d.getVar('WORKDIR')
Brad Bishop977dc1a2019-02-06 16:01:43 -0500672 sharedworkdir = os.path.join(d.getVar('TMPDIR'), "work-shared")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500673 for plain in ss['plaindirs']:
674 pdir = plain.replace(workdir, sstatebuild)
Brad Bishop977dc1a2019-02-06 16:01:43 -0500675 if sharedworkdir in plain:
676 pdir = plain.replace(sharedworkdir, sstatebuild)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500677 bb.utils.mkdirhier(plain)
678 bb.utils.mkdirhier(pdir)
Andrew Geisslerc926e172021-05-07 16:11:35 -0500679 bb.utils.rename(plain, pdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500680
681 d.setVar('SSTATE_BUILDDIR', sstatebuild)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500682 d.setVar('SSTATE_INSTDIR', sstatebuild)
683
684 if d.getVar('SSTATE_SKIP_CREATION') == '1':
685 return
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500686
Brad Bishop08902b02019-08-20 09:16:51 -0400687 sstate_create_package = ['sstate_report_unihash', 'sstate_create_package']
688 if d.getVar('SSTATE_SIG_KEY'):
689 sstate_create_package.append('sstate_sign_package')
690
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500691 for f in (d.getVar('SSTATECREATEFUNCS') or '').split() + \
Brad Bishop08902b02019-08-20 09:16:51 -0400692 sstate_create_package + \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500693 (d.getVar('SSTATEPOSTCREATEFUNCS') or '').split():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500694 # All hooks should run in SSTATE_BUILDDIR.
695 bb.build.exec_func(f, d, (sstatebuild,))
696
Andrew Geissler82c905d2020-04-13 13:39:40 -0500697 # SSTATE_PKG may have been changed by sstate_report_unihash
698 siginfo = d.getVar('SSTATE_PKG') + ".siginfo"
699 if not os.path.exists(siginfo):
700 bb.siggen.dump_this_task(siginfo, d)
701 else:
Andrew Geisslerc182c622020-05-15 14:13:32 -0500702 try:
703 os.utime(siginfo, None)
704 except PermissionError:
705 pass
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500706
707 return
708
William A. Kennington IIIac69b482021-06-02 12:28:27 -0700709sstate_package[vardepsexclude] += "SSTATE_SIG_KEY"
710
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800711def pstaging_fetch(sstatefetch, d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500712 import bb.fetch2
713
714 # Only try and fetch if the user has configured a mirror
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500715 mirrors = d.getVar('SSTATE_MIRRORS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500716 if not mirrors:
717 return
718
719 # Copy the data object and override DL_DIR and SRC_URI
720 localdata = bb.data.createCopy(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500721
722 dldir = localdata.expand("${SSTATE_DIR}")
723 bb.utils.mkdirhier(dldir)
724
725 localdata.delVar('MIRRORS')
726 localdata.setVar('FILESPATH', dldir)
727 localdata.setVar('DL_DIR', dldir)
728 localdata.setVar('PREMIRRORS', mirrors)
729
730 # if BB_NO_NETWORK is set but we also have SSTATE_MIRROR_ALLOW_NETWORK,
731 # we'll want to allow network access for the current set of fetches.
Brad Bishopd89cb5f2019-04-10 09:02:41 -0400732 if bb.utils.to_boolean(localdata.getVar('BB_NO_NETWORK')) and \
733 bb.utils.to_boolean(localdata.getVar('SSTATE_MIRROR_ALLOW_NETWORK')):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500734 localdata.delVar('BB_NO_NETWORK')
735
736 # Try a fetch from the sstate mirror, if it fails just return and
737 # we will build the package
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600738 uris = ['file://{0};downloadfilename={0}'.format(sstatefetch),
739 'file://{0}.siginfo;downloadfilename={0}.siginfo'.format(sstatefetch)]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500740 if bb.utils.to_boolean(d.getVar("SSTATE_VERIFY_SIG"), False):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600741 uris += ['file://{0}.sig;downloadfilename={0}.sig'.format(sstatefetch)]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500742
743 for srcuri in uris:
744 localdata.setVar('SRC_URI', srcuri)
745 try:
746 fetcher = bb.fetch2.Fetch([srcuri], localdata, cache=False)
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500747 fetcher.checkstatus()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500748 fetcher.download()
749
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500750 except bb.fetch2.BBFetchException:
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500751 pass
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500752
753def sstate_setscene(d):
754 shared_state = sstate_state_fromvars(d)
755 accelerate = sstate_installpkg(shared_state, d)
756 if not accelerate:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600757 bb.fatal("No suitable staging package found")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500758
759python sstate_task_prefunc () {
760 shared_state = sstate_state_fromvars(d)
761 sstate_clean(shared_state, d)
762}
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500763sstate_task_prefunc[dirs] = "${WORKDIR}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500764
765python sstate_task_postfunc () {
766 shared_state = sstate_state_fromvars(d)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500767
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500768 for intercept in shared_state['interceptfuncs']:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500769 bb.build.exec_func(intercept, d, (d.getVar("WORKDIR"),))
770
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600771 omask = os.umask(0o002)
772 if omask != 0o002:
773 bb.note("Using umask 0o002 (not %0o) for sstate packaging" % omask)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500774 sstate_package(shared_state, d)
775 os.umask(omask)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500776
777 sstateinst = d.getVar("SSTATE_INSTDIR")
778 d.setVar('SSTATE_FIXMEDIR', shared_state['fixmedir'])
779
780 sstate_installpkgdir(shared_state, d)
781
782 bb.utils.remove(d.getVar("SSTATE_BUILDDIR"), recurse=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500783}
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500784sstate_task_postfunc[dirs] = "${WORKDIR}"
785
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500786
787#
788# Shell function to generate a sstate package from a directory
789# set as SSTATE_BUILDDIR. Will be run from within SSTATE_BUILDDIR.
790#
791sstate_create_package () {
Andrew Geissler82c905d2020-04-13 13:39:40 -0500792 # Exit early if it already exists
Brad Bishop08902b02019-08-20 09:16:51 -0400793 if [ -e ${SSTATE_PKG} ]; then
Andrew Geisslerc182c622020-05-15 14:13:32 -0500794 [ ! -w ${SSTATE_PKG} ] || touch ${SSTATE_PKG}
Brad Bishop08902b02019-08-20 09:16:51 -0400795 return
796 fi
797
Andrew Geisslerc3d88e42020-10-02 09:45:00 -0500798 mkdir --mode=0775 -p `dirname ${SSTATE_PKG}`
Andrew Geissler82c905d2020-04-13 13:39:40 -0500799 TFILE=`mktemp ${SSTATE_PKG}.XXXXXXXX`
800
801 # Use pigz if available
802 OPT="-czS"
803 if [ -x "$(command -v pigz)" ]; then
804 OPT="-I pigz -cS"
805 fi
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800806
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500807 # Need to handle empty directories
808 if [ "$(ls -A)" ]; then
809 set +e
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800810 tar $OPT -f $TFILE *
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500811 ret=$?
812 if [ $ret -ne 0 ] && [ $ret -ne 1 ]; then
813 exit 1
814 fi
815 set -e
816 else
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800817 tar $OPT --file=$TFILE --files-from=/dev/null
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500818 fi
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500819 chmod 0664 $TFILE
Brad Bishop08902b02019-08-20 09:16:51 -0400820 # Skip if it was already created by some other process
821 if [ ! -e ${SSTATE_PKG} ]; then
Andrew Geissler82c905d2020-04-13 13:39:40 -0500822 # Move into place using ln to attempt an atomic op.
823 # Abort if it already exists
824 ln $TFILE ${SSTATE_PKG} && rm $TFILE
Brad Bishop08902b02019-08-20 09:16:51 -0400825 else
826 rm $TFILE
827 fi
Andrew Geisslerc182c622020-05-15 14:13:32 -0500828 [ ! -w ${SSTATE_PKG} ] || touch ${SSTATE_PKG}
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500829}
830
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500831python sstate_sign_package () {
832 from oe.gpg_sign import get_signer
833
Brad Bishop08902b02019-08-20 09:16:51 -0400834
835 signer = get_signer(d, 'local')
836 sstate_pkg = d.getVar('SSTATE_PKG')
837 if os.path.exists(sstate_pkg + '.sig'):
838 os.unlink(sstate_pkg + '.sig')
839 signer.detach_sign(sstate_pkg, d.getVar('SSTATE_SIG_KEY', False), None,
840 d.getVar('SSTATE_SIG_PASSPHRASE'), armor=False)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500841}
842
Brad Bishop19323692019-04-05 15:28:33 -0400843python sstate_report_unihash() {
844 report_unihash = getattr(bb.parse.siggen, 'report_unihash', None)
845
846 if report_unihash:
847 ss = sstate_state_fromvars(d)
848 report_unihash(os.getcwd(), ss['task'], d)
849}
850
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500851#
852# Shell function to decompress and prepare a package for installation
853# Will be run from within SSTATE_INSTDIR.
854#
855sstate_unpack_package () {
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500856 tar -xvzf ${SSTATE_PKG}
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500857 # update .siginfo atime on local/NFS mirror
Andrew Geisslerc3d88e42020-10-02 09:45:00 -0500858 [ -O ${SSTATE_PKG}.siginfo ] && [ -w ${SSTATE_PKG}.siginfo ] && [ -h ${SSTATE_PKG}.siginfo ] && touch -a ${SSTATE_PKG}.siginfo
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500859 # Use "! -w ||" to return true for read only files
860 [ ! -w ${SSTATE_PKG} ] || touch --no-dereference ${SSTATE_PKG}
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500861 [ ! -w ${SSTATE_PKG}.sig ] || [ ! -e ${SSTATE_PKG}.sig ] || touch --no-dereference ${SSTATE_PKG}.sig
862 [ ! -w ${SSTATE_PKG}.siginfo ] || [ ! -e ${SSTATE_PKG}.siginfo ] || touch --no-dereference ${SSTATE_PKG}.siginfo
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500863}
864
865BB_HASHCHECK_FUNCTION = "sstate_checkhashes"
866
Brad Bishop1d80a2e2019-11-15 16:35:03 -0500867def sstate_checkhashes(sq_data, d, siginfo=False, currentcount=0, summary=True, **kwargs):
Brad Bishop08902b02019-08-20 09:16:51 -0400868 found = set()
Andrew Geissler9b4d8b02021-02-19 12:26:16 -0600869 foundLocal = set()
870 foundNet = set()
Brad Bishop08902b02019-08-20 09:16:51 -0400871 missed = set()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500872
Brad Bishop19323692019-04-05 15:28:33 -0400873 def gethash(task):
Brad Bishop08902b02019-08-20 09:16:51 -0400874 return sq_data['unihash'][task]
Brad Bishop19323692019-04-05 15:28:33 -0400875
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500876 def getpathcomponents(task, d):
877 # Magic data from BB_HASHFILENAME
Brad Bishop08902b02019-08-20 09:16:51 -0400878 splithashfn = sq_data['hashfn'][task].split(" ")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500879 spec = splithashfn[1]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500880 if splithashfn[0] == "True":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500881 extrapath = d.getVar("NATIVELSBSTRING") + "/"
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500882 else:
883 extrapath = ""
Brad Bishop08902b02019-08-20 09:16:51 -0400884
885 tname = bb.runqueue.taskname_from_tid(task)[3:]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500886
887 if tname in ["fetch", "unpack", "patch", "populate_lic", "preconfigure"] and splithashfn[2]:
888 spec = splithashfn[2]
889 extrapath = ""
890
891 return spec, extrapath, tname
892
893
Brad Bishop08902b02019-08-20 09:16:51 -0400894 for tid in sq_data['hash']:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500895
Brad Bishop08902b02019-08-20 09:16:51 -0400896 spec, extrapath, tname = getpathcomponents(tid, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500897
Andrew Geissler82c905d2020-04-13 13:39:40 -0500898 sstatefile = d.expand("${SSTATE_DIR}/" + extrapath + generate_sstatefn(spec, gethash(tid), tname, siginfo, d))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500899
900 if os.path.exists(sstatefile):
901 bb.debug(2, "SState: Found valid sstate file %s" % sstatefile)
Brad Bishop08902b02019-08-20 09:16:51 -0400902 found.add(tid)
Andrew Geissler9b4d8b02021-02-19 12:26:16 -0600903 foundLocal.add(tid)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500904 continue
905 else:
Brad Bishop08902b02019-08-20 09:16:51 -0400906 missed.add(tid)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500907 bb.debug(2, "SState: Looked for but didn't find file %s" % sstatefile)
908
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500909 mirrors = d.getVar("SSTATE_MIRRORS")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500910 if mirrors:
911 # Copy the data object and override DL_DIR and SRC_URI
912 localdata = bb.data.createCopy(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500913
914 dldir = localdata.expand("${SSTATE_DIR}")
915 localdata.delVar('MIRRORS')
916 localdata.setVar('FILESPATH', dldir)
917 localdata.setVar('DL_DIR', dldir)
918 localdata.setVar('PREMIRRORS', mirrors)
919
920 bb.debug(2, "SState using premirror of: %s" % mirrors)
921
922 # if BB_NO_NETWORK is set but we also have SSTATE_MIRROR_ALLOW_NETWORK,
923 # we'll want to allow network access for the current set of fetches.
Brad Bishopd89cb5f2019-04-10 09:02:41 -0400924 if bb.utils.to_boolean(localdata.getVar('BB_NO_NETWORK')) and \
925 bb.utils.to_boolean(localdata.getVar('SSTATE_MIRROR_ALLOW_NETWORK')):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500926 localdata.delVar('BB_NO_NETWORK')
927
928 from bb.fetch2 import FetchConnectionCache
929 def checkstatus_init(thread_worker):
930 thread_worker.connection_cache = FetchConnectionCache()
931
932 def checkstatus_end(thread_worker):
933 thread_worker.connection_cache.close_connections()
934
935 def checkstatus(thread_worker, arg):
Brad Bishop08902b02019-08-20 09:16:51 -0400936 (tid, sstatefile) = arg
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500937
938 localdata2 = bb.data.createCopy(localdata)
939 srcuri = "file://" + sstatefile
940 localdata.setVar('SRC_URI', srcuri)
941 bb.debug(2, "SState: Attempting to fetch %s" % srcuri)
942
943 try:
944 fetcher = bb.fetch2.Fetch(srcuri.split(), localdata2,
945 connection_cache=thread_worker.connection_cache)
946 fetcher.checkstatus()
947 bb.debug(2, "SState: Successful fetch test for %s" % srcuri)
Brad Bishop08902b02019-08-20 09:16:51 -0400948 found.add(tid)
Andrew Geissler9b4d8b02021-02-19 12:26:16 -0600949 foundNet.add(tid)
Brad Bishop08902b02019-08-20 09:16:51 -0400950 if tid in missed:
951 missed.remove(tid)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500952 except:
Brad Bishop08902b02019-08-20 09:16:51 -0400953 missed.add(tid)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500954 bb.debug(2, "SState: Unsuccessful fetch test for %s" % srcuri)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600955 pass
Andrew Geissler82c905d2020-04-13 13:39:40 -0500956 if len(tasklist) >= min_tasks:
957 bb.event.fire(bb.event.ProcessProgress(msg, len(tasklist) - thread_worker.tasks.qsize()), d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500958
959 tasklist = []
Andrew Geissler82c905d2020-04-13 13:39:40 -0500960 min_tasks = 100
Brad Bishop08902b02019-08-20 09:16:51 -0400961 for tid in sq_data['hash']:
962 if tid in found:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500963 continue
Brad Bishop08902b02019-08-20 09:16:51 -0400964 spec, extrapath, tname = getpathcomponents(tid, d)
Andrew Geissler82c905d2020-04-13 13:39:40 -0500965 sstatefile = d.expand(extrapath + generate_sstatefn(spec, gethash(tid), tname, siginfo, d))
Brad Bishop08902b02019-08-20 09:16:51 -0400966 tasklist.append((tid, sstatefile))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500967
968 if tasklist:
Andrew Geissler82c905d2020-04-13 13:39:40 -0500969 if len(tasklist) >= min_tasks:
970 msg = "Checking sstate mirror object availability"
971 bb.event.fire(bb.event.ProcessStarted(msg, len(tasklist)), d)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600972
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500973 import multiprocessing
974 nproc = min(multiprocessing.cpu_count(), len(tasklist))
975
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600976 bb.event.enable_threadlock()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500977 pool = oe.utils.ThreadedPool(nproc, len(tasklist),
978 worker_init=checkstatus_init, worker_end=checkstatus_end)
979 for t in tasklist:
980 pool.add_task(checkstatus, t)
981 pool.start()
982 pool.wait_completion()
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600983 bb.event.disable_threadlock()
984
Andrew Geissler82c905d2020-04-13 13:39:40 -0500985 if len(tasklist) >= min_tasks:
986 bb.event.fire(bb.event.ProcessFinished(msg), d)
Brad Bishop96ff1982019-08-19 13:50:42 -0400987
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500988 inheritlist = d.getVar("INHERIT")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500989 if "toaster" in inheritlist:
990 evdata = {'missed': [], 'found': []};
Brad Bishop08902b02019-08-20 09:16:51 -0400991 for tid in missed:
992 spec, extrapath, tname = getpathcomponents(tid, d)
Andrew Geissler82c905d2020-04-13 13:39:40 -0500993 sstatefile = d.expand(extrapath + generate_sstatefn(spec, gethash(tid), tname, False, d))
Brad Bishop08902b02019-08-20 09:16:51 -0400994 evdata['missed'].append((bb.runqueue.fn_from_tid(tid), bb.runqueue.taskname_from_tid(tid), gethash(tid), sstatefile ) )
995 for tid in found:
996 spec, extrapath, tname = getpathcomponents(tid, d)
Andrew Geissler82c905d2020-04-13 13:39:40 -0500997 sstatefile = d.expand(extrapath + generate_sstatefn(spec, gethash(tid), tname, False, d))
Brad Bishop08902b02019-08-20 09:16:51 -0400998 evdata['found'].append((bb.runqueue.fn_from_tid(tid), bb.runqueue.taskname_from_tid(tid), gethash(tid), sstatefile ) )
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500999 bb.event.fire(bb.event.MetadataEvent("MissedSstate", evdata), d)
1000
Brad Bishop1d80a2e2019-11-15 16:35:03 -05001001 if summary:
1002 # Print some summary statistics about the current task completion and how much sstate
1003 # reuse there was. Avoid divide by zero errors.
1004 total = len(sq_data['hash'])
1005 complete = 0
1006 if currentcount:
1007 complete = (len(found) + currentcount) / (total + currentcount) * 100
1008 match = 0
1009 if total:
1010 match = len(found) / total * 100
Andrew Geissler9b4d8b02021-02-19 12:26:16 -06001011 bb.plain("Sstate summary: Wanted %d Local %d Network %d Missed %d Current %d (%d%% match, %d%% complete)" % (total, len(foundLocal), len(foundNet),len(missed), currentcount, match, complete))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001012
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001013 if hasattr(bb.parse.siggen, "checkhashes"):
Brad Bishop08902b02019-08-20 09:16:51 -04001014 bb.parse.siggen.checkhashes(sq_data, missed, found, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001015
Brad Bishop08902b02019-08-20 09:16:51 -04001016 return found
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001017
1018BB_SETSCENE_DEPVALID = "setscene_depvalid"
1019
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001020def setscene_depvalid(task, taskdependees, notneeded, d, log=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001021 # taskdependees is a dict of tasks which depend on task, each being a 3 item list of [PN, TASKNAME, FILENAME]
1022 # task is included in taskdependees too
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001023 # Return - False - We need this dependency
1024 # - True - We can skip this dependency
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001025 import re
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001026
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001027 def logit(msg, log):
1028 if log is not None:
1029 log.append(msg)
1030 else:
1031 bb.debug(2, msg)
1032
1033 logit("Considering setscene task: %s" % (str(taskdependees[task])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001034
1035 def isNativeCross(x):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001036 return x.endswith("-native") or "-cross-" in x or "-crosssdk" in x or x.endswith("-cross")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001037
1038 # We only need to trigger populate_lic through direct dependencies
1039 if taskdependees[task][1] == "do_populate_lic":
1040 return True
1041
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001042 # stash_locale and gcc_stash_builddir are never needed as a dependency for built objects
1043 if taskdependees[task][1] == "do_stash_locale" or taskdependees[task][1] == "do_gcc_stash_builddir":
1044 return True
1045
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001046 # We only need to trigger packagedata through direct dependencies
1047 # but need to preserve packagedata on packagedata links
1048 if taskdependees[task][1] == "do_packagedata":
1049 for dep in taskdependees:
1050 if taskdependees[dep][1] == "do_packagedata":
1051 return False
1052 return True
1053
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001054 for dep in taskdependees:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001055 logit(" considering dependency: %s" % (str(taskdependees[dep])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001056 if task == dep:
1057 continue
1058 if dep in notneeded:
1059 continue
1060 # do_package_write_* and do_package doesn't need do_package
1061 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']:
1062 continue
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001063 # do_package_write_* need do_populate_sysroot as they're mainly postinstall dependencies
1064 if taskdependees[task][1] == "do_populate_sysroot" and taskdependees[dep][1] in ['do_package_write_deb', 'do_package_write_ipk', 'do_package_write_rpm']:
1065 return False
1066 # do_package/packagedata/package_qa don't need do_populate_sysroot
1067 if taskdependees[task][1] == "do_populate_sysroot" and taskdependees[dep][1] in ['do_package', 'do_packagedata', 'do_package_qa']:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001068 continue
1069 # Native/Cross packages don't exist and are noexec anyway
1070 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']:
1071 continue
1072
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001073 # This is due to the [depends] in useradd.bbclass complicating matters
1074 # The logic *is* reversed here due to the way hard setscene dependencies are injected
1075 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':
1076 continue
1077
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001078 # Consider sysroot depending on sysroot tasks
1079 if taskdependees[task][1] == 'do_populate_sysroot' and taskdependees[dep][1] == 'do_populate_sysroot':
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001080 # Allow excluding certain recursive dependencies. If a recipe needs it should add a
1081 # specific dependency itself, rather than relying on one of its dependees to pull
1082 # them in.
1083 # See also http://lists.openembedded.org/pipermail/openembedded-core/2018-January/146324.html
1084 not_needed = False
1085 excludedeps = d.getVar('_SSTATE_EXCLUDEDEPS_SYSROOT')
1086 if excludedeps is None:
1087 # Cache the regular expressions for speed
1088 excludedeps = []
1089 for excl in (d.getVar('SSTATE_EXCLUDEDEPS_SYSROOT') or "").split():
1090 excludedeps.append((re.compile(excl.split('->', 1)[0]), re.compile(excl.split('->', 1)[1])))
1091 d.setVar('_SSTATE_EXCLUDEDEPS_SYSROOT', excludedeps)
1092 for excl in excludedeps:
1093 if excl[0].match(taskdependees[dep][0]):
1094 if excl[1].match(taskdependees[task][0]):
1095 not_needed = True
1096 break
1097 if not_needed:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001098 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001099 # For meta-extsdk-toolchain we want all sysroot dependencies
1100 if taskdependees[dep][0] == 'meta-extsdk-toolchain':
1101 return False
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001102 # Native/Cross populate_sysroot need their dependencies
1103 if isNativeCross(taskdependees[task][0]) and isNativeCross(taskdependees[dep][0]):
1104 return False
1105 # Target populate_sysroot depended on by cross tools need to be installed
1106 if isNativeCross(taskdependees[dep][0]):
1107 return False
1108 # Native/cross tools depended upon by target sysroot are not needed
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001109 # Add an exception for shadow-native as required by useradd.bbclass
1110 if isNativeCross(taskdependees[task][0]) and taskdependees[task][0] != 'shadow-native':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001111 continue
1112 # Target populate_sysroot need their dependencies
1113 return False
1114
1115 if taskdependees[task][1] == 'do_shared_workdir':
1116 continue
1117
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001118 if taskdependees[dep][1] == "do_populate_lic":
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001119 continue
1120
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001121
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001122 # Safe fallthrough default
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001123 logit(" Default setscene dependency fall through due to dependency: %s" % (str(taskdependees[dep])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001124 return False
1125 return True
1126
1127addhandler sstate_eventhandler
1128sstate_eventhandler[eventmask] = "bb.build.TaskSucceeded"
1129python sstate_eventhandler() {
1130 d = e.data
Andrew Geissler82c905d2020-04-13 13:39:40 -05001131 writtensstate = d.getVar('SSTATE_CURRTASK')
1132 if not writtensstate:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001133 taskname = d.getVar("BB_RUNTASK")[3:]
1134 spec = d.getVar('SSTATE_PKGSPEC')
1135 swspec = d.getVar('SSTATE_SWSPEC')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001136 if taskname in ["fetch", "unpack", "patch", "populate_lic", "preconfigure"] and swspec:
1137 d.setVar("SSTATE_PKGSPEC", "${SSTATE_SWSPEC}")
1138 d.setVar("SSTATE_EXTRAPATH", "")
Andrew Geissler82c905d2020-04-13 13:39:40 -05001139 d.setVar("SSTATE_CURRTASK", taskname)
1140 siginfo = d.getVar('SSTATE_PKG') + ".siginfo"
1141 if not os.path.exists(siginfo):
1142 bb.siggen.dump_this_task(siginfo, d)
1143 else:
Andrew Geisslerc182c622020-05-15 14:13:32 -05001144 try:
1145 os.utime(siginfo, None)
1146 except PermissionError:
1147 pass
1148
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001149}
1150
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001151SSTATE_PRUNE_OBSOLETEWORKDIR ?= "1"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001152
Andrew Geissler95ac1b82021-03-31 14:34:31 -05001153#
1154# Event handler which removes manifests and stamps file for recipes which are no
1155# longer 'reachable' in a build where they once were. 'Reachable' refers to
1156# whether a recipe is parsed so recipes in a layer which was removed would no
1157# longer be reachable. Switching between systemd and sysvinit where recipes
1158# became skipped would be another example.
1159#
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001160# Also optionally removes the workdir of those tasks/recipes
1161#
Andrew Geissler95ac1b82021-03-31 14:34:31 -05001162addhandler sstate_eventhandler_reachablestamps
1163sstate_eventhandler_reachablestamps[eventmask] = "bb.event.ReachableStamps"
1164python sstate_eventhandler_reachablestamps() {
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001165 import glob
1166 d = e.data
1167 stamps = e.stamps.values()
1168 removeworkdir = (d.getVar("SSTATE_PRUNE_OBSOLETEWORKDIR", False) == "1")
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001169 preservestampfile = d.expand('${SSTATE_MANIFESTS}/preserve-stamps')
1170 preservestamps = []
1171 if os.path.exists(preservestampfile):
1172 with open(preservestampfile, 'r') as f:
1173 preservestamps = f.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001174 seen = []
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001175
1176 # The machine index contains all the stamps this machine has ever seen in this build directory.
1177 # We should only remove things which this machine once accessed but no longer does.
1178 machineindex = set()
1179 bb.utils.mkdirhier(d.expand("${SSTATE_MANIFESTS}"))
1180 mi = d.expand("${SSTATE_MANIFESTS}/index-machine-${MACHINE}")
1181 if os.path.exists(mi):
1182 with open(mi, "r") as f:
1183 machineindex = set(line.strip() for line in f.readlines())
1184
Brad Bishop316dfdd2018-06-25 12:45:53 -04001185 for a in sorted(list(set(d.getVar("SSTATE_ARCHS").split()))):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001186 toremove = []
1187 i = d.expand("${SSTATE_MANIFESTS}/index-" + a)
1188 if not os.path.exists(i):
1189 continue
William A. Kennington IIIac69b482021-06-02 12:28:27 -07001190 manseen = set()
1191 ignore = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001192 with open(i, "r") as f:
1193 lines = f.readlines()
William A. Kennington IIIac69b482021-06-02 12:28:27 -07001194 for l in reversed(lines):
Brad Bishop19323692019-04-05 15:28:33 -04001195 try:
1196 (stamp, manifest, workdir) = l.split()
William A. Kennington IIIac69b482021-06-02 12:28:27 -07001197 # The index may have multiple entries for the same manifest as the code above only appends
1198 # new entries and there may be an entry with matching manifest but differing version in stamp/workdir.
1199 # The last entry in the list is the valid one, any earlier entries with matching manifests
1200 # should be ignored.
1201 if manifest in manseen:
1202 ignore.append(l)
1203 continue
1204 manseen.add(manifest)
Brad Bishop19323692019-04-05 15:28:33 -04001205 if stamp not in stamps and stamp not in preservestamps and stamp in machineindex:
1206 toremove.append(l)
1207 if stamp not in seen:
1208 bb.debug(2, "Stamp %s is not reachable, removing related manifests" % stamp)
1209 seen.append(stamp)
1210 except ValueError:
1211 bb.fatal("Invalid line '%s' in sstate manifest '%s'" % (l, i))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001212
1213 if toremove:
Brad Bishop316dfdd2018-06-25 12:45:53 -04001214 msg = "Removing %d recipes from the %s sysroot" % (len(toremove), a)
1215 bb.event.fire(bb.event.ProcessStarted(msg, len(toremove)), d)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001216
Brad Bishop316dfdd2018-06-25 12:45:53 -04001217 removed = 0
1218 for r in toremove:
1219 (stamp, manifest, workdir) = r.split()
1220 for m in glob.glob(manifest + ".*"):
1221 if m.endswith(".postrm"):
1222 continue
1223 sstate_clean_manifest(m, d)
1224 bb.utils.remove(stamp + "*")
1225 if removeworkdir:
1226 bb.utils.remove(workdir, recurse = True)
1227 lines.remove(r)
1228 removed = removed + 1
1229 bb.event.fire(bb.event.ProcessProgress(msg, removed), d)
1230
1231 bb.event.fire(bb.event.ProcessFinished(msg), d)
1232
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001233 with open(i, "w") as f:
1234 for l in lines:
William A. Kennington IIIac69b482021-06-02 12:28:27 -07001235 if l in ignore:
1236 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001237 f.write(l)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001238 machineindex |= set(stamps)
1239 with open(mi, "w") as f:
1240 for l in machineindex:
1241 f.write(l + "\n")
1242
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001243 if preservestamps:
1244 os.remove(preservestampfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001245}
Andrew Geissler95ac1b82021-03-31 14:34:31 -05001246
1247
1248#
1249# Bitbake can generate an event showing which setscene tasks are 'stale',
1250# i.e. which ones will be rerun. These are ones where a stamp file is present but
1251# it is stable (e.g. taskhash doesn't match). With that list we can go through
1252# the manifests for matching tasks and "uninstall" those manifests now. We do
1253# this now rather than mid build since the distribution of files between sstate
1254# objects may have changed, new tasks may run first and if those new tasks overlap
1255# with the stale tasks, we'd see overlapping files messages and failures. Thankfully
1256# removing these files is fast.
1257#
1258addhandler sstate_eventhandler_stalesstate
1259sstate_eventhandler_stalesstate[eventmask] = "bb.event.StaleSetSceneTasks"
1260python sstate_eventhandler_stalesstate() {
1261 d = e.data
1262 tasks = e.tasks
1263
1264 bb.utils.mkdirhier(d.expand("${SSTATE_MANIFESTS}"))
1265
1266 for a in list(set(d.getVar("SSTATE_ARCHS").split())):
1267 toremove = []
1268 i = d.expand("${SSTATE_MANIFESTS}/index-" + a)
1269 if not os.path.exists(i):
1270 continue
1271 with open(i, "r") as f:
1272 lines = f.readlines()
1273 for l in lines:
1274 try:
1275 (stamp, manifest, workdir) = l.split()
1276 for tid in tasks:
1277 for s in tasks[tid]:
1278 if s.startswith(stamp):
1279 taskname = bb.runqueue.taskname_from_tid(tid)[3:]
1280 manname = manifest + "." + taskname
1281 if os.path.exists(manname):
1282 bb.debug(2, "Sstate for %s is stale, removing related manifest %s" % (tid, manname))
1283 toremove.append((manname, tid, tasks[tid]))
1284 break
1285 except ValueError:
1286 bb.fatal("Invalid line '%s' in sstate manifest '%s'" % (l, i))
1287
1288 if toremove:
1289 msg = "Removing %d stale sstate objects for arch %s" % (len(toremove), a)
1290 bb.event.fire(bb.event.ProcessStarted(msg, len(toremove)), d)
1291
1292 removed = 0
1293 for (manname, tid, stamps) in toremove:
1294 sstate_clean_manifest(manname, d)
1295 for stamp in stamps:
1296 bb.utils.remove(stamp)
1297 removed = removed + 1
1298 bb.event.fire(bb.event.ProcessProgress(msg, removed), d)
1299
1300 bb.event.fire(bb.event.ProcessFinished(msg), d)
1301}