blob: 0b2885014071f7793fa895ad8c3199bef1ce7144 [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
6def generate_sstatefn(spec, hash, d):
7 if not hash:
8 hash = "INVALID"
9 return hash[:2] + "/" + spec + hash
10
11SSTATE_PKGARCH = "${PACKAGE_ARCH}"
12SSTATE_PKGSPEC = "sstate:${PN}:${PACKAGE_ARCH}${TARGET_VENDOR}-${TARGET_OS}:${PV}:${PR}:${SSTATE_PKGARCH}:${SSTATE_VERSION}:"
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050013SSTATE_SWSPEC = "sstate:${PN}::${PV}:${PR}::${SSTATE_VERSION}:"
Brad Bishop6e60e8b2018-02-01 10:27:11 -050014SSTATE_PKGNAME = "${SSTATE_EXTRAPATH}${@generate_sstatefn(d.getVar('SSTATE_PKGSPEC'), d.getVar('BB_TASKHASH'), d)}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050015SSTATE_PKG = "${SSTATE_DIR}/${SSTATE_PKGNAME}"
16SSTATE_EXTRAPATH = ""
17SSTATE_EXTRAPATHWILDCARD = ""
18SSTATE_PATHSPEC = "${SSTATE_DIR}/${SSTATE_EXTRAPATHWILDCARD}*/${SSTATE_PKGSPEC}"
19
Patrick Williamsc0f7c042017-02-23 20:41:17 -060020# explicitly make PV to depend on evaluated value of PV variable
21PV[vardepvalue] = "${PV}"
22
Patrick Williamsc124f4f2015-09-15 14:41:29 -050023# We don't want the sstate to depend on things like the distro string
24# of the system, we let the sstate paths take care of this.
25SSTATE_EXTRAPATH[vardepvalue] = ""
26
27# For multilib rpm the allarch packagegroup files can overwrite (in theory they're identical)
Brad Bishop6e60e8b2018-02-01 10:27:11 -050028SSTATE_DUPWHITELIST = "${DEPLOY_DIR_IMAGE}/ ${DEPLOY_DIR}/licenses/ ${DEPLOY_DIR_RPM}/noarch/"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050029# Avoid docbook/sgml catalog warnings for now
30SSTATE_DUPWHITELIST += "${STAGING_ETCDIR_NATIVE}/sgml ${STAGING_DATADIR_NATIVE}/sgml"
Brad Bishop316dfdd2018-06-25 12:45:53 -040031# sdk-provides-dummy-nativesdk and nativesdk-buildtools-perl-dummy overlap for different SDKMACHINE
32SSTATE_DUPWHITELIST += "${DEPLOY_DIR_RPM}/sdk_provides_dummy_nativesdk/ ${DEPLOY_DIR_IPK}/sdk-provides-dummy-nativesdk/"
33SSTATE_DUPWHITELIST += "${DEPLOY_DIR_RPM}/buildtools_dummy_nativesdk/ ${DEPLOY_DIR_IPK}/buildtools-dummy-nativesdk/"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050034# Archive the sources for many architectures in one deploy folder
35SSTATE_DUPWHITELIST += "${DEPLOY_DIR_SRC}"
36
Brad Bishop6e60e8b2018-02-01 10:27:11 -050037SSTATE_SCAN_FILES ?= "*.la *-config *_config postinst-*"
38SSTATE_SCAN_CMD ??= 'find ${SSTATE_BUILDDIR} \( -name "${@"\" -o -name \"".join(d.getVar("SSTATE_SCAN_FILES").split())}" \) -type f'
39SSTATE_SCAN_CMD_NATIVE ??= 'grep -Irl -e ${RECIPE_SYSROOT} -e ${RECIPE_SYSROOT_NATIVE} -e ${HOSTTOOLS_DIR} ${SSTATE_BUILDDIR}'
Patrick Williamsc124f4f2015-09-15 14:41:29 -050040
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050041BB_HASHFILENAME = "False ${SSTATE_PKGSPEC} ${SSTATE_SWSPEC}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050042
43SSTATE_ARCHS = " \
44 ${BUILD_ARCH} \
45 ${BUILD_ARCH}_${SDK_ARCH}_${SDK_OS} \
46 ${BUILD_ARCH}_${TARGET_ARCH} \
47 ${SDK_ARCH}_${SDK_OS} \
48 ${SDK_ARCH}_${PACKAGE_ARCH} \
49 allarch \
50 ${PACKAGE_ARCH} \
Brad Bishop316dfdd2018-06-25 12:45:53 -040051 ${PACKAGE_EXTRA_ARCHS} \
52 ${MACHINE_ARCH}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050053
54SSTATE_MANMACH ?= "${SSTATE_PKGARCH}"
55
56SSTATECREATEFUNCS = "sstate_hardcode_path"
57SSTATEPOSTCREATEFUNCS = ""
58SSTATEPREINSTFUNCS = ""
59SSTATEPOSTUNPACKFUNCS = "sstate_hardcode_path_unpack"
60SSTATEPOSTINSTFUNCS = ""
Brad Bishop6e60e8b2018-02-01 10:27:11 -050061EXTRA_STAGING_FIXMES ?= "HOSTTOOLS_DIR"
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050062SSTATECLEANFUNCS = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -050063
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050064# Check whether sstate exists for tasks that support sstate and are in the
65# locked signatures file.
66SIGGEN_LOCKEDSIGS_SSTATE_EXISTS_CHECK ?= 'error'
67
68# Check whether the task's computed hash matches the task's hash in the
69# locked signatures file.
70SIGGEN_LOCKEDSIGS_TASKSIG_CHECK ?= "error"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050071
72# The GnuPG key ID and passphrase to use to sign sstate archives (or unset to
73# not sign)
74SSTATE_SIG_KEY ?= ""
75SSTATE_SIG_PASSPHRASE ?= ""
76# Whether to verify the GnUPG signatures when extracting sstate archives
77SSTATE_VERIFY_SIG ?= "0"
78
Patrick Williamsc124f4f2015-09-15 14:41:29 -050079python () {
80 if bb.data.inherits_class('native', d):
81 d.setVar('SSTATE_PKGARCH', d.getVar('BUILD_ARCH', False))
82 elif bb.data.inherits_class('crosssdk', d):
83 d.setVar('SSTATE_PKGARCH', d.expand("${BUILD_ARCH}_${SDK_ARCH}_${SDK_OS}"))
84 elif bb.data.inherits_class('cross', d):
85 d.setVar('SSTATE_PKGARCH', d.expand("${BUILD_ARCH}_${TARGET_ARCH}"))
86 elif bb.data.inherits_class('nativesdk', d):
87 d.setVar('SSTATE_PKGARCH', d.expand("${SDK_ARCH}_${SDK_OS}"))
88 elif bb.data.inherits_class('cross-canadian', d):
89 d.setVar('SSTATE_PKGARCH', d.expand("${SDK_ARCH}_${PACKAGE_ARCH}"))
Brad Bishop6e60e8b2018-02-01 10:27:11 -050090 elif bb.data.inherits_class('allarch', d) and d.getVar("PACKAGE_ARCH") == "all":
Patrick Williamsc124f4f2015-09-15 14:41:29 -050091 d.setVar('SSTATE_PKGARCH', "allarch")
92 else:
93 d.setVar('SSTATE_MANMACH', d.expand("${PACKAGE_ARCH}"))
94
95 if bb.data.inherits_class('native', d) or bb.data.inherits_class('crosssdk', d) or bb.data.inherits_class('cross', d):
96 d.setVar('SSTATE_EXTRAPATH', "${NATIVELSBSTRING}/")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050097 d.setVar('BB_HASHFILENAME', "True ${SSTATE_PKGSPEC} ${SSTATE_SWSPEC}")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050098 d.setVar('SSTATE_EXTRAPATHWILDCARD', "*/")
99
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500100 unique_tasks = sorted(set((d.getVar('SSTATETASKS') or "").split()))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500101 d.setVar('SSTATETASKS', " ".join(unique_tasks))
102 for task in unique_tasks:
103 d.prependVarFlag(task, 'prefuncs', "sstate_task_prefunc ")
104 d.appendVarFlag(task, 'postfuncs', " sstate_task_postfunc")
105}
106
107def sstate_init(task, d):
108 ss = {}
109 ss['task'] = task
110 ss['dirs'] = []
111 ss['plaindirs'] = []
112 ss['lockfiles'] = []
113 ss['lockfiles-shared'] = []
114 return ss
115
116def sstate_state_fromvars(d, task = None):
117 if task is None:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500118 task = d.getVar('BB_CURRENTTASK')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500119 if not task:
120 bb.fatal("sstate code running without task context?!")
121 task = task.replace("_setscene", "")
122
123 if task.startswith("do_"):
124 task = task[3:]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500125 inputs = (d.getVarFlag("do_" + task, 'sstate-inputdirs') or "").split()
126 outputs = (d.getVarFlag("do_" + task, 'sstate-outputdirs') or "").split()
127 plaindirs = (d.getVarFlag("do_" + task, 'sstate-plaindirs') or "").split()
128 lockfiles = (d.getVarFlag("do_" + task, 'sstate-lockfile') or "").split()
129 lockfilesshared = (d.getVarFlag("do_" + task, 'sstate-lockfile-shared') or "").split()
130 interceptfuncs = (d.getVarFlag("do_" + task, 'sstate-interceptfuncs') or "").split()
131 fixmedir = d.getVarFlag("do_" + task, 'sstate-fixmedir') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500132 if not task or len(inputs) != len(outputs):
133 bb.fatal("sstate variables not setup correctly?!")
134
135 if task == "populate_lic":
136 d.setVar("SSTATE_PKGSPEC", "${SSTATE_SWSPEC}")
137 d.setVar("SSTATE_EXTRAPATH", "")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500138 d.setVar('SSTATE_EXTRAPATHWILDCARD', "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500139
140 ss = sstate_init(task, d)
141 for i in range(len(inputs)):
142 sstate_add(ss, inputs[i], outputs[i], d)
143 ss['lockfiles'] = lockfiles
144 ss['lockfiles-shared'] = lockfilesshared
145 ss['plaindirs'] = plaindirs
146 ss['interceptfuncs'] = interceptfuncs
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500147 ss['fixmedir'] = fixmedir
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500148 return ss
149
150def sstate_add(ss, source, dest, d):
151 if not source.endswith("/"):
152 source = source + "/"
153 if not dest.endswith("/"):
154 dest = dest + "/"
155 source = os.path.normpath(source)
156 dest = os.path.normpath(dest)
157 srcbase = os.path.basename(source)
158 ss['dirs'].append([srcbase, source, dest])
159 return ss
160
161def sstate_install(ss, d):
162 import oe.path
163 import oe.sstatesig
164 import subprocess
165
166 sharedfiles = []
167 shareddirs = []
168 bb.utils.mkdirhier(d.expand("${SSTATE_MANIFESTS}"))
169
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500170 sstateinst = d.expand("${WORKDIR}/sstate-install-%s/" % ss['task'])
171
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500172 manifest, d2 = oe.sstatesig.sstate_get_manifest_filename(ss['task'], d)
173
174 if os.access(manifest, os.R_OK):
175 bb.fatal("Package already staged (%s)?!" % manifest)
176
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600177 d.setVar("SSTATE_INST_POSTRM", manifest + ".postrm")
178
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500179 locks = []
180 for lock in ss['lockfiles-shared']:
181 locks.append(bb.utils.lockfile(lock, True))
182 for lock in ss['lockfiles']:
183 locks.append(bb.utils.lockfile(lock))
184
185 for state in ss['dirs']:
186 bb.debug(2, "Staging files from %s to %s" % (state[1], state[2]))
187 for walkroot, dirs, files in os.walk(state[1]):
188 for file in files:
189 srcpath = os.path.join(walkroot, file)
190 dstpath = srcpath.replace(state[1], state[2])
191 #bb.debug(2, "Staging %s to %s" % (srcpath, dstpath))
192 sharedfiles.append(dstpath)
193 for dir in dirs:
194 srcdir = os.path.join(walkroot, dir)
195 dstdir = srcdir.replace(state[1], state[2])
196 #bb.debug(2, "Staging %s to %s" % (srcdir, dstdir))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500197 if os.path.islink(srcdir):
198 sharedfiles.append(dstdir)
199 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500200 if not dstdir.endswith("/"):
201 dstdir = dstdir + "/"
202 shareddirs.append(dstdir)
203
204 # Check the file list for conflicts against files which already exist
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500205 whitelist = (d.getVar("SSTATE_DUPWHITELIST") or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500206 match = []
207 for f in sharedfiles:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500208 if os.path.exists(f) and not os.path.islink(f):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500209 f = os.path.normpath(f)
210 realmatch = True
211 for w in whitelist:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600212 w = os.path.normpath(w)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500213 if f.startswith(w):
214 realmatch = False
215 break
216 if realmatch:
217 match.append(f)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500218 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 -0500219 search_output = subprocess.Popen(sstate_search_cmd, shell=True, stdout=subprocess.PIPE).communicate()[0]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500220 if search_output:
221 match.append(" (matched in %s)" % search_output.decode('utf-8').rstrip())
222 else:
223 match.append(" (not matched to any task)")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500224 if match:
225 bb.error("The recipe %s is trying to install files into a shared " \
226 "area when those files already exist. Those files and their manifest " \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500227 "location are:\n %s\nPlease verify which recipe should provide the " \
228 "above files.\n\nThe build has stopped, as continuing in this scenario WILL " \
229 "break things - if not now, possibly in the future (we've seen builds fail " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500230 "several months later). If the system knew how to recover from this " \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500231 "automatically it would, however there are several different scenarios " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500232 "which can result in this and we don't know which one this is. It may be " \
233 "you have switched providers of something like virtual/kernel (e.g. from " \
234 "linux-yocto to linux-yocto-dev), in that case you need to execute the " \
235 "clean task for both recipes and it will resolve this error. It may be " \
236 "you changed DISTRO_FEATURES from systemd to udev or vice versa. Cleaning " \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500237 "those recipes should again resolve this error, however switching " \
238 "DISTRO_FEATURES on an existing build directory is not supported - you " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500239 "should really clean out tmp and rebuild (reusing sstate should be safe). " \
240 "It could be the overlapping files detected are harmless in which case " \
241 "adding them to SSTATE_DUPWHITELIST may be the correct solution. It could " \
242 "also be your build is including two different conflicting versions of " \
243 "things (e.g. bluez 4 and bluez 5 and the correct solution for that would " \
244 "be to resolve the conflict. If in doubt, please ask on the mailing list, " \
245 "sharing the error and filelist above." % \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500246 (d.getVar('PN'), "\n ".join(match)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500247 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.")
248
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500249 if ss['fixmedir'] and os.path.exists(ss['fixmedir'] + "/fixmepath.cmd"):
250 sharedfiles.append(ss['fixmedir'] + "/fixmepath.cmd")
251 sharedfiles.append(ss['fixmedir'] + "/fixmepath")
252
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500253 # Write out the manifest
254 f = open(manifest, "w")
255 for file in sharedfiles:
256 f.write(file + "\n")
257
258 # We want to ensure that directories appear at the end of the manifest
259 # so that when we test to see if they should be deleted any contents
260 # added by the task will have been removed first.
261 dirs = sorted(shareddirs, key=len)
262 # Must remove children first, which will have a longer path than the parent
263 for di in reversed(dirs):
264 f.write(di + "\n")
265 f.close()
266
267 # Append to the list of manifests for this PACKAGE_ARCH
268
269 i = d2.expand("${SSTATE_MANIFESTS}/index-${SSTATE_MANMACH}")
270 l = bb.utils.lockfile(i + ".lock")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500271 filedata = d.getVar("STAMP") + " " + d2.getVar("SSTATE_MANFILEPREFIX") + " " + d.getVar("WORKDIR") + "\n"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500272 manifests = []
273 if os.path.exists(i):
274 with open(i, "r") as f:
275 manifests = f.readlines()
276 if filedata not in manifests:
277 with open(i, "a+") as f:
278 f.write(filedata)
279 bb.utils.unlockfile(l)
280
281 # Run the actual file install
282 for state in ss['dirs']:
283 if os.path.exists(state[1]):
284 oe.path.copyhardlinktree(state[1], state[2])
285
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500286 for postinst in (d.getVar('SSTATEPOSTINSTFUNCS') or '').split():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500287 # All hooks should run in the SSTATE_INSTDIR
288 bb.build.exec_func(postinst, d, (sstateinst,))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500289
290 for lock in locks:
291 bb.utils.unlockfile(lock)
292
293sstate_install[vardepsexclude] += "SSTATE_DUPWHITELIST STATE_MANMACH SSTATE_MANFILEPREFIX"
294sstate_install[vardeps] += "${SSTATEPOSTINSTFUNCS}"
295
296def sstate_installpkg(ss, d):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500297 from oe.gpg_sign import get_signer
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500298
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500299 sstateinst = d.expand("${WORKDIR}/sstate-install-%s/" % ss['task'])
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500300 sstatefetch = d.getVar('SSTATE_PKGNAME') + '_' + ss['task'] + ".tgz"
301 sstatepkg = d.getVar('SSTATE_PKG') + '_' + ss['task'] + ".tgz"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500302
303 if not os.path.exists(sstatepkg):
304 pstaging_fetch(sstatefetch, sstatepkg, d)
305
306 if not os.path.isfile(sstatepkg):
307 bb.note("Staging package %s does not exist" % sstatepkg)
308 return False
309
310 sstate_clean(ss, d)
311
312 d.setVar('SSTATE_INSTDIR', sstateinst)
313 d.setVar('SSTATE_PKG', sstatepkg)
314
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500315 if bb.utils.to_boolean(d.getVar("SSTATE_VERIFY_SIG"), False):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500316 signer = get_signer(d, 'local')
317 if not signer.verify(sstatepkg + '.sig'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500318 bb.warn("Cannot verify signature on sstate package %s" % sstatepkg)
319
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500320 # Empty sstateinst directory, ensure its clean
321 if os.path.exists(sstateinst):
322 oe.path.remove(sstateinst)
323 bb.utils.mkdirhier(sstateinst)
324
325 sstateinst = d.getVar("SSTATE_INSTDIR")
326 d.setVar('SSTATE_FIXMEDIR', ss['fixmedir'])
327
328 for f in (d.getVar('SSTATEPREINSTFUNCS') or '').split() + ['sstate_unpack_package']:
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500329 # All hooks should run in the SSTATE_INSTDIR
330 bb.build.exec_func(f, d, (sstateinst,))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500331
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500332 return sstate_installpkgdir(ss, d)
333
334def sstate_installpkgdir(ss, d):
335 import oe.path
336 import subprocess
337
338 sstateinst = d.getVar("SSTATE_INSTDIR")
339 d.setVar('SSTATE_FIXMEDIR', ss['fixmedir'])
340
341 for f in (d.getVar('SSTATEPOSTUNPACKFUNCS') or '').split():
342 # All hooks should run in the SSTATE_INSTDIR
343 bb.build.exec_func(f, d, (sstateinst,))
344
345 def prepdir(dir):
346 # remove dir if it exists, ensure any parent directories do exist
347 if os.path.exists(dir):
348 oe.path.remove(dir)
349 bb.utils.mkdirhier(dir)
350 oe.path.remove(dir)
351
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500352 for state in ss['dirs']:
353 prepdir(state[1])
354 os.rename(sstateinst + state[0], state[1])
355 sstate_install(ss, d)
356
357 for plain in ss['plaindirs']:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500358 workdir = d.getVar('WORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500359 src = sstateinst + "/" + plain.replace(workdir, '')
360 dest = plain
361 bb.utils.mkdirhier(src)
362 prepdir(dest)
363 os.rename(src, dest)
364
365 return True
366
367python sstate_hardcode_path_unpack () {
368 # Fixup hardcoded paths
369 #
370 # Note: The logic below must match the reverse logic in
371 # sstate_hardcode_path(d)
372 import subprocess
373
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500374 sstateinst = d.getVar('SSTATE_INSTDIR')
375 sstatefixmedir = d.getVar('SSTATE_FIXMEDIR')
376 fixmefn = sstateinst + "fixmepath"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500377 if os.path.isfile(fixmefn):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500378 staging_target = d.getVar('RECIPE_SYSROOT')
379 staging_host = d.getVar('RECIPE_SYSROOT_NATIVE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500380
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500381 if bb.data.inherits_class('native', d) or bb.data.inherits_class('cross-canadian', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500382 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRHOST:%s:g'" % (staging_host)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500383 elif bb.data.inherits_class('cross', d) or bb.data.inherits_class('crosssdk', d):
384 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRTARGET:%s:g; s:FIXMESTAGINGDIRHOST:%s:g'" % (staging_target, staging_host)
385 else:
386 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRTARGET:%s:g'" % (staging_target)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500387
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500388 extra_staging_fixmes = d.getVar('EXTRA_STAGING_FIXMES') or ''
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500389 for fixmevar in extra_staging_fixmes.split():
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500390 fixme_path = d.getVar(fixmevar)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500391 sstate_sed_cmd += " -e 's:FIXME_%s:%s:g'" % (fixmevar, fixme_path)
392
393 # Add sstateinst to each filename in fixmepath, use xargs to efficiently call sed
394 sstate_hardcode_cmd = "sed -e 's:^:%s:g' %s | xargs %s" % (sstateinst, fixmefn, sstate_sed_cmd)
395
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500396 # Defer do_populate_sysroot relocation command
397 if sstatefixmedir:
398 bb.utils.mkdirhier(sstatefixmedir)
399 with open(sstatefixmedir + "/fixmepath.cmd", "w") as f:
400 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(fixmefn, sstatefixmedir + "/fixmepath")
401 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(sstateinst, "FIXMEFINALSSTATEINST")
402 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(staging_host, "FIXMEFINALSSTATEHOST")
403 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(staging_target, "FIXMEFINALSSTATETARGET")
404 f.write(sstate_hardcode_cmd)
405 bb.utils.copyfile(fixmefn, sstatefixmedir + "/fixmepath")
406 return
407
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500408 bb.note("Replacing fixme paths in sstate package: %s" % (sstate_hardcode_cmd))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500409 subprocess.check_call(sstate_hardcode_cmd, shell=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500410
411 # Need to remove this or we'd copy it into the target directory and may
412 # conflict with another writer
413 os.remove(fixmefn)
414}
415
416def sstate_clean_cachefile(ss, d):
417 import oe.path
418
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500419 sstatepkgfile = d.getVar('SSTATE_PATHSPEC') + "*_" + ss['task'] + ".tgz*"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500420 bb.note("Removing %s" % sstatepkgfile)
421 oe.path.remove(sstatepkgfile)
422
423def sstate_clean_cachefiles(d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500424 for task in (d.getVar('SSTATETASKS') or "").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500425 ld = d.createCopy()
426 ss = sstate_state_fromvars(ld, task)
427 sstate_clean_cachefile(ss, ld)
428
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500429def sstate_clean_manifest(manifest, d, prefix=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500430 import oe.path
431
432 mfile = open(manifest)
433 entries = mfile.readlines()
434 mfile.close()
435
436 for entry in entries:
437 entry = entry.strip()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500438 if prefix and not entry.startswith("/"):
439 entry = prefix + "/" + entry
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500440 bb.debug(2, "Removing manifest: %s" % entry)
441 # We can race against another package populating directories as we're removing them
442 # so we ignore errors here.
443 try:
444 if entry.endswith("/"):
445 if os.path.islink(entry[:-1]):
446 os.remove(entry[:-1])
447 elif os.path.exists(entry) and len(os.listdir(entry)) == 0:
448 os.rmdir(entry[:-1])
449 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500450 os.remove(entry)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500451 except OSError:
452 pass
453
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600454 postrm = manifest + ".postrm"
455 if os.path.exists(manifest + ".postrm"):
456 import subprocess
457 os.chmod(postrm, 0o755)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500458 subprocess.check_call(postrm, shell=True)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600459 oe.path.remove(postrm)
460
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500461 oe.path.remove(manifest)
462
463def sstate_clean(ss, d):
464 import oe.path
465 import glob
466
467 d2 = d.createCopy()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500468 stamp_clean = d.getVar("STAMPCLEAN")
469 extrainf = d.getVarFlag("do_" + ss['task'], 'stamp-extra-info')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500470 if extrainf:
471 d2.setVar("SSTATE_MANMACH", extrainf)
472 wildcard_stfile = "%s.do_%s*.%s" % (stamp_clean, ss['task'], extrainf)
473 else:
474 wildcard_stfile = "%s.do_%s*" % (stamp_clean, ss['task'])
475
476 manifest = d2.expand("${SSTATE_MANFILEPREFIX}.%s" % ss['task'])
477
478 if os.path.exists(manifest):
479 locks = []
480 for lock in ss['lockfiles-shared']:
481 locks.append(bb.utils.lockfile(lock))
482 for lock in ss['lockfiles']:
483 locks.append(bb.utils.lockfile(lock))
484
485 sstate_clean_manifest(manifest, d)
486
487 for lock in locks:
488 bb.utils.unlockfile(lock)
489
490 # Remove the current and previous stamps, but keep the sigdata.
491 #
492 # The glob() matches do_task* which may match multiple tasks, for
493 # example: do_package and do_package_write_ipk, so we need to
494 # exactly match *.do_task.* and *.do_task_setscene.*
495 rm_stamp = '.do_%s.' % ss['task']
496 rm_setscene = '.do_%s_setscene.' % ss['task']
497 # For BB_SIGNATURE_HANDLER = "noop"
498 rm_nohash = ".do_%s" % ss['task']
499 for stfile in glob.glob(wildcard_stfile):
500 # Keep the sigdata
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500501 if ".sigdata." in stfile or ".sigbasedata." in stfile:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500502 continue
503 # Preserve taint files in the stamps directory
504 if stfile.endswith('.taint'):
505 continue
506 if rm_stamp in stfile or rm_setscene in stfile or \
507 stfile.endswith(rm_nohash):
508 oe.path.remove(stfile)
509
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500510 # Removes the users/groups created by the package
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500511 for cleanfunc in (d.getVar('SSTATECLEANFUNCS') or '').split():
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500512 bb.build.exec_func(cleanfunc, d)
513
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500514sstate_clean[vardepsexclude] = "SSTATE_MANFILEPREFIX"
515
516CLEANFUNCS += "sstate_cleanall"
517
518python sstate_cleanall() {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500519 bb.note("Removing shared state for package %s" % d.getVar('PN'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500520
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500521 manifest_dir = d.getVar('SSTATE_MANIFESTS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500522 if not os.path.exists(manifest_dir):
523 return
524
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500525 tasks = d.getVar('SSTATETASKS').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500526 for name in tasks:
527 ld = d.createCopy()
528 shared_state = sstate_state_fromvars(ld, name)
529 sstate_clean(shared_state, ld)
530}
531
532python sstate_hardcode_path () {
533 import subprocess, platform
534
535 # Need to remove hardcoded paths and fix these when we install the
536 # staging packages.
537 #
538 # Note: the logic in this function needs to match the reverse logic
539 # in sstate_installpkg(ss, d)
540
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500541 staging_target = d.getVar('RECIPE_SYSROOT')
542 staging_host = d.getVar('RECIPE_SYSROOT_NATIVE')
543 sstate_builddir = d.getVar('SSTATE_BUILDDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500544
Brad Bishop316dfdd2018-06-25 12:45:53 -0400545 sstate_sed_cmd = "sed -i -e 's:%s:FIXMESTAGINGDIRHOST:g'" % staging_host
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500546 if bb.data.inherits_class('native', d) or bb.data.inherits_class('cross-canadian', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500547 sstate_grep_cmd = "grep -l -e '%s'" % (staging_host)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500548 elif bb.data.inherits_class('cross', d) or bb.data.inherits_class('crosssdk', d):
549 sstate_grep_cmd = "grep -l -e '%s' -e '%s'" % (staging_target, staging_host)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400550 sstate_sed_cmd += " -e 's:%s:FIXMESTAGINGDIRTARGET:g'" % staging_target
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500551 else:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400552 sstate_grep_cmd = "grep -l -e '%s' -e '%s'" % (staging_target, staging_host)
553 sstate_sed_cmd += " -e 's:%s:FIXMESTAGINGDIRTARGET:g'" % staging_target
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500554
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500555 extra_staging_fixmes = d.getVar('EXTRA_STAGING_FIXMES') or ''
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500556 for fixmevar in extra_staging_fixmes.split():
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500557 fixme_path = d.getVar(fixmevar)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500558 sstate_sed_cmd += " -e 's:%s:FIXME_%s:g'" % (fixme_path, fixmevar)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500559 sstate_grep_cmd += " -e '%s'" % (fixme_path)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500560
561 fixmefn = sstate_builddir + "fixmepath"
562
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500563 sstate_scan_cmd = d.getVar('SSTATE_SCAN_CMD')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500564 sstate_filelist_cmd = "tee %s" % (fixmefn)
565
566 # fixmepath file needs relative paths, drop sstate_builddir prefix
567 sstate_filelist_relative_cmd = "sed -i -e 's:^%s::g' %s" % (sstate_builddir, fixmefn)
568
569 xargs_no_empty_run_cmd = '--no-run-if-empty'
570 if platform.system() == 'Darwin':
571 xargs_no_empty_run_cmd = ''
572
573 # Limit the fixpaths and sed operations based on the initial grep search
574 # This has the side effect of making sure the vfs cache is hot
575 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)
576
577 bb.note("Removing hardcoded paths from sstate package: '%s'" % (sstate_hardcode_cmd))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500578 subprocess.check_output(sstate_hardcode_cmd, shell=True, cwd=sstate_builddir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500579
580 # If the fixmefn is empty, remove it..
581 if os.stat(fixmefn).st_size == 0:
582 os.remove(fixmefn)
583 else:
584 bb.note("Replacing absolute paths in fixmepath file: '%s'" % (sstate_filelist_relative_cmd))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500585 subprocess.check_output(sstate_filelist_relative_cmd, shell=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500586}
587
588def sstate_package(ss, d):
589 import oe.path
590
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500591 tmpdir = d.getVar('TMPDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500592
593 sstatebuild = d.expand("${WORKDIR}/sstate-build-%s/" % ss['task'])
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500594 sstatepkg = d.getVar('SSTATE_PKG') + '_'+ ss['task'] + ".tgz"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500595 bb.utils.remove(sstatebuild, recurse=True)
596 bb.utils.mkdirhier(sstatebuild)
597 bb.utils.mkdirhier(os.path.dirname(sstatepkg))
598 for state in ss['dirs']:
599 if not os.path.exists(state[1]):
600 continue
601 srcbase = state[0].rstrip("/").rsplit('/', 1)[0]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500602 # Find and error for absolute symlinks. We could attempt to relocate but its not
603 # clear where the symlink is relative to in this context. We could add that markup
604 # to sstate tasks but there aren't many of these so better just avoid them entirely.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500605 for walkroot, dirs, files in os.walk(state[1]):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500606 for file in files + dirs:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500607 srcpath = os.path.join(walkroot, file)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500608 if not os.path.islink(srcpath):
609 continue
610 link = os.readlink(srcpath)
611 if not os.path.isabs(link):
612 continue
613 if not link.startswith(tmpdir):
614 continue
615 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 -0500616 bb.debug(2, "Preparing tree %s for packaging at %s" % (state[1], sstatebuild + state[0]))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500617 os.rename(state[1], sstatebuild + state[0])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500618
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500619 workdir = d.getVar('WORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500620 for plain in ss['plaindirs']:
621 pdir = plain.replace(workdir, sstatebuild)
622 bb.utils.mkdirhier(plain)
623 bb.utils.mkdirhier(pdir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500624 os.rename(plain, pdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500625
626 d.setVar('SSTATE_BUILDDIR', sstatebuild)
627 d.setVar('SSTATE_PKG', sstatepkg)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500628 d.setVar('SSTATE_INSTDIR', sstatebuild)
629
630 if d.getVar('SSTATE_SKIP_CREATION') == '1':
631 return
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500632
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500633 for f in (d.getVar('SSTATECREATEFUNCS') or '').split() + \
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500634 ['sstate_create_package', 'sstate_sign_package'] + \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500635 (d.getVar('SSTATEPOSTCREATEFUNCS') or '').split():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500636 # All hooks should run in SSTATE_BUILDDIR.
637 bb.build.exec_func(f, d, (sstatebuild,))
638
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500639 bb.siggen.dump_this_task(sstatepkg + ".siginfo", d)
640
641 return
642
643def pstaging_fetch(sstatefetch, sstatepkg, d):
644 import bb.fetch2
645
646 # Only try and fetch if the user has configured a mirror
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500647 mirrors = d.getVar('SSTATE_MIRRORS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500648 if not mirrors:
649 return
650
651 # Copy the data object and override DL_DIR and SRC_URI
652 localdata = bb.data.createCopy(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500653
654 dldir = localdata.expand("${SSTATE_DIR}")
655 bb.utils.mkdirhier(dldir)
656
657 localdata.delVar('MIRRORS')
658 localdata.setVar('FILESPATH', dldir)
659 localdata.setVar('DL_DIR', dldir)
660 localdata.setVar('PREMIRRORS', mirrors)
661
662 # if BB_NO_NETWORK is set but we also have SSTATE_MIRROR_ALLOW_NETWORK,
663 # we'll want to allow network access for the current set of fetches.
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500664 if localdata.getVar('BB_NO_NETWORK') == "1" and localdata.getVar('SSTATE_MIRROR_ALLOW_NETWORK') == "1":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500665 localdata.delVar('BB_NO_NETWORK')
666
667 # Try a fetch from the sstate mirror, if it fails just return and
668 # we will build the package
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600669 uris = ['file://{0};downloadfilename={0}'.format(sstatefetch),
670 'file://{0}.siginfo;downloadfilename={0}.siginfo'.format(sstatefetch)]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500671 if bb.utils.to_boolean(d.getVar("SSTATE_VERIFY_SIG"), False):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600672 uris += ['file://{0}.sig;downloadfilename={0}.sig'.format(sstatefetch)]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500673
674 for srcuri in uris:
675 localdata.setVar('SRC_URI', srcuri)
676 try:
677 fetcher = bb.fetch2.Fetch([srcuri], localdata, cache=False)
678 fetcher.download()
679
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500680 except bb.fetch2.BBFetchException:
681 break
682
683def sstate_setscene(d):
684 shared_state = sstate_state_fromvars(d)
685 accelerate = sstate_installpkg(shared_state, d)
686 if not accelerate:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600687 bb.fatal("No suitable staging package found")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500688
689python sstate_task_prefunc () {
690 shared_state = sstate_state_fromvars(d)
691 sstate_clean(shared_state, d)
692}
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500693sstate_task_prefunc[dirs] = "${WORKDIR}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500694
695python sstate_task_postfunc () {
696 shared_state = sstate_state_fromvars(d)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500697
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500698 for intercept in shared_state['interceptfuncs']:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500699 bb.build.exec_func(intercept, d, (d.getVar("WORKDIR"),))
700
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600701 omask = os.umask(0o002)
702 if omask != 0o002:
703 bb.note("Using umask 0o002 (not %0o) for sstate packaging" % omask)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500704 sstate_package(shared_state, d)
705 os.umask(omask)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500706
707 sstateinst = d.getVar("SSTATE_INSTDIR")
708 d.setVar('SSTATE_FIXMEDIR', shared_state['fixmedir'])
709
710 sstate_installpkgdir(shared_state, d)
711
712 bb.utils.remove(d.getVar("SSTATE_BUILDDIR"), recurse=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500713}
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500714sstate_task_postfunc[dirs] = "${WORKDIR}"
715
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500716
717#
718# Shell function to generate a sstate package from a directory
719# set as SSTATE_BUILDDIR. Will be run from within SSTATE_BUILDDIR.
720#
721sstate_create_package () {
722 TFILE=`mktemp ${SSTATE_PKG}.XXXXXXXX`
723 # Need to handle empty directories
724 if [ "$(ls -A)" ]; then
725 set +e
726 tar -czf $TFILE *
727 ret=$?
728 if [ $ret -ne 0 ] && [ $ret -ne 1 ]; then
729 exit 1
730 fi
731 set -e
732 else
733 tar -cz --file=$TFILE --files-from=/dev/null
734 fi
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500735 chmod 0664 $TFILE
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500736 mv -f $TFILE ${SSTATE_PKG}
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500737}
738
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500739python sstate_sign_package () {
740 from oe.gpg_sign import get_signer
741
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500742 if d.getVar('SSTATE_SIG_KEY'):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500743 signer = get_signer(d, 'local')
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500744 sstate_pkg = d.getVar('SSTATE_PKG')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500745 if os.path.exists(sstate_pkg + '.sig'):
746 os.unlink(sstate_pkg + '.sig')
747 signer.detach_sign(sstate_pkg, d.getVar('SSTATE_SIG_KEY', False), None,
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500748 d.getVar('SSTATE_SIG_PASSPHRASE'), armor=False)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500749}
750
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500751#
752# Shell function to decompress and prepare a package for installation
753# Will be run from within SSTATE_INSTDIR.
754#
755sstate_unpack_package () {
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500756 tar -xvzf ${SSTATE_PKG}
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500757 # update .siginfo atime on local/NFS mirror
758 [ -w ${SSTATE_PKG}.siginfo ] && [ -h ${SSTATE_PKG}.siginfo ] && touch -a ${SSTATE_PKG}.siginfo
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500759 # Use "! -w ||" to return true for read only files
760 [ ! -w ${SSTATE_PKG} ] || touch --no-dereference ${SSTATE_PKG}
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500761 [ ! -w ${SSTATE_PKG}.sig ] || [ ! -e ${SSTATE_PKG}.sig ] || touch --no-dereference ${SSTATE_PKG}.sig
762 [ ! -w ${SSTATE_PKG}.siginfo ] || [ ! -e ${SSTATE_PKG}.siginfo ] || touch --no-dereference ${SSTATE_PKG}.siginfo
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500763}
764
765BB_HASHCHECK_FUNCTION = "sstate_checkhashes"
766
767def sstate_checkhashes(sq_fn, sq_task, sq_hash, sq_hashfn, d, siginfo=False):
768
769 ret = []
770 missed = []
771 extension = ".tgz"
772 if siginfo:
773 extension = extension + ".siginfo"
774
775 def getpathcomponents(task, d):
776 # Magic data from BB_HASHFILENAME
777 splithashfn = sq_hashfn[task].split(" ")
778 spec = splithashfn[1]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500779 if splithashfn[0] == "True":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500780 extrapath = d.getVar("NATIVELSBSTRING") + "/"
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500781 else:
782 extrapath = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500783
784 tname = sq_task[task][3:]
785
786 if tname in ["fetch", "unpack", "patch", "populate_lic", "preconfigure"] and splithashfn[2]:
787 spec = splithashfn[2]
788 extrapath = ""
789
790 return spec, extrapath, tname
791
792
793 for task in range(len(sq_fn)):
794
795 spec, extrapath, tname = getpathcomponents(task, d)
796
797 sstatefile = d.expand("${SSTATE_DIR}/" + extrapath + generate_sstatefn(spec, sq_hash[task], d) + "_" + tname + extension)
798
799 if os.path.exists(sstatefile):
800 bb.debug(2, "SState: Found valid sstate file %s" % sstatefile)
801 ret.append(task)
802 continue
803 else:
804 missed.append(task)
805 bb.debug(2, "SState: Looked for but didn't find file %s" % sstatefile)
806
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500807 mirrors = d.getVar("SSTATE_MIRRORS")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500808 if mirrors:
809 # Copy the data object and override DL_DIR and SRC_URI
810 localdata = bb.data.createCopy(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500811
812 dldir = localdata.expand("${SSTATE_DIR}")
813 localdata.delVar('MIRRORS')
814 localdata.setVar('FILESPATH', dldir)
815 localdata.setVar('DL_DIR', dldir)
816 localdata.setVar('PREMIRRORS', mirrors)
817
818 bb.debug(2, "SState using premirror of: %s" % mirrors)
819
820 # if BB_NO_NETWORK is set but we also have SSTATE_MIRROR_ALLOW_NETWORK,
821 # we'll want to allow network access for the current set of fetches.
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500822 if localdata.getVar('BB_NO_NETWORK') == "1" and localdata.getVar('SSTATE_MIRROR_ALLOW_NETWORK') == "1":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500823 localdata.delVar('BB_NO_NETWORK')
824
825 from bb.fetch2 import FetchConnectionCache
826 def checkstatus_init(thread_worker):
827 thread_worker.connection_cache = FetchConnectionCache()
828
829 def checkstatus_end(thread_worker):
830 thread_worker.connection_cache.close_connections()
831
832 def checkstatus(thread_worker, arg):
833 (task, sstatefile) = arg
834
835 localdata2 = bb.data.createCopy(localdata)
836 srcuri = "file://" + sstatefile
837 localdata.setVar('SRC_URI', srcuri)
838 bb.debug(2, "SState: Attempting to fetch %s" % srcuri)
839
840 try:
841 fetcher = bb.fetch2.Fetch(srcuri.split(), localdata2,
842 connection_cache=thread_worker.connection_cache)
843 fetcher.checkstatus()
844 bb.debug(2, "SState: Successful fetch test for %s" % srcuri)
845 ret.append(task)
846 if task in missed:
847 missed.remove(task)
848 except:
849 missed.append(task)
850 bb.debug(2, "SState: Unsuccessful fetch test for %s" % srcuri)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600851 pass
Brad Bishop316dfdd2018-06-25 12:45:53 -0400852 bb.event.fire(bb.event.ProcessProgress(msg, len(tasklist) - thread_worker.tasks.qsize()), d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500853
854 tasklist = []
855 for task in range(len(sq_fn)):
856 if task in ret:
857 continue
858 spec, extrapath, tname = getpathcomponents(task, d)
859 sstatefile = d.expand(extrapath + generate_sstatefn(spec, sq_hash[task], d) + "_" + tname + extension)
860 tasklist.append((task, sstatefile))
861
862 if tasklist:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400863 msg = "Checking sstate mirror object availability"
864 bb.event.fire(bb.event.ProcessStarted(msg, len(tasklist)), d)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600865
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500866 import multiprocessing
867 nproc = min(multiprocessing.cpu_count(), len(tasklist))
868
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600869 bb.event.enable_threadlock()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500870 pool = oe.utils.ThreadedPool(nproc, len(tasklist),
871 worker_init=checkstatus_init, worker_end=checkstatus_end)
872 for t in tasklist:
873 pool.add_task(checkstatus, t)
874 pool.start()
875 pool.wait_completion()
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600876 bb.event.disable_threadlock()
877
Brad Bishop316dfdd2018-06-25 12:45:53 -0400878 bb.event.fire(bb.event.ProcessFinished(msg), d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500879
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500880 inheritlist = d.getVar("INHERIT")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500881 if "toaster" in inheritlist:
882 evdata = {'missed': [], 'found': []};
883 for task in missed:
884 spec, extrapath, tname = getpathcomponents(task, d)
885 sstatefile = d.expand(extrapath + generate_sstatefn(spec, sq_hash[task], d) + "_" + tname + ".tgz")
886 evdata['missed'].append( (sq_fn[task], sq_task[task], sq_hash[task], sstatefile ) )
887 for task in ret:
888 spec, extrapath, tname = getpathcomponents(task, d)
889 sstatefile = d.expand(extrapath + generate_sstatefn(spec, sq_hash[task], d) + "_" + tname + ".tgz")
890 evdata['found'].append( (sq_fn[task], sq_task[task], sq_hash[task], sstatefile ) )
891 bb.event.fire(bb.event.MetadataEvent("MissedSstate", evdata), d)
892
893 if hasattr(bb.parse.siggen, "checkhashes"):
894 bb.parse.siggen.checkhashes(missed, ret, sq_fn, sq_task, sq_hash, sq_hashfn, d)
895
896 return ret
897
898BB_SETSCENE_DEPVALID = "setscene_depvalid"
899
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500900def setscene_depvalid(task, taskdependees, notneeded, d, log=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500901 # taskdependees is a dict of tasks which depend on task, each being a 3 item list of [PN, TASKNAME, FILENAME]
902 # task is included in taskdependees too
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500903 # Return - False - We need this dependency
904 # - True - We can skip this dependency
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500905
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500906 def logit(msg, log):
907 if log is not None:
908 log.append(msg)
909 else:
910 bb.debug(2, msg)
911
912 logit("Considering setscene task: %s" % (str(taskdependees[task])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500913
914 def isNativeCross(x):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500915 return x.endswith("-native") or "-cross-" in x or "-crosssdk" in x or x.endswith("-cross")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500916
917 # We only need to trigger populate_lic through direct dependencies
918 if taskdependees[task][1] == "do_populate_lic":
919 return True
920
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500921 # stash_locale and gcc_stash_builddir are never needed as a dependency for built objects
922 if taskdependees[task][1] == "do_stash_locale" or taskdependees[task][1] == "do_gcc_stash_builddir":
923 return True
924
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500925 # We only need to trigger packagedata through direct dependencies
926 # but need to preserve packagedata on packagedata links
927 if taskdependees[task][1] == "do_packagedata":
928 for dep in taskdependees:
929 if taskdependees[dep][1] == "do_packagedata":
930 return False
931 return True
932
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500933 for dep in taskdependees:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500934 logit(" considering dependency: %s" % (str(taskdependees[dep])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500935 if task == dep:
936 continue
937 if dep in notneeded:
938 continue
939 # do_package_write_* and do_package doesn't need do_package
940 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']:
941 continue
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500942 # do_package_write_* need do_populate_sysroot as they're mainly postinstall dependencies
943 if taskdependees[task][1] == "do_populate_sysroot" and taskdependees[dep][1] in ['do_package_write_deb', 'do_package_write_ipk', 'do_package_write_rpm']:
944 return False
945 # do_package/packagedata/package_qa don't need do_populate_sysroot
946 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 -0500947 continue
948 # Native/Cross packages don't exist and are noexec anyway
949 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']:
950 continue
951
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500952 # This is due to the [depends] in useradd.bbclass complicating matters
953 # The logic *is* reversed here due to the way hard setscene dependencies are injected
954 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':
955 continue
956
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500957 # Consider sysroot depending on sysroot tasks
958 if taskdependees[task][1] == 'do_populate_sysroot' and taskdependees[dep][1] == 'do_populate_sysroot':
959 # base-passwd/shadow-sysroot don't need their dependencies
960 if taskdependees[dep][0].endswith(("base-passwd", "shadow-sysroot")):
961 continue
962 # Nothing need depend on libc-initial/gcc-cross-initial
963 if "-initial" in taskdependees[task][0]:
964 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600965 # For meta-extsdk-toolchain we want all sysroot dependencies
966 if taskdependees[dep][0] == 'meta-extsdk-toolchain':
967 return False
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500968 # Native/Cross populate_sysroot need their dependencies
969 if isNativeCross(taskdependees[task][0]) and isNativeCross(taskdependees[dep][0]):
970 return False
971 # Target populate_sysroot depended on by cross tools need to be installed
972 if isNativeCross(taskdependees[dep][0]):
973 return False
974 # Native/cross tools depended upon by target sysroot are not needed
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500975 # Add an exception for shadow-native as required by useradd.bbclass
976 if isNativeCross(taskdependees[task][0]) and taskdependees[task][0] != 'shadow-native':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500977 continue
978 # Target populate_sysroot need their dependencies
979 return False
980
981 if taskdependees[task][1] == 'do_shared_workdir':
982 continue
983
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500984 if taskdependees[dep][1] == "do_populate_lic":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500985 continue
986
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500987
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500988 # Safe fallthrough default
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500989 logit(" Default setscene dependency fall through due to dependency: %s" % (str(taskdependees[dep])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500990 return False
991 return True
992
993addhandler sstate_eventhandler
994sstate_eventhandler[eventmask] = "bb.build.TaskSucceeded"
995python sstate_eventhandler() {
996 d = e.data
997 # When we write an sstate package we rewrite the SSTATE_PKG
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500998 spkg = d.getVar('SSTATE_PKG')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500999 if not spkg.endswith(".tgz"):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001000 taskname = d.getVar("BB_RUNTASK")[3:]
1001 spec = d.getVar('SSTATE_PKGSPEC')
1002 swspec = d.getVar('SSTATE_SWSPEC')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001003 if taskname in ["fetch", "unpack", "patch", "populate_lic", "preconfigure"] and swspec:
1004 d.setVar("SSTATE_PKGSPEC", "${SSTATE_SWSPEC}")
1005 d.setVar("SSTATE_EXTRAPATH", "")
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001006 sstatepkg = d.getVar('SSTATE_PKG')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001007 bb.siggen.dump_this_task(sstatepkg + '_' + taskname + ".tgz" ".siginfo", d)
1008}
1009
1010SSTATE_PRUNE_OBSOLETEWORKDIR = "1"
1011
1012# Event handler which removes manifests and stamps file for
1013# recipes which are no longer reachable in a build where they
1014# once were.
1015# Also optionally removes the workdir of those tasks/recipes
1016#
1017addhandler sstate_eventhandler2
1018sstate_eventhandler2[eventmask] = "bb.event.ReachableStamps"
1019python sstate_eventhandler2() {
1020 import glob
1021 d = e.data
1022 stamps = e.stamps.values()
1023 removeworkdir = (d.getVar("SSTATE_PRUNE_OBSOLETEWORKDIR", False) == "1")
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001024 preservestampfile = d.expand('${SSTATE_MANIFESTS}/preserve-stamps')
1025 preservestamps = []
1026 if os.path.exists(preservestampfile):
1027 with open(preservestampfile, 'r') as f:
1028 preservestamps = f.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001029 seen = []
Brad Bishop316dfdd2018-06-25 12:45:53 -04001030 for a in sorted(list(set(d.getVar("SSTATE_ARCHS").split()))):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001031 toremove = []
1032 i = d.expand("${SSTATE_MANIFESTS}/index-" + a)
1033 if not os.path.exists(i):
1034 continue
1035 with open(i, "r") as f:
1036 lines = f.readlines()
1037 for l in lines:
1038 (stamp, manifest, workdir) = l.split()
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001039 if stamp not in stamps and stamp not in preservestamps:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001040 toremove.append(l)
1041 if stamp not in seen:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001042 bb.debug(2, "Stamp %s is not reachable, removing related manifests" % stamp)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001043 seen.append(stamp)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001044
1045 if toremove:
Brad Bishop316dfdd2018-06-25 12:45:53 -04001046 msg = "Removing %d recipes from the %s sysroot" % (len(toremove), a)
1047 bb.event.fire(bb.event.ProcessStarted(msg, len(toremove)), d)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001048
Brad Bishop316dfdd2018-06-25 12:45:53 -04001049 removed = 0
1050 for r in toremove:
1051 (stamp, manifest, workdir) = r.split()
1052 for m in glob.glob(manifest + ".*"):
1053 if m.endswith(".postrm"):
1054 continue
1055 sstate_clean_manifest(m, d)
1056 bb.utils.remove(stamp + "*")
1057 if removeworkdir:
1058 bb.utils.remove(workdir, recurse = True)
1059 lines.remove(r)
1060 removed = removed + 1
1061 bb.event.fire(bb.event.ProcessProgress(msg, removed), d)
1062
1063 bb.event.fire(bb.event.ProcessFinished(msg), d)
1064
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001065 with open(i, "w") as f:
1066 for l in lines:
1067 f.write(l)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001068 if preservestamps:
1069 os.remove(preservestampfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001070}