blob: 787172b408da819fb339c9d2c5cc962f0af7541e [file] [log] [blame]
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001SSTATE_VERSION = "8"
Andrew Geisslereff27472021-10-29 15:35:00 -05002
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)
Andrew Geissler7e0e3c02022-02-25 20:34:39 +000053SSTATE_ALLOW_OVERLAP_FILES = "${DEPLOY_DIR}/licenses/"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050054# Avoid docbook/sgml catalog warnings for now
Andrew Geissler7e0e3c02022-02-25 20:34:39 +000055SSTATE_ALLOW_OVERLAP_FILES += "${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
Andrew Geissler7e0e3c02022-02-25 20:34:39 +000057SSTATE_ALLOW_OVERLAP_FILES += "${DEPLOY_DIR_RPM}/sdk_provides_dummy_nativesdk/ ${DEPLOY_DIR_IPK}/sdk-provides-dummy-nativesdk/"
58SSTATE_ALLOW_OVERLAP_FILES += "${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
Andrew Geissler7e0e3c02022-02-25 20:34:39 +000060SSTATE_ALLOW_OVERLAP_FILES += "${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
Andrew Geissler7e0e3c02022-02-25 20:34:39 +000062SSTATE_ALLOW_OVERLAP_FILES += "${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
Andrew Geissler7e0e3c02022-02-25 20:34:39 +000064SSTATE_ALLOW_OVERLAP_FILES += "${DEPLOY_DIR_IMAGE}/ovmf"
65SSTATE_ALLOW_OVERLAP_FILES += "${DEPLOY_DIR_IMAGE}/grub-efi"
66SSTATE_ALLOW_OVERLAP_FILES += "${DEPLOY_DIR_IMAGE}/systemd-boot"
67SSTATE_ALLOW_OVERLAP_FILES += "${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
Andrew Geissler7e0e3c02022-02-25 20:34:39 +000097SSTATECREATEFUNCS += "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
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000263 whitelist = (d.getVar("SSTATE_ALLOW_OVERLAP_FILES") 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 " \
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000299 "adding them to SSTATE_ALLOW_OVERLAP_FILES may be the correct solution. It could " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500300 "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
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000353sstate_install[vardepsexclude] += "SSTATE_ALLOW_OVERLAP_FILES STATE_MANMACH SSTATE_MANFILEPREFIX"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500354sstate_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
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000865 if [ -h ${SSTATE_PKG} ] && [ ! -e ${SSTATE_PKG} ]; then
866 # There is a symbolic link, but it links to nothing.
867 # Forcefully replace it with the new file.
868 ln -f $TFILE ${SSTATE_PKG} || true
869 elif [ ! -e ${SSTATE_PKG} ]; then
Andrew Geissler82c905d2020-04-13 13:39:40 -0500870 # Move into place using ln to attempt an atomic op.
871 # Abort if it already exists
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000872 ln $TFILE ${SSTATE_PKG} || true
Brad Bishop08902b02019-08-20 09:16:51 -0400873 else
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000874 touch ${SSTATE_PKG} 2>/dev/null || true
Brad Bishop08902b02019-08-20 09:16:51 -0400875 fi
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000876 rm $TFILE
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500877}
878
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500879python sstate_sign_package () {
880 from oe.gpg_sign import get_signer
881
Brad Bishop08902b02019-08-20 09:16:51 -0400882
883 signer = get_signer(d, 'local')
884 sstate_pkg = d.getVar('SSTATE_PKG')
885 if os.path.exists(sstate_pkg + '.sig'):
886 os.unlink(sstate_pkg + '.sig')
887 signer.detach_sign(sstate_pkg, d.getVar('SSTATE_SIG_KEY', False), None,
888 d.getVar('SSTATE_SIG_PASSPHRASE'), armor=False)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500889}
890
Brad Bishop19323692019-04-05 15:28:33 -0400891python sstate_report_unihash() {
892 report_unihash = getattr(bb.parse.siggen, 'report_unihash', None)
893
894 if report_unihash:
895 ss = sstate_state_fromvars(d)
896 report_unihash(os.getcwd(), ss['task'], d)
897}
898
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500899#
900# Shell function to decompress and prepare a package for installation
901# Will be run from within SSTATE_INSTDIR.
902#
903sstate_unpack_package () {
Andrew Geisslereff27472021-10-29 15:35:00 -0500904 ZSTD="zstd -T${ZSTD_THREADS}"
905 # Use pzstd if available
906 if [ -x "$(command -v pzstd)" ]; then
907 ZSTD="pzstd -p ${ZSTD_THREADS}"
908 fi
909
Andrew Geissler595f6302022-01-24 19:11:47 +0000910 tar -I "$ZSTD" -xvpf ${SSTATE_PKG}
911 # update .siginfo atime on local/NFS mirror if it is a symbolic link
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000912 [ ! -h ${SSTATE_PKG}.siginfo ] || [ ! -e ${SSTATE_PKG}.siginfo ] || touch -a ${SSTATE_PKG}.siginfo 2>/dev/null || true
Andrew Geissler595f6302022-01-24 19:11:47 +0000913 # update each symbolic link instead of any referenced file
914 touch --no-dereference ${SSTATE_PKG} 2>/dev/null || true
915 [ ! -e ${SSTATE_PKG}.sig ] || touch --no-dereference ${SSTATE_PKG}.sig 2>/dev/null || true
916 [ ! -e ${SSTATE_PKG}.siginfo ] || touch --no-dereference ${SSTATE_PKG}.siginfo 2>/dev/null || true
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500917}
918
919BB_HASHCHECK_FUNCTION = "sstate_checkhashes"
920
Brad Bishop1d80a2e2019-11-15 16:35:03 -0500921def sstate_checkhashes(sq_data, d, siginfo=False, currentcount=0, summary=True, **kwargs):
Brad Bishop08902b02019-08-20 09:16:51 -0400922 found = set()
923 missed = set()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500924
Brad Bishop19323692019-04-05 15:28:33 -0400925 def gethash(task):
Brad Bishop08902b02019-08-20 09:16:51 -0400926 return sq_data['unihash'][task]
Brad Bishop19323692019-04-05 15:28:33 -0400927
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500928 def getpathcomponents(task, d):
929 # Magic data from BB_HASHFILENAME
Brad Bishop08902b02019-08-20 09:16:51 -0400930 splithashfn = sq_data['hashfn'][task].split(" ")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500931 spec = splithashfn[1]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500932 if splithashfn[0] == "True":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500933 extrapath = d.getVar("NATIVELSBSTRING") + "/"
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500934 else:
935 extrapath = ""
Brad Bishop08902b02019-08-20 09:16:51 -0400936
937 tname = bb.runqueue.taskname_from_tid(task)[3:]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500938
939 if tname in ["fetch", "unpack", "patch", "populate_lic", "preconfigure"] and splithashfn[2]:
940 spec = splithashfn[2]
941 extrapath = ""
942
943 return spec, extrapath, tname
944
Andrew Geissler595f6302022-01-24 19:11:47 +0000945 def getsstatefile(tid, siginfo, d):
946 spec, extrapath, tname = getpathcomponents(tid, d)
947 return extrapath + generate_sstatefn(spec, gethash(tid), tname, siginfo, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500948
Brad Bishop08902b02019-08-20 09:16:51 -0400949 for tid in sq_data['hash']:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500950
Andrew Geissler595f6302022-01-24 19:11:47 +0000951 sstatefile = d.expand("${SSTATE_DIR}/" + getsstatefile(tid, siginfo, d))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500952
953 if os.path.exists(sstatefile):
Brad Bishop08902b02019-08-20 09:16:51 -0400954 found.add(tid)
Andrew Geisslereff27472021-10-29 15:35:00 -0500955 bb.debug(2, "SState: Found valid sstate file %s" % sstatefile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500956 else:
Brad Bishop08902b02019-08-20 09:16:51 -0400957 missed.add(tid)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500958 bb.debug(2, "SState: Looked for but didn't find file %s" % sstatefile)
959
Andrew Geisslereff27472021-10-29 15:35:00 -0500960 foundLocal = len(found)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500961 mirrors = d.getVar("SSTATE_MIRRORS")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500962 if mirrors:
963 # Copy the data object and override DL_DIR and SRC_URI
964 localdata = bb.data.createCopy(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500965
966 dldir = localdata.expand("${SSTATE_DIR}")
967 localdata.delVar('MIRRORS')
968 localdata.setVar('FILESPATH', dldir)
969 localdata.setVar('DL_DIR', dldir)
970 localdata.setVar('PREMIRRORS', mirrors)
971
972 bb.debug(2, "SState using premirror of: %s" % mirrors)
973
974 # if BB_NO_NETWORK is set but we also have SSTATE_MIRROR_ALLOW_NETWORK,
975 # we'll want to allow network access for the current set of fetches.
Brad Bishopd89cb5f2019-04-10 09:02:41 -0400976 if bb.utils.to_boolean(localdata.getVar('BB_NO_NETWORK')) and \
977 bb.utils.to_boolean(localdata.getVar('SSTATE_MIRROR_ALLOW_NETWORK')):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500978 localdata.delVar('BB_NO_NETWORK')
979
980 from bb.fetch2 import FetchConnectionCache
981 def checkstatus_init(thread_worker):
982 thread_worker.connection_cache = FetchConnectionCache()
983
984 def checkstatus_end(thread_worker):
985 thread_worker.connection_cache.close_connections()
986
987 def checkstatus(thread_worker, arg):
Brad Bishop08902b02019-08-20 09:16:51 -0400988 (tid, sstatefile) = arg
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500989
990 localdata2 = bb.data.createCopy(localdata)
991 srcuri = "file://" + sstatefile
992 localdata.setVar('SRC_URI', srcuri)
993 bb.debug(2, "SState: Attempting to fetch %s" % srcuri)
994
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000995 import traceback
996
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500997 try:
998 fetcher = bb.fetch2.Fetch(srcuri.split(), localdata2,
999 connection_cache=thread_worker.connection_cache)
1000 fetcher.checkstatus()
1001 bb.debug(2, "SState: Successful fetch test for %s" % srcuri)
Brad Bishop08902b02019-08-20 09:16:51 -04001002 found.add(tid)
Andrew Geissler595f6302022-01-24 19:11:47 +00001003 missed.remove(tid)
Andrew Geisslereff27472021-10-29 15:35:00 -05001004 except bb.fetch2.FetchError as e:
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001005 bb.debug(2, "SState: Unsuccessful fetch test for %s (%s)\n%s" % (srcuri, repr(e), traceback.format_exc()))
Andrew Geisslereff27472021-10-29 15:35:00 -05001006 except Exception as e:
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001007 bb.error("SState: cannot test %s: %s\n%s" % (srcuri, repr(e), traceback.format_exc()))
Andrew Geissler595f6302022-01-24 19:11:47 +00001008
1009 if progress:
Andrew Geissler82c905d2020-04-13 13:39:40 -05001010 bb.event.fire(bb.event.ProcessProgress(msg, len(tasklist) - thread_worker.tasks.qsize()), d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001011
1012 tasklist = []
Andrew Geissler595f6302022-01-24 19:11:47 +00001013 for tid in missed:
1014 sstatefile = d.expand(getsstatefile(tid, siginfo, d))
Brad Bishop08902b02019-08-20 09:16:51 -04001015 tasklist.append((tid, sstatefile))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001016
1017 if tasklist:
Andrew Geisslerd159c7f2021-09-02 21:05:58 -05001018 nproc = min(int(d.getVar("BB_NUMBER_THREADS")), len(tasklist))
1019
Andrew Geissler595f6302022-01-24 19:11:47 +00001020 progress = len(tasklist) >= 100
1021 if progress:
Andrew Geissler82c905d2020-04-13 13:39:40 -05001022 msg = "Checking sstate mirror object availability"
1023 bb.event.fire(bb.event.ProcessStarted(msg, len(tasklist)), d)
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001024
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001025 # Have to setup the fetcher environment here rather than in each thread as it would race
1026 fetcherenv = bb.fetch2.get_fetcher_environment(d)
1027 with bb.utils.environment(**fetcherenv):
1028 bb.event.enable_threadlock()
1029 pool = oe.utils.ThreadedPool(nproc, len(tasklist),
1030 worker_init=checkstatus_init, worker_end=checkstatus_end,
1031 name="sstate_checkhashes-")
1032 for t in tasklist:
1033 pool.add_task(checkstatus, t)
1034 pool.start()
1035 pool.wait_completion()
1036 bb.event.disable_threadlock()
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001037
Andrew Geissler595f6302022-01-24 19:11:47 +00001038 if progress:
Andrew Geissler82c905d2020-04-13 13:39:40 -05001039 bb.event.fire(bb.event.ProcessFinished(msg), d)
Brad Bishop96ff1982019-08-19 13:50:42 -04001040
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001041 inheritlist = d.getVar("INHERIT")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001042 if "toaster" in inheritlist:
1043 evdata = {'missed': [], 'found': []};
Brad Bishop08902b02019-08-20 09:16:51 -04001044 for tid in missed:
Andrew Geissler595f6302022-01-24 19:11:47 +00001045 sstatefile = d.expand(getsstatefile(tid, False, d))
Brad Bishop08902b02019-08-20 09:16:51 -04001046 evdata['missed'].append((bb.runqueue.fn_from_tid(tid), bb.runqueue.taskname_from_tid(tid), gethash(tid), sstatefile ) )
1047 for tid in found:
Andrew Geissler595f6302022-01-24 19:11:47 +00001048 sstatefile = d.expand(getsstatefile(tid, False, d))
Brad Bishop08902b02019-08-20 09:16:51 -04001049 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 -05001050 bb.event.fire(bb.event.MetadataEvent("MissedSstate", evdata), d)
1051
Brad Bishop1d80a2e2019-11-15 16:35:03 -05001052 if summary:
1053 # Print some summary statistics about the current task completion and how much sstate
1054 # reuse there was. Avoid divide by zero errors.
1055 total = len(sq_data['hash'])
1056 complete = 0
1057 if currentcount:
1058 complete = (len(found) + currentcount) / (total + currentcount) * 100
1059 match = 0
1060 if total:
1061 match = len(found) / total * 100
Andrew Geisslereff27472021-10-29 15:35:00 -05001062 bb.plain("Sstate summary: Wanted %d Local %d Mirrors %d Missed %d Current %d (%d%% match, %d%% complete)" %
1063 (total, foundLocal, len(found)-foundLocal, len(missed), currentcount, match, complete))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001064
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001065 if hasattr(bb.parse.siggen, "checkhashes"):
Brad Bishop08902b02019-08-20 09:16:51 -04001066 bb.parse.siggen.checkhashes(sq_data, missed, found, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001067
Brad Bishop08902b02019-08-20 09:16:51 -04001068 return found
Patrick Williams213cb262021-08-07 19:21:33 -05001069setscene_depvalid[vardepsexclude] = "SSTATE_EXCLUDEDEPS_SYSROOT"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001070
1071BB_SETSCENE_DEPVALID = "setscene_depvalid"
1072
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001073def setscene_depvalid(task, taskdependees, notneeded, d, log=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001074 # taskdependees is a dict of tasks which depend on task, each being a 3 item list of [PN, TASKNAME, FILENAME]
1075 # task is included in taskdependees too
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001076 # Return - False - We need this dependency
1077 # - True - We can skip this dependency
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001078 import re
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001079
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001080 def logit(msg, log):
1081 if log is not None:
1082 log.append(msg)
1083 else:
1084 bb.debug(2, msg)
1085
1086 logit("Considering setscene task: %s" % (str(taskdependees[task])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001087
Andrew Geissler5199d832021-09-24 16:47:35 -05001088 directtasks = ["do_populate_lic", "do_deploy_source_date_epoch", "do_shared_workdir", "do_stash_locale", "do_gcc_stash_builddir"]
1089
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001090 def isNativeCross(x):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001091 return x.endswith("-native") or "-cross-" in x or "-crosssdk" in x or x.endswith("-cross")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001092
Andrew Geissler5199d832021-09-24 16:47:35 -05001093 # We only need to trigger deploy_source_date_epoch through direct dependencies
1094 if taskdependees[task][1] in directtasks:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001095 return True
1096
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001097 # We only need to trigger packagedata through direct dependencies
1098 # but need to preserve packagedata on packagedata links
1099 if taskdependees[task][1] == "do_packagedata":
1100 for dep in taskdependees:
1101 if taskdependees[dep][1] == "do_packagedata":
1102 return False
1103 return True
1104
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001105 for dep in taskdependees:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001106 logit(" considering dependency: %s" % (str(taskdependees[dep])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001107 if task == dep:
1108 continue
1109 if dep in notneeded:
1110 continue
1111 # do_package_write_* and do_package doesn't need do_package
1112 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']:
1113 continue
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001114 # do_package_write_* need do_populate_sysroot as they're mainly postinstall dependencies
1115 if taskdependees[task][1] == "do_populate_sysroot" and taskdependees[dep][1] in ['do_package_write_deb', 'do_package_write_ipk', 'do_package_write_rpm']:
1116 return False
Andrew Geissler5199d832021-09-24 16:47:35 -05001117 # do_package/packagedata/package_qa/deploy don't need do_populate_sysroot
1118 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 -05001119 continue
1120 # Native/Cross packages don't exist and are noexec anyway
1121 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']:
1122 continue
1123
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001124 # This is due to the [depends] in useradd.bbclass complicating matters
1125 # The logic *is* reversed here due to the way hard setscene dependencies are injected
1126 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':
1127 continue
1128
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001129 # Consider sysroot depending on sysroot tasks
1130 if taskdependees[task][1] == 'do_populate_sysroot' and taskdependees[dep][1] == 'do_populate_sysroot':
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001131 # Allow excluding certain recursive dependencies. If a recipe needs it should add a
1132 # specific dependency itself, rather than relying on one of its dependees to pull
1133 # them in.
1134 # See also http://lists.openembedded.org/pipermail/openembedded-core/2018-January/146324.html
1135 not_needed = False
1136 excludedeps = d.getVar('_SSTATE_EXCLUDEDEPS_SYSROOT')
1137 if excludedeps is None:
1138 # Cache the regular expressions for speed
1139 excludedeps = []
1140 for excl in (d.getVar('SSTATE_EXCLUDEDEPS_SYSROOT') or "").split():
1141 excludedeps.append((re.compile(excl.split('->', 1)[0]), re.compile(excl.split('->', 1)[1])))
1142 d.setVar('_SSTATE_EXCLUDEDEPS_SYSROOT', excludedeps)
1143 for excl in excludedeps:
1144 if excl[0].match(taskdependees[dep][0]):
1145 if excl[1].match(taskdependees[task][0]):
1146 not_needed = True
1147 break
1148 if not_needed:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001149 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001150 # For meta-extsdk-toolchain we want all sysroot dependencies
1151 if taskdependees[dep][0] == 'meta-extsdk-toolchain':
1152 return False
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001153 # Native/Cross populate_sysroot need their dependencies
1154 if isNativeCross(taskdependees[task][0]) and isNativeCross(taskdependees[dep][0]):
1155 return False
1156 # Target populate_sysroot depended on by cross tools need to be installed
1157 if isNativeCross(taskdependees[dep][0]):
1158 return False
1159 # Native/cross tools depended upon by target sysroot are not needed
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001160 # Add an exception for shadow-native as required by useradd.bbclass
1161 if isNativeCross(taskdependees[task][0]) and taskdependees[task][0] != 'shadow-native':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001162 continue
1163 # Target populate_sysroot need their dependencies
1164 return False
1165
Andrew Geissler5199d832021-09-24 16:47:35 -05001166 if taskdependees[dep][1] in directtasks:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001167 continue
1168
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001169 # Safe fallthrough default
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001170 logit(" Default setscene dependency fall through due to dependency: %s" % (str(taskdependees[dep])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001171 return False
1172 return True
1173
1174addhandler sstate_eventhandler
1175sstate_eventhandler[eventmask] = "bb.build.TaskSucceeded"
1176python sstate_eventhandler() {
1177 d = e.data
Andrew Geissler82c905d2020-04-13 13:39:40 -05001178 writtensstate = d.getVar('SSTATE_CURRTASK')
1179 if not writtensstate:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001180 taskname = d.getVar("BB_RUNTASK")[3:]
1181 spec = d.getVar('SSTATE_PKGSPEC')
1182 swspec = d.getVar('SSTATE_SWSPEC')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001183 if taskname in ["fetch", "unpack", "patch", "populate_lic", "preconfigure"] and swspec:
1184 d.setVar("SSTATE_PKGSPEC", "${SSTATE_SWSPEC}")
1185 d.setVar("SSTATE_EXTRAPATH", "")
Andrew Geissler82c905d2020-04-13 13:39:40 -05001186 d.setVar("SSTATE_CURRTASK", taskname)
1187 siginfo = d.getVar('SSTATE_PKG') + ".siginfo"
1188 if not os.path.exists(siginfo):
1189 bb.siggen.dump_this_task(siginfo, d)
1190 else:
Andrew Geisslerc182c622020-05-15 14:13:32 -05001191 try:
1192 os.utime(siginfo, None)
1193 except PermissionError:
1194 pass
Andrew Geissler5f350902021-07-23 13:09:54 -04001195 except OSError as e:
1196 # Handle read-only file systems gracefully
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001197 import errno
Andrew Geissler5f350902021-07-23 13:09:54 -04001198 if e.errno != errno.EROFS:
1199 raise e
Andrew Geisslerc182c622020-05-15 14:13:32 -05001200
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001201}
1202
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001203SSTATE_PRUNE_OBSOLETEWORKDIR ?= "1"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001204
Andrew Geissler95ac1b82021-03-31 14:34:31 -05001205#
1206# Event handler which removes manifests and stamps file for recipes which are no
1207# longer 'reachable' in a build where they once were. 'Reachable' refers to
1208# whether a recipe is parsed so recipes in a layer which was removed would no
1209# longer be reachable. Switching between systemd and sysvinit where recipes
1210# became skipped would be another example.
1211#
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001212# Also optionally removes the workdir of those tasks/recipes
1213#
Andrew Geissler95ac1b82021-03-31 14:34:31 -05001214addhandler sstate_eventhandler_reachablestamps
1215sstate_eventhandler_reachablestamps[eventmask] = "bb.event.ReachableStamps"
1216python sstate_eventhandler_reachablestamps() {
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001217 import glob
1218 d = e.data
1219 stamps = e.stamps.values()
1220 removeworkdir = (d.getVar("SSTATE_PRUNE_OBSOLETEWORKDIR", False) == "1")
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001221 preservestampfile = d.expand('${SSTATE_MANIFESTS}/preserve-stamps')
1222 preservestamps = []
1223 if os.path.exists(preservestampfile):
1224 with open(preservestampfile, 'r') as f:
1225 preservestamps = f.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001226 seen = []
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001227
1228 # The machine index contains all the stamps this machine has ever seen in this build directory.
1229 # We should only remove things which this machine once accessed but no longer does.
1230 machineindex = set()
1231 bb.utils.mkdirhier(d.expand("${SSTATE_MANIFESTS}"))
1232 mi = d.expand("${SSTATE_MANIFESTS}/index-machine-${MACHINE}")
1233 if os.path.exists(mi):
1234 with open(mi, "r") as f:
1235 machineindex = set(line.strip() for line in f.readlines())
1236
Brad Bishop316dfdd2018-06-25 12:45:53 -04001237 for a in sorted(list(set(d.getVar("SSTATE_ARCHS").split()))):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001238 toremove = []
1239 i = d.expand("${SSTATE_MANIFESTS}/index-" + a)
1240 if not os.path.exists(i):
1241 continue
William A. Kennington IIIac69b482021-06-02 12:28:27 -07001242 manseen = set()
1243 ignore = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001244 with open(i, "r") as f:
1245 lines = f.readlines()
William A. Kennington IIIac69b482021-06-02 12:28:27 -07001246 for l in reversed(lines):
Brad Bishop19323692019-04-05 15:28:33 -04001247 try:
1248 (stamp, manifest, workdir) = l.split()
William A. Kennington IIIac69b482021-06-02 12:28:27 -07001249 # The index may have multiple entries for the same manifest as the code above only appends
1250 # new entries and there may be an entry with matching manifest but differing version in stamp/workdir.
1251 # The last entry in the list is the valid one, any earlier entries with matching manifests
1252 # should be ignored.
1253 if manifest in manseen:
1254 ignore.append(l)
1255 continue
1256 manseen.add(manifest)
Brad Bishop19323692019-04-05 15:28:33 -04001257 if stamp not in stamps and stamp not in preservestamps and stamp in machineindex:
1258 toremove.append(l)
1259 if stamp not in seen:
1260 bb.debug(2, "Stamp %s is not reachable, removing related manifests" % stamp)
1261 seen.append(stamp)
1262 except ValueError:
1263 bb.fatal("Invalid line '%s' in sstate manifest '%s'" % (l, i))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001264
1265 if toremove:
Brad Bishop316dfdd2018-06-25 12:45:53 -04001266 msg = "Removing %d recipes from the %s sysroot" % (len(toremove), a)
1267 bb.event.fire(bb.event.ProcessStarted(msg, len(toremove)), d)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001268
Brad Bishop316dfdd2018-06-25 12:45:53 -04001269 removed = 0
1270 for r in toremove:
1271 (stamp, manifest, workdir) = r.split()
1272 for m in glob.glob(manifest + ".*"):
1273 if m.endswith(".postrm"):
1274 continue
1275 sstate_clean_manifest(m, d)
1276 bb.utils.remove(stamp + "*")
1277 if removeworkdir:
1278 bb.utils.remove(workdir, recurse = True)
1279 lines.remove(r)
1280 removed = removed + 1
1281 bb.event.fire(bb.event.ProcessProgress(msg, removed), d)
1282
1283 bb.event.fire(bb.event.ProcessFinished(msg), d)
1284
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001285 with open(i, "w") as f:
1286 for l in lines:
William A. Kennington IIIac69b482021-06-02 12:28:27 -07001287 if l in ignore:
1288 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001289 f.write(l)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001290 machineindex |= set(stamps)
1291 with open(mi, "w") as f:
1292 for l in machineindex:
1293 f.write(l + "\n")
1294
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001295 if preservestamps:
1296 os.remove(preservestampfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001297}
Andrew Geissler95ac1b82021-03-31 14:34:31 -05001298
1299
1300#
1301# Bitbake can generate an event showing which setscene tasks are 'stale',
1302# i.e. which ones will be rerun. These are ones where a stamp file is present but
1303# it is stable (e.g. taskhash doesn't match). With that list we can go through
1304# the manifests for matching tasks and "uninstall" those manifests now. We do
1305# this now rather than mid build since the distribution of files between sstate
1306# objects may have changed, new tasks may run first and if those new tasks overlap
1307# with the stale tasks, we'd see overlapping files messages and failures. Thankfully
1308# removing these files is fast.
1309#
1310addhandler sstate_eventhandler_stalesstate
1311sstate_eventhandler_stalesstate[eventmask] = "bb.event.StaleSetSceneTasks"
1312python sstate_eventhandler_stalesstate() {
1313 d = e.data
1314 tasks = e.tasks
1315
1316 bb.utils.mkdirhier(d.expand("${SSTATE_MANIFESTS}"))
1317
1318 for a in list(set(d.getVar("SSTATE_ARCHS").split())):
1319 toremove = []
1320 i = d.expand("${SSTATE_MANIFESTS}/index-" + a)
1321 if not os.path.exists(i):
1322 continue
1323 with open(i, "r") as f:
1324 lines = f.readlines()
1325 for l in lines:
1326 try:
1327 (stamp, manifest, workdir) = l.split()
1328 for tid in tasks:
1329 for s in tasks[tid]:
1330 if s.startswith(stamp):
1331 taskname = bb.runqueue.taskname_from_tid(tid)[3:]
1332 manname = manifest + "." + taskname
1333 if os.path.exists(manname):
1334 bb.debug(2, "Sstate for %s is stale, removing related manifest %s" % (tid, manname))
1335 toremove.append((manname, tid, tasks[tid]))
1336 break
1337 except ValueError:
1338 bb.fatal("Invalid line '%s' in sstate manifest '%s'" % (l, i))
1339
1340 if toremove:
1341 msg = "Removing %d stale sstate objects for arch %s" % (len(toremove), a)
1342 bb.event.fire(bb.event.ProcessStarted(msg, len(toremove)), d)
1343
1344 removed = 0
1345 for (manname, tid, stamps) in toremove:
1346 sstate_clean_manifest(manname, d)
1347 for stamp in stamps:
1348 bb.utils.remove(stamp)
1349 removed = removed + 1
1350 bb.event.fire(bb.event.ProcessProgress(msg, removed), d)
1351
1352 bb.event.fire(bb.event.ProcessFinished(msg), d)
1353}