blob: 7f4b1f6804cc42ba4d72073beeca08f89c342241 [file] [log] [blame]
Patrick Williams93c203f2021-10-06 16:15:23 -05001SSTATE_VERSION = "5"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002
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 Williams93c203f2021-10-06 16:15:23 -050070SSTATE_HASHEQUIV_FILEMAP ?= " \
71 populate_sysroot:*/postinst-useradd-*:${TMPDIR} \
72 populate_sysroot:*/postinst-useradd-*:${COREBASE} \
73 populate_sysroot:*/postinst-useradd-*:regex-\s(PATH|PSEUDO_IGNORE_PATHS|HOME|LOGNAME|OMP_NUM_THREADS|USER)=.*\s \
74 populate_sysroot:*/crossscripts/*:${TMPDIR} \
75 populate_sysroot:*/crossscripts/*:${COREBASE} \
76 "
Patrick Williamsc124f4f2015-09-15 14:41:29 -050077
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050078BB_HASHFILENAME = "False ${SSTATE_PKGSPEC} ${SSTATE_SWSPEC}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050079
80SSTATE_ARCHS = " \
81 ${BUILD_ARCH} \
Andrew Geissler6ce62a22020-11-30 19:58:47 -060082 ${BUILD_ARCH}_${ORIGNATIVELSBSTRING} \
Patrick Williamsc124f4f2015-09-15 14:41:29 -050083 ${BUILD_ARCH}_${SDK_ARCH}_${SDK_OS} \
84 ${BUILD_ARCH}_${TARGET_ARCH} \
85 ${SDK_ARCH}_${SDK_OS} \
86 ${SDK_ARCH}_${PACKAGE_ARCH} \
87 allarch \
88 ${PACKAGE_ARCH} \
Brad Bishop316dfdd2018-06-25 12:45:53 -040089 ${PACKAGE_EXTRA_ARCHS} \
90 ${MACHINE_ARCH}"
Andrew Geissler6ce62a22020-11-30 19:58:47 -060091SSTATE_ARCHS[vardepsexclude] = "ORIGNATIVELSBSTRING"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050092
93SSTATE_MANMACH ?= "${SSTATE_PKGARCH}"
94
95SSTATECREATEFUNCS = "sstate_hardcode_path"
Brad Bishop19323692019-04-05 15:28:33 -040096SSTATECREATEFUNCS[vardeps] = "SSTATE_SCAN_FILES"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050097SSTATEPOSTCREATEFUNCS = ""
98SSTATEPREINSTFUNCS = ""
99SSTATEPOSTUNPACKFUNCS = "sstate_hardcode_path_unpack"
100SSTATEPOSTINSTFUNCS = ""
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500101EXTRA_STAGING_FIXMES ?= "HOSTTOOLS_DIR"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500102
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500103# Check whether sstate exists for tasks that support sstate and are in the
104# locked signatures file.
105SIGGEN_LOCKEDSIGS_SSTATE_EXISTS_CHECK ?= 'error'
106
107# Check whether the task's computed hash matches the task's hash in the
108# locked signatures file.
109SIGGEN_LOCKEDSIGS_TASKSIG_CHECK ?= "error"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500110
111# The GnuPG key ID and passphrase to use to sign sstate archives (or unset to
112# not sign)
113SSTATE_SIG_KEY ?= ""
114SSTATE_SIG_PASSPHRASE ?= ""
115# Whether to verify the GnUPG signatures when extracting sstate archives
116SSTATE_VERIFY_SIG ?= "0"
117
Brad Bishop19323692019-04-05 15:28:33 -0400118SSTATE_HASHEQUIV_METHOD ?= "oe.sstatesig.OEOuthashBasic"
119SSTATE_HASHEQUIV_METHOD[doc] = "The fully-qualified function used to calculate \
120 the output hash for a task, which in turn is used to determine equivalency. \
121 "
122
Brad Bishop19323692019-04-05 15:28:33 -0400123SSTATE_HASHEQUIV_REPORT_TASKDATA ?= "0"
124SSTATE_HASHEQUIV_REPORT_TASKDATA[doc] = "Report additional useful data to the \
125 hash equivalency server, such as PN, PV, taskname, etc. This information \
126 is very useful for developers looking at task data, but may leak sensitive \
127 data if the equivalence server is public. \
128 "
129
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500130python () {
131 if bb.data.inherits_class('native', d):
132 d.setVar('SSTATE_PKGARCH', d.getVar('BUILD_ARCH', False))
133 elif bb.data.inherits_class('crosssdk', d):
134 d.setVar('SSTATE_PKGARCH', d.expand("${BUILD_ARCH}_${SDK_ARCH}_${SDK_OS}"))
135 elif bb.data.inherits_class('cross', d):
136 d.setVar('SSTATE_PKGARCH', d.expand("${BUILD_ARCH}_${TARGET_ARCH}"))
137 elif bb.data.inherits_class('nativesdk', d):
138 d.setVar('SSTATE_PKGARCH', d.expand("${SDK_ARCH}_${SDK_OS}"))
139 elif bb.data.inherits_class('cross-canadian', d):
140 d.setVar('SSTATE_PKGARCH', d.expand("${SDK_ARCH}_${PACKAGE_ARCH}"))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500141 elif bb.data.inherits_class('allarch', d) and d.getVar("PACKAGE_ARCH") == "all":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500142 d.setVar('SSTATE_PKGARCH', "allarch")
143 else:
144 d.setVar('SSTATE_MANMACH', d.expand("${PACKAGE_ARCH}"))
145
146 if bb.data.inherits_class('native', d) or bb.data.inherits_class('crosssdk', d) or bb.data.inherits_class('cross', d):
147 d.setVar('SSTATE_EXTRAPATH', "${NATIVELSBSTRING}/")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500148 d.setVar('BB_HASHFILENAME', "True ${SSTATE_PKGSPEC} ${SSTATE_SWSPEC}")
Brad Bishop19323692019-04-05 15:28:33 -0400149 d.setVar('SSTATE_EXTRAPATHWILDCARD', "${NATIVELSBSTRING}/")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500150
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500151 unique_tasks = sorted(set((d.getVar('SSTATETASKS') or "").split()))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500152 d.setVar('SSTATETASKS', " ".join(unique_tasks))
153 for task in unique_tasks:
154 d.prependVarFlag(task, 'prefuncs', "sstate_task_prefunc ")
155 d.appendVarFlag(task, 'postfuncs', " sstate_task_postfunc")
156}
157
158def sstate_init(task, d):
159 ss = {}
160 ss['task'] = task
161 ss['dirs'] = []
162 ss['plaindirs'] = []
163 ss['lockfiles'] = []
164 ss['lockfiles-shared'] = []
165 return ss
166
167def sstate_state_fromvars(d, task = None):
168 if task is None:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500169 task = d.getVar('BB_CURRENTTASK')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500170 if not task:
171 bb.fatal("sstate code running without task context?!")
172 task = task.replace("_setscene", "")
173
174 if task.startswith("do_"):
175 task = task[3:]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500176 inputs = (d.getVarFlag("do_" + task, 'sstate-inputdirs') or "").split()
177 outputs = (d.getVarFlag("do_" + task, 'sstate-outputdirs') or "").split()
178 plaindirs = (d.getVarFlag("do_" + task, 'sstate-plaindirs') or "").split()
179 lockfiles = (d.getVarFlag("do_" + task, 'sstate-lockfile') or "").split()
180 lockfilesshared = (d.getVarFlag("do_" + task, 'sstate-lockfile-shared') or "").split()
181 interceptfuncs = (d.getVarFlag("do_" + task, 'sstate-interceptfuncs') or "").split()
182 fixmedir = d.getVarFlag("do_" + task, 'sstate-fixmedir') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500183 if not task or len(inputs) != len(outputs):
184 bb.fatal("sstate variables not setup correctly?!")
185
186 if task == "populate_lic":
187 d.setVar("SSTATE_PKGSPEC", "${SSTATE_SWSPEC}")
188 d.setVar("SSTATE_EXTRAPATH", "")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500189 d.setVar('SSTATE_EXTRAPATHWILDCARD', "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500190
191 ss = sstate_init(task, d)
192 for i in range(len(inputs)):
193 sstate_add(ss, inputs[i], outputs[i], d)
194 ss['lockfiles'] = lockfiles
195 ss['lockfiles-shared'] = lockfilesshared
196 ss['plaindirs'] = plaindirs
197 ss['interceptfuncs'] = interceptfuncs
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500198 ss['fixmedir'] = fixmedir
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500199 return ss
200
201def sstate_add(ss, source, dest, d):
202 if not source.endswith("/"):
203 source = source + "/"
204 if not dest.endswith("/"):
205 dest = dest + "/"
206 source = os.path.normpath(source)
207 dest = os.path.normpath(dest)
208 srcbase = os.path.basename(source)
209 ss['dirs'].append([srcbase, source, dest])
210 return ss
211
212def sstate_install(ss, d):
213 import oe.path
214 import oe.sstatesig
215 import subprocess
216
217 sharedfiles = []
218 shareddirs = []
219 bb.utils.mkdirhier(d.expand("${SSTATE_MANIFESTS}"))
220
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500221 sstateinst = d.expand("${WORKDIR}/sstate-install-%s/" % ss['task'])
222
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500223 manifest, d2 = oe.sstatesig.sstate_get_manifest_filename(ss['task'], d)
224
225 if os.access(manifest, os.R_OK):
226 bb.fatal("Package already staged (%s)?!" % manifest)
227
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600228 d.setVar("SSTATE_INST_POSTRM", manifest + ".postrm")
229
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500230 locks = []
231 for lock in ss['lockfiles-shared']:
232 locks.append(bb.utils.lockfile(lock, True))
233 for lock in ss['lockfiles']:
234 locks.append(bb.utils.lockfile(lock))
235
236 for state in ss['dirs']:
237 bb.debug(2, "Staging files from %s to %s" % (state[1], state[2]))
238 for walkroot, dirs, files in os.walk(state[1]):
239 for file in files:
240 srcpath = os.path.join(walkroot, file)
241 dstpath = srcpath.replace(state[1], state[2])
242 #bb.debug(2, "Staging %s to %s" % (srcpath, dstpath))
243 sharedfiles.append(dstpath)
244 for dir in dirs:
245 srcdir = os.path.join(walkroot, dir)
246 dstdir = srcdir.replace(state[1], state[2])
247 #bb.debug(2, "Staging %s to %s" % (srcdir, dstdir))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500248 if os.path.islink(srcdir):
249 sharedfiles.append(dstdir)
250 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500251 if not dstdir.endswith("/"):
252 dstdir = dstdir + "/"
253 shareddirs.append(dstdir)
254
255 # Check the file list for conflicts against files which already exist
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500256 whitelist = (d.getVar("SSTATE_DUPWHITELIST") or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500257 match = []
258 for f in sharedfiles:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500259 if os.path.exists(f) and not os.path.islink(f):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500260 f = os.path.normpath(f)
261 realmatch = True
262 for w in whitelist:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600263 w = os.path.normpath(w)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500264 if f.startswith(w):
265 realmatch = False
266 break
267 if realmatch:
268 match.append(f)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500269 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 -0500270 search_output = subprocess.Popen(sstate_search_cmd, shell=True, stdout=subprocess.PIPE).communicate()[0]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500271 if search_output:
272 match.append(" (matched in %s)" % search_output.decode('utf-8').rstrip())
273 else:
274 match.append(" (not matched to any task)")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500275 if match:
276 bb.error("The recipe %s is trying to install files into a shared " \
277 "area when those files already exist. Those files and their manifest " \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500278 "location are:\n %s\nPlease verify which recipe should provide the " \
279 "above files.\n\nThe build has stopped, as continuing in this scenario WILL " \
280 "break things - if not now, possibly in the future (we've seen builds fail " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500281 "several months later). If the system knew how to recover from this " \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500282 "automatically it would, however there are several different scenarios " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500283 "which can result in this and we don't know which one this is. It may be " \
284 "you have switched providers of something like virtual/kernel (e.g. from " \
285 "linux-yocto to linux-yocto-dev), in that case you need to execute the " \
286 "clean task for both recipes and it will resolve this error. It may be " \
287 "you changed DISTRO_FEATURES from systemd to udev or vice versa. Cleaning " \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500288 "those recipes should again resolve this error, however switching " \
289 "DISTRO_FEATURES on an existing build directory is not supported - you " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500290 "should really clean out tmp and rebuild (reusing sstate should be safe). " \
291 "It could be the overlapping files detected are harmless in which case " \
292 "adding them to SSTATE_DUPWHITELIST may be the correct solution. It could " \
293 "also be your build is including two different conflicting versions of " \
294 "things (e.g. bluez 4 and bluez 5 and the correct solution for that would " \
295 "be to resolve the conflict. If in doubt, please ask on the mailing list, " \
296 "sharing the error and filelist above." % \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500297 (d.getVar('PN'), "\n ".join(match)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500298 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.")
299
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500300 if ss['fixmedir'] and os.path.exists(ss['fixmedir'] + "/fixmepath.cmd"):
301 sharedfiles.append(ss['fixmedir'] + "/fixmepath.cmd")
302 sharedfiles.append(ss['fixmedir'] + "/fixmepath")
303
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500304 # Write out the manifest
305 f = open(manifest, "w")
306 for file in sharedfiles:
307 f.write(file + "\n")
308
309 # We want to ensure that directories appear at the end of the manifest
310 # so that when we test to see if they should be deleted any contents
311 # added by the task will have been removed first.
312 dirs = sorted(shareddirs, key=len)
313 # Must remove children first, which will have a longer path than the parent
314 for di in reversed(dirs):
315 f.write(di + "\n")
316 f.close()
317
318 # Append to the list of manifests for this PACKAGE_ARCH
319
320 i = d2.expand("${SSTATE_MANIFESTS}/index-${SSTATE_MANMACH}")
321 l = bb.utils.lockfile(i + ".lock")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500322 filedata = d.getVar("STAMP") + " " + d2.getVar("SSTATE_MANFILEPREFIX") + " " + d.getVar("WORKDIR") + "\n"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500323 manifests = []
324 if os.path.exists(i):
325 with open(i, "r") as f:
326 manifests = f.readlines()
William A. Kennington IIIac69b482021-06-02 12:28:27 -0700327 # We append new entries, we don't remove older entries which may have the same
328 # manifest name but different versions from stamp/workdir. See below.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500329 if filedata not in manifests:
330 with open(i, "a+") as f:
331 f.write(filedata)
332 bb.utils.unlockfile(l)
333
334 # Run the actual file install
335 for state in ss['dirs']:
336 if os.path.exists(state[1]):
337 oe.path.copyhardlinktree(state[1], state[2])
338
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500339 for postinst in (d.getVar('SSTATEPOSTINSTFUNCS') or '').split():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500340 # All hooks should run in the SSTATE_INSTDIR
341 bb.build.exec_func(postinst, d, (sstateinst,))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500342
343 for lock in locks:
344 bb.utils.unlockfile(lock)
345
346sstate_install[vardepsexclude] += "SSTATE_DUPWHITELIST STATE_MANMACH SSTATE_MANFILEPREFIX"
347sstate_install[vardeps] += "${SSTATEPOSTINSTFUNCS}"
348
349def sstate_installpkg(ss, d):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500350 from oe.gpg_sign import get_signer
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500351
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500352 sstateinst = d.expand("${WORKDIR}/sstate-install-%s/" % ss['task'])
Andrew Geissler82c905d2020-04-13 13:39:40 -0500353 d.setVar("SSTATE_CURRTASK", ss['task'])
354 sstatefetch = d.getVar('SSTATE_PKGNAME')
355 sstatepkg = d.getVar('SSTATE_PKG')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500356
357 if not os.path.exists(sstatepkg):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800358 pstaging_fetch(sstatefetch, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500359
360 if not os.path.isfile(sstatepkg):
Brad Bishop08902b02019-08-20 09:16:51 -0400361 bb.note("Sstate package %s does not exist" % sstatepkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500362 return False
363
364 sstate_clean(ss, d)
365
366 d.setVar('SSTATE_INSTDIR', sstateinst)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500367
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500368 if bb.utils.to_boolean(d.getVar("SSTATE_VERIFY_SIG"), False):
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500369 if not os.path.isfile(sstatepkg + '.sig'):
370 bb.warn("No signature file for sstate package %s, skipping acceleration..." % sstatepkg)
371 return False
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500372 signer = get_signer(d, 'local')
373 if not signer.verify(sstatepkg + '.sig'):
Brad Bishop08902b02019-08-20 09:16:51 -0400374 bb.warn("Cannot verify signature on sstate package %s, skipping acceleration..." % sstatepkg)
375 return False
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500376
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500377 # Empty sstateinst directory, ensure its clean
378 if os.path.exists(sstateinst):
379 oe.path.remove(sstateinst)
380 bb.utils.mkdirhier(sstateinst)
381
382 sstateinst = d.getVar("SSTATE_INSTDIR")
383 d.setVar('SSTATE_FIXMEDIR', ss['fixmedir'])
384
385 for f in (d.getVar('SSTATEPREINSTFUNCS') or '').split() + ['sstate_unpack_package']:
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500386 # All hooks should run in the SSTATE_INSTDIR
387 bb.build.exec_func(f, d, (sstateinst,))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500388
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500389 return sstate_installpkgdir(ss, d)
390
391def sstate_installpkgdir(ss, d):
392 import oe.path
393 import subprocess
394
395 sstateinst = d.getVar("SSTATE_INSTDIR")
396 d.setVar('SSTATE_FIXMEDIR', ss['fixmedir'])
397
398 for f in (d.getVar('SSTATEPOSTUNPACKFUNCS') or '').split():
399 # All hooks should run in the SSTATE_INSTDIR
400 bb.build.exec_func(f, d, (sstateinst,))
401
402 def prepdir(dir):
403 # remove dir if it exists, ensure any parent directories do exist
404 if os.path.exists(dir):
405 oe.path.remove(dir)
406 bb.utils.mkdirhier(dir)
407 oe.path.remove(dir)
408
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500409 for state in ss['dirs']:
410 prepdir(state[1])
Andrew Geisslerc926e172021-05-07 16:11:35 -0500411 bb.utils.rename(sstateinst + state[0], state[1])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500412 sstate_install(ss, d)
413
414 for plain in ss['plaindirs']:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500415 workdir = d.getVar('WORKDIR')
Brad Bishop977dc1a2019-02-06 16:01:43 -0500416 sharedworkdir = os.path.join(d.getVar('TMPDIR'), "work-shared")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500417 src = sstateinst + "/" + plain.replace(workdir, '')
Brad Bishop977dc1a2019-02-06 16:01:43 -0500418 if sharedworkdir in plain:
419 src = sstateinst + "/" + plain.replace(sharedworkdir, '')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500420 dest = plain
421 bb.utils.mkdirhier(src)
422 prepdir(dest)
Andrew Geisslerc926e172021-05-07 16:11:35 -0500423 bb.utils.rename(src, dest)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500424
425 return True
426
427python sstate_hardcode_path_unpack () {
428 # Fixup hardcoded paths
429 #
430 # Note: The logic below must match the reverse logic in
431 # sstate_hardcode_path(d)
432 import subprocess
433
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500434 sstateinst = d.getVar('SSTATE_INSTDIR')
435 sstatefixmedir = d.getVar('SSTATE_FIXMEDIR')
436 fixmefn = sstateinst + "fixmepath"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500437 if os.path.isfile(fixmefn):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500438 staging_target = d.getVar('RECIPE_SYSROOT')
439 staging_host = d.getVar('RECIPE_SYSROOT_NATIVE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500440
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500441 if bb.data.inherits_class('native', d) or bb.data.inherits_class('cross-canadian', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500442 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRHOST:%s:g'" % (staging_host)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500443 elif bb.data.inherits_class('cross', d) or bb.data.inherits_class('crosssdk', d):
444 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRTARGET:%s:g; s:FIXMESTAGINGDIRHOST:%s:g'" % (staging_target, staging_host)
445 else:
446 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRTARGET:%s:g'" % (staging_target)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500447
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500448 extra_staging_fixmes = d.getVar('EXTRA_STAGING_FIXMES') or ''
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500449 for fixmevar in extra_staging_fixmes.split():
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500450 fixme_path = d.getVar(fixmevar)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500451 sstate_sed_cmd += " -e 's:FIXME_%s:%s:g'" % (fixmevar, fixme_path)
452
453 # Add sstateinst to each filename in fixmepath, use xargs to efficiently call sed
454 sstate_hardcode_cmd = "sed -e 's:^:%s:g' %s | xargs %s" % (sstateinst, fixmefn, sstate_sed_cmd)
455
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500456 # Defer do_populate_sysroot relocation command
457 if sstatefixmedir:
458 bb.utils.mkdirhier(sstatefixmedir)
459 with open(sstatefixmedir + "/fixmepath.cmd", "w") as f:
460 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(fixmefn, sstatefixmedir + "/fixmepath")
461 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(sstateinst, "FIXMEFINALSSTATEINST")
462 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(staging_host, "FIXMEFINALSSTATEHOST")
463 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(staging_target, "FIXMEFINALSSTATETARGET")
464 f.write(sstate_hardcode_cmd)
465 bb.utils.copyfile(fixmefn, sstatefixmedir + "/fixmepath")
466 return
467
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500468 bb.note("Replacing fixme paths in sstate package: %s" % (sstate_hardcode_cmd))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500469 subprocess.check_call(sstate_hardcode_cmd, shell=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500470
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800471 # Need to remove this or we'd copy it into the target directory and may
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500472 # conflict with another writer
473 os.remove(fixmefn)
474}
475
476def sstate_clean_cachefile(ss, d):
477 import oe.path
478
Brad Bishopa5c52ff2018-11-23 10:55:50 +1300479 if d.getVarFlag('do_%s' % ss['task'], 'task'):
Andrew Geissler82c905d2020-04-13 13:39:40 -0500480 d.setVar("SSTATE_PATH_CURRTASK", ss['task'])
481 sstatepkgfile = d.getVar('SSTATE_PATHSPEC')
Brad Bishopa5c52ff2018-11-23 10:55:50 +1300482 bb.note("Removing %s" % sstatepkgfile)
483 oe.path.remove(sstatepkgfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500484
485def sstate_clean_cachefiles(d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500486 for task in (d.getVar('SSTATETASKS') or "").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500487 ld = d.createCopy()
488 ss = sstate_state_fromvars(ld, task)
489 sstate_clean_cachefile(ss, ld)
490
Andrew Geissler5f350902021-07-23 13:09:54 -0400491def sstate_clean_manifest(manifest, d, canrace=False, prefix=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500492 import oe.path
493
494 mfile = open(manifest)
495 entries = mfile.readlines()
496 mfile.close()
497
498 for entry in entries:
499 entry = entry.strip()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500500 if prefix and not entry.startswith("/"):
501 entry = prefix + "/" + entry
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500502 bb.debug(2, "Removing manifest: %s" % entry)
503 # We can race against another package populating directories as we're removing them
504 # so we ignore errors here.
505 try:
506 if entry.endswith("/"):
507 if os.path.islink(entry[:-1]):
508 os.remove(entry[:-1])
Andrew Geissler5f350902021-07-23 13:09:54 -0400509 elif os.path.exists(entry) and len(os.listdir(entry)) == 0 and not canrace:
510 # Removing directories whilst builds are in progress exposes a race. Only
511 # do it in contexts where it is safe to do so.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500512 os.rmdir(entry[:-1])
513 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500514 os.remove(entry)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500515 except OSError:
516 pass
517
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600518 postrm = manifest + ".postrm"
519 if os.path.exists(manifest + ".postrm"):
520 import subprocess
521 os.chmod(postrm, 0o755)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500522 subprocess.check_call(postrm, shell=True)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600523 oe.path.remove(postrm)
524
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500525 oe.path.remove(manifest)
526
527def sstate_clean(ss, d):
528 import oe.path
529 import glob
530
531 d2 = d.createCopy()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500532 stamp_clean = d.getVar("STAMPCLEAN")
533 extrainf = d.getVarFlag("do_" + ss['task'], 'stamp-extra-info')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500534 if extrainf:
535 d2.setVar("SSTATE_MANMACH", extrainf)
536 wildcard_stfile = "%s.do_%s*.%s" % (stamp_clean, ss['task'], extrainf)
537 else:
538 wildcard_stfile = "%s.do_%s*" % (stamp_clean, ss['task'])
539
540 manifest = d2.expand("${SSTATE_MANFILEPREFIX}.%s" % ss['task'])
541
542 if os.path.exists(manifest):
543 locks = []
544 for lock in ss['lockfiles-shared']:
545 locks.append(bb.utils.lockfile(lock))
546 for lock in ss['lockfiles']:
547 locks.append(bb.utils.lockfile(lock))
548
Andrew Geissler5f350902021-07-23 13:09:54 -0400549 sstate_clean_manifest(manifest, d, canrace=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500550
551 for lock in locks:
552 bb.utils.unlockfile(lock)
553
554 # Remove the current and previous stamps, but keep the sigdata.
555 #
556 # The glob() matches do_task* which may match multiple tasks, for
557 # example: do_package and do_package_write_ipk, so we need to
558 # exactly match *.do_task.* and *.do_task_setscene.*
559 rm_stamp = '.do_%s.' % ss['task']
560 rm_setscene = '.do_%s_setscene.' % ss['task']
561 # For BB_SIGNATURE_HANDLER = "noop"
562 rm_nohash = ".do_%s" % ss['task']
563 for stfile in glob.glob(wildcard_stfile):
564 # Keep the sigdata
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500565 if ".sigdata." in stfile or ".sigbasedata." in stfile:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500566 continue
567 # Preserve taint files in the stamps directory
568 if stfile.endswith('.taint'):
569 continue
570 if rm_stamp in stfile or rm_setscene in stfile or \
571 stfile.endswith(rm_nohash):
572 oe.path.remove(stfile)
573
574sstate_clean[vardepsexclude] = "SSTATE_MANFILEPREFIX"
575
576CLEANFUNCS += "sstate_cleanall"
577
578python sstate_cleanall() {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500579 bb.note("Removing shared state for package %s" % d.getVar('PN'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500580
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500581 manifest_dir = d.getVar('SSTATE_MANIFESTS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500582 if not os.path.exists(manifest_dir):
583 return
584
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500585 tasks = d.getVar('SSTATETASKS').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500586 for name in tasks:
587 ld = d.createCopy()
588 shared_state = sstate_state_fromvars(ld, name)
589 sstate_clean(shared_state, ld)
590}
591
592python sstate_hardcode_path () {
593 import subprocess, platform
594
595 # Need to remove hardcoded paths and fix these when we install the
596 # staging packages.
597 #
598 # Note: the logic in this function needs to match the reverse logic
599 # in sstate_installpkg(ss, d)
600
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500601 staging_target = d.getVar('RECIPE_SYSROOT')
602 staging_host = d.getVar('RECIPE_SYSROOT_NATIVE')
603 sstate_builddir = d.getVar('SSTATE_BUILDDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500604
Brad Bishop316dfdd2018-06-25 12:45:53 -0400605 sstate_sed_cmd = "sed -i -e 's:%s:FIXMESTAGINGDIRHOST:g'" % staging_host
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500606 if bb.data.inherits_class('native', d) or bb.data.inherits_class('cross-canadian', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500607 sstate_grep_cmd = "grep -l -e '%s'" % (staging_host)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500608 elif bb.data.inherits_class('cross', d) or bb.data.inherits_class('crosssdk', d):
609 sstate_grep_cmd = "grep -l -e '%s' -e '%s'" % (staging_target, staging_host)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400610 sstate_sed_cmd += " -e 's:%s:FIXMESTAGINGDIRTARGET:g'" % staging_target
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500611 else:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400612 sstate_grep_cmd = "grep -l -e '%s' -e '%s'" % (staging_target, staging_host)
613 sstate_sed_cmd += " -e 's:%s:FIXMESTAGINGDIRTARGET:g'" % staging_target
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500614
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500615 extra_staging_fixmes = d.getVar('EXTRA_STAGING_FIXMES') or ''
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500616 for fixmevar in extra_staging_fixmes.split():
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500617 fixme_path = d.getVar(fixmevar)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500618 sstate_sed_cmd += " -e 's:%s:FIXME_%s:g'" % (fixme_path, fixmevar)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500619 sstate_grep_cmd += " -e '%s'" % (fixme_path)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500620
621 fixmefn = sstate_builddir + "fixmepath"
622
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500623 sstate_scan_cmd = d.getVar('SSTATE_SCAN_CMD')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500624 sstate_filelist_cmd = "tee %s" % (fixmefn)
625
626 # fixmepath file needs relative paths, drop sstate_builddir prefix
627 sstate_filelist_relative_cmd = "sed -i -e 's:^%s::g' %s" % (sstate_builddir, fixmefn)
628
629 xargs_no_empty_run_cmd = '--no-run-if-empty'
630 if platform.system() == 'Darwin':
631 xargs_no_empty_run_cmd = ''
632
633 # Limit the fixpaths and sed operations based on the initial grep search
634 # This has the side effect of making sure the vfs cache is hot
635 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)
636
637 bb.note("Removing hardcoded paths from sstate package: '%s'" % (sstate_hardcode_cmd))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500638 subprocess.check_output(sstate_hardcode_cmd, shell=True, cwd=sstate_builddir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500639
640 # If the fixmefn is empty, remove it..
641 if os.stat(fixmefn).st_size == 0:
642 os.remove(fixmefn)
643 else:
644 bb.note("Replacing absolute paths in fixmepath file: '%s'" % (sstate_filelist_relative_cmd))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500645 subprocess.check_output(sstate_filelist_relative_cmd, shell=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500646}
647
648def sstate_package(ss, d):
649 import oe.path
Andrew Geissler5199d832021-09-24 16:47:35 -0500650 import time
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500651
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500652 tmpdir = d.getVar('TMPDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500653
Andrew Geissler5199d832021-09-24 16:47:35 -0500654 fixtime = False
655 if ss['task'] == "package":
656 fixtime = True
657
658 def fixtimestamp(root, path):
659 f = os.path.join(root, path)
660 if os.lstat(f).st_mtime > sde:
661 os.utime(f, (sde, sde), follow_symlinks=False)
662
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500663 sstatebuild = d.expand("${WORKDIR}/sstate-build-%s/" % ss['task'])
Andrew Geissler5199d832021-09-24 16:47:35 -0500664 sde = int(d.getVar("SOURCE_DATE_EPOCH") or time.time())
Andrew Geissler82c905d2020-04-13 13:39:40 -0500665 d.setVar("SSTATE_CURRTASK", ss['task'])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500666 bb.utils.remove(sstatebuild, recurse=True)
667 bb.utils.mkdirhier(sstatebuild)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500668 for state in ss['dirs']:
669 if not os.path.exists(state[1]):
670 continue
671 srcbase = state[0].rstrip("/").rsplit('/', 1)[0]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500672 # Find and error for absolute symlinks. We could attempt to relocate but its not
673 # clear where the symlink is relative to in this context. We could add that markup
674 # to sstate tasks but there aren't many of these so better just avoid them entirely.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500675 for walkroot, dirs, files in os.walk(state[1]):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500676 for file in files + dirs:
Andrew Geissler5199d832021-09-24 16:47:35 -0500677 if fixtime:
678 fixtimestamp(walkroot, file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500679 srcpath = os.path.join(walkroot, file)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500680 if not os.path.islink(srcpath):
681 continue
682 link = os.readlink(srcpath)
683 if not os.path.isabs(link):
684 continue
685 if not link.startswith(tmpdir):
686 continue
687 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 -0500688 bb.debug(2, "Preparing tree %s for packaging at %s" % (state[1], sstatebuild + state[0]))
Andrew Geisslerc926e172021-05-07 16:11:35 -0500689 bb.utils.rename(state[1], sstatebuild + state[0])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500690
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500691 workdir = d.getVar('WORKDIR')
Brad Bishop977dc1a2019-02-06 16:01:43 -0500692 sharedworkdir = os.path.join(d.getVar('TMPDIR'), "work-shared")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500693 for plain in ss['plaindirs']:
694 pdir = plain.replace(workdir, sstatebuild)
Brad Bishop977dc1a2019-02-06 16:01:43 -0500695 if sharedworkdir in plain:
696 pdir = plain.replace(sharedworkdir, sstatebuild)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500697 bb.utils.mkdirhier(plain)
698 bb.utils.mkdirhier(pdir)
Andrew Geisslerc926e172021-05-07 16:11:35 -0500699 bb.utils.rename(plain, pdir)
Andrew Geissler5199d832021-09-24 16:47:35 -0500700 if fixtime:
701 fixtimestamp(pdir, "")
702 for walkroot, dirs, files in os.walk(pdir):
703 for file in files + dirs:
704 fixtimestamp(walkroot, file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500705
706 d.setVar('SSTATE_BUILDDIR', sstatebuild)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500707 d.setVar('SSTATE_INSTDIR', sstatebuild)
708
709 if d.getVar('SSTATE_SKIP_CREATION') == '1':
710 return
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500711
Brad Bishop08902b02019-08-20 09:16:51 -0400712 sstate_create_package = ['sstate_report_unihash', 'sstate_create_package']
713 if d.getVar('SSTATE_SIG_KEY'):
714 sstate_create_package.append('sstate_sign_package')
715
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500716 for f in (d.getVar('SSTATECREATEFUNCS') or '').split() + \
Brad Bishop08902b02019-08-20 09:16:51 -0400717 sstate_create_package + \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500718 (d.getVar('SSTATEPOSTCREATEFUNCS') or '').split():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500719 # All hooks should run in SSTATE_BUILDDIR.
720 bb.build.exec_func(f, d, (sstatebuild,))
721
Andrew Geissler82c905d2020-04-13 13:39:40 -0500722 # SSTATE_PKG may have been changed by sstate_report_unihash
723 siginfo = d.getVar('SSTATE_PKG') + ".siginfo"
724 if not os.path.exists(siginfo):
725 bb.siggen.dump_this_task(siginfo, d)
726 else:
Andrew Geisslerc182c622020-05-15 14:13:32 -0500727 try:
728 os.utime(siginfo, None)
729 except PermissionError:
730 pass
Andrew Geissler5f350902021-07-23 13:09:54 -0400731 except OSError as e:
732 # Handle read-only file systems gracefully
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500733 import errno
Andrew Geissler5f350902021-07-23 13:09:54 -0400734 if e.errno != errno.EROFS:
735 raise e
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500736
737 return
738
William A. Kennington IIIac69b482021-06-02 12:28:27 -0700739sstate_package[vardepsexclude] += "SSTATE_SIG_KEY"
740
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800741def pstaging_fetch(sstatefetch, d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500742 import bb.fetch2
743
744 # Only try and fetch if the user has configured a mirror
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500745 mirrors = d.getVar('SSTATE_MIRRORS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500746 if not mirrors:
747 return
748
749 # Copy the data object and override DL_DIR and SRC_URI
750 localdata = bb.data.createCopy(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500751
752 dldir = localdata.expand("${SSTATE_DIR}")
753 bb.utils.mkdirhier(dldir)
754
755 localdata.delVar('MIRRORS')
756 localdata.setVar('FILESPATH', dldir)
757 localdata.setVar('DL_DIR', dldir)
758 localdata.setVar('PREMIRRORS', mirrors)
Andrew Geissler5199d832021-09-24 16:47:35 -0500759 localdata.setVar('SRCPV', d.getVar('SRCPV'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500760
761 # if BB_NO_NETWORK is set but we also have SSTATE_MIRROR_ALLOW_NETWORK,
762 # we'll want to allow network access for the current set of fetches.
Brad Bishopd89cb5f2019-04-10 09:02:41 -0400763 if bb.utils.to_boolean(localdata.getVar('BB_NO_NETWORK')) and \
764 bb.utils.to_boolean(localdata.getVar('SSTATE_MIRROR_ALLOW_NETWORK')):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500765 localdata.delVar('BB_NO_NETWORK')
766
767 # Try a fetch from the sstate mirror, if it fails just return and
768 # we will build the package
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600769 uris = ['file://{0};downloadfilename={0}'.format(sstatefetch),
770 'file://{0}.siginfo;downloadfilename={0}.siginfo'.format(sstatefetch)]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500771 if bb.utils.to_boolean(d.getVar("SSTATE_VERIFY_SIG"), False):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600772 uris += ['file://{0}.sig;downloadfilename={0}.sig'.format(sstatefetch)]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500773
774 for srcuri in uris:
775 localdata.setVar('SRC_URI', srcuri)
776 try:
777 fetcher = bb.fetch2.Fetch([srcuri], localdata, cache=False)
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500778 fetcher.checkstatus()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500779 fetcher.download()
780
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500781 except bb.fetch2.BBFetchException:
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500782 pass
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500783
Andrew Geissler5199d832021-09-24 16:47:35 -0500784pstaging_fetch[vardepsexclude] += "SRCPV"
785
786
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500787def sstate_setscene(d):
788 shared_state = sstate_state_fromvars(d)
789 accelerate = sstate_installpkg(shared_state, d)
790 if not accelerate:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600791 bb.fatal("No suitable staging package found")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500792
793python sstate_task_prefunc () {
794 shared_state = sstate_state_fromvars(d)
795 sstate_clean(shared_state, d)
796}
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500797sstate_task_prefunc[dirs] = "${WORKDIR}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500798
799python sstate_task_postfunc () {
800 shared_state = sstate_state_fromvars(d)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500801
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500802 for intercept in shared_state['interceptfuncs']:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500803 bb.build.exec_func(intercept, d, (d.getVar("WORKDIR"),))
804
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600805 omask = os.umask(0o002)
806 if omask != 0o002:
807 bb.note("Using umask 0o002 (not %0o) for sstate packaging" % omask)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500808 sstate_package(shared_state, d)
809 os.umask(omask)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500810
811 sstateinst = d.getVar("SSTATE_INSTDIR")
812 d.setVar('SSTATE_FIXMEDIR', shared_state['fixmedir'])
813
814 sstate_installpkgdir(shared_state, d)
815
816 bb.utils.remove(d.getVar("SSTATE_BUILDDIR"), recurse=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500817}
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500818sstate_task_postfunc[dirs] = "${WORKDIR}"
819
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500820
821#
822# Shell function to generate a sstate package from a directory
823# set as SSTATE_BUILDDIR. Will be run from within SSTATE_BUILDDIR.
824#
825sstate_create_package () {
Andrew Geissler82c905d2020-04-13 13:39:40 -0500826 # Exit early if it already exists
Brad Bishop08902b02019-08-20 09:16:51 -0400827 if [ -e ${SSTATE_PKG} ]; then
Andrew Geisslerc182c622020-05-15 14:13:32 -0500828 [ ! -w ${SSTATE_PKG} ] || touch ${SSTATE_PKG}
Brad Bishop08902b02019-08-20 09:16:51 -0400829 return
830 fi
831
Andrew Geisslerc3d88e42020-10-02 09:45:00 -0500832 mkdir --mode=0775 -p `dirname ${SSTATE_PKG}`
Andrew Geissler82c905d2020-04-13 13:39:40 -0500833 TFILE=`mktemp ${SSTATE_PKG}.XXXXXXXX`
834
835 # Use pigz if available
836 OPT="-czS"
837 if [ -x "$(command -v pigz)" ]; then
838 OPT="-I pigz -cS"
839 fi
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800840
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500841 # Need to handle empty directories
842 if [ "$(ls -A)" ]; then
843 set +e
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800844 tar $OPT -f $TFILE *
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500845 ret=$?
846 if [ $ret -ne 0 ] && [ $ret -ne 1 ]; then
847 exit 1
848 fi
849 set -e
850 else
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800851 tar $OPT --file=$TFILE --files-from=/dev/null
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500852 fi
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500853 chmod 0664 $TFILE
Brad Bishop08902b02019-08-20 09:16:51 -0400854 # Skip if it was already created by some other process
855 if [ ! -e ${SSTATE_PKG} ]; then
Andrew Geissler82c905d2020-04-13 13:39:40 -0500856 # Move into place using ln to attempt an atomic op.
857 # Abort if it already exists
858 ln $TFILE ${SSTATE_PKG} && rm $TFILE
Brad Bishop08902b02019-08-20 09:16:51 -0400859 else
860 rm $TFILE
861 fi
Andrew Geisslerc182c622020-05-15 14:13:32 -0500862 [ ! -w ${SSTATE_PKG} ] || touch ${SSTATE_PKG}
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500863}
864
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500865python sstate_sign_package () {
866 from oe.gpg_sign import get_signer
867
Brad Bishop08902b02019-08-20 09:16:51 -0400868
869 signer = get_signer(d, 'local')
870 sstate_pkg = d.getVar('SSTATE_PKG')
871 if os.path.exists(sstate_pkg + '.sig'):
872 os.unlink(sstate_pkg + '.sig')
873 signer.detach_sign(sstate_pkg, d.getVar('SSTATE_SIG_KEY', False), None,
874 d.getVar('SSTATE_SIG_PASSPHRASE'), armor=False)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500875}
876
Brad Bishop19323692019-04-05 15:28:33 -0400877python sstate_report_unihash() {
878 report_unihash = getattr(bb.parse.siggen, 'report_unihash', None)
879
880 if report_unihash:
881 ss = sstate_state_fromvars(d)
882 report_unihash(os.getcwd(), ss['task'], d)
883}
884
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500885#
886# Shell function to decompress and prepare a package for installation
887# Will be run from within SSTATE_INSTDIR.
888#
889sstate_unpack_package () {
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500890 tar -xvzf ${SSTATE_PKG}
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500891 # update .siginfo atime on local/NFS mirror
Andrew Geisslerc3d88e42020-10-02 09:45:00 -0500892 [ -O ${SSTATE_PKG}.siginfo ] && [ -w ${SSTATE_PKG}.siginfo ] && [ -h ${SSTATE_PKG}.siginfo ] && touch -a ${SSTATE_PKG}.siginfo
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500893 # Use "! -w ||" to return true for read only files
894 [ ! -w ${SSTATE_PKG} ] || touch --no-dereference ${SSTATE_PKG}
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500895 [ ! -w ${SSTATE_PKG}.sig ] || [ ! -e ${SSTATE_PKG}.sig ] || touch --no-dereference ${SSTATE_PKG}.sig
896 [ ! -w ${SSTATE_PKG}.siginfo ] || [ ! -e ${SSTATE_PKG}.siginfo ] || touch --no-dereference ${SSTATE_PKG}.siginfo
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500897}
898
899BB_HASHCHECK_FUNCTION = "sstate_checkhashes"
900
Brad Bishop1d80a2e2019-11-15 16:35:03 -0500901def sstate_checkhashes(sq_data, d, siginfo=False, currentcount=0, summary=True, **kwargs):
Brad Bishop08902b02019-08-20 09:16:51 -0400902 found = set()
Andrew Geissler9b4d8b02021-02-19 12:26:16 -0600903 foundLocal = set()
904 foundNet = set()
Brad Bishop08902b02019-08-20 09:16:51 -0400905 missed = set()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500906
Brad Bishop19323692019-04-05 15:28:33 -0400907 def gethash(task):
Brad Bishop08902b02019-08-20 09:16:51 -0400908 return sq_data['unihash'][task]
Brad Bishop19323692019-04-05 15:28:33 -0400909
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500910 def getpathcomponents(task, d):
911 # Magic data from BB_HASHFILENAME
Brad Bishop08902b02019-08-20 09:16:51 -0400912 splithashfn = sq_data['hashfn'][task].split(" ")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500913 spec = splithashfn[1]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500914 if splithashfn[0] == "True":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500915 extrapath = d.getVar("NATIVELSBSTRING") + "/"
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500916 else:
917 extrapath = ""
Brad Bishop08902b02019-08-20 09:16:51 -0400918
919 tname = bb.runqueue.taskname_from_tid(task)[3:]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500920
921 if tname in ["fetch", "unpack", "patch", "populate_lic", "preconfigure"] and splithashfn[2]:
922 spec = splithashfn[2]
923 extrapath = ""
924
925 return spec, extrapath, tname
926
927
Brad Bishop08902b02019-08-20 09:16:51 -0400928 for tid in sq_data['hash']:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500929
Brad Bishop08902b02019-08-20 09:16:51 -0400930 spec, extrapath, tname = getpathcomponents(tid, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500931
Andrew Geissler82c905d2020-04-13 13:39:40 -0500932 sstatefile = d.expand("${SSTATE_DIR}/" + extrapath + generate_sstatefn(spec, gethash(tid), tname, siginfo, d))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500933
934 if os.path.exists(sstatefile):
935 bb.debug(2, "SState: Found valid sstate file %s" % sstatefile)
Brad Bishop08902b02019-08-20 09:16:51 -0400936 found.add(tid)
Andrew Geissler9b4d8b02021-02-19 12:26:16 -0600937 foundLocal.add(tid)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500938 continue
939 else:
Brad Bishop08902b02019-08-20 09:16:51 -0400940 missed.add(tid)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500941 bb.debug(2, "SState: Looked for but didn't find file %s" % sstatefile)
942
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500943 mirrors = d.getVar("SSTATE_MIRRORS")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500944 if mirrors:
945 # Copy the data object and override DL_DIR and SRC_URI
946 localdata = bb.data.createCopy(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500947
948 dldir = localdata.expand("${SSTATE_DIR}")
949 localdata.delVar('MIRRORS')
950 localdata.setVar('FILESPATH', dldir)
951 localdata.setVar('DL_DIR', dldir)
952 localdata.setVar('PREMIRRORS', mirrors)
953
954 bb.debug(2, "SState using premirror of: %s" % mirrors)
955
956 # if BB_NO_NETWORK is set but we also have SSTATE_MIRROR_ALLOW_NETWORK,
957 # we'll want to allow network access for the current set of fetches.
Brad Bishopd89cb5f2019-04-10 09:02:41 -0400958 if bb.utils.to_boolean(localdata.getVar('BB_NO_NETWORK')) and \
959 bb.utils.to_boolean(localdata.getVar('SSTATE_MIRROR_ALLOW_NETWORK')):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500960 localdata.delVar('BB_NO_NETWORK')
961
962 from bb.fetch2 import FetchConnectionCache
963 def checkstatus_init(thread_worker):
964 thread_worker.connection_cache = FetchConnectionCache()
965
966 def checkstatus_end(thread_worker):
967 thread_worker.connection_cache.close_connections()
968
969 def checkstatus(thread_worker, arg):
Brad Bishop08902b02019-08-20 09:16:51 -0400970 (tid, sstatefile) = arg
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500971
972 localdata2 = bb.data.createCopy(localdata)
973 srcuri = "file://" + sstatefile
974 localdata.setVar('SRC_URI', srcuri)
975 bb.debug(2, "SState: Attempting to fetch %s" % srcuri)
976
977 try:
978 fetcher = bb.fetch2.Fetch(srcuri.split(), localdata2,
979 connection_cache=thread_worker.connection_cache)
980 fetcher.checkstatus()
981 bb.debug(2, "SState: Successful fetch test for %s" % srcuri)
Brad Bishop08902b02019-08-20 09:16:51 -0400982 found.add(tid)
Andrew Geissler9b4d8b02021-02-19 12:26:16 -0600983 foundNet.add(tid)
Brad Bishop08902b02019-08-20 09:16:51 -0400984 if tid in missed:
985 missed.remove(tid)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500986 except:
Brad Bishop08902b02019-08-20 09:16:51 -0400987 missed.add(tid)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500988 bb.debug(2, "SState: Unsuccessful fetch test for %s" % srcuri)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600989 pass
Andrew Geissler82c905d2020-04-13 13:39:40 -0500990 if len(tasklist) >= min_tasks:
991 bb.event.fire(bb.event.ProcessProgress(msg, len(tasklist) - thread_worker.tasks.qsize()), d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500992
993 tasklist = []
Andrew Geissler82c905d2020-04-13 13:39:40 -0500994 min_tasks = 100
Brad Bishop08902b02019-08-20 09:16:51 -0400995 for tid in sq_data['hash']:
996 if tid in found:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500997 continue
Brad Bishop08902b02019-08-20 09:16:51 -0400998 spec, extrapath, tname = getpathcomponents(tid, d)
Andrew Geissler82c905d2020-04-13 13:39:40 -0500999 sstatefile = d.expand(extrapath + generate_sstatefn(spec, gethash(tid), tname, siginfo, d))
Brad Bishop08902b02019-08-20 09:16:51 -04001000 tasklist.append((tid, sstatefile))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001001
1002 if tasklist:
Andrew Geisslerd159c7f2021-09-02 21:05:58 -05001003 nproc = min(int(d.getVar("BB_NUMBER_THREADS")), len(tasklist))
1004
Andrew Geissler82c905d2020-04-13 13:39:40 -05001005 if len(tasklist) >= min_tasks:
1006 msg = "Checking sstate mirror object availability"
1007 bb.event.fire(bb.event.ProcessStarted(msg, len(tasklist)), d)
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001008
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001009 bb.event.enable_threadlock()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001010 pool = oe.utils.ThreadedPool(nproc, len(tasklist),
1011 worker_init=checkstatus_init, worker_end=checkstatus_end)
1012 for t in tasklist:
1013 pool.add_task(checkstatus, t)
1014 pool.start()
1015 pool.wait_completion()
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001016 bb.event.disable_threadlock()
1017
Andrew Geissler82c905d2020-04-13 13:39:40 -05001018 if len(tasklist) >= min_tasks:
1019 bb.event.fire(bb.event.ProcessFinished(msg), d)
Brad Bishop96ff1982019-08-19 13:50:42 -04001020
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001021 inheritlist = d.getVar("INHERIT")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001022 if "toaster" in inheritlist:
1023 evdata = {'missed': [], 'found': []};
Brad Bishop08902b02019-08-20 09:16:51 -04001024 for tid in missed:
1025 spec, extrapath, tname = getpathcomponents(tid, d)
Andrew Geissler82c905d2020-04-13 13:39:40 -05001026 sstatefile = d.expand(extrapath + generate_sstatefn(spec, gethash(tid), tname, False, d))
Brad Bishop08902b02019-08-20 09:16:51 -04001027 evdata['missed'].append((bb.runqueue.fn_from_tid(tid), bb.runqueue.taskname_from_tid(tid), gethash(tid), sstatefile ) )
1028 for tid in found:
1029 spec, extrapath, tname = getpathcomponents(tid, d)
Andrew Geissler82c905d2020-04-13 13:39:40 -05001030 sstatefile = d.expand(extrapath + generate_sstatefn(spec, gethash(tid), tname, False, d))
Brad Bishop08902b02019-08-20 09:16:51 -04001031 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 -05001032 bb.event.fire(bb.event.MetadataEvent("MissedSstate", evdata), d)
1033
Brad Bishop1d80a2e2019-11-15 16:35:03 -05001034 if summary:
1035 # Print some summary statistics about the current task completion and how much sstate
1036 # reuse there was. Avoid divide by zero errors.
1037 total = len(sq_data['hash'])
1038 complete = 0
1039 if currentcount:
1040 complete = (len(found) + currentcount) / (total + currentcount) * 100
1041 match = 0
1042 if total:
1043 match = len(found) / total * 100
Andrew Geissler9b4d8b02021-02-19 12:26:16 -06001044 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 -08001045
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001046 if hasattr(bb.parse.siggen, "checkhashes"):
Brad Bishop08902b02019-08-20 09:16:51 -04001047 bb.parse.siggen.checkhashes(sq_data, missed, found, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001048
Brad Bishop08902b02019-08-20 09:16:51 -04001049 return found
Patrick Williams213cb262021-08-07 19:21:33 -05001050setscene_depvalid[vardepsexclude] = "SSTATE_EXCLUDEDEPS_SYSROOT"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001051
1052BB_SETSCENE_DEPVALID = "setscene_depvalid"
1053
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001054def setscene_depvalid(task, taskdependees, notneeded, d, log=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001055 # taskdependees is a dict of tasks which depend on task, each being a 3 item list of [PN, TASKNAME, FILENAME]
1056 # task is included in taskdependees too
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001057 # Return - False - We need this dependency
1058 # - True - We can skip this dependency
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001059 import re
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001060
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001061 def logit(msg, log):
1062 if log is not None:
1063 log.append(msg)
1064 else:
1065 bb.debug(2, msg)
1066
1067 logit("Considering setscene task: %s" % (str(taskdependees[task])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001068
Andrew Geissler5199d832021-09-24 16:47:35 -05001069 directtasks = ["do_populate_lic", "do_deploy_source_date_epoch", "do_shared_workdir", "do_stash_locale", "do_gcc_stash_builddir"]
1070
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001071 def isNativeCross(x):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001072 return x.endswith("-native") or "-cross-" in x or "-crosssdk" in x or x.endswith("-cross")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001073
Andrew Geissler5199d832021-09-24 16:47:35 -05001074 # We only need to trigger deploy_source_date_epoch through direct dependencies
1075 if taskdependees[task][1] in directtasks:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001076 return True
1077
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001078 # We only need to trigger packagedata through direct dependencies
1079 # but need to preserve packagedata on packagedata links
1080 if taskdependees[task][1] == "do_packagedata":
1081 for dep in taskdependees:
1082 if taskdependees[dep][1] == "do_packagedata":
1083 return False
1084 return True
1085
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001086 for dep in taskdependees:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001087 logit(" considering dependency: %s" % (str(taskdependees[dep])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001088 if task == dep:
1089 continue
1090 if dep in notneeded:
1091 continue
1092 # do_package_write_* and do_package doesn't need do_package
1093 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']:
1094 continue
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001095 # do_package_write_* need do_populate_sysroot as they're mainly postinstall dependencies
1096 if taskdependees[task][1] == "do_populate_sysroot" and taskdependees[dep][1] in ['do_package_write_deb', 'do_package_write_ipk', 'do_package_write_rpm']:
1097 return False
Andrew Geissler5199d832021-09-24 16:47:35 -05001098 # do_package/packagedata/package_qa/deploy don't need do_populate_sysroot
1099 if taskdependees[task][1] == "do_populate_sysroot" and taskdependees[dep][1] in ['do_package', 'do_packagedata', 'do_package_qa', 'do_deploy']:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001100 continue
1101 # Native/Cross packages don't exist and are noexec anyway
1102 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']:
1103 continue
1104
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001105 # This is due to the [depends] in useradd.bbclass complicating matters
1106 # The logic *is* reversed here due to the way hard setscene dependencies are injected
1107 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':
1108 continue
1109
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001110 # Consider sysroot depending on sysroot tasks
1111 if taskdependees[task][1] == 'do_populate_sysroot' and taskdependees[dep][1] == 'do_populate_sysroot':
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001112 # Allow excluding certain recursive dependencies. If a recipe needs it should add a
1113 # specific dependency itself, rather than relying on one of its dependees to pull
1114 # them in.
1115 # See also http://lists.openembedded.org/pipermail/openembedded-core/2018-January/146324.html
1116 not_needed = False
1117 excludedeps = d.getVar('_SSTATE_EXCLUDEDEPS_SYSROOT')
1118 if excludedeps is None:
1119 # Cache the regular expressions for speed
1120 excludedeps = []
1121 for excl in (d.getVar('SSTATE_EXCLUDEDEPS_SYSROOT') or "").split():
1122 excludedeps.append((re.compile(excl.split('->', 1)[0]), re.compile(excl.split('->', 1)[1])))
1123 d.setVar('_SSTATE_EXCLUDEDEPS_SYSROOT', excludedeps)
1124 for excl in excludedeps:
1125 if excl[0].match(taskdependees[dep][0]):
1126 if excl[1].match(taskdependees[task][0]):
1127 not_needed = True
1128 break
1129 if not_needed:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001130 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001131 # For meta-extsdk-toolchain we want all sysroot dependencies
1132 if taskdependees[dep][0] == 'meta-extsdk-toolchain':
1133 return False
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001134 # Native/Cross populate_sysroot need their dependencies
1135 if isNativeCross(taskdependees[task][0]) and isNativeCross(taskdependees[dep][0]):
1136 return False
1137 # Target populate_sysroot depended on by cross tools need to be installed
1138 if isNativeCross(taskdependees[dep][0]):
1139 return False
1140 # Native/cross tools depended upon by target sysroot are not needed
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001141 # Add an exception for shadow-native as required by useradd.bbclass
1142 if isNativeCross(taskdependees[task][0]) and taskdependees[task][0] != 'shadow-native':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001143 continue
1144 # Target populate_sysroot need their dependencies
1145 return False
1146
Andrew Geissler5199d832021-09-24 16:47:35 -05001147 if taskdependees[dep][1] in directtasks:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001148 continue
1149
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001150 # Safe fallthrough default
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001151 logit(" Default setscene dependency fall through due to dependency: %s" % (str(taskdependees[dep])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001152 return False
1153 return True
1154
1155addhandler sstate_eventhandler
1156sstate_eventhandler[eventmask] = "bb.build.TaskSucceeded"
1157python sstate_eventhandler() {
1158 d = e.data
Andrew Geissler82c905d2020-04-13 13:39:40 -05001159 writtensstate = d.getVar('SSTATE_CURRTASK')
1160 if not writtensstate:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001161 taskname = d.getVar("BB_RUNTASK")[3:]
1162 spec = d.getVar('SSTATE_PKGSPEC')
1163 swspec = d.getVar('SSTATE_SWSPEC')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001164 if taskname in ["fetch", "unpack", "patch", "populate_lic", "preconfigure"] and swspec:
1165 d.setVar("SSTATE_PKGSPEC", "${SSTATE_SWSPEC}")
1166 d.setVar("SSTATE_EXTRAPATH", "")
Andrew Geissler82c905d2020-04-13 13:39:40 -05001167 d.setVar("SSTATE_CURRTASK", taskname)
1168 siginfo = d.getVar('SSTATE_PKG') + ".siginfo"
1169 if not os.path.exists(siginfo):
1170 bb.siggen.dump_this_task(siginfo, d)
1171 else:
Andrew Geisslerc182c622020-05-15 14:13:32 -05001172 try:
1173 os.utime(siginfo, None)
1174 except PermissionError:
1175 pass
Andrew Geissler5f350902021-07-23 13:09:54 -04001176 except OSError as e:
1177 # Handle read-only file systems gracefully
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001178 import errno
Andrew Geissler5f350902021-07-23 13:09:54 -04001179 if e.errno != errno.EROFS:
1180 raise e
Andrew Geisslerc182c622020-05-15 14:13:32 -05001181
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001182}
1183
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001184SSTATE_PRUNE_OBSOLETEWORKDIR ?= "1"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001185
Andrew Geissler95ac1b82021-03-31 14:34:31 -05001186#
1187# Event handler which removes manifests and stamps file for recipes which are no
1188# longer 'reachable' in a build where they once were. 'Reachable' refers to
1189# whether a recipe is parsed so recipes in a layer which was removed would no
1190# longer be reachable. Switching between systemd and sysvinit where recipes
1191# became skipped would be another example.
1192#
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001193# Also optionally removes the workdir of those tasks/recipes
1194#
Andrew Geissler95ac1b82021-03-31 14:34:31 -05001195addhandler sstate_eventhandler_reachablestamps
1196sstate_eventhandler_reachablestamps[eventmask] = "bb.event.ReachableStamps"
1197python sstate_eventhandler_reachablestamps() {
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001198 import glob
1199 d = e.data
1200 stamps = e.stamps.values()
1201 removeworkdir = (d.getVar("SSTATE_PRUNE_OBSOLETEWORKDIR", False) == "1")
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001202 preservestampfile = d.expand('${SSTATE_MANIFESTS}/preserve-stamps')
1203 preservestamps = []
1204 if os.path.exists(preservestampfile):
1205 with open(preservestampfile, 'r') as f:
1206 preservestamps = f.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001207 seen = []
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001208
1209 # The machine index contains all the stamps this machine has ever seen in this build directory.
1210 # We should only remove things which this machine once accessed but no longer does.
1211 machineindex = set()
1212 bb.utils.mkdirhier(d.expand("${SSTATE_MANIFESTS}"))
1213 mi = d.expand("${SSTATE_MANIFESTS}/index-machine-${MACHINE}")
1214 if os.path.exists(mi):
1215 with open(mi, "r") as f:
1216 machineindex = set(line.strip() for line in f.readlines())
1217
Brad Bishop316dfdd2018-06-25 12:45:53 -04001218 for a in sorted(list(set(d.getVar("SSTATE_ARCHS").split()))):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001219 toremove = []
1220 i = d.expand("${SSTATE_MANIFESTS}/index-" + a)
1221 if not os.path.exists(i):
1222 continue
William A. Kennington IIIac69b482021-06-02 12:28:27 -07001223 manseen = set()
1224 ignore = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001225 with open(i, "r") as f:
1226 lines = f.readlines()
William A. Kennington IIIac69b482021-06-02 12:28:27 -07001227 for l in reversed(lines):
Brad Bishop19323692019-04-05 15:28:33 -04001228 try:
1229 (stamp, manifest, workdir) = l.split()
William A. Kennington IIIac69b482021-06-02 12:28:27 -07001230 # The index may have multiple entries for the same manifest as the code above only appends
1231 # new entries and there may be an entry with matching manifest but differing version in stamp/workdir.
1232 # The last entry in the list is the valid one, any earlier entries with matching manifests
1233 # should be ignored.
1234 if manifest in manseen:
1235 ignore.append(l)
1236 continue
1237 manseen.add(manifest)
Brad Bishop19323692019-04-05 15:28:33 -04001238 if stamp not in stamps and stamp not in preservestamps and stamp in machineindex:
1239 toremove.append(l)
1240 if stamp not in seen:
1241 bb.debug(2, "Stamp %s is not reachable, removing related manifests" % stamp)
1242 seen.append(stamp)
1243 except ValueError:
1244 bb.fatal("Invalid line '%s' in sstate manifest '%s'" % (l, i))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001245
1246 if toremove:
Brad Bishop316dfdd2018-06-25 12:45:53 -04001247 msg = "Removing %d recipes from the %s sysroot" % (len(toremove), a)
1248 bb.event.fire(bb.event.ProcessStarted(msg, len(toremove)), d)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001249
Brad Bishop316dfdd2018-06-25 12:45:53 -04001250 removed = 0
1251 for r in toremove:
1252 (stamp, manifest, workdir) = r.split()
1253 for m in glob.glob(manifest + ".*"):
1254 if m.endswith(".postrm"):
1255 continue
1256 sstate_clean_manifest(m, d)
1257 bb.utils.remove(stamp + "*")
1258 if removeworkdir:
1259 bb.utils.remove(workdir, recurse = True)
1260 lines.remove(r)
1261 removed = removed + 1
1262 bb.event.fire(bb.event.ProcessProgress(msg, removed), d)
1263
1264 bb.event.fire(bb.event.ProcessFinished(msg), d)
1265
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001266 with open(i, "w") as f:
1267 for l in lines:
William A. Kennington IIIac69b482021-06-02 12:28:27 -07001268 if l in ignore:
1269 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001270 f.write(l)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001271 machineindex |= set(stamps)
1272 with open(mi, "w") as f:
1273 for l in machineindex:
1274 f.write(l + "\n")
1275
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001276 if preservestamps:
1277 os.remove(preservestampfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001278}
Andrew Geissler95ac1b82021-03-31 14:34:31 -05001279
1280
1281#
1282# Bitbake can generate an event showing which setscene tasks are 'stale',
1283# i.e. which ones will be rerun. These are ones where a stamp file is present but
1284# it is stable (e.g. taskhash doesn't match). With that list we can go through
1285# the manifests for matching tasks and "uninstall" those manifests now. We do
1286# this now rather than mid build since the distribution of files between sstate
1287# objects may have changed, new tasks may run first and if those new tasks overlap
1288# with the stale tasks, we'd see overlapping files messages and failures. Thankfully
1289# removing these files is fast.
1290#
1291addhandler sstate_eventhandler_stalesstate
1292sstate_eventhandler_stalesstate[eventmask] = "bb.event.StaleSetSceneTasks"
1293python sstate_eventhandler_stalesstate() {
1294 d = e.data
1295 tasks = e.tasks
1296
1297 bb.utils.mkdirhier(d.expand("${SSTATE_MANIFESTS}"))
1298
1299 for a in list(set(d.getVar("SSTATE_ARCHS").split())):
1300 toremove = []
1301 i = d.expand("${SSTATE_MANIFESTS}/index-" + a)
1302 if not os.path.exists(i):
1303 continue
1304 with open(i, "r") as f:
1305 lines = f.readlines()
1306 for l in lines:
1307 try:
1308 (stamp, manifest, workdir) = l.split()
1309 for tid in tasks:
1310 for s in tasks[tid]:
1311 if s.startswith(stamp):
1312 taskname = bb.runqueue.taskname_from_tid(tid)[3:]
1313 manname = manifest + "." + taskname
1314 if os.path.exists(manname):
1315 bb.debug(2, "Sstate for %s is stale, removing related manifest %s" % (tid, manname))
1316 toremove.append((manname, tid, tasks[tid]))
1317 break
1318 except ValueError:
1319 bb.fatal("Invalid line '%s' in sstate manifest '%s'" % (l, i))
1320
1321 if toremove:
1322 msg = "Removing %d stale sstate objects for arch %s" % (len(toremove), a)
1323 bb.event.fire(bb.event.ProcessStarted(msg, len(toremove)), d)
1324
1325 removed = 0
1326 for (manname, tid, stamps) in toremove:
1327 sstate_clean_manifest(manname, d)
1328 for stamp in stamps:
1329 bb.utils.remove(stamp)
1330 removed = removed + 1
1331 bb.event.fire(bb.event.ProcessProgress(msg, removed), d)
1332
1333 bb.event.fire(bb.event.ProcessFinished(msg), d)
1334}