blob: b45da4fb23159353522f2127cb807b0ab825d225 [file] [log] [blame]
Andrew Geisslereff27472021-10-29 15:35:00 -05001SSTATE_VERSION = "7"
2
3SSTATE_ZSTD_CLEVEL ??= "8"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05004
5SSTATE_MANIFESTS ?= "${TMPDIR}/sstate-control"
6SSTATE_MANFILEPREFIX = "${SSTATE_MANIFESTS}/manifest-${SSTATE_MANMACH}-${PN}"
7
Andrew Geissler82c905d2020-04-13 13:39:40 -05008def generate_sstatefn(spec, hash, taskname, siginfo, d):
9 if taskname is None:
10 return ""
Andrew Geisslereff27472021-10-29 15:35:00 -050011 extension = ".tar.zst"
Andrew Geissler82c905d2020-04-13 13:39:40 -050012 # 8 chars reserved for siginfo
13 limit = 254 - 8
14 if siginfo:
15 limit = 254
Andrew Geisslereff27472021-10-29 15:35:00 -050016 extension = ".tar.zst.siginfo"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050017 if not hash:
18 hash = "INVALID"
Andrew Geissler82c905d2020-04-13 13:39:40 -050019 fn = spec + hash + "_" + taskname + extension
20 # If the filename is too long, attempt to reduce it
21 if len(fn) > limit:
22 components = spec.split(":")
23 # Fields 0,5,6 are mandatory, 1 is most useful, 2,3,4 are just for information
24 # 7 is for the separators
Andrew Geissler595f6302022-01-24 19:11:47 +000025 avail = (limit - len(hash + "_" + taskname + extension) - len(components[0]) - len(components[1]) - len(components[5]) - len(components[6]) - 7) // 3
Andrew Geissler82c905d2020-04-13 13:39:40 -050026 components[2] = components[2][:avail]
27 components[3] = components[3][:avail]
28 components[4] = components[4][:avail]
29 spec = ":".join(components)
30 fn = spec + hash + "_" + taskname + extension
31 if len(fn) > limit:
32 bb.fatal("Unable to reduce sstate name to less than 255 chararacters")
33 return hash[:2] + "/" + hash[2:4] + "/" + fn
Patrick Williamsc124f4f2015-09-15 14:41:29 -050034
35SSTATE_PKGARCH = "${PACKAGE_ARCH}"
36SSTATE_PKGSPEC = "sstate:${PN}:${PACKAGE_ARCH}${TARGET_VENDOR}-${TARGET_OS}:${PV}:${PR}:${SSTATE_PKGARCH}:${SSTATE_VERSION}:"
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050037SSTATE_SWSPEC = "sstate:${PN}::${PV}:${PR}::${SSTATE_VERSION}:"
Andrew Geissler82c905d2020-04-13 13:39:40 -050038SSTATE_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 -050039SSTATE_PKG = "${SSTATE_DIR}/${SSTATE_PKGNAME}"
40SSTATE_EXTRAPATH = ""
41SSTATE_EXTRAPATHWILDCARD = ""
Andrew Geisslereff27472021-10-29 15:35:00 -050042SSTATE_PATHSPEC = "${SSTATE_DIR}/${SSTATE_EXTRAPATHWILDCARD}*/*/${SSTATE_PKGSPEC}*_${SSTATE_PATH_CURRTASK}.tar.zst*"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050043
Patrick Williamsc0f7c042017-02-23 20:41:17 -060044# explicitly make PV to depend on evaluated value of PV variable
45PV[vardepvalue] = "${PV}"
46
Patrick Williamsc124f4f2015-09-15 14:41:29 -050047# We don't want the sstate to depend on things like the distro string
48# of the system, we let the sstate paths take care of this.
49SSTATE_EXTRAPATH[vardepvalue] = ""
Brad Bishop19323692019-04-05 15:28:33 -040050SSTATE_EXTRAPATHWILDCARD[vardepvalue] = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -050051
52# For multilib rpm the allarch packagegroup files can overwrite (in theory they're identical)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080053SSTATE_DUPWHITELIST = "${DEPLOY_DIR}/licenses/"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050054# Avoid docbook/sgml catalog warnings for now
55SSTATE_DUPWHITELIST += "${STAGING_ETCDIR_NATIVE}/sgml ${STAGING_DATADIR_NATIVE}/sgml"
Brad Bishop316dfdd2018-06-25 12:45:53 -040056# sdk-provides-dummy-nativesdk and nativesdk-buildtools-perl-dummy overlap for different SDKMACHINE
57SSTATE_DUPWHITELIST += "${DEPLOY_DIR_RPM}/sdk_provides_dummy_nativesdk/ ${DEPLOY_DIR_IPK}/sdk-provides-dummy-nativesdk/"
58SSTATE_DUPWHITELIST += "${DEPLOY_DIR_RPM}/buildtools_dummy_nativesdk/ ${DEPLOY_DIR_IPK}/buildtools-dummy-nativesdk/"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080059# target-sdk-provides-dummy overlaps that allarch is disabled when multilib is used
60SSTATE_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 -050061# Archive the sources for many architectures in one deploy folder
62SSTATE_DUPWHITELIST += "${DEPLOY_DIR_SRC}"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080063# ovmf/grub-efi/systemd-boot/intel-microcode multilib recipes can generate identical overlapping files
64SSTATE_DUPWHITELIST += "${DEPLOY_DIR_IMAGE}/ovmf"
65SSTATE_DUPWHITELIST += "${DEPLOY_DIR_IMAGE}/grub-efi"
66SSTATE_DUPWHITELIST += "${DEPLOY_DIR_IMAGE}/systemd-boot"
67SSTATE_DUPWHITELIST += "${DEPLOY_DIR_IMAGE}/microcode"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050068
Brad Bishop6e60e8b2018-02-01 10:27:11 -050069SSTATE_SCAN_FILES ?= "*.la *-config *_config postinst-*"
70SSTATE_SCAN_CMD ??= 'find ${SSTATE_BUILDDIR} \( -name "${@"\" -o -name \"".join(d.getVar("SSTATE_SCAN_FILES").split())}" \) -type f'
71SSTATE_SCAN_CMD_NATIVE ??= 'grep -Irl -e ${RECIPE_SYSROOT} -e ${RECIPE_SYSROOT_NATIVE} -e ${HOSTTOOLS_DIR} ${SSTATE_BUILDDIR}'
Patrick Williams93c203f2021-10-06 16:15:23 -050072SSTATE_HASHEQUIV_FILEMAP ?= " \
73 populate_sysroot:*/postinst-useradd-*:${TMPDIR} \
74 populate_sysroot:*/postinst-useradd-*:${COREBASE} \
75 populate_sysroot:*/postinst-useradd-*:regex-\s(PATH|PSEUDO_IGNORE_PATHS|HOME|LOGNAME|OMP_NUM_THREADS|USER)=.*\s \
76 populate_sysroot:*/crossscripts/*:${TMPDIR} \
77 populate_sysroot:*/crossscripts/*:${COREBASE} \
78 "
Patrick Williamsc124f4f2015-09-15 14:41:29 -050079
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050080BB_HASHFILENAME = "False ${SSTATE_PKGSPEC} ${SSTATE_SWSPEC}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050081
82SSTATE_ARCHS = " \
83 ${BUILD_ARCH} \
Andrew Geissler6ce62a22020-11-30 19:58:47 -060084 ${BUILD_ARCH}_${ORIGNATIVELSBSTRING} \
Patrick Williamsc124f4f2015-09-15 14:41:29 -050085 ${BUILD_ARCH}_${SDK_ARCH}_${SDK_OS} \
86 ${BUILD_ARCH}_${TARGET_ARCH} \
87 ${SDK_ARCH}_${SDK_OS} \
88 ${SDK_ARCH}_${PACKAGE_ARCH} \
89 allarch \
90 ${PACKAGE_ARCH} \
Brad Bishop316dfdd2018-06-25 12:45:53 -040091 ${PACKAGE_EXTRA_ARCHS} \
92 ${MACHINE_ARCH}"
Andrew Geissler6ce62a22020-11-30 19:58:47 -060093SSTATE_ARCHS[vardepsexclude] = "ORIGNATIVELSBSTRING"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050094
95SSTATE_MANMACH ?= "${SSTATE_PKGARCH}"
96
97SSTATECREATEFUNCS = "sstate_hardcode_path"
Brad Bishop19323692019-04-05 15:28:33 -040098SSTATECREATEFUNCS[vardeps] = "SSTATE_SCAN_FILES"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050099SSTATEPOSTCREATEFUNCS = ""
100SSTATEPREINSTFUNCS = ""
101SSTATEPOSTUNPACKFUNCS = "sstate_hardcode_path_unpack"
102SSTATEPOSTINSTFUNCS = ""
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500103EXTRA_STAGING_FIXMES ?= "HOSTTOOLS_DIR"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500104
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500105# Check whether sstate exists for tasks that support sstate and are in the
106# locked signatures file.
107SIGGEN_LOCKEDSIGS_SSTATE_EXISTS_CHECK ?= 'error'
108
109# Check whether the task's computed hash matches the task's hash in the
110# locked signatures file.
111SIGGEN_LOCKEDSIGS_TASKSIG_CHECK ?= "error"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500112
113# The GnuPG key ID and passphrase to use to sign sstate archives (or unset to
114# not sign)
115SSTATE_SIG_KEY ?= ""
116SSTATE_SIG_PASSPHRASE ?= ""
117# Whether to verify the GnUPG signatures when extracting sstate archives
118SSTATE_VERIFY_SIG ?= "0"
Andrew Geisslereff27472021-10-29 15:35:00 -0500119# List of signatures to consider valid.
120SSTATE_VALID_SIGS ??= ""
121SSTATE_VALID_SIGS[vardepvalue] = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500122
Brad Bishop19323692019-04-05 15:28:33 -0400123SSTATE_HASHEQUIV_METHOD ?= "oe.sstatesig.OEOuthashBasic"
124SSTATE_HASHEQUIV_METHOD[doc] = "The fully-qualified function used to calculate \
125 the output hash for a task, which in turn is used to determine equivalency. \
126 "
127
Brad Bishop19323692019-04-05 15:28:33 -0400128SSTATE_HASHEQUIV_REPORT_TASKDATA ?= "0"
129SSTATE_HASHEQUIV_REPORT_TASKDATA[doc] = "Report additional useful data to the \
130 hash equivalency server, such as PN, PV, taskname, etc. This information \
131 is very useful for developers looking at task data, but may leak sensitive \
132 data if the equivalence server is public. \
133 "
134
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500135python () {
136 if bb.data.inherits_class('native', d):
137 d.setVar('SSTATE_PKGARCH', d.getVar('BUILD_ARCH', False))
138 elif bb.data.inherits_class('crosssdk', d):
139 d.setVar('SSTATE_PKGARCH', d.expand("${BUILD_ARCH}_${SDK_ARCH}_${SDK_OS}"))
140 elif bb.data.inherits_class('cross', d):
141 d.setVar('SSTATE_PKGARCH', d.expand("${BUILD_ARCH}_${TARGET_ARCH}"))
142 elif bb.data.inherits_class('nativesdk', d):
143 d.setVar('SSTATE_PKGARCH', d.expand("${SDK_ARCH}_${SDK_OS}"))
144 elif bb.data.inherits_class('cross-canadian', d):
145 d.setVar('SSTATE_PKGARCH', d.expand("${SDK_ARCH}_${PACKAGE_ARCH}"))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500146 elif bb.data.inherits_class('allarch', d) and d.getVar("PACKAGE_ARCH") == "all":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500147 d.setVar('SSTATE_PKGARCH', "allarch")
148 else:
149 d.setVar('SSTATE_MANMACH', d.expand("${PACKAGE_ARCH}"))
150
151 if bb.data.inherits_class('native', d) or bb.data.inherits_class('crosssdk', d) or bb.data.inherits_class('cross', d):
152 d.setVar('SSTATE_EXTRAPATH', "${NATIVELSBSTRING}/")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500153 d.setVar('BB_HASHFILENAME', "True ${SSTATE_PKGSPEC} ${SSTATE_SWSPEC}")
Brad Bishop19323692019-04-05 15:28:33 -0400154 d.setVar('SSTATE_EXTRAPATHWILDCARD', "${NATIVELSBSTRING}/")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500155
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500156 unique_tasks = sorted(set((d.getVar('SSTATETASKS') or "").split()))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500157 d.setVar('SSTATETASKS', " ".join(unique_tasks))
158 for task in unique_tasks:
159 d.prependVarFlag(task, 'prefuncs', "sstate_task_prefunc ")
160 d.appendVarFlag(task, 'postfuncs', " sstate_task_postfunc")
Andrew Geissler595f6302022-01-24 19:11:47 +0000161 d.setVarFlag(task, 'network', '1')
162 d.setVarFlag(task + "_setscene", 'network', '1')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500163}
164
165def sstate_init(task, d):
166 ss = {}
167 ss['task'] = task
168 ss['dirs'] = []
169 ss['plaindirs'] = []
170 ss['lockfiles'] = []
171 ss['lockfiles-shared'] = []
172 return ss
173
174def sstate_state_fromvars(d, task = None):
175 if task is None:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500176 task = d.getVar('BB_CURRENTTASK')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500177 if not task:
178 bb.fatal("sstate code running without task context?!")
179 task = task.replace("_setscene", "")
180
181 if task.startswith("do_"):
182 task = task[3:]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500183 inputs = (d.getVarFlag("do_" + task, 'sstate-inputdirs') or "").split()
184 outputs = (d.getVarFlag("do_" + task, 'sstate-outputdirs') or "").split()
185 plaindirs = (d.getVarFlag("do_" + task, 'sstate-plaindirs') or "").split()
186 lockfiles = (d.getVarFlag("do_" + task, 'sstate-lockfile') or "").split()
187 lockfilesshared = (d.getVarFlag("do_" + task, 'sstate-lockfile-shared') or "").split()
188 interceptfuncs = (d.getVarFlag("do_" + task, 'sstate-interceptfuncs') or "").split()
189 fixmedir = d.getVarFlag("do_" + task, 'sstate-fixmedir') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500190 if not task or len(inputs) != len(outputs):
191 bb.fatal("sstate variables not setup correctly?!")
192
193 if task == "populate_lic":
194 d.setVar("SSTATE_PKGSPEC", "${SSTATE_SWSPEC}")
195 d.setVar("SSTATE_EXTRAPATH", "")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500196 d.setVar('SSTATE_EXTRAPATHWILDCARD', "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500197
198 ss = sstate_init(task, d)
199 for i in range(len(inputs)):
200 sstate_add(ss, inputs[i], outputs[i], d)
201 ss['lockfiles'] = lockfiles
202 ss['lockfiles-shared'] = lockfilesshared
203 ss['plaindirs'] = plaindirs
204 ss['interceptfuncs'] = interceptfuncs
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500205 ss['fixmedir'] = fixmedir
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500206 return ss
207
208def sstate_add(ss, source, dest, d):
209 if not source.endswith("/"):
210 source = source + "/"
211 if not dest.endswith("/"):
212 dest = dest + "/"
213 source = os.path.normpath(source)
214 dest = os.path.normpath(dest)
215 srcbase = os.path.basename(source)
216 ss['dirs'].append([srcbase, source, dest])
217 return ss
218
219def sstate_install(ss, d):
220 import oe.path
221 import oe.sstatesig
222 import subprocess
223
224 sharedfiles = []
225 shareddirs = []
226 bb.utils.mkdirhier(d.expand("${SSTATE_MANIFESTS}"))
227
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500228 sstateinst = d.expand("${WORKDIR}/sstate-install-%s/" % ss['task'])
229
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500230 manifest, d2 = oe.sstatesig.sstate_get_manifest_filename(ss['task'], d)
231
232 if os.access(manifest, os.R_OK):
233 bb.fatal("Package already staged (%s)?!" % manifest)
234
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600235 d.setVar("SSTATE_INST_POSTRM", manifest + ".postrm")
236
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500237 locks = []
238 for lock in ss['lockfiles-shared']:
239 locks.append(bb.utils.lockfile(lock, True))
240 for lock in ss['lockfiles']:
241 locks.append(bb.utils.lockfile(lock))
242
243 for state in ss['dirs']:
244 bb.debug(2, "Staging files from %s to %s" % (state[1], state[2]))
245 for walkroot, dirs, files in os.walk(state[1]):
246 for file in files:
247 srcpath = os.path.join(walkroot, file)
248 dstpath = srcpath.replace(state[1], state[2])
249 #bb.debug(2, "Staging %s to %s" % (srcpath, dstpath))
250 sharedfiles.append(dstpath)
251 for dir in dirs:
252 srcdir = os.path.join(walkroot, dir)
253 dstdir = srcdir.replace(state[1], state[2])
254 #bb.debug(2, "Staging %s to %s" % (srcdir, dstdir))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500255 if os.path.islink(srcdir):
256 sharedfiles.append(dstdir)
257 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500258 if not dstdir.endswith("/"):
259 dstdir = dstdir + "/"
260 shareddirs.append(dstdir)
261
262 # Check the file list for conflicts against files which already exist
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500263 whitelist = (d.getVar("SSTATE_DUPWHITELIST") or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500264 match = []
265 for f in sharedfiles:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500266 if os.path.exists(f) and not os.path.islink(f):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500267 f = os.path.normpath(f)
268 realmatch = True
269 for w in whitelist:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600270 w = os.path.normpath(w)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500271 if f.startswith(w):
272 realmatch = False
273 break
274 if realmatch:
275 match.append(f)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500276 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 -0500277 search_output = subprocess.Popen(sstate_search_cmd, shell=True, stdout=subprocess.PIPE).communicate()[0]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500278 if search_output:
279 match.append(" (matched in %s)" % search_output.decode('utf-8').rstrip())
280 else:
281 match.append(" (not matched to any task)")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500282 if match:
283 bb.error("The recipe %s is trying to install files into a shared " \
284 "area when those files already exist. Those files and their manifest " \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500285 "location are:\n %s\nPlease verify which recipe should provide the " \
286 "above files.\n\nThe build has stopped, as continuing in this scenario WILL " \
287 "break things - if not now, possibly in the future (we've seen builds fail " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500288 "several months later). If the system knew how to recover from this " \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500289 "automatically it would, however there are several different scenarios " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500290 "which can result in this and we don't know which one this is. It may be " \
291 "you have switched providers of something like virtual/kernel (e.g. from " \
292 "linux-yocto to linux-yocto-dev), in that case you need to execute the " \
293 "clean task for both recipes and it will resolve this error. It may be " \
294 "you changed DISTRO_FEATURES from systemd to udev or vice versa. Cleaning " \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500295 "those recipes should again resolve this error, however switching " \
296 "DISTRO_FEATURES on an existing build directory is not supported - you " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500297 "should really clean out tmp and rebuild (reusing sstate should be safe). " \
298 "It could be the overlapping files detected are harmless in which case " \
299 "adding them to SSTATE_DUPWHITELIST may be the correct solution. It could " \
300 "also be your build is including two different conflicting versions of " \
301 "things (e.g. bluez 4 and bluez 5 and the correct solution for that would " \
302 "be to resolve the conflict. If in doubt, please ask on the mailing list, " \
303 "sharing the error and filelist above." % \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500304 (d.getVar('PN'), "\n ".join(match)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500305 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.")
306
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500307 if ss['fixmedir'] and os.path.exists(ss['fixmedir'] + "/fixmepath.cmd"):
308 sharedfiles.append(ss['fixmedir'] + "/fixmepath.cmd")
309 sharedfiles.append(ss['fixmedir'] + "/fixmepath")
310
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500311 # Write out the manifest
312 f = open(manifest, "w")
313 for file in sharedfiles:
314 f.write(file + "\n")
315
316 # We want to ensure that directories appear at the end of the manifest
317 # so that when we test to see if they should be deleted any contents
318 # added by the task will have been removed first.
319 dirs = sorted(shareddirs, key=len)
320 # Must remove children first, which will have a longer path than the parent
321 for di in reversed(dirs):
322 f.write(di + "\n")
323 f.close()
324
325 # Append to the list of manifests for this PACKAGE_ARCH
326
327 i = d2.expand("${SSTATE_MANIFESTS}/index-${SSTATE_MANMACH}")
328 l = bb.utils.lockfile(i + ".lock")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500329 filedata = d.getVar("STAMP") + " " + d2.getVar("SSTATE_MANFILEPREFIX") + " " + d.getVar("WORKDIR") + "\n"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500330 manifests = []
331 if os.path.exists(i):
332 with open(i, "r") as f:
333 manifests = f.readlines()
William A. Kennington IIIac69b482021-06-02 12:28:27 -0700334 # We append new entries, we don't remove older entries which may have the same
335 # manifest name but different versions from stamp/workdir. See below.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500336 if filedata not in manifests:
337 with open(i, "a+") as f:
338 f.write(filedata)
339 bb.utils.unlockfile(l)
340
341 # Run the actual file install
342 for state in ss['dirs']:
343 if os.path.exists(state[1]):
344 oe.path.copyhardlinktree(state[1], state[2])
345
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500346 for postinst in (d.getVar('SSTATEPOSTINSTFUNCS') or '').split():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500347 # All hooks should run in the SSTATE_INSTDIR
348 bb.build.exec_func(postinst, d, (sstateinst,))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500349
350 for lock in locks:
351 bb.utils.unlockfile(lock)
352
353sstate_install[vardepsexclude] += "SSTATE_DUPWHITELIST STATE_MANMACH SSTATE_MANFILEPREFIX"
354sstate_install[vardeps] += "${SSTATEPOSTINSTFUNCS}"
355
356def sstate_installpkg(ss, d):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500357 from oe.gpg_sign import get_signer
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500358
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500359 sstateinst = d.expand("${WORKDIR}/sstate-install-%s/" % ss['task'])
Andrew Geissler82c905d2020-04-13 13:39:40 -0500360 d.setVar("SSTATE_CURRTASK", ss['task'])
361 sstatefetch = d.getVar('SSTATE_PKGNAME')
362 sstatepkg = d.getVar('SSTATE_PKG')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500363
364 if not os.path.exists(sstatepkg):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800365 pstaging_fetch(sstatefetch, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500366
367 if not os.path.isfile(sstatepkg):
Brad Bishop08902b02019-08-20 09:16:51 -0400368 bb.note("Sstate package %s does not exist" % sstatepkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500369 return False
370
371 sstate_clean(ss, d)
372
373 d.setVar('SSTATE_INSTDIR', sstateinst)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500374
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500375 if bb.utils.to_boolean(d.getVar("SSTATE_VERIFY_SIG"), False):
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500376 if not os.path.isfile(sstatepkg + '.sig'):
377 bb.warn("No signature file for sstate package %s, skipping acceleration..." % sstatepkg)
378 return False
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500379 signer = get_signer(d, 'local')
Andrew Geisslereff27472021-10-29 15:35:00 -0500380 if not signer.verify(sstatepkg + '.sig', d.getVar("SSTATE_VALID_SIGS")):
Brad Bishop08902b02019-08-20 09:16:51 -0400381 bb.warn("Cannot verify signature on sstate package %s, skipping acceleration..." % sstatepkg)
382 return False
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500383
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500384 # Empty sstateinst directory, ensure its clean
385 if os.path.exists(sstateinst):
386 oe.path.remove(sstateinst)
387 bb.utils.mkdirhier(sstateinst)
388
389 sstateinst = d.getVar("SSTATE_INSTDIR")
390 d.setVar('SSTATE_FIXMEDIR', ss['fixmedir'])
391
392 for f in (d.getVar('SSTATEPREINSTFUNCS') or '').split() + ['sstate_unpack_package']:
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500393 # All hooks should run in the SSTATE_INSTDIR
394 bb.build.exec_func(f, d, (sstateinst,))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500395
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500396 return sstate_installpkgdir(ss, d)
397
398def sstate_installpkgdir(ss, d):
399 import oe.path
400 import subprocess
401
402 sstateinst = d.getVar("SSTATE_INSTDIR")
403 d.setVar('SSTATE_FIXMEDIR', ss['fixmedir'])
404
405 for f in (d.getVar('SSTATEPOSTUNPACKFUNCS') or '').split():
406 # All hooks should run in the SSTATE_INSTDIR
407 bb.build.exec_func(f, d, (sstateinst,))
408
409 def prepdir(dir):
410 # remove dir if it exists, ensure any parent directories do exist
411 if os.path.exists(dir):
412 oe.path.remove(dir)
413 bb.utils.mkdirhier(dir)
414 oe.path.remove(dir)
415
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500416 for state in ss['dirs']:
417 prepdir(state[1])
Andrew Geisslerc926e172021-05-07 16:11:35 -0500418 bb.utils.rename(sstateinst + state[0], state[1])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500419 sstate_install(ss, d)
420
421 for plain in ss['plaindirs']:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500422 workdir = d.getVar('WORKDIR')
Brad Bishop977dc1a2019-02-06 16:01:43 -0500423 sharedworkdir = os.path.join(d.getVar('TMPDIR'), "work-shared")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500424 src = sstateinst + "/" + plain.replace(workdir, '')
Brad Bishop977dc1a2019-02-06 16:01:43 -0500425 if sharedworkdir in plain:
426 src = sstateinst + "/" + plain.replace(sharedworkdir, '')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500427 dest = plain
428 bb.utils.mkdirhier(src)
429 prepdir(dest)
Andrew Geisslerc926e172021-05-07 16:11:35 -0500430 bb.utils.rename(src, dest)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500431
432 return True
433
434python sstate_hardcode_path_unpack () {
435 # Fixup hardcoded paths
436 #
437 # Note: The logic below must match the reverse logic in
438 # sstate_hardcode_path(d)
439 import subprocess
440
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500441 sstateinst = d.getVar('SSTATE_INSTDIR')
442 sstatefixmedir = d.getVar('SSTATE_FIXMEDIR')
443 fixmefn = sstateinst + "fixmepath"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500444 if os.path.isfile(fixmefn):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500445 staging_target = d.getVar('RECIPE_SYSROOT')
446 staging_host = d.getVar('RECIPE_SYSROOT_NATIVE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500447
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500448 if bb.data.inherits_class('native', d) or bb.data.inherits_class('cross-canadian', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500449 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRHOST:%s:g'" % (staging_host)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500450 elif bb.data.inherits_class('cross', d) or bb.data.inherits_class('crosssdk', d):
451 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRTARGET:%s:g; s:FIXMESTAGINGDIRHOST:%s:g'" % (staging_target, staging_host)
452 else:
453 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRTARGET:%s:g'" % (staging_target)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500454
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500455 extra_staging_fixmes = d.getVar('EXTRA_STAGING_FIXMES') or ''
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500456 for fixmevar in extra_staging_fixmes.split():
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500457 fixme_path = d.getVar(fixmevar)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500458 sstate_sed_cmd += " -e 's:FIXME_%s:%s:g'" % (fixmevar, fixme_path)
459
460 # Add sstateinst to each filename in fixmepath, use xargs to efficiently call sed
461 sstate_hardcode_cmd = "sed -e 's:^:%s:g' %s | xargs %s" % (sstateinst, fixmefn, sstate_sed_cmd)
462
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500463 # Defer do_populate_sysroot relocation command
464 if sstatefixmedir:
465 bb.utils.mkdirhier(sstatefixmedir)
466 with open(sstatefixmedir + "/fixmepath.cmd", "w") as f:
467 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(fixmefn, sstatefixmedir + "/fixmepath")
468 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(sstateinst, "FIXMEFINALSSTATEINST")
469 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(staging_host, "FIXMEFINALSSTATEHOST")
470 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(staging_target, "FIXMEFINALSSTATETARGET")
471 f.write(sstate_hardcode_cmd)
472 bb.utils.copyfile(fixmefn, sstatefixmedir + "/fixmepath")
473 return
474
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500475 bb.note("Replacing fixme paths in sstate package: %s" % (sstate_hardcode_cmd))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500476 subprocess.check_call(sstate_hardcode_cmd, shell=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500477
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800478 # Need to remove this or we'd copy it into the target directory and may
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500479 # conflict with another writer
480 os.remove(fixmefn)
481}
482
483def sstate_clean_cachefile(ss, d):
484 import oe.path
485
Brad Bishopa5c52ff2018-11-23 10:55:50 +1300486 if d.getVarFlag('do_%s' % ss['task'], 'task'):
Andrew Geissler82c905d2020-04-13 13:39:40 -0500487 d.setVar("SSTATE_PATH_CURRTASK", ss['task'])
488 sstatepkgfile = d.getVar('SSTATE_PATHSPEC')
Brad Bishopa5c52ff2018-11-23 10:55:50 +1300489 bb.note("Removing %s" % sstatepkgfile)
490 oe.path.remove(sstatepkgfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500491
492def sstate_clean_cachefiles(d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500493 for task in (d.getVar('SSTATETASKS') or "").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500494 ld = d.createCopy()
495 ss = sstate_state_fromvars(ld, task)
496 sstate_clean_cachefile(ss, ld)
497
Andrew Geissler5f350902021-07-23 13:09:54 -0400498def sstate_clean_manifest(manifest, d, canrace=False, prefix=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500499 import oe.path
500
501 mfile = open(manifest)
502 entries = mfile.readlines()
503 mfile.close()
504
505 for entry in entries:
506 entry = entry.strip()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500507 if prefix and not entry.startswith("/"):
508 entry = prefix + "/" + entry
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500509 bb.debug(2, "Removing manifest: %s" % entry)
510 # We can race against another package populating directories as we're removing them
511 # so we ignore errors here.
512 try:
513 if entry.endswith("/"):
514 if os.path.islink(entry[:-1]):
515 os.remove(entry[:-1])
Andrew Geissler5f350902021-07-23 13:09:54 -0400516 elif os.path.exists(entry) and len(os.listdir(entry)) == 0 and not canrace:
517 # Removing directories whilst builds are in progress exposes a race. Only
518 # do it in contexts where it is safe to do so.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500519 os.rmdir(entry[:-1])
520 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500521 os.remove(entry)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500522 except OSError:
523 pass
524
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600525 postrm = manifest + ".postrm"
526 if os.path.exists(manifest + ".postrm"):
527 import subprocess
528 os.chmod(postrm, 0o755)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500529 subprocess.check_call(postrm, shell=True)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600530 oe.path.remove(postrm)
531
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500532 oe.path.remove(manifest)
533
534def sstate_clean(ss, d):
535 import oe.path
536 import glob
537
538 d2 = d.createCopy()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500539 stamp_clean = d.getVar("STAMPCLEAN")
540 extrainf = d.getVarFlag("do_" + ss['task'], 'stamp-extra-info')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500541 if extrainf:
542 d2.setVar("SSTATE_MANMACH", extrainf)
543 wildcard_stfile = "%s.do_%s*.%s" % (stamp_clean, ss['task'], extrainf)
544 else:
545 wildcard_stfile = "%s.do_%s*" % (stamp_clean, ss['task'])
546
547 manifest = d2.expand("${SSTATE_MANFILEPREFIX}.%s" % ss['task'])
548
549 if os.path.exists(manifest):
550 locks = []
551 for lock in ss['lockfiles-shared']:
552 locks.append(bb.utils.lockfile(lock))
553 for lock in ss['lockfiles']:
554 locks.append(bb.utils.lockfile(lock))
555
Andrew Geissler5f350902021-07-23 13:09:54 -0400556 sstate_clean_manifest(manifest, d, canrace=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500557
558 for lock in locks:
559 bb.utils.unlockfile(lock)
560
561 # Remove the current and previous stamps, but keep the sigdata.
562 #
563 # The glob() matches do_task* which may match multiple tasks, for
564 # example: do_package and do_package_write_ipk, so we need to
565 # exactly match *.do_task.* and *.do_task_setscene.*
566 rm_stamp = '.do_%s.' % ss['task']
567 rm_setscene = '.do_%s_setscene.' % ss['task']
568 # For BB_SIGNATURE_HANDLER = "noop"
569 rm_nohash = ".do_%s" % ss['task']
570 for stfile in glob.glob(wildcard_stfile):
571 # Keep the sigdata
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500572 if ".sigdata." in stfile or ".sigbasedata." in stfile:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500573 continue
574 # Preserve taint files in the stamps directory
575 if stfile.endswith('.taint'):
576 continue
577 if rm_stamp in stfile or rm_setscene in stfile or \
578 stfile.endswith(rm_nohash):
579 oe.path.remove(stfile)
580
581sstate_clean[vardepsexclude] = "SSTATE_MANFILEPREFIX"
582
583CLEANFUNCS += "sstate_cleanall"
584
585python sstate_cleanall() {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500586 bb.note("Removing shared state for package %s" % d.getVar('PN'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500587
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500588 manifest_dir = d.getVar('SSTATE_MANIFESTS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500589 if not os.path.exists(manifest_dir):
590 return
591
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500592 tasks = d.getVar('SSTATETASKS').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500593 for name in tasks:
594 ld = d.createCopy()
595 shared_state = sstate_state_fromvars(ld, name)
596 sstate_clean(shared_state, ld)
597}
598
599python sstate_hardcode_path () {
600 import subprocess, platform
601
602 # Need to remove hardcoded paths and fix these when we install the
603 # staging packages.
604 #
605 # Note: the logic in this function needs to match the reverse logic
606 # in sstate_installpkg(ss, d)
607
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500608 staging_target = d.getVar('RECIPE_SYSROOT')
609 staging_host = d.getVar('RECIPE_SYSROOT_NATIVE')
610 sstate_builddir = d.getVar('SSTATE_BUILDDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500611
Brad Bishop316dfdd2018-06-25 12:45:53 -0400612 sstate_sed_cmd = "sed -i -e 's:%s:FIXMESTAGINGDIRHOST:g'" % staging_host
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500613 if bb.data.inherits_class('native', d) or bb.data.inherits_class('cross-canadian', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500614 sstate_grep_cmd = "grep -l -e '%s'" % (staging_host)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500615 elif bb.data.inherits_class('cross', d) or bb.data.inherits_class('crosssdk', d):
616 sstate_grep_cmd = "grep -l -e '%s' -e '%s'" % (staging_target, staging_host)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400617 sstate_sed_cmd += " -e 's:%s:FIXMESTAGINGDIRTARGET:g'" % staging_target
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500618 else:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400619 sstate_grep_cmd = "grep -l -e '%s' -e '%s'" % (staging_target, staging_host)
620 sstate_sed_cmd += " -e 's:%s:FIXMESTAGINGDIRTARGET:g'" % staging_target
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500621
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500622 extra_staging_fixmes = d.getVar('EXTRA_STAGING_FIXMES') or ''
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500623 for fixmevar in extra_staging_fixmes.split():
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500624 fixme_path = d.getVar(fixmevar)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500625 sstate_sed_cmd += " -e 's:%s:FIXME_%s:g'" % (fixme_path, fixmevar)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500626 sstate_grep_cmd += " -e '%s'" % (fixme_path)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500627
628 fixmefn = sstate_builddir + "fixmepath"
629
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500630 sstate_scan_cmd = d.getVar('SSTATE_SCAN_CMD')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500631 sstate_filelist_cmd = "tee %s" % (fixmefn)
632
633 # fixmepath file needs relative paths, drop sstate_builddir prefix
634 sstate_filelist_relative_cmd = "sed -i -e 's:^%s::g' %s" % (sstate_builddir, fixmefn)
635
636 xargs_no_empty_run_cmd = '--no-run-if-empty'
637 if platform.system() == 'Darwin':
638 xargs_no_empty_run_cmd = ''
639
640 # Limit the fixpaths and sed operations based on the initial grep search
641 # This has the side effect of making sure the vfs cache is hot
642 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)
643
644 bb.note("Removing hardcoded paths from sstate package: '%s'" % (sstate_hardcode_cmd))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500645 subprocess.check_output(sstate_hardcode_cmd, shell=True, cwd=sstate_builddir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500646
647 # If the fixmefn is empty, remove it..
648 if os.stat(fixmefn).st_size == 0:
649 os.remove(fixmefn)
650 else:
651 bb.note("Replacing absolute paths in fixmepath file: '%s'" % (sstate_filelist_relative_cmd))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500652 subprocess.check_output(sstate_filelist_relative_cmd, shell=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500653}
654
655def sstate_package(ss, d):
656 import oe.path
Andrew Geissler5199d832021-09-24 16:47:35 -0500657 import time
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500658
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500659 tmpdir = d.getVar('TMPDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500660
Andrew Geissler5199d832021-09-24 16:47:35 -0500661 fixtime = False
662 if ss['task'] == "package":
663 fixtime = True
664
665 def fixtimestamp(root, path):
666 f = os.path.join(root, path)
667 if os.lstat(f).st_mtime > sde:
668 os.utime(f, (sde, sde), follow_symlinks=False)
669
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500670 sstatebuild = d.expand("${WORKDIR}/sstate-build-%s/" % ss['task'])
Andrew Geissler5199d832021-09-24 16:47:35 -0500671 sde = int(d.getVar("SOURCE_DATE_EPOCH") or time.time())
Andrew Geissler82c905d2020-04-13 13:39:40 -0500672 d.setVar("SSTATE_CURRTASK", ss['task'])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500673 bb.utils.remove(sstatebuild, recurse=True)
674 bb.utils.mkdirhier(sstatebuild)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500675 for state in ss['dirs']:
676 if not os.path.exists(state[1]):
677 continue
678 srcbase = state[0].rstrip("/").rsplit('/', 1)[0]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500679 # Find and error for absolute symlinks. We could attempt to relocate but its not
680 # clear where the symlink is relative to in this context. We could add that markup
681 # to sstate tasks but there aren't many of these so better just avoid them entirely.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500682 for walkroot, dirs, files in os.walk(state[1]):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500683 for file in files + dirs:
Andrew Geissler5199d832021-09-24 16:47:35 -0500684 if fixtime:
685 fixtimestamp(walkroot, file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500686 srcpath = os.path.join(walkroot, file)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500687 if not os.path.islink(srcpath):
688 continue
689 link = os.readlink(srcpath)
690 if not os.path.isabs(link):
691 continue
692 if not link.startswith(tmpdir):
693 continue
694 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 -0500695 bb.debug(2, "Preparing tree %s for packaging at %s" % (state[1], sstatebuild + state[0]))
Andrew Geisslerc926e172021-05-07 16:11:35 -0500696 bb.utils.rename(state[1], sstatebuild + state[0])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500697
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500698 workdir = d.getVar('WORKDIR')
Brad Bishop977dc1a2019-02-06 16:01:43 -0500699 sharedworkdir = os.path.join(d.getVar('TMPDIR'), "work-shared")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500700 for plain in ss['plaindirs']:
701 pdir = plain.replace(workdir, sstatebuild)
Brad Bishop977dc1a2019-02-06 16:01:43 -0500702 if sharedworkdir in plain:
703 pdir = plain.replace(sharedworkdir, sstatebuild)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500704 bb.utils.mkdirhier(plain)
705 bb.utils.mkdirhier(pdir)
Andrew Geisslerc926e172021-05-07 16:11:35 -0500706 bb.utils.rename(plain, pdir)
Andrew Geissler5199d832021-09-24 16:47:35 -0500707 if fixtime:
708 fixtimestamp(pdir, "")
709 for walkroot, dirs, files in os.walk(pdir):
710 for file in files + dirs:
711 fixtimestamp(walkroot, file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500712
713 d.setVar('SSTATE_BUILDDIR', sstatebuild)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500714 d.setVar('SSTATE_INSTDIR', sstatebuild)
715
716 if d.getVar('SSTATE_SKIP_CREATION') == '1':
717 return
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500718
Brad Bishop08902b02019-08-20 09:16:51 -0400719 sstate_create_package = ['sstate_report_unihash', 'sstate_create_package']
720 if d.getVar('SSTATE_SIG_KEY'):
721 sstate_create_package.append('sstate_sign_package')
722
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500723 for f in (d.getVar('SSTATECREATEFUNCS') or '').split() + \
Brad Bishop08902b02019-08-20 09:16:51 -0400724 sstate_create_package + \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500725 (d.getVar('SSTATEPOSTCREATEFUNCS') or '').split():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500726 # All hooks should run in SSTATE_BUILDDIR.
727 bb.build.exec_func(f, d, (sstatebuild,))
728
Andrew Geissler82c905d2020-04-13 13:39:40 -0500729 # SSTATE_PKG may have been changed by sstate_report_unihash
730 siginfo = d.getVar('SSTATE_PKG') + ".siginfo"
731 if not os.path.exists(siginfo):
732 bb.siggen.dump_this_task(siginfo, d)
733 else:
Andrew Geisslerc182c622020-05-15 14:13:32 -0500734 try:
735 os.utime(siginfo, None)
736 except PermissionError:
737 pass
Andrew Geissler5f350902021-07-23 13:09:54 -0400738 except OSError as e:
739 # Handle read-only file systems gracefully
Patrick Williams0ca19cc2021-08-16 14:03:13 -0500740 import errno
Andrew Geissler5f350902021-07-23 13:09:54 -0400741 if e.errno != errno.EROFS:
742 raise e
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500743
744 return
745
William A. Kennington IIIac69b482021-06-02 12:28:27 -0700746sstate_package[vardepsexclude] += "SSTATE_SIG_KEY"
747
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800748def pstaging_fetch(sstatefetch, d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500749 import bb.fetch2
750
751 # Only try and fetch if the user has configured a mirror
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500752 mirrors = d.getVar('SSTATE_MIRRORS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500753 if not mirrors:
754 return
755
756 # Copy the data object and override DL_DIR and SRC_URI
757 localdata = bb.data.createCopy(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500758
759 dldir = localdata.expand("${SSTATE_DIR}")
760 bb.utils.mkdirhier(dldir)
761
762 localdata.delVar('MIRRORS')
763 localdata.setVar('FILESPATH', dldir)
764 localdata.setVar('DL_DIR', dldir)
765 localdata.setVar('PREMIRRORS', mirrors)
Andrew Geissler5199d832021-09-24 16:47:35 -0500766 localdata.setVar('SRCPV', d.getVar('SRCPV'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500767
768 # if BB_NO_NETWORK is set but we also have SSTATE_MIRROR_ALLOW_NETWORK,
769 # we'll want to allow network access for the current set of fetches.
Brad Bishopd89cb5f2019-04-10 09:02:41 -0400770 if bb.utils.to_boolean(localdata.getVar('BB_NO_NETWORK')) and \
771 bb.utils.to_boolean(localdata.getVar('SSTATE_MIRROR_ALLOW_NETWORK')):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500772 localdata.delVar('BB_NO_NETWORK')
773
774 # Try a fetch from the sstate mirror, if it fails just return and
775 # we will build the package
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600776 uris = ['file://{0};downloadfilename={0}'.format(sstatefetch),
777 'file://{0}.siginfo;downloadfilename={0}.siginfo'.format(sstatefetch)]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500778 if bb.utils.to_boolean(d.getVar("SSTATE_VERIFY_SIG"), False):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600779 uris += ['file://{0}.sig;downloadfilename={0}.sig'.format(sstatefetch)]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500780
781 for srcuri in uris:
782 localdata.setVar('SRC_URI', srcuri)
783 try:
784 fetcher = bb.fetch2.Fetch([srcuri], localdata, cache=False)
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500785 fetcher.checkstatus()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500786 fetcher.download()
787
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500788 except bb.fetch2.BBFetchException:
Andrew Geissler4ed12e12020-06-05 18:00:41 -0500789 pass
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500790
Andrew Geissler5199d832021-09-24 16:47:35 -0500791pstaging_fetch[vardepsexclude] += "SRCPV"
792
793
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500794def sstate_setscene(d):
795 shared_state = sstate_state_fromvars(d)
796 accelerate = sstate_installpkg(shared_state, d)
797 if not accelerate:
Andrew Geissler595f6302022-01-24 19:11:47 +0000798 msg = "No sstate archive obtainable, will run full task instead."
799 bb.warn(msg)
800 raise bb.BBHandledException(msg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500801
802python sstate_task_prefunc () {
803 shared_state = sstate_state_fromvars(d)
804 sstate_clean(shared_state, d)
805}
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500806sstate_task_prefunc[dirs] = "${WORKDIR}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500807
808python sstate_task_postfunc () {
809 shared_state = sstate_state_fromvars(d)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500810
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500811 for intercept in shared_state['interceptfuncs']:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500812 bb.build.exec_func(intercept, d, (d.getVar("WORKDIR"),))
813
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600814 omask = os.umask(0o002)
815 if omask != 0o002:
816 bb.note("Using umask 0o002 (not %0o) for sstate packaging" % omask)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500817 sstate_package(shared_state, d)
818 os.umask(omask)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500819
820 sstateinst = d.getVar("SSTATE_INSTDIR")
821 d.setVar('SSTATE_FIXMEDIR', shared_state['fixmedir'])
822
823 sstate_installpkgdir(shared_state, d)
824
825 bb.utils.remove(d.getVar("SSTATE_BUILDDIR"), recurse=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500826}
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500827sstate_task_postfunc[dirs] = "${WORKDIR}"
828
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500829
830#
831# Shell function to generate a sstate package from a directory
832# set as SSTATE_BUILDDIR. Will be run from within SSTATE_BUILDDIR.
833#
834sstate_create_package () {
Andrew Geissler82c905d2020-04-13 13:39:40 -0500835 # Exit early if it already exists
Brad Bishop08902b02019-08-20 09:16:51 -0400836 if [ -e ${SSTATE_PKG} ]; then
Andrew Geisslereff27472021-10-29 15:35:00 -0500837 touch ${SSTATE_PKG} 2>/dev/null || true
Brad Bishop08902b02019-08-20 09:16:51 -0400838 return
839 fi
840
Andrew Geisslerc3d88e42020-10-02 09:45:00 -0500841 mkdir --mode=0775 -p `dirname ${SSTATE_PKG}`
Andrew Geissler82c905d2020-04-13 13:39:40 -0500842 TFILE=`mktemp ${SSTATE_PKG}.XXXXXXXX`
843
Andrew Geisslereff27472021-10-29 15:35:00 -0500844 OPT="-cS"
845 ZSTD="zstd -${SSTATE_ZSTD_CLEVEL} -T${ZSTD_THREADS}"
846 # Use pzstd if available
847 if [ -x "$(command -v pzstd)" ]; then
848 ZSTD="pzstd -${SSTATE_ZSTD_CLEVEL} -p ${ZSTD_THREADS}"
Andrew Geissler82c905d2020-04-13 13:39:40 -0500849 fi
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800850
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500851 # Need to handle empty directories
852 if [ "$(ls -A)" ]; then
853 set +e
Andrew Geisslereff27472021-10-29 15:35:00 -0500854 tar -I "$ZSTD" $OPT -f $TFILE *
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500855 ret=$?
856 if [ $ret -ne 0 ] && [ $ret -ne 1 ]; then
857 exit 1
858 fi
859 set -e
860 else
Andrew Geisslereff27472021-10-29 15:35:00 -0500861 tar -I "$ZSTD" $OPT --file=$TFILE --files-from=/dev/null
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500862 fi
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500863 chmod 0664 $TFILE
Brad Bishop08902b02019-08-20 09:16:51 -0400864 # Skip if it was already created by some other process
865 if [ ! -e ${SSTATE_PKG} ]; then
Andrew Geissler82c905d2020-04-13 13:39:40 -0500866 # Move into place using ln to attempt an atomic op.
867 # Abort if it already exists
868 ln $TFILE ${SSTATE_PKG} && rm $TFILE
Brad Bishop08902b02019-08-20 09:16:51 -0400869 else
870 rm $TFILE
871 fi
Andrew Geisslereff27472021-10-29 15:35:00 -0500872 touch ${SSTATE_PKG} 2>/dev/null || true
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500873}
874
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500875python sstate_sign_package () {
876 from oe.gpg_sign import get_signer
877
Brad Bishop08902b02019-08-20 09:16:51 -0400878
879 signer = get_signer(d, 'local')
880 sstate_pkg = d.getVar('SSTATE_PKG')
881 if os.path.exists(sstate_pkg + '.sig'):
882 os.unlink(sstate_pkg + '.sig')
883 signer.detach_sign(sstate_pkg, d.getVar('SSTATE_SIG_KEY', False), None,
884 d.getVar('SSTATE_SIG_PASSPHRASE'), armor=False)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500885}
886
Brad Bishop19323692019-04-05 15:28:33 -0400887python sstate_report_unihash() {
888 report_unihash = getattr(bb.parse.siggen, 'report_unihash', None)
889
890 if report_unihash:
891 ss = sstate_state_fromvars(d)
892 report_unihash(os.getcwd(), ss['task'], d)
893}
894
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500895#
896# Shell function to decompress and prepare a package for installation
897# Will be run from within SSTATE_INSTDIR.
898#
899sstate_unpack_package () {
Andrew Geisslereff27472021-10-29 15:35:00 -0500900 ZSTD="zstd -T${ZSTD_THREADS}"
901 # Use pzstd if available
902 if [ -x "$(command -v pzstd)" ]; then
903 ZSTD="pzstd -p ${ZSTD_THREADS}"
904 fi
905
Andrew Geissler595f6302022-01-24 19:11:47 +0000906 tar -I "$ZSTD" -xvpf ${SSTATE_PKG}
907 # update .siginfo atime on local/NFS mirror if it is a symbolic link
908 [ ! -h ${SSTATE_PKG}.siginfo ] || touch -a ${SSTATE_PKG}.siginfo 2>/dev/null || true
909 # update each symbolic link instead of any referenced file
910 touch --no-dereference ${SSTATE_PKG} 2>/dev/null || true
911 [ ! -e ${SSTATE_PKG}.sig ] || touch --no-dereference ${SSTATE_PKG}.sig 2>/dev/null || true
912 [ ! -e ${SSTATE_PKG}.siginfo ] || touch --no-dereference ${SSTATE_PKG}.siginfo 2>/dev/null || true
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500913}
914
915BB_HASHCHECK_FUNCTION = "sstate_checkhashes"
916
Brad Bishop1d80a2e2019-11-15 16:35:03 -0500917def sstate_checkhashes(sq_data, d, siginfo=False, currentcount=0, summary=True, **kwargs):
Brad Bishop08902b02019-08-20 09:16:51 -0400918 found = set()
919 missed = set()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500920
Brad Bishop19323692019-04-05 15:28:33 -0400921 def gethash(task):
Brad Bishop08902b02019-08-20 09:16:51 -0400922 return sq_data['unihash'][task]
Brad Bishop19323692019-04-05 15:28:33 -0400923
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500924 def getpathcomponents(task, d):
925 # Magic data from BB_HASHFILENAME
Brad Bishop08902b02019-08-20 09:16:51 -0400926 splithashfn = sq_data['hashfn'][task].split(" ")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500927 spec = splithashfn[1]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500928 if splithashfn[0] == "True":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500929 extrapath = d.getVar("NATIVELSBSTRING") + "/"
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500930 else:
931 extrapath = ""
Brad Bishop08902b02019-08-20 09:16:51 -0400932
933 tname = bb.runqueue.taskname_from_tid(task)[3:]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500934
935 if tname in ["fetch", "unpack", "patch", "populate_lic", "preconfigure"] and splithashfn[2]:
936 spec = splithashfn[2]
937 extrapath = ""
938
939 return spec, extrapath, tname
940
Andrew Geissler595f6302022-01-24 19:11:47 +0000941 def getsstatefile(tid, siginfo, d):
942 spec, extrapath, tname = getpathcomponents(tid, d)
943 return extrapath + generate_sstatefn(spec, gethash(tid), tname, siginfo, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500944
Brad Bishop08902b02019-08-20 09:16:51 -0400945 for tid in sq_data['hash']:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500946
Andrew Geissler595f6302022-01-24 19:11:47 +0000947 sstatefile = d.expand("${SSTATE_DIR}/" + getsstatefile(tid, siginfo, d))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500948
949 if os.path.exists(sstatefile):
Brad Bishop08902b02019-08-20 09:16:51 -0400950 found.add(tid)
Andrew Geisslereff27472021-10-29 15:35:00 -0500951 bb.debug(2, "SState: Found valid sstate file %s" % sstatefile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500952 else:
Brad Bishop08902b02019-08-20 09:16:51 -0400953 missed.add(tid)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500954 bb.debug(2, "SState: Looked for but didn't find file %s" % sstatefile)
955
Andrew Geisslereff27472021-10-29 15:35:00 -0500956 foundLocal = len(found)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500957 mirrors = d.getVar("SSTATE_MIRRORS")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500958 if mirrors:
959 # Copy the data object and override DL_DIR and SRC_URI
960 localdata = bb.data.createCopy(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500961
962 dldir = localdata.expand("${SSTATE_DIR}")
963 localdata.delVar('MIRRORS')
964 localdata.setVar('FILESPATH', dldir)
965 localdata.setVar('DL_DIR', dldir)
966 localdata.setVar('PREMIRRORS', mirrors)
967
968 bb.debug(2, "SState using premirror of: %s" % mirrors)
969
970 # if BB_NO_NETWORK is set but we also have SSTATE_MIRROR_ALLOW_NETWORK,
971 # we'll want to allow network access for the current set of fetches.
Brad Bishopd89cb5f2019-04-10 09:02:41 -0400972 if bb.utils.to_boolean(localdata.getVar('BB_NO_NETWORK')) and \
973 bb.utils.to_boolean(localdata.getVar('SSTATE_MIRROR_ALLOW_NETWORK')):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500974 localdata.delVar('BB_NO_NETWORK')
975
976 from bb.fetch2 import FetchConnectionCache
977 def checkstatus_init(thread_worker):
978 thread_worker.connection_cache = FetchConnectionCache()
979
980 def checkstatus_end(thread_worker):
981 thread_worker.connection_cache.close_connections()
982
983 def checkstatus(thread_worker, arg):
Brad Bishop08902b02019-08-20 09:16:51 -0400984 (tid, sstatefile) = arg
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500985
986 localdata2 = bb.data.createCopy(localdata)
987 srcuri = "file://" + sstatefile
988 localdata.setVar('SRC_URI', srcuri)
989 bb.debug(2, "SState: Attempting to fetch %s" % srcuri)
990
991 try:
992 fetcher = bb.fetch2.Fetch(srcuri.split(), localdata2,
993 connection_cache=thread_worker.connection_cache)
994 fetcher.checkstatus()
995 bb.debug(2, "SState: Successful fetch test for %s" % srcuri)
Brad Bishop08902b02019-08-20 09:16:51 -0400996 found.add(tid)
Andrew Geissler595f6302022-01-24 19:11:47 +0000997 missed.remove(tid)
Andrew Geisslereff27472021-10-29 15:35:00 -0500998 except bb.fetch2.FetchError as e:
Andrew Geissler595f6302022-01-24 19:11:47 +0000999 bb.debug(2, "SState: Unsuccessful fetch test for %s (%s)" % (srcuri, repr(e)))
Andrew Geisslereff27472021-10-29 15:35:00 -05001000 except Exception as e:
Andrew Geissler595f6302022-01-24 19:11:47 +00001001 bb.error("SState: cannot test %s: %s" % (srcuri, repr(e)))
1002
1003 if progress:
Andrew Geissler82c905d2020-04-13 13:39:40 -05001004 bb.event.fire(bb.event.ProcessProgress(msg, len(tasklist) - thread_worker.tasks.qsize()), d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001005
1006 tasklist = []
Andrew Geissler595f6302022-01-24 19:11:47 +00001007 for tid in missed:
1008 sstatefile = d.expand(getsstatefile(tid, siginfo, d))
Brad Bishop08902b02019-08-20 09:16:51 -04001009 tasklist.append((tid, sstatefile))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001010
1011 if tasklist:
Andrew Geisslerd159c7f2021-09-02 21:05:58 -05001012 nproc = min(int(d.getVar("BB_NUMBER_THREADS")), len(tasklist))
1013
Andrew Geissler595f6302022-01-24 19:11:47 +00001014 progress = len(tasklist) >= 100
1015 if progress:
Andrew Geissler82c905d2020-04-13 13:39:40 -05001016 msg = "Checking sstate mirror object availability"
1017 bb.event.fire(bb.event.ProcessStarted(msg, len(tasklist)), d)
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001018
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001019 bb.event.enable_threadlock()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001020 pool = oe.utils.ThreadedPool(nproc, len(tasklist),
Andrew Geissler595f6302022-01-24 19:11:47 +00001021 worker_init=checkstatus_init, worker_end=checkstatus_end,
1022 name="sstate_checkhashes-")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001023 for t in tasklist:
1024 pool.add_task(checkstatus, t)
1025 pool.start()
1026 pool.wait_completion()
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001027 bb.event.disable_threadlock()
1028
Andrew Geissler595f6302022-01-24 19:11:47 +00001029 if progress:
Andrew Geissler82c905d2020-04-13 13:39:40 -05001030 bb.event.fire(bb.event.ProcessFinished(msg), d)
Brad Bishop96ff1982019-08-19 13:50:42 -04001031
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001032 inheritlist = d.getVar("INHERIT")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001033 if "toaster" in inheritlist:
1034 evdata = {'missed': [], 'found': []};
Brad Bishop08902b02019-08-20 09:16:51 -04001035 for tid in missed:
Andrew Geissler595f6302022-01-24 19:11:47 +00001036 sstatefile = d.expand(getsstatefile(tid, False, d))
Brad Bishop08902b02019-08-20 09:16:51 -04001037 evdata['missed'].append((bb.runqueue.fn_from_tid(tid), bb.runqueue.taskname_from_tid(tid), gethash(tid), sstatefile ) )
1038 for tid in found:
Andrew Geissler595f6302022-01-24 19:11:47 +00001039 sstatefile = d.expand(getsstatefile(tid, False, d))
Brad Bishop08902b02019-08-20 09:16:51 -04001040 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 -05001041 bb.event.fire(bb.event.MetadataEvent("MissedSstate", evdata), d)
1042
Brad Bishop1d80a2e2019-11-15 16:35:03 -05001043 if summary:
1044 # Print some summary statistics about the current task completion and how much sstate
1045 # reuse there was. Avoid divide by zero errors.
1046 total = len(sq_data['hash'])
1047 complete = 0
1048 if currentcount:
1049 complete = (len(found) + currentcount) / (total + currentcount) * 100
1050 match = 0
1051 if total:
1052 match = len(found) / total * 100
Andrew Geisslereff27472021-10-29 15:35:00 -05001053 bb.plain("Sstate summary: Wanted %d Local %d Mirrors %d Missed %d Current %d (%d%% match, %d%% complete)" %
1054 (total, foundLocal, len(found)-foundLocal, len(missed), currentcount, match, complete))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001055
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001056 if hasattr(bb.parse.siggen, "checkhashes"):
Brad Bishop08902b02019-08-20 09:16:51 -04001057 bb.parse.siggen.checkhashes(sq_data, missed, found, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001058
Brad Bishop08902b02019-08-20 09:16:51 -04001059 return found
Patrick Williams213cb262021-08-07 19:21:33 -05001060setscene_depvalid[vardepsexclude] = "SSTATE_EXCLUDEDEPS_SYSROOT"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001061
1062BB_SETSCENE_DEPVALID = "setscene_depvalid"
1063
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001064def setscene_depvalid(task, taskdependees, notneeded, d, log=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001065 # taskdependees is a dict of tasks which depend on task, each being a 3 item list of [PN, TASKNAME, FILENAME]
1066 # task is included in taskdependees too
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001067 # Return - False - We need this dependency
1068 # - True - We can skip this dependency
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001069 import re
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001070
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001071 def logit(msg, log):
1072 if log is not None:
1073 log.append(msg)
1074 else:
1075 bb.debug(2, msg)
1076
1077 logit("Considering setscene task: %s" % (str(taskdependees[task])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001078
Andrew Geissler5199d832021-09-24 16:47:35 -05001079 directtasks = ["do_populate_lic", "do_deploy_source_date_epoch", "do_shared_workdir", "do_stash_locale", "do_gcc_stash_builddir"]
1080
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001081 def isNativeCross(x):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001082 return x.endswith("-native") or "-cross-" in x or "-crosssdk" in x or x.endswith("-cross")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001083
Andrew Geissler5199d832021-09-24 16:47:35 -05001084 # We only need to trigger deploy_source_date_epoch through direct dependencies
1085 if taskdependees[task][1] in directtasks:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001086 return True
1087
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001088 # We only need to trigger packagedata through direct dependencies
1089 # but need to preserve packagedata on packagedata links
1090 if taskdependees[task][1] == "do_packagedata":
1091 for dep in taskdependees:
1092 if taskdependees[dep][1] == "do_packagedata":
1093 return False
1094 return True
1095
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001096 for dep in taskdependees:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001097 logit(" considering dependency: %s" % (str(taskdependees[dep])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001098 if task == dep:
1099 continue
1100 if dep in notneeded:
1101 continue
1102 # do_package_write_* and do_package doesn't need do_package
1103 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']:
1104 continue
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001105 # do_package_write_* need do_populate_sysroot as they're mainly postinstall dependencies
1106 if taskdependees[task][1] == "do_populate_sysroot" and taskdependees[dep][1] in ['do_package_write_deb', 'do_package_write_ipk', 'do_package_write_rpm']:
1107 return False
Andrew Geissler5199d832021-09-24 16:47:35 -05001108 # do_package/packagedata/package_qa/deploy don't need do_populate_sysroot
1109 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 -05001110 continue
1111 # Native/Cross packages don't exist and are noexec anyway
1112 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']:
1113 continue
1114
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001115 # This is due to the [depends] in useradd.bbclass complicating matters
1116 # The logic *is* reversed here due to the way hard setscene dependencies are injected
1117 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':
1118 continue
1119
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001120 # Consider sysroot depending on sysroot tasks
1121 if taskdependees[task][1] == 'do_populate_sysroot' and taskdependees[dep][1] == 'do_populate_sysroot':
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001122 # Allow excluding certain recursive dependencies. If a recipe needs it should add a
1123 # specific dependency itself, rather than relying on one of its dependees to pull
1124 # them in.
1125 # See also http://lists.openembedded.org/pipermail/openembedded-core/2018-January/146324.html
1126 not_needed = False
1127 excludedeps = d.getVar('_SSTATE_EXCLUDEDEPS_SYSROOT')
1128 if excludedeps is None:
1129 # Cache the regular expressions for speed
1130 excludedeps = []
1131 for excl in (d.getVar('SSTATE_EXCLUDEDEPS_SYSROOT') or "").split():
1132 excludedeps.append((re.compile(excl.split('->', 1)[0]), re.compile(excl.split('->', 1)[1])))
1133 d.setVar('_SSTATE_EXCLUDEDEPS_SYSROOT', excludedeps)
1134 for excl in excludedeps:
1135 if excl[0].match(taskdependees[dep][0]):
1136 if excl[1].match(taskdependees[task][0]):
1137 not_needed = True
1138 break
1139 if not_needed:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001140 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001141 # For meta-extsdk-toolchain we want all sysroot dependencies
1142 if taskdependees[dep][0] == 'meta-extsdk-toolchain':
1143 return False
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001144 # Native/Cross populate_sysroot need their dependencies
1145 if isNativeCross(taskdependees[task][0]) and isNativeCross(taskdependees[dep][0]):
1146 return False
1147 # Target populate_sysroot depended on by cross tools need to be installed
1148 if isNativeCross(taskdependees[dep][0]):
1149 return False
1150 # Native/cross tools depended upon by target sysroot are not needed
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001151 # Add an exception for shadow-native as required by useradd.bbclass
1152 if isNativeCross(taskdependees[task][0]) and taskdependees[task][0] != 'shadow-native':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001153 continue
1154 # Target populate_sysroot need their dependencies
1155 return False
1156
Andrew Geissler5199d832021-09-24 16:47:35 -05001157 if taskdependees[dep][1] in directtasks:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001158 continue
1159
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001160 # Safe fallthrough default
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001161 logit(" Default setscene dependency fall through due to dependency: %s" % (str(taskdependees[dep])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001162 return False
1163 return True
1164
1165addhandler sstate_eventhandler
1166sstate_eventhandler[eventmask] = "bb.build.TaskSucceeded"
1167python sstate_eventhandler() {
1168 d = e.data
Andrew Geissler82c905d2020-04-13 13:39:40 -05001169 writtensstate = d.getVar('SSTATE_CURRTASK')
1170 if not writtensstate:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001171 taskname = d.getVar("BB_RUNTASK")[3:]
1172 spec = d.getVar('SSTATE_PKGSPEC')
1173 swspec = d.getVar('SSTATE_SWSPEC')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001174 if taskname in ["fetch", "unpack", "patch", "populate_lic", "preconfigure"] and swspec:
1175 d.setVar("SSTATE_PKGSPEC", "${SSTATE_SWSPEC}")
1176 d.setVar("SSTATE_EXTRAPATH", "")
Andrew Geissler82c905d2020-04-13 13:39:40 -05001177 d.setVar("SSTATE_CURRTASK", taskname)
1178 siginfo = d.getVar('SSTATE_PKG') + ".siginfo"
1179 if not os.path.exists(siginfo):
1180 bb.siggen.dump_this_task(siginfo, d)
1181 else:
Andrew Geisslerc182c622020-05-15 14:13:32 -05001182 try:
1183 os.utime(siginfo, None)
1184 except PermissionError:
1185 pass
Andrew Geissler5f350902021-07-23 13:09:54 -04001186 except OSError as e:
1187 # Handle read-only file systems gracefully
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001188 import errno
Andrew Geissler5f350902021-07-23 13:09:54 -04001189 if e.errno != errno.EROFS:
1190 raise e
Andrew Geisslerc182c622020-05-15 14:13:32 -05001191
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001192}
1193
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001194SSTATE_PRUNE_OBSOLETEWORKDIR ?= "1"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001195
Andrew Geissler95ac1b82021-03-31 14:34:31 -05001196#
1197# Event handler which removes manifests and stamps file for recipes which are no
1198# longer 'reachable' in a build where they once were. 'Reachable' refers to
1199# whether a recipe is parsed so recipes in a layer which was removed would no
1200# longer be reachable. Switching between systemd and sysvinit where recipes
1201# became skipped would be another example.
1202#
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001203# Also optionally removes the workdir of those tasks/recipes
1204#
Andrew Geissler95ac1b82021-03-31 14:34:31 -05001205addhandler sstate_eventhandler_reachablestamps
1206sstate_eventhandler_reachablestamps[eventmask] = "bb.event.ReachableStamps"
1207python sstate_eventhandler_reachablestamps() {
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001208 import glob
1209 d = e.data
1210 stamps = e.stamps.values()
1211 removeworkdir = (d.getVar("SSTATE_PRUNE_OBSOLETEWORKDIR", False) == "1")
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001212 preservestampfile = d.expand('${SSTATE_MANIFESTS}/preserve-stamps')
1213 preservestamps = []
1214 if os.path.exists(preservestampfile):
1215 with open(preservestampfile, 'r') as f:
1216 preservestamps = f.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001217 seen = []
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001218
1219 # The machine index contains all the stamps this machine has ever seen in this build directory.
1220 # We should only remove things which this machine once accessed but no longer does.
1221 machineindex = set()
1222 bb.utils.mkdirhier(d.expand("${SSTATE_MANIFESTS}"))
1223 mi = d.expand("${SSTATE_MANIFESTS}/index-machine-${MACHINE}")
1224 if os.path.exists(mi):
1225 with open(mi, "r") as f:
1226 machineindex = set(line.strip() for line in f.readlines())
1227
Brad Bishop316dfdd2018-06-25 12:45:53 -04001228 for a in sorted(list(set(d.getVar("SSTATE_ARCHS").split()))):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001229 toremove = []
1230 i = d.expand("${SSTATE_MANIFESTS}/index-" + a)
1231 if not os.path.exists(i):
1232 continue
William A. Kennington IIIac69b482021-06-02 12:28:27 -07001233 manseen = set()
1234 ignore = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001235 with open(i, "r") as f:
1236 lines = f.readlines()
William A. Kennington IIIac69b482021-06-02 12:28:27 -07001237 for l in reversed(lines):
Brad Bishop19323692019-04-05 15:28:33 -04001238 try:
1239 (stamp, manifest, workdir) = l.split()
William A. Kennington IIIac69b482021-06-02 12:28:27 -07001240 # The index may have multiple entries for the same manifest as the code above only appends
1241 # new entries and there may be an entry with matching manifest but differing version in stamp/workdir.
1242 # The last entry in the list is the valid one, any earlier entries with matching manifests
1243 # should be ignored.
1244 if manifest in manseen:
1245 ignore.append(l)
1246 continue
1247 manseen.add(manifest)
Brad Bishop19323692019-04-05 15:28:33 -04001248 if stamp not in stamps and stamp not in preservestamps and stamp in machineindex:
1249 toremove.append(l)
1250 if stamp not in seen:
1251 bb.debug(2, "Stamp %s is not reachable, removing related manifests" % stamp)
1252 seen.append(stamp)
1253 except ValueError:
1254 bb.fatal("Invalid line '%s' in sstate manifest '%s'" % (l, i))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001255
1256 if toremove:
Brad Bishop316dfdd2018-06-25 12:45:53 -04001257 msg = "Removing %d recipes from the %s sysroot" % (len(toremove), a)
1258 bb.event.fire(bb.event.ProcessStarted(msg, len(toremove)), d)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001259
Brad Bishop316dfdd2018-06-25 12:45:53 -04001260 removed = 0
1261 for r in toremove:
1262 (stamp, manifest, workdir) = r.split()
1263 for m in glob.glob(manifest + ".*"):
1264 if m.endswith(".postrm"):
1265 continue
1266 sstate_clean_manifest(m, d)
1267 bb.utils.remove(stamp + "*")
1268 if removeworkdir:
1269 bb.utils.remove(workdir, recurse = True)
1270 lines.remove(r)
1271 removed = removed + 1
1272 bb.event.fire(bb.event.ProcessProgress(msg, removed), d)
1273
1274 bb.event.fire(bb.event.ProcessFinished(msg), d)
1275
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001276 with open(i, "w") as f:
1277 for l in lines:
William A. Kennington IIIac69b482021-06-02 12:28:27 -07001278 if l in ignore:
1279 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001280 f.write(l)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001281 machineindex |= set(stamps)
1282 with open(mi, "w") as f:
1283 for l in machineindex:
1284 f.write(l + "\n")
1285
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001286 if preservestamps:
1287 os.remove(preservestampfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001288}
Andrew Geissler95ac1b82021-03-31 14:34:31 -05001289
1290
1291#
1292# Bitbake can generate an event showing which setscene tasks are 'stale',
1293# i.e. which ones will be rerun. These are ones where a stamp file is present but
1294# it is stable (e.g. taskhash doesn't match). With that list we can go through
1295# the manifests for matching tasks and "uninstall" those manifests now. We do
1296# this now rather than mid build since the distribution of files between sstate
1297# objects may have changed, new tasks may run first and if those new tasks overlap
1298# with the stale tasks, we'd see overlapping files messages and failures. Thankfully
1299# removing these files is fast.
1300#
1301addhandler sstate_eventhandler_stalesstate
1302sstate_eventhandler_stalesstate[eventmask] = "bb.event.StaleSetSceneTasks"
1303python sstate_eventhandler_stalesstate() {
1304 d = e.data
1305 tasks = e.tasks
1306
1307 bb.utils.mkdirhier(d.expand("${SSTATE_MANIFESTS}"))
1308
1309 for a in list(set(d.getVar("SSTATE_ARCHS").split())):
1310 toremove = []
1311 i = d.expand("${SSTATE_MANIFESTS}/index-" + a)
1312 if not os.path.exists(i):
1313 continue
1314 with open(i, "r") as f:
1315 lines = f.readlines()
1316 for l in lines:
1317 try:
1318 (stamp, manifest, workdir) = l.split()
1319 for tid in tasks:
1320 for s in tasks[tid]:
1321 if s.startswith(stamp):
1322 taskname = bb.runqueue.taskname_from_tid(tid)[3:]
1323 manname = manifest + "." + taskname
1324 if os.path.exists(manname):
1325 bb.debug(2, "Sstate for %s is stale, removing related manifest %s" % (tid, manname))
1326 toremove.append((manname, tid, tasks[tid]))
1327 break
1328 except ValueError:
1329 bb.fatal("Invalid line '%s' in sstate manifest '%s'" % (l, i))
1330
1331 if toremove:
1332 msg = "Removing %d stale sstate objects for arch %s" % (len(toremove), a)
1333 bb.event.fire(bb.event.ProcessStarted(msg, len(toremove)), d)
1334
1335 removed = 0
1336 for (manname, tid, stamps) in toremove:
1337 sstate_clean_manifest(manname, d)
1338 for stamp in stamps:
1339 bb.utils.remove(stamp)
1340 removed = removed + 1
1341 bb.event.fire(bb.event.ProcessProgress(msg, removed), d)
1342
1343 bb.event.fire(bb.event.ProcessFinished(msg), d)
1344}