blob: c73c3b42a7fa82635e7bddbcb751462543cc38d0 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001SSTATE_VERSION = "3"
2
3SSTATE_MANIFESTS ?= "${TMPDIR}/sstate-control"
4SSTATE_MANFILEPREFIX = "${SSTATE_MANIFESTS}/manifest-${SSTATE_MANMACH}-${PN}"
5
Andrew Geissler82c905d2020-04-13 13:39:40 -05006def generate_sstatefn(spec, hash, taskname, siginfo, d):
7 if taskname is None:
8 return ""
9 extension = ".tgz"
10 # 8 chars reserved for siginfo
11 limit = 254 - 8
12 if siginfo:
13 limit = 254
14 extension = ".tgz.siginfo"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050015 if not hash:
16 hash = "INVALID"
Andrew Geissler82c905d2020-04-13 13:39:40 -050017 fn = spec + hash + "_" + taskname + extension
18 # If the filename is too long, attempt to reduce it
19 if len(fn) > limit:
20 components = spec.split(":")
21 # Fields 0,5,6 are mandatory, 1 is most useful, 2,3,4 are just for information
22 # 7 is for the separators
23 avail = (254 - len(hash + "_" + taskname + extension) - len(components[0]) - len(components[1]) - len(components[5]) - len(components[6]) - 7) // 3
24 components[2] = components[2][:avail]
25 components[3] = components[3][:avail]
26 components[4] = components[4][:avail]
27 spec = ":".join(components)
28 fn = spec + hash + "_" + taskname + extension
29 if len(fn) > limit:
30 bb.fatal("Unable to reduce sstate name to less than 255 chararacters")
31 return hash[:2] + "/" + hash[2:4] + "/" + fn
Patrick Williamsc124f4f2015-09-15 14:41:29 -050032
33SSTATE_PKGARCH = "${PACKAGE_ARCH}"
34SSTATE_PKGSPEC = "sstate:${PN}:${PACKAGE_ARCH}${TARGET_VENDOR}-${TARGET_OS}:${PV}:${PR}:${SSTATE_PKGARCH}:${SSTATE_VERSION}:"
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050035SSTATE_SWSPEC = "sstate:${PN}::${PV}:${PR}::${SSTATE_VERSION}:"
Andrew Geissler82c905d2020-04-13 13:39:40 -050036SSTATE_PKGNAME = "${SSTATE_EXTRAPATH}${@generate_sstatefn(d.getVar('SSTATE_PKGSPEC'), d.getVar('BB_UNIHASH'), d.getVar('SSTATE_CURRTASK'), False, d)}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050037SSTATE_PKG = "${SSTATE_DIR}/${SSTATE_PKGNAME}"
38SSTATE_EXTRAPATH = ""
39SSTATE_EXTRAPATHWILDCARD = ""
Andrew Geissler82c905d2020-04-13 13:39:40 -050040SSTATE_PATHSPEC = "${SSTATE_DIR}/${SSTATE_EXTRAPATHWILDCARD}*/*/${SSTATE_PKGSPEC}*_${SSTATE_PATH_CURRTASK}.tgz*"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050041
Patrick Williamsc0f7c042017-02-23 20:41:17 -060042# explicitly make PV to depend on evaluated value of PV variable
43PV[vardepvalue] = "${PV}"
44
Patrick Williamsc124f4f2015-09-15 14:41:29 -050045# We don't want the sstate to depend on things like the distro string
46# of the system, we let the sstate paths take care of this.
47SSTATE_EXTRAPATH[vardepvalue] = ""
Brad Bishop19323692019-04-05 15:28:33 -040048SSTATE_EXTRAPATHWILDCARD[vardepvalue] = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -050049
50# For multilib rpm the allarch packagegroup files can overwrite (in theory they're identical)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080051SSTATE_DUPWHITELIST = "${DEPLOY_DIR}/licenses/"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050052# Avoid docbook/sgml catalog warnings for now
53SSTATE_DUPWHITELIST += "${STAGING_ETCDIR_NATIVE}/sgml ${STAGING_DATADIR_NATIVE}/sgml"
Brad Bishop316dfdd2018-06-25 12:45:53 -040054# sdk-provides-dummy-nativesdk and nativesdk-buildtools-perl-dummy overlap for different SDKMACHINE
55SSTATE_DUPWHITELIST += "${DEPLOY_DIR_RPM}/sdk_provides_dummy_nativesdk/ ${DEPLOY_DIR_IPK}/sdk-provides-dummy-nativesdk/"
56SSTATE_DUPWHITELIST += "${DEPLOY_DIR_RPM}/buildtools_dummy_nativesdk/ ${DEPLOY_DIR_IPK}/buildtools-dummy-nativesdk/"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080057# target-sdk-provides-dummy overlaps that allarch is disabled when multilib is used
58SSTATE_DUPWHITELIST += "${COMPONENTS_DIR}/sdk-provides-dummy-target/ ${DEPLOY_DIR_RPM}/sdk_provides_dummy_target/ ${DEPLOY_DIR_IPK}/sdk-provides-dummy-target/"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050059# Archive the sources for many architectures in one deploy folder
60SSTATE_DUPWHITELIST += "${DEPLOY_DIR_SRC}"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080061# ovmf/grub-efi/systemd-boot/intel-microcode multilib recipes can generate identical overlapping files
62SSTATE_DUPWHITELIST += "${DEPLOY_DIR_IMAGE}/ovmf"
63SSTATE_DUPWHITELIST += "${DEPLOY_DIR_IMAGE}/grub-efi"
64SSTATE_DUPWHITELIST += "${DEPLOY_DIR_IMAGE}/systemd-boot"
65SSTATE_DUPWHITELIST += "${DEPLOY_DIR_IMAGE}/microcode"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050066
Brad Bishop6e60e8b2018-02-01 10:27:11 -050067SSTATE_SCAN_FILES ?= "*.la *-config *_config postinst-*"
68SSTATE_SCAN_CMD ??= 'find ${SSTATE_BUILDDIR} \( -name "${@"\" -o -name \"".join(d.getVar("SSTATE_SCAN_FILES").split())}" \) -type f'
69SSTATE_SCAN_CMD_NATIVE ??= 'grep -Irl -e ${RECIPE_SYSROOT} -e ${RECIPE_SYSROOT_NATIVE} -e ${HOSTTOOLS_DIR} ${SSTATE_BUILDDIR}'
Patrick Williamsc124f4f2015-09-15 14:41:29 -050070
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050071BB_HASHFILENAME = "False ${SSTATE_PKGSPEC} ${SSTATE_SWSPEC}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050072
73SSTATE_ARCHS = " \
74 ${BUILD_ARCH} \
75 ${BUILD_ARCH}_${SDK_ARCH}_${SDK_OS} \
76 ${BUILD_ARCH}_${TARGET_ARCH} \
77 ${SDK_ARCH}_${SDK_OS} \
78 ${SDK_ARCH}_${PACKAGE_ARCH} \
79 allarch \
80 ${PACKAGE_ARCH} \
Brad Bishop316dfdd2018-06-25 12:45:53 -040081 ${PACKAGE_EXTRA_ARCHS} \
82 ${MACHINE_ARCH}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050083
84SSTATE_MANMACH ?= "${SSTATE_PKGARCH}"
85
86SSTATECREATEFUNCS = "sstate_hardcode_path"
Brad Bishop19323692019-04-05 15:28:33 -040087SSTATECREATEFUNCS[vardeps] = "SSTATE_SCAN_FILES"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050088SSTATEPOSTCREATEFUNCS = ""
89SSTATEPREINSTFUNCS = ""
90SSTATEPOSTUNPACKFUNCS = "sstate_hardcode_path_unpack"
91SSTATEPOSTINSTFUNCS = ""
Brad Bishop6e60e8b2018-02-01 10:27:11 -050092EXTRA_STAGING_FIXMES ?= "HOSTTOOLS_DIR"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050093
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050094# Check whether sstate exists for tasks that support sstate and are in the
95# locked signatures file.
96SIGGEN_LOCKEDSIGS_SSTATE_EXISTS_CHECK ?= 'error'
97
98# Check whether the task's computed hash matches the task's hash in the
99# locked signatures file.
100SIGGEN_LOCKEDSIGS_TASKSIG_CHECK ?= "error"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500101
102# The GnuPG key ID and passphrase to use to sign sstate archives (or unset to
103# not sign)
104SSTATE_SIG_KEY ?= ""
105SSTATE_SIG_PASSPHRASE ?= ""
106# Whether to verify the GnUPG signatures when extracting sstate archives
107SSTATE_VERIFY_SIG ?= "0"
108
Brad Bishop19323692019-04-05 15:28:33 -0400109SSTATE_HASHEQUIV_METHOD ?= "oe.sstatesig.OEOuthashBasic"
110SSTATE_HASHEQUIV_METHOD[doc] = "The fully-qualified function used to calculate \
111 the output hash for a task, which in turn is used to determine equivalency. \
112 "
113
Brad Bishop19323692019-04-05 15:28:33 -0400114SSTATE_HASHEQUIV_REPORT_TASKDATA ?= "0"
115SSTATE_HASHEQUIV_REPORT_TASKDATA[doc] = "Report additional useful data to the \
116 hash equivalency server, such as PN, PV, taskname, etc. This information \
117 is very useful for developers looking at task data, but may leak sensitive \
118 data if the equivalence server is public. \
119 "
120
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500121python () {
122 if bb.data.inherits_class('native', d):
123 d.setVar('SSTATE_PKGARCH', d.getVar('BUILD_ARCH', False))
124 elif bb.data.inherits_class('crosssdk', d):
125 d.setVar('SSTATE_PKGARCH', d.expand("${BUILD_ARCH}_${SDK_ARCH}_${SDK_OS}"))
126 elif bb.data.inherits_class('cross', d):
127 d.setVar('SSTATE_PKGARCH', d.expand("${BUILD_ARCH}_${TARGET_ARCH}"))
128 elif bb.data.inherits_class('nativesdk', d):
129 d.setVar('SSTATE_PKGARCH', d.expand("${SDK_ARCH}_${SDK_OS}"))
130 elif bb.data.inherits_class('cross-canadian', d):
131 d.setVar('SSTATE_PKGARCH', d.expand("${SDK_ARCH}_${PACKAGE_ARCH}"))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500132 elif bb.data.inherits_class('allarch', d) and d.getVar("PACKAGE_ARCH") == "all":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500133 d.setVar('SSTATE_PKGARCH', "allarch")
134 else:
135 d.setVar('SSTATE_MANMACH', d.expand("${PACKAGE_ARCH}"))
136
137 if bb.data.inherits_class('native', d) or bb.data.inherits_class('crosssdk', d) or bb.data.inherits_class('cross', d):
138 d.setVar('SSTATE_EXTRAPATH', "${NATIVELSBSTRING}/")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500139 d.setVar('BB_HASHFILENAME', "True ${SSTATE_PKGSPEC} ${SSTATE_SWSPEC}")
Brad Bishop19323692019-04-05 15:28:33 -0400140 d.setVar('SSTATE_EXTRAPATHWILDCARD', "${NATIVELSBSTRING}/")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500141
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500142 unique_tasks = sorted(set((d.getVar('SSTATETASKS') or "").split()))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500143 d.setVar('SSTATETASKS', " ".join(unique_tasks))
144 for task in unique_tasks:
145 d.prependVarFlag(task, 'prefuncs', "sstate_task_prefunc ")
146 d.appendVarFlag(task, 'postfuncs', " sstate_task_postfunc")
147}
148
149def sstate_init(task, d):
150 ss = {}
151 ss['task'] = task
152 ss['dirs'] = []
153 ss['plaindirs'] = []
154 ss['lockfiles'] = []
155 ss['lockfiles-shared'] = []
156 return ss
157
158def sstate_state_fromvars(d, task = None):
159 if task is None:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500160 task = d.getVar('BB_CURRENTTASK')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500161 if not task:
162 bb.fatal("sstate code running without task context?!")
163 task = task.replace("_setscene", "")
164
165 if task.startswith("do_"):
166 task = task[3:]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500167 inputs = (d.getVarFlag("do_" + task, 'sstate-inputdirs') or "").split()
168 outputs = (d.getVarFlag("do_" + task, 'sstate-outputdirs') or "").split()
169 plaindirs = (d.getVarFlag("do_" + task, 'sstate-plaindirs') or "").split()
170 lockfiles = (d.getVarFlag("do_" + task, 'sstate-lockfile') or "").split()
171 lockfilesshared = (d.getVarFlag("do_" + task, 'sstate-lockfile-shared') or "").split()
172 interceptfuncs = (d.getVarFlag("do_" + task, 'sstate-interceptfuncs') or "").split()
173 fixmedir = d.getVarFlag("do_" + task, 'sstate-fixmedir') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500174 if not task or len(inputs) != len(outputs):
175 bb.fatal("sstate variables not setup correctly?!")
176
177 if task == "populate_lic":
178 d.setVar("SSTATE_PKGSPEC", "${SSTATE_SWSPEC}")
179 d.setVar("SSTATE_EXTRAPATH", "")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500180 d.setVar('SSTATE_EXTRAPATHWILDCARD', "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500181
182 ss = sstate_init(task, d)
183 for i in range(len(inputs)):
184 sstate_add(ss, inputs[i], outputs[i], d)
185 ss['lockfiles'] = lockfiles
186 ss['lockfiles-shared'] = lockfilesshared
187 ss['plaindirs'] = plaindirs
188 ss['interceptfuncs'] = interceptfuncs
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500189 ss['fixmedir'] = fixmedir
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500190 return ss
191
192def sstate_add(ss, source, dest, d):
193 if not source.endswith("/"):
194 source = source + "/"
195 if not dest.endswith("/"):
196 dest = dest + "/"
197 source = os.path.normpath(source)
198 dest = os.path.normpath(dest)
199 srcbase = os.path.basename(source)
200 ss['dirs'].append([srcbase, source, dest])
201 return ss
202
203def sstate_install(ss, d):
204 import oe.path
205 import oe.sstatesig
206 import subprocess
207
208 sharedfiles = []
209 shareddirs = []
210 bb.utils.mkdirhier(d.expand("${SSTATE_MANIFESTS}"))
211
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500212 sstateinst = d.expand("${WORKDIR}/sstate-install-%s/" % ss['task'])
213
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500214 manifest, d2 = oe.sstatesig.sstate_get_manifest_filename(ss['task'], d)
215
216 if os.access(manifest, os.R_OK):
217 bb.fatal("Package already staged (%s)?!" % manifest)
218
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600219 d.setVar("SSTATE_INST_POSTRM", manifest + ".postrm")
220
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500221 locks = []
222 for lock in ss['lockfiles-shared']:
223 locks.append(bb.utils.lockfile(lock, True))
224 for lock in ss['lockfiles']:
225 locks.append(bb.utils.lockfile(lock))
226
227 for state in ss['dirs']:
228 bb.debug(2, "Staging files from %s to %s" % (state[1], state[2]))
229 for walkroot, dirs, files in os.walk(state[1]):
230 for file in files:
231 srcpath = os.path.join(walkroot, file)
232 dstpath = srcpath.replace(state[1], state[2])
233 #bb.debug(2, "Staging %s to %s" % (srcpath, dstpath))
234 sharedfiles.append(dstpath)
235 for dir in dirs:
236 srcdir = os.path.join(walkroot, dir)
237 dstdir = srcdir.replace(state[1], state[2])
238 #bb.debug(2, "Staging %s to %s" % (srcdir, dstdir))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500239 if os.path.islink(srcdir):
240 sharedfiles.append(dstdir)
241 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500242 if not dstdir.endswith("/"):
243 dstdir = dstdir + "/"
244 shareddirs.append(dstdir)
245
246 # Check the file list for conflicts against files which already exist
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500247 whitelist = (d.getVar("SSTATE_DUPWHITELIST") or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500248 match = []
249 for f in sharedfiles:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500250 if os.path.exists(f) and not os.path.islink(f):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500251 f = os.path.normpath(f)
252 realmatch = True
253 for w in whitelist:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600254 w = os.path.normpath(w)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500255 if f.startswith(w):
256 realmatch = False
257 break
258 if realmatch:
259 match.append(f)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500260 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 -0500261 search_output = subprocess.Popen(sstate_search_cmd, shell=True, stdout=subprocess.PIPE).communicate()[0]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500262 if search_output:
263 match.append(" (matched in %s)" % search_output.decode('utf-8').rstrip())
264 else:
265 match.append(" (not matched to any task)")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500266 if match:
267 bb.error("The recipe %s is trying to install files into a shared " \
268 "area when those files already exist. Those files and their manifest " \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500269 "location are:\n %s\nPlease verify which recipe should provide the " \
270 "above files.\n\nThe build has stopped, as continuing in this scenario WILL " \
271 "break things - if not now, possibly in the future (we've seen builds fail " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500272 "several months later). If the system knew how to recover from this " \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500273 "automatically it would, however there are several different scenarios " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500274 "which can result in this and we don't know which one this is. It may be " \
275 "you have switched providers of something like virtual/kernel (e.g. from " \
276 "linux-yocto to linux-yocto-dev), in that case you need to execute the " \
277 "clean task for both recipes and it will resolve this error. It may be " \
278 "you changed DISTRO_FEATURES from systemd to udev or vice versa. Cleaning " \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500279 "those recipes should again resolve this error, however switching " \
280 "DISTRO_FEATURES on an existing build directory is not supported - you " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500281 "should really clean out tmp and rebuild (reusing sstate should be safe). " \
282 "It could be the overlapping files detected are harmless in which case " \
283 "adding them to SSTATE_DUPWHITELIST may be the correct solution. It could " \
284 "also be your build is including two different conflicting versions of " \
285 "things (e.g. bluez 4 and bluez 5 and the correct solution for that would " \
286 "be to resolve the conflict. If in doubt, please ask on the mailing list, " \
287 "sharing the error and filelist above." % \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500288 (d.getVar('PN'), "\n ".join(match)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500289 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.")
290
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500291 if ss['fixmedir'] and os.path.exists(ss['fixmedir'] + "/fixmepath.cmd"):
292 sharedfiles.append(ss['fixmedir'] + "/fixmepath.cmd")
293 sharedfiles.append(ss['fixmedir'] + "/fixmepath")
294
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500295 # Write out the manifest
296 f = open(manifest, "w")
297 for file in sharedfiles:
298 f.write(file + "\n")
299
300 # We want to ensure that directories appear at the end of the manifest
301 # so that when we test to see if they should be deleted any contents
302 # added by the task will have been removed first.
303 dirs = sorted(shareddirs, key=len)
304 # Must remove children first, which will have a longer path than the parent
305 for di in reversed(dirs):
306 f.write(di + "\n")
307 f.close()
308
309 # Append to the list of manifests for this PACKAGE_ARCH
310
311 i = d2.expand("${SSTATE_MANIFESTS}/index-${SSTATE_MANMACH}")
312 l = bb.utils.lockfile(i + ".lock")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500313 filedata = d.getVar("STAMP") + " " + d2.getVar("SSTATE_MANFILEPREFIX") + " " + d.getVar("WORKDIR") + "\n"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500314 manifests = []
315 if os.path.exists(i):
316 with open(i, "r") as f:
317 manifests = f.readlines()
318 if filedata not in manifests:
319 with open(i, "a+") as f:
320 f.write(filedata)
321 bb.utils.unlockfile(l)
322
323 # Run the actual file install
324 for state in ss['dirs']:
325 if os.path.exists(state[1]):
326 oe.path.copyhardlinktree(state[1], state[2])
327
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500328 for postinst in (d.getVar('SSTATEPOSTINSTFUNCS') or '').split():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500329 # All hooks should run in the SSTATE_INSTDIR
330 bb.build.exec_func(postinst, d, (sstateinst,))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500331
332 for lock in locks:
333 bb.utils.unlockfile(lock)
334
335sstate_install[vardepsexclude] += "SSTATE_DUPWHITELIST STATE_MANMACH SSTATE_MANFILEPREFIX"
336sstate_install[vardeps] += "${SSTATEPOSTINSTFUNCS}"
337
338def sstate_installpkg(ss, d):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500339 from oe.gpg_sign import get_signer
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500340
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500341 sstateinst = d.expand("${WORKDIR}/sstate-install-%s/" % ss['task'])
Andrew Geissler82c905d2020-04-13 13:39:40 -0500342 d.setVar("SSTATE_CURRTASK", ss['task'])
343 sstatefetch = d.getVar('SSTATE_PKGNAME')
344 sstatepkg = d.getVar('SSTATE_PKG')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500345
346 if not os.path.exists(sstatepkg):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800347 pstaging_fetch(sstatefetch, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500348
349 if not os.path.isfile(sstatepkg):
Brad Bishop08902b02019-08-20 09:16:51 -0400350 bb.note("Sstate package %s does not exist" % sstatepkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500351 return False
352
353 sstate_clean(ss, d)
354
355 d.setVar('SSTATE_INSTDIR', sstateinst)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500356
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500357 if bb.utils.to_boolean(d.getVar("SSTATE_VERIFY_SIG"), False):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500358 signer = get_signer(d, 'local')
359 if not signer.verify(sstatepkg + '.sig'):
Brad Bishop08902b02019-08-20 09:16:51 -0400360 bb.warn("Cannot verify signature on sstate package %s, skipping acceleration..." % sstatepkg)
361 return False
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500362
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500363 # Empty sstateinst directory, ensure its clean
364 if os.path.exists(sstateinst):
365 oe.path.remove(sstateinst)
366 bb.utils.mkdirhier(sstateinst)
367
368 sstateinst = d.getVar("SSTATE_INSTDIR")
369 d.setVar('SSTATE_FIXMEDIR', ss['fixmedir'])
370
371 for f in (d.getVar('SSTATEPREINSTFUNCS') or '').split() + ['sstate_unpack_package']:
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500372 # All hooks should run in the SSTATE_INSTDIR
373 bb.build.exec_func(f, d, (sstateinst,))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500374
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500375 return sstate_installpkgdir(ss, d)
376
377def sstate_installpkgdir(ss, d):
378 import oe.path
379 import subprocess
380
381 sstateinst = d.getVar("SSTATE_INSTDIR")
382 d.setVar('SSTATE_FIXMEDIR', ss['fixmedir'])
383
384 for f in (d.getVar('SSTATEPOSTUNPACKFUNCS') or '').split():
385 # All hooks should run in the SSTATE_INSTDIR
386 bb.build.exec_func(f, d, (sstateinst,))
387
388 def prepdir(dir):
389 # remove dir if it exists, ensure any parent directories do exist
390 if os.path.exists(dir):
391 oe.path.remove(dir)
392 bb.utils.mkdirhier(dir)
393 oe.path.remove(dir)
394
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500395 for state in ss['dirs']:
396 prepdir(state[1])
397 os.rename(sstateinst + state[0], state[1])
398 sstate_install(ss, d)
399
400 for plain in ss['plaindirs']:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500401 workdir = d.getVar('WORKDIR')
Brad Bishop977dc1a2019-02-06 16:01:43 -0500402 sharedworkdir = os.path.join(d.getVar('TMPDIR'), "work-shared")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500403 src = sstateinst + "/" + plain.replace(workdir, '')
Brad Bishop977dc1a2019-02-06 16:01:43 -0500404 if sharedworkdir in plain:
405 src = sstateinst + "/" + plain.replace(sharedworkdir, '')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500406 dest = plain
407 bb.utils.mkdirhier(src)
408 prepdir(dest)
409 os.rename(src, dest)
410
411 return True
412
413python sstate_hardcode_path_unpack () {
414 # Fixup hardcoded paths
415 #
416 # Note: The logic below must match the reverse logic in
417 # sstate_hardcode_path(d)
418 import subprocess
419
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500420 sstateinst = d.getVar('SSTATE_INSTDIR')
421 sstatefixmedir = d.getVar('SSTATE_FIXMEDIR')
422 fixmefn = sstateinst + "fixmepath"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500423 if os.path.isfile(fixmefn):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500424 staging_target = d.getVar('RECIPE_SYSROOT')
425 staging_host = d.getVar('RECIPE_SYSROOT_NATIVE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500426
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500427 if bb.data.inherits_class('native', d) or bb.data.inherits_class('cross-canadian', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500428 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRHOST:%s:g'" % (staging_host)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500429 elif bb.data.inherits_class('cross', d) or bb.data.inherits_class('crosssdk', d):
430 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRTARGET:%s:g; s:FIXMESTAGINGDIRHOST:%s:g'" % (staging_target, staging_host)
431 else:
432 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRTARGET:%s:g'" % (staging_target)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500433
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500434 extra_staging_fixmes = d.getVar('EXTRA_STAGING_FIXMES') or ''
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500435 for fixmevar in extra_staging_fixmes.split():
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500436 fixme_path = d.getVar(fixmevar)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500437 sstate_sed_cmd += " -e 's:FIXME_%s:%s:g'" % (fixmevar, fixme_path)
438
439 # Add sstateinst to each filename in fixmepath, use xargs to efficiently call sed
440 sstate_hardcode_cmd = "sed -e 's:^:%s:g' %s | xargs %s" % (sstateinst, fixmefn, sstate_sed_cmd)
441
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500442 # Defer do_populate_sysroot relocation command
443 if sstatefixmedir:
444 bb.utils.mkdirhier(sstatefixmedir)
445 with open(sstatefixmedir + "/fixmepath.cmd", "w") as f:
446 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(fixmefn, sstatefixmedir + "/fixmepath")
447 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(sstateinst, "FIXMEFINALSSTATEINST")
448 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(staging_host, "FIXMEFINALSSTATEHOST")
449 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(staging_target, "FIXMEFINALSSTATETARGET")
450 f.write(sstate_hardcode_cmd)
451 bb.utils.copyfile(fixmefn, sstatefixmedir + "/fixmepath")
452 return
453
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500454 bb.note("Replacing fixme paths in sstate package: %s" % (sstate_hardcode_cmd))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500455 subprocess.check_call(sstate_hardcode_cmd, shell=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500456
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800457 # Need to remove this or we'd copy it into the target directory and may
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500458 # conflict with another writer
459 os.remove(fixmefn)
460}
461
462def sstate_clean_cachefile(ss, d):
463 import oe.path
464
Brad Bishopa5c52ff2018-11-23 10:55:50 +1300465 if d.getVarFlag('do_%s' % ss['task'], 'task'):
Andrew Geissler82c905d2020-04-13 13:39:40 -0500466 d.setVar("SSTATE_PATH_CURRTASK", ss['task'])
467 sstatepkgfile = d.getVar('SSTATE_PATHSPEC')
Brad Bishopa5c52ff2018-11-23 10:55:50 +1300468 bb.note("Removing %s" % sstatepkgfile)
469 oe.path.remove(sstatepkgfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500470
471def sstate_clean_cachefiles(d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500472 for task in (d.getVar('SSTATETASKS') or "").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500473 ld = d.createCopy()
474 ss = sstate_state_fromvars(ld, task)
475 sstate_clean_cachefile(ss, ld)
476
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500477def sstate_clean_manifest(manifest, d, prefix=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500478 import oe.path
479
480 mfile = open(manifest)
481 entries = mfile.readlines()
482 mfile.close()
483
484 for entry in entries:
485 entry = entry.strip()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500486 if prefix and not entry.startswith("/"):
487 entry = prefix + "/" + entry
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500488 bb.debug(2, "Removing manifest: %s" % entry)
489 # We can race against another package populating directories as we're removing them
490 # so we ignore errors here.
491 try:
492 if entry.endswith("/"):
493 if os.path.islink(entry[:-1]):
494 os.remove(entry[:-1])
495 elif os.path.exists(entry) and len(os.listdir(entry)) == 0:
496 os.rmdir(entry[:-1])
497 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500498 os.remove(entry)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500499 except OSError:
500 pass
501
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600502 postrm = manifest + ".postrm"
503 if os.path.exists(manifest + ".postrm"):
504 import subprocess
505 os.chmod(postrm, 0o755)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500506 subprocess.check_call(postrm, shell=True)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600507 oe.path.remove(postrm)
508
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500509 oe.path.remove(manifest)
510
511def sstate_clean(ss, d):
512 import oe.path
513 import glob
514
515 d2 = d.createCopy()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500516 stamp_clean = d.getVar("STAMPCLEAN")
517 extrainf = d.getVarFlag("do_" + ss['task'], 'stamp-extra-info')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500518 if extrainf:
519 d2.setVar("SSTATE_MANMACH", extrainf)
520 wildcard_stfile = "%s.do_%s*.%s" % (stamp_clean, ss['task'], extrainf)
521 else:
522 wildcard_stfile = "%s.do_%s*" % (stamp_clean, ss['task'])
523
524 manifest = d2.expand("${SSTATE_MANFILEPREFIX}.%s" % ss['task'])
525
526 if os.path.exists(manifest):
527 locks = []
528 for lock in ss['lockfiles-shared']:
529 locks.append(bb.utils.lockfile(lock))
530 for lock in ss['lockfiles']:
531 locks.append(bb.utils.lockfile(lock))
532
533 sstate_clean_manifest(manifest, d)
534
535 for lock in locks:
536 bb.utils.unlockfile(lock)
537
538 # Remove the current and previous stamps, but keep the sigdata.
539 #
540 # The glob() matches do_task* which may match multiple tasks, for
541 # example: do_package and do_package_write_ipk, so we need to
542 # exactly match *.do_task.* and *.do_task_setscene.*
543 rm_stamp = '.do_%s.' % ss['task']
544 rm_setscene = '.do_%s_setscene.' % ss['task']
545 # For BB_SIGNATURE_HANDLER = "noop"
546 rm_nohash = ".do_%s" % ss['task']
547 for stfile in glob.glob(wildcard_stfile):
548 # Keep the sigdata
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500549 if ".sigdata." in stfile or ".sigbasedata." in stfile:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500550 continue
551 # Preserve taint files in the stamps directory
552 if stfile.endswith('.taint'):
553 continue
554 if rm_stamp in stfile or rm_setscene in stfile or \
555 stfile.endswith(rm_nohash):
556 oe.path.remove(stfile)
557
558sstate_clean[vardepsexclude] = "SSTATE_MANFILEPREFIX"
559
560CLEANFUNCS += "sstate_cleanall"
561
562python sstate_cleanall() {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500563 bb.note("Removing shared state for package %s" % d.getVar('PN'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500564
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500565 manifest_dir = d.getVar('SSTATE_MANIFESTS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500566 if not os.path.exists(manifest_dir):
567 return
568
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500569 tasks = d.getVar('SSTATETASKS').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500570 for name in tasks:
571 ld = d.createCopy()
572 shared_state = sstate_state_fromvars(ld, name)
573 sstate_clean(shared_state, ld)
574}
575
576python sstate_hardcode_path () {
577 import subprocess, platform
578
579 # Need to remove hardcoded paths and fix these when we install the
580 # staging packages.
581 #
582 # Note: the logic in this function needs to match the reverse logic
583 # in sstate_installpkg(ss, d)
584
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500585 staging_target = d.getVar('RECIPE_SYSROOT')
586 staging_host = d.getVar('RECIPE_SYSROOT_NATIVE')
587 sstate_builddir = d.getVar('SSTATE_BUILDDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500588
Brad Bishop316dfdd2018-06-25 12:45:53 -0400589 sstate_sed_cmd = "sed -i -e 's:%s:FIXMESTAGINGDIRHOST:g'" % staging_host
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500590 if bb.data.inherits_class('native', d) or bb.data.inherits_class('cross-canadian', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500591 sstate_grep_cmd = "grep -l -e '%s'" % (staging_host)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500592 elif bb.data.inherits_class('cross', d) or bb.data.inherits_class('crosssdk', d):
593 sstate_grep_cmd = "grep -l -e '%s' -e '%s'" % (staging_target, staging_host)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400594 sstate_sed_cmd += " -e 's:%s:FIXMESTAGINGDIRTARGET:g'" % staging_target
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500595 else:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400596 sstate_grep_cmd = "grep -l -e '%s' -e '%s'" % (staging_target, staging_host)
597 sstate_sed_cmd += " -e 's:%s:FIXMESTAGINGDIRTARGET:g'" % staging_target
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500598
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500599 extra_staging_fixmes = d.getVar('EXTRA_STAGING_FIXMES') or ''
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500600 for fixmevar in extra_staging_fixmes.split():
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500601 fixme_path = d.getVar(fixmevar)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500602 sstate_sed_cmd += " -e 's:%s:FIXME_%s:g'" % (fixme_path, fixmevar)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500603 sstate_grep_cmd += " -e '%s'" % (fixme_path)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500604
605 fixmefn = sstate_builddir + "fixmepath"
606
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500607 sstate_scan_cmd = d.getVar('SSTATE_SCAN_CMD')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500608 sstate_filelist_cmd = "tee %s" % (fixmefn)
609
610 # fixmepath file needs relative paths, drop sstate_builddir prefix
611 sstate_filelist_relative_cmd = "sed -i -e 's:^%s::g' %s" % (sstate_builddir, fixmefn)
612
613 xargs_no_empty_run_cmd = '--no-run-if-empty'
614 if platform.system() == 'Darwin':
615 xargs_no_empty_run_cmd = ''
616
617 # Limit the fixpaths and sed operations based on the initial grep search
618 # This has the side effect of making sure the vfs cache is hot
619 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)
620
621 bb.note("Removing hardcoded paths from sstate package: '%s'" % (sstate_hardcode_cmd))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500622 subprocess.check_output(sstate_hardcode_cmd, shell=True, cwd=sstate_builddir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500623
624 # If the fixmefn is empty, remove it..
625 if os.stat(fixmefn).st_size == 0:
626 os.remove(fixmefn)
627 else:
628 bb.note("Replacing absolute paths in fixmepath file: '%s'" % (sstate_filelist_relative_cmd))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500629 subprocess.check_output(sstate_filelist_relative_cmd, shell=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500630}
631
632def sstate_package(ss, d):
633 import oe.path
634
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500635 tmpdir = d.getVar('TMPDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500636
637 sstatebuild = d.expand("${WORKDIR}/sstate-build-%s/" % ss['task'])
Andrew Geissler82c905d2020-04-13 13:39:40 -0500638 d.setVar("SSTATE_CURRTASK", ss['task'])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500639 bb.utils.remove(sstatebuild, recurse=True)
640 bb.utils.mkdirhier(sstatebuild)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500641 for state in ss['dirs']:
642 if not os.path.exists(state[1]):
643 continue
644 srcbase = state[0].rstrip("/").rsplit('/', 1)[0]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500645 # Find and error for absolute symlinks. We could attempt to relocate but its not
646 # clear where the symlink is relative to in this context. We could add that markup
647 # to sstate tasks but there aren't many of these so better just avoid them entirely.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500648 for walkroot, dirs, files in os.walk(state[1]):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500649 for file in files + dirs:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500650 srcpath = os.path.join(walkroot, file)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500651 if not os.path.islink(srcpath):
652 continue
653 link = os.readlink(srcpath)
654 if not os.path.isabs(link):
655 continue
656 if not link.startswith(tmpdir):
657 continue
658 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 -0500659 bb.debug(2, "Preparing tree %s for packaging at %s" % (state[1], sstatebuild + state[0]))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500660 os.rename(state[1], sstatebuild + state[0])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500661
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500662 workdir = d.getVar('WORKDIR')
Brad Bishop977dc1a2019-02-06 16:01:43 -0500663 sharedworkdir = os.path.join(d.getVar('TMPDIR'), "work-shared")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500664 for plain in ss['plaindirs']:
665 pdir = plain.replace(workdir, sstatebuild)
Brad Bishop977dc1a2019-02-06 16:01:43 -0500666 if sharedworkdir in plain:
667 pdir = plain.replace(sharedworkdir, sstatebuild)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500668 bb.utils.mkdirhier(plain)
669 bb.utils.mkdirhier(pdir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500670 os.rename(plain, pdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500671
672 d.setVar('SSTATE_BUILDDIR', sstatebuild)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500673 d.setVar('SSTATE_INSTDIR', sstatebuild)
674
675 if d.getVar('SSTATE_SKIP_CREATION') == '1':
676 return
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500677
Brad Bishop08902b02019-08-20 09:16:51 -0400678 sstate_create_package = ['sstate_report_unihash', 'sstate_create_package']
679 if d.getVar('SSTATE_SIG_KEY'):
680 sstate_create_package.append('sstate_sign_package')
681
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500682 for f in (d.getVar('SSTATECREATEFUNCS') or '').split() + \
Brad Bishop08902b02019-08-20 09:16:51 -0400683 sstate_create_package + \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500684 (d.getVar('SSTATEPOSTCREATEFUNCS') or '').split():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500685 # All hooks should run in SSTATE_BUILDDIR.
686 bb.build.exec_func(f, d, (sstatebuild,))
687
Andrew Geissler82c905d2020-04-13 13:39:40 -0500688 # SSTATE_PKG may have been changed by sstate_report_unihash
689 siginfo = d.getVar('SSTATE_PKG') + ".siginfo"
690 if not os.path.exists(siginfo):
691 bb.siggen.dump_this_task(siginfo, d)
692 else:
693 os.utime(siginfo, None)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500694
695 return
696
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800697def pstaging_fetch(sstatefetch, d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500698 import bb.fetch2
699
700 # Only try and fetch if the user has configured a mirror
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500701 mirrors = d.getVar('SSTATE_MIRRORS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500702 if not mirrors:
703 return
704
705 # Copy the data object and override DL_DIR and SRC_URI
706 localdata = bb.data.createCopy(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500707
708 dldir = localdata.expand("${SSTATE_DIR}")
709 bb.utils.mkdirhier(dldir)
710
711 localdata.delVar('MIRRORS')
712 localdata.setVar('FILESPATH', dldir)
713 localdata.setVar('DL_DIR', dldir)
714 localdata.setVar('PREMIRRORS', mirrors)
715
716 # if BB_NO_NETWORK is set but we also have SSTATE_MIRROR_ALLOW_NETWORK,
717 # we'll want to allow network access for the current set of fetches.
Brad Bishopd89cb5f2019-04-10 09:02:41 -0400718 if bb.utils.to_boolean(localdata.getVar('BB_NO_NETWORK')) and \
719 bb.utils.to_boolean(localdata.getVar('SSTATE_MIRROR_ALLOW_NETWORK')):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500720 localdata.delVar('BB_NO_NETWORK')
721
722 # Try a fetch from the sstate mirror, if it fails just return and
723 # we will build the package
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600724 uris = ['file://{0};downloadfilename={0}'.format(sstatefetch),
725 'file://{0}.siginfo;downloadfilename={0}.siginfo'.format(sstatefetch)]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500726 if bb.utils.to_boolean(d.getVar("SSTATE_VERIFY_SIG"), False):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600727 uris += ['file://{0}.sig;downloadfilename={0}.sig'.format(sstatefetch)]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500728
729 for srcuri in uris:
730 localdata.setVar('SRC_URI', srcuri)
731 try:
732 fetcher = bb.fetch2.Fetch([srcuri], localdata, cache=False)
733 fetcher.download()
734
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500735 except bb.fetch2.BBFetchException:
736 break
737
738def sstate_setscene(d):
739 shared_state = sstate_state_fromvars(d)
740 accelerate = sstate_installpkg(shared_state, d)
741 if not accelerate:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600742 bb.fatal("No suitable staging package found")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500743
744python sstate_task_prefunc () {
745 shared_state = sstate_state_fromvars(d)
746 sstate_clean(shared_state, d)
747}
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500748sstate_task_prefunc[dirs] = "${WORKDIR}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500749
750python sstate_task_postfunc () {
751 shared_state = sstate_state_fromvars(d)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500752
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500753 for intercept in shared_state['interceptfuncs']:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500754 bb.build.exec_func(intercept, d, (d.getVar("WORKDIR"),))
755
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600756 omask = os.umask(0o002)
757 if omask != 0o002:
758 bb.note("Using umask 0o002 (not %0o) for sstate packaging" % omask)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500759 sstate_package(shared_state, d)
760 os.umask(omask)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500761
762 sstateinst = d.getVar("SSTATE_INSTDIR")
763 d.setVar('SSTATE_FIXMEDIR', shared_state['fixmedir'])
764
765 sstate_installpkgdir(shared_state, d)
766
767 bb.utils.remove(d.getVar("SSTATE_BUILDDIR"), recurse=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500768}
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500769sstate_task_postfunc[dirs] = "${WORKDIR}"
770
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500771
772#
773# Shell function to generate a sstate package from a directory
774# set as SSTATE_BUILDDIR. Will be run from within SSTATE_BUILDDIR.
775#
776sstate_create_package () {
Andrew Geissler82c905d2020-04-13 13:39:40 -0500777 # Exit early if it already exists
Brad Bishop08902b02019-08-20 09:16:51 -0400778 if [ -e ${SSTATE_PKG} ]; then
Andrew Geissler82c905d2020-04-13 13:39:40 -0500779 touch ${SSTATE_PKG}
Brad Bishop08902b02019-08-20 09:16:51 -0400780 return
781 fi
782
Andrew Geissler82c905d2020-04-13 13:39:40 -0500783 mkdir -p `dirname ${SSTATE_PKG}`
784 TFILE=`mktemp ${SSTATE_PKG}.XXXXXXXX`
785
786 # Use pigz if available
787 OPT="-czS"
788 if [ -x "$(command -v pigz)" ]; then
789 OPT="-I pigz -cS"
790 fi
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800791
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500792 # Need to handle empty directories
793 if [ "$(ls -A)" ]; then
794 set +e
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800795 tar $OPT -f $TFILE *
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500796 ret=$?
797 if [ $ret -ne 0 ] && [ $ret -ne 1 ]; then
798 exit 1
799 fi
800 set -e
801 else
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800802 tar $OPT --file=$TFILE --files-from=/dev/null
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500803 fi
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500804 chmod 0664 $TFILE
Brad Bishop08902b02019-08-20 09:16:51 -0400805 # Skip if it was already created by some other process
806 if [ ! -e ${SSTATE_PKG} ]; then
Andrew Geissler82c905d2020-04-13 13:39:40 -0500807 # Move into place using ln to attempt an atomic op.
808 # Abort if it already exists
809 ln $TFILE ${SSTATE_PKG} && rm $TFILE
Brad Bishop08902b02019-08-20 09:16:51 -0400810 else
811 rm $TFILE
812 fi
Andrew Geissler82c905d2020-04-13 13:39:40 -0500813 touch ${SSTATE_PKG}
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500814}
815
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500816python sstate_sign_package () {
817 from oe.gpg_sign import get_signer
818
Brad Bishop08902b02019-08-20 09:16:51 -0400819
820 signer = get_signer(d, 'local')
821 sstate_pkg = d.getVar('SSTATE_PKG')
822 if os.path.exists(sstate_pkg + '.sig'):
823 os.unlink(sstate_pkg + '.sig')
824 signer.detach_sign(sstate_pkg, d.getVar('SSTATE_SIG_KEY', False), None,
825 d.getVar('SSTATE_SIG_PASSPHRASE'), armor=False)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500826}
827
Brad Bishop19323692019-04-05 15:28:33 -0400828python sstate_report_unihash() {
829 report_unihash = getattr(bb.parse.siggen, 'report_unihash', None)
830
831 if report_unihash:
832 ss = sstate_state_fromvars(d)
833 report_unihash(os.getcwd(), ss['task'], d)
834}
835
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500836#
837# Shell function to decompress and prepare a package for installation
838# Will be run from within SSTATE_INSTDIR.
839#
840sstate_unpack_package () {
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500841 tar -xvzf ${SSTATE_PKG}
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500842 # update .siginfo atime on local/NFS mirror
843 [ -w ${SSTATE_PKG}.siginfo ] && [ -h ${SSTATE_PKG}.siginfo ] && touch -a ${SSTATE_PKG}.siginfo
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500844 # Use "! -w ||" to return true for read only files
845 [ ! -w ${SSTATE_PKG} ] || touch --no-dereference ${SSTATE_PKG}
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500846 [ ! -w ${SSTATE_PKG}.sig ] || [ ! -e ${SSTATE_PKG}.sig ] || touch --no-dereference ${SSTATE_PKG}.sig
847 [ ! -w ${SSTATE_PKG}.siginfo ] || [ ! -e ${SSTATE_PKG}.siginfo ] || touch --no-dereference ${SSTATE_PKG}.siginfo
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500848}
849
850BB_HASHCHECK_FUNCTION = "sstate_checkhashes"
851
Brad Bishop1d80a2e2019-11-15 16:35:03 -0500852def sstate_checkhashes(sq_data, d, siginfo=False, currentcount=0, summary=True, **kwargs):
Brad Bishop08902b02019-08-20 09:16:51 -0400853 found = set()
854 missed = set()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500855
Brad Bishop19323692019-04-05 15:28:33 -0400856 def gethash(task):
Brad Bishop08902b02019-08-20 09:16:51 -0400857 return sq_data['unihash'][task]
Brad Bishop19323692019-04-05 15:28:33 -0400858
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500859 def getpathcomponents(task, d):
860 # Magic data from BB_HASHFILENAME
Brad Bishop08902b02019-08-20 09:16:51 -0400861 splithashfn = sq_data['hashfn'][task].split(" ")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500862 spec = splithashfn[1]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500863 if splithashfn[0] == "True":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500864 extrapath = d.getVar("NATIVELSBSTRING") + "/"
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500865 else:
866 extrapath = ""
Brad Bishop08902b02019-08-20 09:16:51 -0400867
868 tname = bb.runqueue.taskname_from_tid(task)[3:]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500869
870 if tname in ["fetch", "unpack", "patch", "populate_lic", "preconfigure"] and splithashfn[2]:
871 spec = splithashfn[2]
872 extrapath = ""
873
874 return spec, extrapath, tname
875
876
Brad Bishop08902b02019-08-20 09:16:51 -0400877 for tid in sq_data['hash']:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500878
Brad Bishop08902b02019-08-20 09:16:51 -0400879 spec, extrapath, tname = getpathcomponents(tid, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500880
Andrew Geissler82c905d2020-04-13 13:39:40 -0500881 sstatefile = d.expand("${SSTATE_DIR}/" + extrapath + generate_sstatefn(spec, gethash(tid), tname, siginfo, d))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500882
883 if os.path.exists(sstatefile):
884 bb.debug(2, "SState: Found valid sstate file %s" % sstatefile)
Brad Bishop08902b02019-08-20 09:16:51 -0400885 found.add(tid)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500886 continue
887 else:
Brad Bishop08902b02019-08-20 09:16:51 -0400888 missed.add(tid)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500889 bb.debug(2, "SState: Looked for but didn't find file %s" % sstatefile)
890
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500891 mirrors = d.getVar("SSTATE_MIRRORS")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500892 if mirrors:
893 # Copy the data object and override DL_DIR and SRC_URI
894 localdata = bb.data.createCopy(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500895
896 dldir = localdata.expand("${SSTATE_DIR}")
897 localdata.delVar('MIRRORS')
898 localdata.setVar('FILESPATH', dldir)
899 localdata.setVar('DL_DIR', dldir)
900 localdata.setVar('PREMIRRORS', mirrors)
901
902 bb.debug(2, "SState using premirror of: %s" % mirrors)
903
904 # if BB_NO_NETWORK is set but we also have SSTATE_MIRROR_ALLOW_NETWORK,
905 # we'll want to allow network access for the current set of fetches.
Brad Bishopd89cb5f2019-04-10 09:02:41 -0400906 if bb.utils.to_boolean(localdata.getVar('BB_NO_NETWORK')) and \
907 bb.utils.to_boolean(localdata.getVar('SSTATE_MIRROR_ALLOW_NETWORK')):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500908 localdata.delVar('BB_NO_NETWORK')
909
910 from bb.fetch2 import FetchConnectionCache
911 def checkstatus_init(thread_worker):
912 thread_worker.connection_cache = FetchConnectionCache()
913
914 def checkstatus_end(thread_worker):
915 thread_worker.connection_cache.close_connections()
916
917 def checkstatus(thread_worker, arg):
Brad Bishop08902b02019-08-20 09:16:51 -0400918 (tid, sstatefile) = arg
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500919
920 localdata2 = bb.data.createCopy(localdata)
921 srcuri = "file://" + sstatefile
922 localdata.setVar('SRC_URI', srcuri)
923 bb.debug(2, "SState: Attempting to fetch %s" % srcuri)
924
925 try:
926 fetcher = bb.fetch2.Fetch(srcuri.split(), localdata2,
927 connection_cache=thread_worker.connection_cache)
928 fetcher.checkstatus()
929 bb.debug(2, "SState: Successful fetch test for %s" % srcuri)
Brad Bishop08902b02019-08-20 09:16:51 -0400930 found.add(tid)
931 if tid in missed:
932 missed.remove(tid)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500933 except:
Brad Bishop08902b02019-08-20 09:16:51 -0400934 missed.add(tid)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500935 bb.debug(2, "SState: Unsuccessful fetch test for %s" % srcuri)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600936 pass
Andrew Geissler82c905d2020-04-13 13:39:40 -0500937 if len(tasklist) >= min_tasks:
938 bb.event.fire(bb.event.ProcessProgress(msg, len(tasklist) - thread_worker.tasks.qsize()), d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500939
940 tasklist = []
Andrew Geissler82c905d2020-04-13 13:39:40 -0500941 min_tasks = 100
Brad Bishop08902b02019-08-20 09:16:51 -0400942 for tid in sq_data['hash']:
943 if tid in found:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500944 continue
Brad Bishop08902b02019-08-20 09:16:51 -0400945 spec, extrapath, tname = getpathcomponents(tid, d)
Andrew Geissler82c905d2020-04-13 13:39:40 -0500946 sstatefile = d.expand(extrapath + generate_sstatefn(spec, gethash(tid), tname, siginfo, d))
Brad Bishop08902b02019-08-20 09:16:51 -0400947 tasklist.append((tid, sstatefile))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500948
949 if tasklist:
Andrew Geissler82c905d2020-04-13 13:39:40 -0500950 if len(tasklist) >= min_tasks:
951 msg = "Checking sstate mirror object availability"
952 bb.event.fire(bb.event.ProcessStarted(msg, len(tasklist)), d)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600953
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500954 import multiprocessing
955 nproc = min(multiprocessing.cpu_count(), len(tasklist))
956
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600957 bb.event.enable_threadlock()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500958 pool = oe.utils.ThreadedPool(nproc, len(tasklist),
959 worker_init=checkstatus_init, worker_end=checkstatus_end)
960 for t in tasklist:
961 pool.add_task(checkstatus, t)
962 pool.start()
963 pool.wait_completion()
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600964 bb.event.disable_threadlock()
965
Andrew Geissler82c905d2020-04-13 13:39:40 -0500966 if len(tasklist) >= min_tasks:
967 bb.event.fire(bb.event.ProcessFinished(msg), d)
Brad Bishop96ff1982019-08-19 13:50:42 -0400968
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500969 inheritlist = d.getVar("INHERIT")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500970 if "toaster" in inheritlist:
971 evdata = {'missed': [], 'found': []};
Brad Bishop08902b02019-08-20 09:16:51 -0400972 for tid in missed:
973 spec, extrapath, tname = getpathcomponents(tid, d)
Andrew Geissler82c905d2020-04-13 13:39:40 -0500974 sstatefile = d.expand(extrapath + generate_sstatefn(spec, gethash(tid), tname, False, d))
Brad Bishop08902b02019-08-20 09:16:51 -0400975 evdata['missed'].append((bb.runqueue.fn_from_tid(tid), bb.runqueue.taskname_from_tid(tid), gethash(tid), sstatefile ) )
976 for tid in found:
977 spec, extrapath, tname = getpathcomponents(tid, d)
Andrew Geissler82c905d2020-04-13 13:39:40 -0500978 sstatefile = d.expand(extrapath + generate_sstatefn(spec, gethash(tid), tname, False, d))
Brad Bishop08902b02019-08-20 09:16:51 -0400979 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 -0500980 bb.event.fire(bb.event.MetadataEvent("MissedSstate", evdata), d)
981
Brad Bishop1d80a2e2019-11-15 16:35:03 -0500982 if summary:
983 # Print some summary statistics about the current task completion and how much sstate
984 # reuse there was. Avoid divide by zero errors.
985 total = len(sq_data['hash'])
986 complete = 0
987 if currentcount:
988 complete = (len(found) + currentcount) / (total + currentcount) * 100
989 match = 0
990 if total:
991 match = len(found) / total * 100
992 bb.plain("Sstate summary: Wanted %d Found %d Missed %d Current %d (%d%% match, %d%% complete)" % (total, len(found), len(missed), currentcount, match, complete))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800993
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500994 if hasattr(bb.parse.siggen, "checkhashes"):
Brad Bishop08902b02019-08-20 09:16:51 -0400995 bb.parse.siggen.checkhashes(sq_data, missed, found, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500996
Brad Bishop08902b02019-08-20 09:16:51 -0400997 return found
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500998
999BB_SETSCENE_DEPVALID = "setscene_depvalid"
1000
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001001def setscene_depvalid(task, taskdependees, notneeded, d, log=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001002 # taskdependees is a dict of tasks which depend on task, each being a 3 item list of [PN, TASKNAME, FILENAME]
1003 # task is included in taskdependees too
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001004 # Return - False - We need this dependency
1005 # - True - We can skip this dependency
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001006 import re
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001007
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001008 def logit(msg, log):
1009 if log is not None:
1010 log.append(msg)
1011 else:
1012 bb.debug(2, msg)
1013
1014 logit("Considering setscene task: %s" % (str(taskdependees[task])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001015
1016 def isNativeCross(x):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001017 return x.endswith("-native") or "-cross-" in x or "-crosssdk" in x or x.endswith("-cross")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001018
1019 # We only need to trigger populate_lic through direct dependencies
1020 if taskdependees[task][1] == "do_populate_lic":
1021 return True
1022
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001023 # stash_locale and gcc_stash_builddir are never needed as a dependency for built objects
1024 if taskdependees[task][1] == "do_stash_locale" or taskdependees[task][1] == "do_gcc_stash_builddir":
1025 return True
1026
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001027 # We only need to trigger packagedata through direct dependencies
1028 # but need to preserve packagedata on packagedata links
1029 if taskdependees[task][1] == "do_packagedata":
1030 for dep in taskdependees:
1031 if taskdependees[dep][1] == "do_packagedata":
1032 return False
1033 return True
1034
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001035 for dep in taskdependees:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001036 logit(" considering dependency: %s" % (str(taskdependees[dep])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001037 if task == dep:
1038 continue
1039 if dep in notneeded:
1040 continue
1041 # do_package_write_* and do_package doesn't need do_package
1042 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']:
1043 continue
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001044 # do_package_write_* need do_populate_sysroot as they're mainly postinstall dependencies
1045 if taskdependees[task][1] == "do_populate_sysroot" and taskdependees[dep][1] in ['do_package_write_deb', 'do_package_write_ipk', 'do_package_write_rpm']:
1046 return False
1047 # do_package/packagedata/package_qa don't need do_populate_sysroot
1048 if taskdependees[task][1] == "do_populate_sysroot" and taskdependees[dep][1] in ['do_package', 'do_packagedata', 'do_package_qa']:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001049 continue
1050 # Native/Cross packages don't exist and are noexec anyway
1051 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']:
1052 continue
1053
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001054 # This is due to the [depends] in useradd.bbclass complicating matters
1055 # The logic *is* reversed here due to the way hard setscene dependencies are injected
1056 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':
1057 continue
1058
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001059 # Consider sysroot depending on sysroot tasks
1060 if taskdependees[task][1] == 'do_populate_sysroot' and taskdependees[dep][1] == 'do_populate_sysroot':
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001061 # Allow excluding certain recursive dependencies. If a recipe needs it should add a
1062 # specific dependency itself, rather than relying on one of its dependees to pull
1063 # them in.
1064 # See also http://lists.openembedded.org/pipermail/openembedded-core/2018-January/146324.html
1065 not_needed = False
1066 excludedeps = d.getVar('_SSTATE_EXCLUDEDEPS_SYSROOT')
1067 if excludedeps is None:
1068 # Cache the regular expressions for speed
1069 excludedeps = []
1070 for excl in (d.getVar('SSTATE_EXCLUDEDEPS_SYSROOT') or "").split():
1071 excludedeps.append((re.compile(excl.split('->', 1)[0]), re.compile(excl.split('->', 1)[1])))
1072 d.setVar('_SSTATE_EXCLUDEDEPS_SYSROOT', excludedeps)
1073 for excl in excludedeps:
1074 if excl[0].match(taskdependees[dep][0]):
1075 if excl[1].match(taskdependees[task][0]):
1076 not_needed = True
1077 break
1078 if not_needed:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001079 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001080 # For meta-extsdk-toolchain we want all sysroot dependencies
1081 if taskdependees[dep][0] == 'meta-extsdk-toolchain':
1082 return False
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001083 # Native/Cross populate_sysroot need their dependencies
1084 if isNativeCross(taskdependees[task][0]) and isNativeCross(taskdependees[dep][0]):
1085 return False
1086 # Target populate_sysroot depended on by cross tools need to be installed
1087 if isNativeCross(taskdependees[dep][0]):
1088 return False
1089 # Native/cross tools depended upon by target sysroot are not needed
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001090 # Add an exception for shadow-native as required by useradd.bbclass
1091 if isNativeCross(taskdependees[task][0]) and taskdependees[task][0] != 'shadow-native':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001092 continue
1093 # Target populate_sysroot need their dependencies
1094 return False
1095
1096 if taskdependees[task][1] == 'do_shared_workdir':
1097 continue
1098
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001099 if taskdependees[dep][1] == "do_populate_lic":
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001100 continue
1101
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001102
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001103 # Safe fallthrough default
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001104 logit(" Default setscene dependency fall through due to dependency: %s" % (str(taskdependees[dep])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001105 return False
1106 return True
1107
1108addhandler sstate_eventhandler
1109sstate_eventhandler[eventmask] = "bb.build.TaskSucceeded"
1110python sstate_eventhandler() {
1111 d = e.data
Andrew Geissler82c905d2020-04-13 13:39:40 -05001112 writtensstate = d.getVar('SSTATE_CURRTASK')
1113 if not writtensstate:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001114 taskname = d.getVar("BB_RUNTASK")[3:]
1115 spec = d.getVar('SSTATE_PKGSPEC')
1116 swspec = d.getVar('SSTATE_SWSPEC')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001117 if taskname in ["fetch", "unpack", "patch", "populate_lic", "preconfigure"] and swspec:
1118 d.setVar("SSTATE_PKGSPEC", "${SSTATE_SWSPEC}")
1119 d.setVar("SSTATE_EXTRAPATH", "")
Andrew Geissler82c905d2020-04-13 13:39:40 -05001120 d.setVar("SSTATE_CURRTASK", taskname)
1121 siginfo = d.getVar('SSTATE_PKG') + ".siginfo"
1122 if not os.path.exists(siginfo):
1123 bb.siggen.dump_this_task(siginfo, d)
1124 else:
1125 os.utime(siginfo, None)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001126}
1127
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001128SSTATE_PRUNE_OBSOLETEWORKDIR ?= "1"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001129
1130# Event handler which removes manifests and stamps file for
1131# recipes which are no longer reachable in a build where they
1132# once were.
1133# Also optionally removes the workdir of those tasks/recipes
1134#
1135addhandler sstate_eventhandler2
1136sstate_eventhandler2[eventmask] = "bb.event.ReachableStamps"
1137python sstate_eventhandler2() {
1138 import glob
1139 d = e.data
1140 stamps = e.stamps.values()
1141 removeworkdir = (d.getVar("SSTATE_PRUNE_OBSOLETEWORKDIR", False) == "1")
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001142 preservestampfile = d.expand('${SSTATE_MANIFESTS}/preserve-stamps')
1143 preservestamps = []
1144 if os.path.exists(preservestampfile):
1145 with open(preservestampfile, 'r') as f:
1146 preservestamps = f.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001147 seen = []
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001148
1149 # The machine index contains all the stamps this machine has ever seen in this build directory.
1150 # We should only remove things which this machine once accessed but no longer does.
1151 machineindex = set()
1152 bb.utils.mkdirhier(d.expand("${SSTATE_MANIFESTS}"))
1153 mi = d.expand("${SSTATE_MANIFESTS}/index-machine-${MACHINE}")
1154 if os.path.exists(mi):
1155 with open(mi, "r") as f:
1156 machineindex = set(line.strip() for line in f.readlines())
1157
Brad Bishop316dfdd2018-06-25 12:45:53 -04001158 for a in sorted(list(set(d.getVar("SSTATE_ARCHS").split()))):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001159 toremove = []
1160 i = d.expand("${SSTATE_MANIFESTS}/index-" + a)
1161 if not os.path.exists(i):
1162 continue
1163 with open(i, "r") as f:
1164 lines = f.readlines()
1165 for l in lines:
Brad Bishop19323692019-04-05 15:28:33 -04001166 try:
1167 (stamp, manifest, workdir) = l.split()
1168 if stamp not in stamps and stamp not in preservestamps and stamp in machineindex:
1169 toremove.append(l)
1170 if stamp not in seen:
1171 bb.debug(2, "Stamp %s is not reachable, removing related manifests" % stamp)
1172 seen.append(stamp)
1173 except ValueError:
1174 bb.fatal("Invalid line '%s' in sstate manifest '%s'" % (l, i))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001175
1176 if toremove:
Brad Bishop316dfdd2018-06-25 12:45:53 -04001177 msg = "Removing %d recipes from the %s sysroot" % (len(toremove), a)
1178 bb.event.fire(bb.event.ProcessStarted(msg, len(toremove)), d)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001179
Brad Bishop316dfdd2018-06-25 12:45:53 -04001180 removed = 0
1181 for r in toremove:
1182 (stamp, manifest, workdir) = r.split()
1183 for m in glob.glob(manifest + ".*"):
1184 if m.endswith(".postrm"):
1185 continue
1186 sstate_clean_manifest(m, d)
1187 bb.utils.remove(stamp + "*")
1188 if removeworkdir:
1189 bb.utils.remove(workdir, recurse = True)
1190 lines.remove(r)
1191 removed = removed + 1
1192 bb.event.fire(bb.event.ProcessProgress(msg, removed), d)
1193
1194 bb.event.fire(bb.event.ProcessFinished(msg), d)
1195
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001196 with open(i, "w") as f:
1197 for l in lines:
1198 f.write(l)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001199 machineindex |= set(stamps)
1200 with open(mi, "w") as f:
1201 for l in machineindex:
1202 f.write(l + "\n")
1203
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001204 if preservestamps:
1205 os.remove(preservestampfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001206}