blob: e30fbe12809797568f502f40cb84465bcbcf3011 [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"
31# Archive the sources for many architectures in one deploy folder
32SSTATE_DUPWHITELIST += "${DEPLOY_DIR_SRC}"
33
Brad Bishop6e60e8b2018-02-01 10:27:11 -050034SSTATE_SCAN_FILES ?= "*.la *-config *_config postinst-*"
35SSTATE_SCAN_CMD ??= 'find ${SSTATE_BUILDDIR} \( -name "${@"\" -o -name \"".join(d.getVar("SSTATE_SCAN_FILES").split())}" \) -type f'
36SSTATE_SCAN_CMD_NATIVE ??= 'grep -Irl -e ${RECIPE_SYSROOT} -e ${RECIPE_SYSROOT_NATIVE} -e ${HOSTTOOLS_DIR} ${SSTATE_BUILDDIR}'
Patrick Williamsc124f4f2015-09-15 14:41:29 -050037
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050038BB_HASHFILENAME = "False ${SSTATE_PKGSPEC} ${SSTATE_SWSPEC}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050039
40SSTATE_ARCHS = " \
41 ${BUILD_ARCH} \
42 ${BUILD_ARCH}_${SDK_ARCH}_${SDK_OS} \
43 ${BUILD_ARCH}_${TARGET_ARCH} \
44 ${SDK_ARCH}_${SDK_OS} \
45 ${SDK_ARCH}_${PACKAGE_ARCH} \
46 allarch \
47 ${PACKAGE_ARCH} \
48 ${MACHINE}"
49
50SSTATE_MANMACH ?= "${SSTATE_PKGARCH}"
51
52SSTATECREATEFUNCS = "sstate_hardcode_path"
53SSTATEPOSTCREATEFUNCS = ""
54SSTATEPREINSTFUNCS = ""
55SSTATEPOSTUNPACKFUNCS = "sstate_hardcode_path_unpack"
56SSTATEPOSTINSTFUNCS = ""
Brad Bishop6e60e8b2018-02-01 10:27:11 -050057EXTRA_STAGING_FIXMES ?= "HOSTTOOLS_DIR"
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050058SSTATECLEANFUNCS = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -050059
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050060# Check whether sstate exists for tasks that support sstate and are in the
61# locked signatures file.
62SIGGEN_LOCKEDSIGS_SSTATE_EXISTS_CHECK ?= 'error'
63
64# Check whether the task's computed hash matches the task's hash in the
65# locked signatures file.
66SIGGEN_LOCKEDSIGS_TASKSIG_CHECK ?= "error"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050067
68# The GnuPG key ID and passphrase to use to sign sstate archives (or unset to
69# not sign)
70SSTATE_SIG_KEY ?= ""
71SSTATE_SIG_PASSPHRASE ?= ""
72# Whether to verify the GnUPG signatures when extracting sstate archives
73SSTATE_VERIFY_SIG ?= "0"
74
Patrick Williamsc124f4f2015-09-15 14:41:29 -050075python () {
76 if bb.data.inherits_class('native', d):
77 d.setVar('SSTATE_PKGARCH', d.getVar('BUILD_ARCH', False))
78 elif bb.data.inherits_class('crosssdk', d):
79 d.setVar('SSTATE_PKGARCH', d.expand("${BUILD_ARCH}_${SDK_ARCH}_${SDK_OS}"))
80 elif bb.data.inherits_class('cross', d):
81 d.setVar('SSTATE_PKGARCH', d.expand("${BUILD_ARCH}_${TARGET_ARCH}"))
82 elif bb.data.inherits_class('nativesdk', d):
83 d.setVar('SSTATE_PKGARCH', d.expand("${SDK_ARCH}_${SDK_OS}"))
84 elif bb.data.inherits_class('cross-canadian', d):
85 d.setVar('SSTATE_PKGARCH', d.expand("${SDK_ARCH}_${PACKAGE_ARCH}"))
Brad Bishop6e60e8b2018-02-01 10:27:11 -050086 elif bb.data.inherits_class('allarch', d) and d.getVar("PACKAGE_ARCH") == "all":
Patrick Williamsc124f4f2015-09-15 14:41:29 -050087 d.setVar('SSTATE_PKGARCH', "allarch")
88 else:
89 d.setVar('SSTATE_MANMACH', d.expand("${PACKAGE_ARCH}"))
90
91 if bb.data.inherits_class('native', d) or bb.data.inherits_class('crosssdk', d) or bb.data.inherits_class('cross', d):
92 d.setVar('SSTATE_EXTRAPATH', "${NATIVELSBSTRING}/")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050093 d.setVar('BB_HASHFILENAME', "True ${SSTATE_PKGSPEC} ${SSTATE_SWSPEC}")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050094 d.setVar('SSTATE_EXTRAPATHWILDCARD', "*/")
95
Brad Bishop6e60e8b2018-02-01 10:27:11 -050096 unique_tasks = sorted(set((d.getVar('SSTATETASKS') or "").split()))
Patrick Williamsc124f4f2015-09-15 14:41:29 -050097 d.setVar('SSTATETASKS', " ".join(unique_tasks))
98 for task in unique_tasks:
99 d.prependVarFlag(task, 'prefuncs', "sstate_task_prefunc ")
100 d.appendVarFlag(task, 'postfuncs', " sstate_task_postfunc")
101}
102
103def sstate_init(task, d):
104 ss = {}
105 ss['task'] = task
106 ss['dirs'] = []
107 ss['plaindirs'] = []
108 ss['lockfiles'] = []
109 ss['lockfiles-shared'] = []
110 return ss
111
112def sstate_state_fromvars(d, task = None):
113 if task is None:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500114 task = d.getVar('BB_CURRENTTASK')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500115 if not task:
116 bb.fatal("sstate code running without task context?!")
117 task = task.replace("_setscene", "")
118
119 if task.startswith("do_"):
120 task = task[3:]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500121 inputs = (d.getVarFlag("do_" + task, 'sstate-inputdirs') or "").split()
122 outputs = (d.getVarFlag("do_" + task, 'sstate-outputdirs') or "").split()
123 plaindirs = (d.getVarFlag("do_" + task, 'sstate-plaindirs') or "").split()
124 lockfiles = (d.getVarFlag("do_" + task, 'sstate-lockfile') or "").split()
125 lockfilesshared = (d.getVarFlag("do_" + task, 'sstate-lockfile-shared') or "").split()
126 interceptfuncs = (d.getVarFlag("do_" + task, 'sstate-interceptfuncs') or "").split()
127 fixmedir = d.getVarFlag("do_" + task, 'sstate-fixmedir') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500128 if not task or len(inputs) != len(outputs):
129 bb.fatal("sstate variables not setup correctly?!")
130
131 if task == "populate_lic":
132 d.setVar("SSTATE_PKGSPEC", "${SSTATE_SWSPEC}")
133 d.setVar("SSTATE_EXTRAPATH", "")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500134 d.setVar('SSTATE_EXTRAPATHWILDCARD', "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500135
136 ss = sstate_init(task, d)
137 for i in range(len(inputs)):
138 sstate_add(ss, inputs[i], outputs[i], d)
139 ss['lockfiles'] = lockfiles
140 ss['lockfiles-shared'] = lockfilesshared
141 ss['plaindirs'] = plaindirs
142 ss['interceptfuncs'] = interceptfuncs
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500143 ss['fixmedir'] = fixmedir
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500144 return ss
145
146def sstate_add(ss, source, dest, d):
147 if not source.endswith("/"):
148 source = source + "/"
149 if not dest.endswith("/"):
150 dest = dest + "/"
151 source = os.path.normpath(source)
152 dest = os.path.normpath(dest)
153 srcbase = os.path.basename(source)
154 ss['dirs'].append([srcbase, source, dest])
155 return ss
156
157def sstate_install(ss, d):
158 import oe.path
159 import oe.sstatesig
160 import subprocess
161
162 sharedfiles = []
163 shareddirs = []
164 bb.utils.mkdirhier(d.expand("${SSTATE_MANIFESTS}"))
165
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500166 sstateinst = d.expand("${WORKDIR}/sstate-install-%s/" % ss['task'])
167
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500168 manifest, d2 = oe.sstatesig.sstate_get_manifest_filename(ss['task'], d)
169
170 if os.access(manifest, os.R_OK):
171 bb.fatal("Package already staged (%s)?!" % manifest)
172
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600173 d.setVar("SSTATE_INST_POSTRM", manifest + ".postrm")
174
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500175 locks = []
176 for lock in ss['lockfiles-shared']:
177 locks.append(bb.utils.lockfile(lock, True))
178 for lock in ss['lockfiles']:
179 locks.append(bb.utils.lockfile(lock))
180
181 for state in ss['dirs']:
182 bb.debug(2, "Staging files from %s to %s" % (state[1], state[2]))
183 for walkroot, dirs, files in os.walk(state[1]):
184 for file in files:
185 srcpath = os.path.join(walkroot, file)
186 dstpath = srcpath.replace(state[1], state[2])
187 #bb.debug(2, "Staging %s to %s" % (srcpath, dstpath))
188 sharedfiles.append(dstpath)
189 for dir in dirs:
190 srcdir = os.path.join(walkroot, dir)
191 dstdir = srcdir.replace(state[1], state[2])
192 #bb.debug(2, "Staging %s to %s" % (srcdir, dstdir))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500193 if os.path.islink(srcdir):
194 sharedfiles.append(dstdir)
195 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500196 if not dstdir.endswith("/"):
197 dstdir = dstdir + "/"
198 shareddirs.append(dstdir)
199
200 # Check the file list for conflicts against files which already exist
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500201 whitelist = (d.getVar("SSTATE_DUPWHITELIST") or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500202 match = []
203 for f in sharedfiles:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500204 if os.path.exists(f) and not os.path.islink(f):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500205 f = os.path.normpath(f)
206 realmatch = True
207 for w in whitelist:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600208 w = os.path.normpath(w)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500209 if f.startswith(w):
210 realmatch = False
211 break
212 if realmatch:
213 match.append(f)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500214 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 -0500215 search_output = subprocess.Popen(sstate_search_cmd, shell=True, stdout=subprocess.PIPE).communicate()[0]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500216 if search_output:
217 match.append(" (matched in %s)" % search_output.decode('utf-8').rstrip())
218 else:
219 match.append(" (not matched to any task)")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500220 if match:
221 bb.error("The recipe %s is trying to install files into a shared " \
222 "area when those files already exist. Those files and their manifest " \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500223 "location are:\n %s\nPlease verify which recipe should provide the " \
224 "above files.\n\nThe build has stopped, as continuing in this scenario WILL " \
225 "break things - if not now, possibly in the future (we've seen builds fail " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500226 "several months later). If the system knew how to recover from this " \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500227 "automatically it would, however there are several different scenarios " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500228 "which can result in this and we don't know which one this is. It may be " \
229 "you have switched providers of something like virtual/kernel (e.g. from " \
230 "linux-yocto to linux-yocto-dev), in that case you need to execute the " \
231 "clean task for both recipes and it will resolve this error. It may be " \
232 "you changed DISTRO_FEATURES from systemd to udev or vice versa. Cleaning " \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500233 "those recipes should again resolve this error, however switching " \
234 "DISTRO_FEATURES on an existing build directory is not supported - you " \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500235 "should really clean out tmp and rebuild (reusing sstate should be safe). " \
236 "It could be the overlapping files detected are harmless in which case " \
237 "adding them to SSTATE_DUPWHITELIST may be the correct solution. It could " \
238 "also be your build is including two different conflicting versions of " \
239 "things (e.g. bluez 4 and bluez 5 and the correct solution for that would " \
240 "be to resolve the conflict. If in doubt, please ask on the mailing list, " \
241 "sharing the error and filelist above." % \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500242 (d.getVar('PN'), "\n ".join(match)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500243 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.")
244
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500245 if ss['fixmedir'] and os.path.exists(ss['fixmedir'] + "/fixmepath.cmd"):
246 sharedfiles.append(ss['fixmedir'] + "/fixmepath.cmd")
247 sharedfiles.append(ss['fixmedir'] + "/fixmepath")
248
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500249 # Write out the manifest
250 f = open(manifest, "w")
251 for file in sharedfiles:
252 f.write(file + "\n")
253
254 # We want to ensure that directories appear at the end of the manifest
255 # so that when we test to see if they should be deleted any contents
256 # added by the task will have been removed first.
257 dirs = sorted(shareddirs, key=len)
258 # Must remove children first, which will have a longer path than the parent
259 for di in reversed(dirs):
260 f.write(di + "\n")
261 f.close()
262
263 # Append to the list of manifests for this PACKAGE_ARCH
264
265 i = d2.expand("${SSTATE_MANIFESTS}/index-${SSTATE_MANMACH}")
266 l = bb.utils.lockfile(i + ".lock")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500267 filedata = d.getVar("STAMP") + " " + d2.getVar("SSTATE_MANFILEPREFIX") + " " + d.getVar("WORKDIR") + "\n"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500268 manifests = []
269 if os.path.exists(i):
270 with open(i, "r") as f:
271 manifests = f.readlines()
272 if filedata not in manifests:
273 with open(i, "a+") as f:
274 f.write(filedata)
275 bb.utils.unlockfile(l)
276
277 # Run the actual file install
278 for state in ss['dirs']:
279 if os.path.exists(state[1]):
280 oe.path.copyhardlinktree(state[1], state[2])
281
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500282 for postinst in (d.getVar('SSTATEPOSTINSTFUNCS') or '').split():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500283 # All hooks should run in the SSTATE_INSTDIR
284 bb.build.exec_func(postinst, d, (sstateinst,))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500285
286 for lock in locks:
287 bb.utils.unlockfile(lock)
288
289sstate_install[vardepsexclude] += "SSTATE_DUPWHITELIST STATE_MANMACH SSTATE_MANFILEPREFIX"
290sstate_install[vardeps] += "${SSTATEPOSTINSTFUNCS}"
291
292def sstate_installpkg(ss, d):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500293 from oe.gpg_sign import get_signer
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500294
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500295 sstateinst = d.expand("${WORKDIR}/sstate-install-%s/" % ss['task'])
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500296 sstatefetch = d.getVar('SSTATE_PKGNAME') + '_' + ss['task'] + ".tgz"
297 sstatepkg = d.getVar('SSTATE_PKG') + '_' + ss['task'] + ".tgz"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500298
299 if not os.path.exists(sstatepkg):
300 pstaging_fetch(sstatefetch, sstatepkg, d)
301
302 if not os.path.isfile(sstatepkg):
303 bb.note("Staging package %s does not exist" % sstatepkg)
304 return False
305
306 sstate_clean(ss, d)
307
308 d.setVar('SSTATE_INSTDIR', sstateinst)
309 d.setVar('SSTATE_PKG', sstatepkg)
310
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500311 if bb.utils.to_boolean(d.getVar("SSTATE_VERIFY_SIG"), False):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500312 signer = get_signer(d, 'local')
313 if not signer.verify(sstatepkg + '.sig'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500314 bb.warn("Cannot verify signature on sstate package %s" % sstatepkg)
315
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500316 # Empty sstateinst directory, ensure its clean
317 if os.path.exists(sstateinst):
318 oe.path.remove(sstateinst)
319 bb.utils.mkdirhier(sstateinst)
320
321 sstateinst = d.getVar("SSTATE_INSTDIR")
322 d.setVar('SSTATE_FIXMEDIR', ss['fixmedir'])
323
324 for f in (d.getVar('SSTATEPREINSTFUNCS') or '').split() + ['sstate_unpack_package']:
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500325 # All hooks should run in the SSTATE_INSTDIR
326 bb.build.exec_func(f, d, (sstateinst,))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500327
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500328 return sstate_installpkgdir(ss, d)
329
330def sstate_installpkgdir(ss, d):
331 import oe.path
332 import subprocess
333
334 sstateinst = d.getVar("SSTATE_INSTDIR")
335 d.setVar('SSTATE_FIXMEDIR', ss['fixmedir'])
336
337 for f in (d.getVar('SSTATEPOSTUNPACKFUNCS') or '').split():
338 # All hooks should run in the SSTATE_INSTDIR
339 bb.build.exec_func(f, d, (sstateinst,))
340
341 def prepdir(dir):
342 # remove dir if it exists, ensure any parent directories do exist
343 if os.path.exists(dir):
344 oe.path.remove(dir)
345 bb.utils.mkdirhier(dir)
346 oe.path.remove(dir)
347
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500348 for state in ss['dirs']:
349 prepdir(state[1])
350 os.rename(sstateinst + state[0], state[1])
351 sstate_install(ss, d)
352
353 for plain in ss['plaindirs']:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500354 workdir = d.getVar('WORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500355 src = sstateinst + "/" + plain.replace(workdir, '')
356 dest = plain
357 bb.utils.mkdirhier(src)
358 prepdir(dest)
359 os.rename(src, dest)
360
361 return True
362
363python sstate_hardcode_path_unpack () {
364 # Fixup hardcoded paths
365 #
366 # Note: The logic below must match the reverse logic in
367 # sstate_hardcode_path(d)
368 import subprocess
369
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500370 sstateinst = d.getVar('SSTATE_INSTDIR')
371 sstatefixmedir = d.getVar('SSTATE_FIXMEDIR')
372 fixmefn = sstateinst + "fixmepath"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500373 if os.path.isfile(fixmefn):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500374 staging_target = d.getVar('RECIPE_SYSROOT')
375 staging_host = d.getVar('RECIPE_SYSROOT_NATIVE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500376
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500377 if bb.data.inherits_class('native', d) or bb.data.inherits_class('cross-canadian', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500378 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRHOST:%s:g'" % (staging_host)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500379 elif bb.data.inherits_class('cross', d) or bb.data.inherits_class('crosssdk', d):
380 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRTARGET:%s:g; s:FIXMESTAGINGDIRHOST:%s:g'" % (staging_target, staging_host)
381 else:
382 sstate_sed_cmd = "sed -i -e 's:FIXMESTAGINGDIRTARGET:%s:g'" % (staging_target)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500383
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500384 extra_staging_fixmes = d.getVar('EXTRA_STAGING_FIXMES') or ''
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500385 for fixmevar in extra_staging_fixmes.split():
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500386 fixme_path = d.getVar(fixmevar)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500387 sstate_sed_cmd += " -e 's:FIXME_%s:%s:g'" % (fixmevar, fixme_path)
388
389 # Add sstateinst to each filename in fixmepath, use xargs to efficiently call sed
390 sstate_hardcode_cmd = "sed -e 's:^:%s:g' %s | xargs %s" % (sstateinst, fixmefn, sstate_sed_cmd)
391
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500392 # Defer do_populate_sysroot relocation command
393 if sstatefixmedir:
394 bb.utils.mkdirhier(sstatefixmedir)
395 with open(sstatefixmedir + "/fixmepath.cmd", "w") as f:
396 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(fixmefn, sstatefixmedir + "/fixmepath")
397 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(sstateinst, "FIXMEFINALSSTATEINST")
398 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(staging_host, "FIXMEFINALSSTATEHOST")
399 sstate_hardcode_cmd = sstate_hardcode_cmd.replace(staging_target, "FIXMEFINALSSTATETARGET")
400 f.write(sstate_hardcode_cmd)
401 bb.utils.copyfile(fixmefn, sstatefixmedir + "/fixmepath")
402 return
403
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500404 bb.note("Replacing fixme paths in sstate package: %s" % (sstate_hardcode_cmd))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500405 subprocess.check_call(sstate_hardcode_cmd, shell=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500406
407 # Need to remove this or we'd copy it into the target directory and may
408 # conflict with another writer
409 os.remove(fixmefn)
410}
411
412def sstate_clean_cachefile(ss, d):
413 import oe.path
414
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500415 sstatepkgfile = d.getVar('SSTATE_PATHSPEC') + "*_" + ss['task'] + ".tgz*"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500416 bb.note("Removing %s" % sstatepkgfile)
417 oe.path.remove(sstatepkgfile)
418
419def sstate_clean_cachefiles(d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500420 for task in (d.getVar('SSTATETASKS') or "").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500421 ld = d.createCopy()
422 ss = sstate_state_fromvars(ld, task)
423 sstate_clean_cachefile(ss, ld)
424
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500425def sstate_clean_manifest(manifest, d, prefix=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500426 import oe.path
427
428 mfile = open(manifest)
429 entries = mfile.readlines()
430 mfile.close()
431
432 for entry in entries:
433 entry = entry.strip()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500434 if prefix and not entry.startswith("/"):
435 entry = prefix + "/" + entry
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500436 bb.debug(2, "Removing manifest: %s" % entry)
437 # We can race against another package populating directories as we're removing them
438 # so we ignore errors here.
439 try:
440 if entry.endswith("/"):
441 if os.path.islink(entry[:-1]):
442 os.remove(entry[:-1])
443 elif os.path.exists(entry) and len(os.listdir(entry)) == 0:
444 os.rmdir(entry[:-1])
445 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500446 os.remove(entry)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500447 except OSError:
448 pass
449
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600450 postrm = manifest + ".postrm"
451 if os.path.exists(manifest + ".postrm"):
452 import subprocess
453 os.chmod(postrm, 0o755)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500454 subprocess.check_call(postrm, shell=True)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600455 oe.path.remove(postrm)
456
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500457 oe.path.remove(manifest)
458
459def sstate_clean(ss, d):
460 import oe.path
461 import glob
462
463 d2 = d.createCopy()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500464 stamp_clean = d.getVar("STAMPCLEAN")
465 extrainf = d.getVarFlag("do_" + ss['task'], 'stamp-extra-info')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500466 if extrainf:
467 d2.setVar("SSTATE_MANMACH", extrainf)
468 wildcard_stfile = "%s.do_%s*.%s" % (stamp_clean, ss['task'], extrainf)
469 else:
470 wildcard_stfile = "%s.do_%s*" % (stamp_clean, ss['task'])
471
472 manifest = d2.expand("${SSTATE_MANFILEPREFIX}.%s" % ss['task'])
473
474 if os.path.exists(manifest):
475 locks = []
476 for lock in ss['lockfiles-shared']:
477 locks.append(bb.utils.lockfile(lock))
478 for lock in ss['lockfiles']:
479 locks.append(bb.utils.lockfile(lock))
480
481 sstate_clean_manifest(manifest, d)
482
483 for lock in locks:
484 bb.utils.unlockfile(lock)
485
486 # Remove the current and previous stamps, but keep the sigdata.
487 #
488 # The glob() matches do_task* which may match multiple tasks, for
489 # example: do_package and do_package_write_ipk, so we need to
490 # exactly match *.do_task.* and *.do_task_setscene.*
491 rm_stamp = '.do_%s.' % ss['task']
492 rm_setscene = '.do_%s_setscene.' % ss['task']
493 # For BB_SIGNATURE_HANDLER = "noop"
494 rm_nohash = ".do_%s" % ss['task']
495 for stfile in glob.glob(wildcard_stfile):
496 # Keep the sigdata
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500497 if ".sigdata." in stfile or ".sigbasedata." in stfile:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500498 continue
499 # Preserve taint files in the stamps directory
500 if stfile.endswith('.taint'):
501 continue
502 if rm_stamp in stfile or rm_setscene in stfile or \
503 stfile.endswith(rm_nohash):
504 oe.path.remove(stfile)
505
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500506 # Removes the users/groups created by the package
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500507 for cleanfunc in (d.getVar('SSTATECLEANFUNCS') or '').split():
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500508 bb.build.exec_func(cleanfunc, d)
509
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500510sstate_clean[vardepsexclude] = "SSTATE_MANFILEPREFIX"
511
512CLEANFUNCS += "sstate_cleanall"
513
514python sstate_cleanall() {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500515 bb.note("Removing shared state for package %s" % d.getVar('PN'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500516
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500517 manifest_dir = d.getVar('SSTATE_MANIFESTS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500518 if not os.path.exists(manifest_dir):
519 return
520
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500521 tasks = d.getVar('SSTATETASKS').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500522 for name in tasks:
523 ld = d.createCopy()
524 shared_state = sstate_state_fromvars(ld, name)
525 sstate_clean(shared_state, ld)
526}
527
528python sstate_hardcode_path () {
529 import subprocess, platform
530
531 # Need to remove hardcoded paths and fix these when we install the
532 # staging packages.
533 #
534 # Note: the logic in this function needs to match the reverse logic
535 # in sstate_installpkg(ss, d)
536
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500537 staging_target = d.getVar('RECIPE_SYSROOT')
538 staging_host = d.getVar('RECIPE_SYSROOT_NATIVE')
539 sstate_builddir = d.getVar('SSTATE_BUILDDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500540
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500541 if bb.data.inherits_class('native', d) or bb.data.inherits_class('cross-canadian', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500542 sstate_grep_cmd = "grep -l -e '%s'" % (staging_host)
543 sstate_sed_cmd = "sed -i -e 's:%s:FIXMESTAGINGDIRHOST:g'" % (staging_host)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500544 elif bb.data.inherits_class('cross', d) or bb.data.inherits_class('crosssdk', d):
545 sstate_grep_cmd = "grep -l -e '%s' -e '%s'" % (staging_target, staging_host)
546 sstate_sed_cmd = "sed -i -e 's:%s:FIXMESTAGINGDIRTARGET:g; s:%s:FIXMESTAGINGDIRHOST:g'" % (staging_target, staging_host)
547 else:
548 sstate_grep_cmd = "grep -l -e '%s'" % (staging_target)
549 sstate_sed_cmd = "sed -i -e 's:%s:FIXMESTAGINGDIRTARGET:g'" % (staging_target)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500550
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500551 extra_staging_fixmes = d.getVar('EXTRA_STAGING_FIXMES') or ''
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500552 for fixmevar in extra_staging_fixmes.split():
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500553 fixme_path = d.getVar(fixmevar)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500554 sstate_sed_cmd += " -e 's:%s:FIXME_%s:g'" % (fixme_path, fixmevar)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500555 sstate_grep_cmd += " -e '%s'" % (fixme_path)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500556
557 fixmefn = sstate_builddir + "fixmepath"
558
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500559 sstate_scan_cmd = d.getVar('SSTATE_SCAN_CMD')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500560 sstate_filelist_cmd = "tee %s" % (fixmefn)
561
562 # fixmepath file needs relative paths, drop sstate_builddir prefix
563 sstate_filelist_relative_cmd = "sed -i -e 's:^%s::g' %s" % (sstate_builddir, fixmefn)
564
565 xargs_no_empty_run_cmd = '--no-run-if-empty'
566 if platform.system() == 'Darwin':
567 xargs_no_empty_run_cmd = ''
568
569 # Limit the fixpaths and sed operations based on the initial grep search
570 # This has the side effect of making sure the vfs cache is hot
571 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)
572
573 bb.note("Removing hardcoded paths from sstate package: '%s'" % (sstate_hardcode_cmd))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500574 subprocess.check_output(sstate_hardcode_cmd, shell=True, cwd=sstate_builddir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500575
576 # If the fixmefn is empty, remove it..
577 if os.stat(fixmefn).st_size == 0:
578 os.remove(fixmefn)
579 else:
580 bb.note("Replacing absolute paths in fixmepath file: '%s'" % (sstate_filelist_relative_cmd))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500581 subprocess.check_output(sstate_filelist_relative_cmd, shell=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500582}
583
584def sstate_package(ss, d):
585 import oe.path
586
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500587 tmpdir = d.getVar('TMPDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500588
589 sstatebuild = d.expand("${WORKDIR}/sstate-build-%s/" % ss['task'])
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500590 sstatepkg = d.getVar('SSTATE_PKG') + '_'+ ss['task'] + ".tgz"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500591 bb.utils.remove(sstatebuild, recurse=True)
592 bb.utils.mkdirhier(sstatebuild)
593 bb.utils.mkdirhier(os.path.dirname(sstatepkg))
594 for state in ss['dirs']:
595 if not os.path.exists(state[1]):
596 continue
597 srcbase = state[0].rstrip("/").rsplit('/', 1)[0]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500598 # Find and error for absolute symlinks. We could attempt to relocate but its not
599 # clear where the symlink is relative to in this context. We could add that markup
600 # to sstate tasks but there aren't many of these so better just avoid them entirely.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500601 for walkroot, dirs, files in os.walk(state[1]):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500602 for file in files + dirs:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500603 srcpath = os.path.join(walkroot, file)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500604 if not os.path.islink(srcpath):
605 continue
606 link = os.readlink(srcpath)
607 if not os.path.isabs(link):
608 continue
609 if not link.startswith(tmpdir):
610 continue
611 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 -0500612 bb.debug(2, "Preparing tree %s for packaging at %s" % (state[1], sstatebuild + state[0]))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500613 os.rename(state[1], sstatebuild + state[0])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500614
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500615 workdir = d.getVar('WORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500616 for plain in ss['plaindirs']:
617 pdir = plain.replace(workdir, sstatebuild)
618 bb.utils.mkdirhier(plain)
619 bb.utils.mkdirhier(pdir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500620 os.rename(plain, pdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500621
622 d.setVar('SSTATE_BUILDDIR', sstatebuild)
623 d.setVar('SSTATE_PKG', sstatepkg)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500624 d.setVar('SSTATE_INSTDIR', sstatebuild)
625
626 if d.getVar('SSTATE_SKIP_CREATION') == '1':
627 return
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500628
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500629 for f in (d.getVar('SSTATECREATEFUNCS') or '').split() + \
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500630 ['sstate_create_package', 'sstate_sign_package'] + \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500631 (d.getVar('SSTATEPOSTCREATEFUNCS') or '').split():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500632 # All hooks should run in SSTATE_BUILDDIR.
633 bb.build.exec_func(f, d, (sstatebuild,))
634
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500635 bb.siggen.dump_this_task(sstatepkg + ".siginfo", d)
636
637 return
638
639def pstaging_fetch(sstatefetch, sstatepkg, d):
640 import bb.fetch2
641
642 # Only try and fetch if the user has configured a mirror
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500643 mirrors = d.getVar('SSTATE_MIRRORS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500644 if not mirrors:
645 return
646
647 # Copy the data object and override DL_DIR and SRC_URI
648 localdata = bb.data.createCopy(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500649
650 dldir = localdata.expand("${SSTATE_DIR}")
651 bb.utils.mkdirhier(dldir)
652
653 localdata.delVar('MIRRORS')
654 localdata.setVar('FILESPATH', dldir)
655 localdata.setVar('DL_DIR', dldir)
656 localdata.setVar('PREMIRRORS', mirrors)
657
658 # if BB_NO_NETWORK is set but we also have SSTATE_MIRROR_ALLOW_NETWORK,
659 # we'll want to allow network access for the current set of fetches.
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500660 if localdata.getVar('BB_NO_NETWORK') == "1" and localdata.getVar('SSTATE_MIRROR_ALLOW_NETWORK') == "1":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500661 localdata.delVar('BB_NO_NETWORK')
662
663 # Try a fetch from the sstate mirror, if it fails just return and
664 # we will build the package
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600665 uris = ['file://{0};downloadfilename={0}'.format(sstatefetch),
666 'file://{0}.siginfo;downloadfilename={0}.siginfo'.format(sstatefetch)]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500667 if bb.utils.to_boolean(d.getVar("SSTATE_VERIFY_SIG"), False):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600668 uris += ['file://{0}.sig;downloadfilename={0}.sig'.format(sstatefetch)]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500669
670 for srcuri in uris:
671 localdata.setVar('SRC_URI', srcuri)
672 try:
673 fetcher = bb.fetch2.Fetch([srcuri], localdata, cache=False)
674 fetcher.download()
675
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500676 except bb.fetch2.BBFetchException:
677 break
678
679def sstate_setscene(d):
680 shared_state = sstate_state_fromvars(d)
681 accelerate = sstate_installpkg(shared_state, d)
682 if not accelerate:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600683 bb.fatal("No suitable staging package found")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500684
685python sstate_task_prefunc () {
686 shared_state = sstate_state_fromvars(d)
687 sstate_clean(shared_state, d)
688}
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500689sstate_task_prefunc[dirs] = "${WORKDIR}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500690
691python sstate_task_postfunc () {
692 shared_state = sstate_state_fromvars(d)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500693
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500694 for intercept in shared_state['interceptfuncs']:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500695 bb.build.exec_func(intercept, d, (d.getVar("WORKDIR"),))
696
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600697 omask = os.umask(0o002)
698 if omask != 0o002:
699 bb.note("Using umask 0o002 (not %0o) for sstate packaging" % omask)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500700 sstate_package(shared_state, d)
701 os.umask(omask)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500702
703 sstateinst = d.getVar("SSTATE_INSTDIR")
704 d.setVar('SSTATE_FIXMEDIR', shared_state['fixmedir'])
705
706 sstate_installpkgdir(shared_state, d)
707
708 bb.utils.remove(d.getVar("SSTATE_BUILDDIR"), recurse=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500709}
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500710sstate_task_postfunc[dirs] = "${WORKDIR}"
711
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500712
713#
714# Shell function to generate a sstate package from a directory
715# set as SSTATE_BUILDDIR. Will be run from within SSTATE_BUILDDIR.
716#
717sstate_create_package () {
718 TFILE=`mktemp ${SSTATE_PKG}.XXXXXXXX`
719 # Need to handle empty directories
720 if [ "$(ls -A)" ]; then
721 set +e
722 tar -czf $TFILE *
723 ret=$?
724 if [ $ret -ne 0 ] && [ $ret -ne 1 ]; then
725 exit 1
726 fi
727 set -e
728 else
729 tar -cz --file=$TFILE --files-from=/dev/null
730 fi
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500731 chmod 0664 $TFILE
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500732 mv -f $TFILE ${SSTATE_PKG}
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500733}
734
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500735python sstate_sign_package () {
736 from oe.gpg_sign import get_signer
737
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500738 if d.getVar('SSTATE_SIG_KEY'):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500739 signer = get_signer(d, 'local')
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500740 sstate_pkg = d.getVar('SSTATE_PKG')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500741 if os.path.exists(sstate_pkg + '.sig'):
742 os.unlink(sstate_pkg + '.sig')
743 signer.detach_sign(sstate_pkg, d.getVar('SSTATE_SIG_KEY', False), None,
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500744 d.getVar('SSTATE_SIG_PASSPHRASE'), armor=False)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500745}
746
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500747#
748# Shell function to decompress and prepare a package for installation
749# Will be run from within SSTATE_INSTDIR.
750#
751sstate_unpack_package () {
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500752 tar -xvzf ${SSTATE_PKG}
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500753 # update .siginfo atime on local/NFS mirror
754 [ -w ${SSTATE_PKG}.siginfo ] && [ -h ${SSTATE_PKG}.siginfo ] && touch -a ${SSTATE_PKG}.siginfo
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500755 # Use "! -w ||" to return true for read only files
756 [ ! -w ${SSTATE_PKG} ] || touch --no-dereference ${SSTATE_PKG}
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500757 [ ! -w ${SSTATE_PKG}.sig ] || [ ! -e ${SSTATE_PKG}.sig ] || touch --no-dereference ${SSTATE_PKG}.sig
758 [ ! -w ${SSTATE_PKG}.siginfo ] || [ ! -e ${SSTATE_PKG}.siginfo ] || touch --no-dereference ${SSTATE_PKG}.siginfo
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500759}
760
761BB_HASHCHECK_FUNCTION = "sstate_checkhashes"
762
763def sstate_checkhashes(sq_fn, sq_task, sq_hash, sq_hashfn, d, siginfo=False):
764
765 ret = []
766 missed = []
767 extension = ".tgz"
768 if siginfo:
769 extension = extension + ".siginfo"
770
771 def getpathcomponents(task, d):
772 # Magic data from BB_HASHFILENAME
773 splithashfn = sq_hashfn[task].split(" ")
774 spec = splithashfn[1]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500775 if splithashfn[0] == "True":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500776 extrapath = d.getVar("NATIVELSBSTRING") + "/"
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500777 else:
778 extrapath = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500779
780 tname = sq_task[task][3:]
781
782 if tname in ["fetch", "unpack", "patch", "populate_lic", "preconfigure"] and splithashfn[2]:
783 spec = splithashfn[2]
784 extrapath = ""
785
786 return spec, extrapath, tname
787
788
789 for task in range(len(sq_fn)):
790
791 spec, extrapath, tname = getpathcomponents(task, d)
792
793 sstatefile = d.expand("${SSTATE_DIR}/" + extrapath + generate_sstatefn(spec, sq_hash[task], d) + "_" + tname + extension)
794
795 if os.path.exists(sstatefile):
796 bb.debug(2, "SState: Found valid sstate file %s" % sstatefile)
797 ret.append(task)
798 continue
799 else:
800 missed.append(task)
801 bb.debug(2, "SState: Looked for but didn't find file %s" % sstatefile)
802
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500803 mirrors = d.getVar("SSTATE_MIRRORS")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500804 if mirrors:
805 # Copy the data object and override DL_DIR and SRC_URI
806 localdata = bb.data.createCopy(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500807
808 dldir = localdata.expand("${SSTATE_DIR}")
809 localdata.delVar('MIRRORS')
810 localdata.setVar('FILESPATH', dldir)
811 localdata.setVar('DL_DIR', dldir)
812 localdata.setVar('PREMIRRORS', mirrors)
813
814 bb.debug(2, "SState using premirror of: %s" % mirrors)
815
816 # if BB_NO_NETWORK is set but we also have SSTATE_MIRROR_ALLOW_NETWORK,
817 # we'll want to allow network access for the current set of fetches.
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500818 if localdata.getVar('BB_NO_NETWORK') == "1" and localdata.getVar('SSTATE_MIRROR_ALLOW_NETWORK') == "1":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500819 localdata.delVar('BB_NO_NETWORK')
820
821 from bb.fetch2 import FetchConnectionCache
822 def checkstatus_init(thread_worker):
823 thread_worker.connection_cache = FetchConnectionCache()
824
825 def checkstatus_end(thread_worker):
826 thread_worker.connection_cache.close_connections()
827
828 def checkstatus(thread_worker, arg):
829 (task, sstatefile) = arg
830
831 localdata2 = bb.data.createCopy(localdata)
832 srcuri = "file://" + sstatefile
833 localdata.setVar('SRC_URI', srcuri)
834 bb.debug(2, "SState: Attempting to fetch %s" % srcuri)
835
836 try:
837 fetcher = bb.fetch2.Fetch(srcuri.split(), localdata2,
838 connection_cache=thread_worker.connection_cache)
839 fetcher.checkstatus()
840 bb.debug(2, "SState: Successful fetch test for %s" % srcuri)
841 ret.append(task)
842 if task in missed:
843 missed.remove(task)
844 except:
845 missed.append(task)
846 bb.debug(2, "SState: Unsuccessful fetch test for %s" % srcuri)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600847 pass
848 bb.event.fire(bb.event.ProcessProgress("Checking sstate mirror object availability", len(tasklist) - thread_worker.tasks.qsize()), d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500849
850 tasklist = []
851 for task in range(len(sq_fn)):
852 if task in ret:
853 continue
854 spec, extrapath, tname = getpathcomponents(task, d)
855 sstatefile = d.expand(extrapath + generate_sstatefn(spec, sq_hash[task], d) + "_" + tname + extension)
856 tasklist.append((task, sstatefile))
857
858 if tasklist:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600859 bb.event.fire(bb.event.ProcessStarted("Checking sstate mirror object availability", len(tasklist)), d)
860
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500861 import multiprocessing
862 nproc = min(multiprocessing.cpu_count(), len(tasklist))
863
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600864 bb.event.enable_threadlock()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500865 pool = oe.utils.ThreadedPool(nproc, len(tasklist),
866 worker_init=checkstatus_init, worker_end=checkstatus_end)
867 for t in tasklist:
868 pool.add_task(checkstatus, t)
869 pool.start()
870 pool.wait_completion()
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600871 bb.event.disable_threadlock()
872
873 bb.event.fire(bb.event.ProcessFinished("Checking sstate mirror object availability"), d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500874
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500875 inheritlist = d.getVar("INHERIT")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500876 if "toaster" in inheritlist:
877 evdata = {'missed': [], 'found': []};
878 for task in missed:
879 spec, extrapath, tname = getpathcomponents(task, d)
880 sstatefile = d.expand(extrapath + generate_sstatefn(spec, sq_hash[task], d) + "_" + tname + ".tgz")
881 evdata['missed'].append( (sq_fn[task], sq_task[task], sq_hash[task], sstatefile ) )
882 for task in ret:
883 spec, extrapath, tname = getpathcomponents(task, d)
884 sstatefile = d.expand(extrapath + generate_sstatefn(spec, sq_hash[task], d) + "_" + tname + ".tgz")
885 evdata['found'].append( (sq_fn[task], sq_task[task], sq_hash[task], sstatefile ) )
886 bb.event.fire(bb.event.MetadataEvent("MissedSstate", evdata), d)
887
888 if hasattr(bb.parse.siggen, "checkhashes"):
889 bb.parse.siggen.checkhashes(missed, ret, sq_fn, sq_task, sq_hash, sq_hashfn, d)
890
891 return ret
892
893BB_SETSCENE_DEPVALID = "setscene_depvalid"
894
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500895def setscene_depvalid(task, taskdependees, notneeded, d, log=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500896 # taskdependees is a dict of tasks which depend on task, each being a 3 item list of [PN, TASKNAME, FILENAME]
897 # task is included in taskdependees too
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500898 # Return - False - We need this dependency
899 # - True - We can skip this dependency
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500900
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500901 def logit(msg, log):
902 if log is not None:
903 log.append(msg)
904 else:
905 bb.debug(2, msg)
906
907 logit("Considering setscene task: %s" % (str(taskdependees[task])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500908
909 def isNativeCross(x):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500910 return x.endswith("-native") or "-cross-" in x or "-crosssdk" in x or x.endswith("-cross")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500911
912 # We only need to trigger populate_lic through direct dependencies
913 if taskdependees[task][1] == "do_populate_lic":
914 return True
915
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500916 # stash_locale and gcc_stash_builddir are never needed as a dependency for built objects
917 if taskdependees[task][1] == "do_stash_locale" or taskdependees[task][1] == "do_gcc_stash_builddir":
918 return True
919
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500920 # We only need to trigger packagedata through direct dependencies
921 # but need to preserve packagedata on packagedata links
922 if taskdependees[task][1] == "do_packagedata":
923 for dep in taskdependees:
924 if taskdependees[dep][1] == "do_packagedata":
925 return False
926 return True
927
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500928 for dep in taskdependees:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500929 logit(" considering dependency: %s" % (str(taskdependees[dep])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500930 if task == dep:
931 continue
932 if dep in notneeded:
933 continue
934 # do_package_write_* and do_package doesn't need do_package
935 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']:
936 continue
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500937 # do_package_write_* need do_populate_sysroot as they're mainly postinstall dependencies
938 if taskdependees[task][1] == "do_populate_sysroot" and taskdependees[dep][1] in ['do_package_write_deb', 'do_package_write_ipk', 'do_package_write_rpm']:
939 return False
940 # do_package/packagedata/package_qa don't need do_populate_sysroot
941 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 -0500942 continue
943 # Native/Cross packages don't exist and are noexec anyway
944 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']:
945 continue
946
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500947 # This is due to the [depends] in useradd.bbclass complicating matters
948 # The logic *is* reversed here due to the way hard setscene dependencies are injected
949 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':
950 continue
951
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500952 # Consider sysroot depending on sysroot tasks
953 if taskdependees[task][1] == 'do_populate_sysroot' and taskdependees[dep][1] == 'do_populate_sysroot':
954 # base-passwd/shadow-sysroot don't need their dependencies
955 if taskdependees[dep][0].endswith(("base-passwd", "shadow-sysroot")):
956 continue
957 # Nothing need depend on libc-initial/gcc-cross-initial
958 if "-initial" in taskdependees[task][0]:
959 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600960 # For meta-extsdk-toolchain we want all sysroot dependencies
961 if taskdependees[dep][0] == 'meta-extsdk-toolchain':
962 return False
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500963 # Native/Cross populate_sysroot need their dependencies
964 if isNativeCross(taskdependees[task][0]) and isNativeCross(taskdependees[dep][0]):
965 return False
966 # Target populate_sysroot depended on by cross tools need to be installed
967 if isNativeCross(taskdependees[dep][0]):
968 return False
969 # Native/cross tools depended upon by target sysroot are not needed
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500970 # Add an exception for shadow-native as required by useradd.bbclass
971 if isNativeCross(taskdependees[task][0]) and taskdependees[task][0] != 'shadow-native':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500972 continue
973 # Target populate_sysroot need their dependencies
974 return False
975
976 if taskdependees[task][1] == 'do_shared_workdir':
977 continue
978
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500979 if taskdependees[dep][1] == "do_populate_lic":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500980 continue
981
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500982
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500983 # Safe fallthrough default
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500984 logit(" Default setscene dependency fall through due to dependency: %s" % (str(taskdependees[dep])), log)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500985 return False
986 return True
987
988addhandler sstate_eventhandler
989sstate_eventhandler[eventmask] = "bb.build.TaskSucceeded"
990python sstate_eventhandler() {
991 d = e.data
992 # When we write an sstate package we rewrite the SSTATE_PKG
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500993 spkg = d.getVar('SSTATE_PKG')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500994 if not spkg.endswith(".tgz"):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500995 taskname = d.getVar("BB_RUNTASK")[3:]
996 spec = d.getVar('SSTATE_PKGSPEC')
997 swspec = d.getVar('SSTATE_SWSPEC')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500998 if taskname in ["fetch", "unpack", "patch", "populate_lic", "preconfigure"] and swspec:
999 d.setVar("SSTATE_PKGSPEC", "${SSTATE_SWSPEC}")
1000 d.setVar("SSTATE_EXTRAPATH", "")
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001001 sstatepkg = d.getVar('SSTATE_PKG')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001002 bb.siggen.dump_this_task(sstatepkg + '_' + taskname + ".tgz" ".siginfo", d)
1003}
1004
1005SSTATE_PRUNE_OBSOLETEWORKDIR = "1"
1006
1007# Event handler which removes manifests and stamps file for
1008# recipes which are no longer reachable in a build where they
1009# once were.
1010# Also optionally removes the workdir of those tasks/recipes
1011#
1012addhandler sstate_eventhandler2
1013sstate_eventhandler2[eventmask] = "bb.event.ReachableStamps"
1014python sstate_eventhandler2() {
1015 import glob
1016 d = e.data
1017 stamps = e.stamps.values()
1018 removeworkdir = (d.getVar("SSTATE_PRUNE_OBSOLETEWORKDIR", False) == "1")
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001019 preservestampfile = d.expand('${SSTATE_MANIFESTS}/preserve-stamps')
1020 preservestamps = []
1021 if os.path.exists(preservestampfile):
1022 with open(preservestampfile, 'r') as f:
1023 preservestamps = f.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001024 seen = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001025 for a in d.getVar("SSTATE_ARCHS").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001026 toremove = []
1027 i = d.expand("${SSTATE_MANIFESTS}/index-" + a)
1028 if not os.path.exists(i):
1029 continue
1030 with open(i, "r") as f:
1031 lines = f.readlines()
1032 for l in lines:
1033 (stamp, manifest, workdir) = l.split()
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001034 if stamp not in stamps and stamp not in preservestamps:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001035 toremove.append(l)
1036 if stamp not in seen:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001037 bb.debug(2, "Stamp %s is not reachable, removing related manifests" % stamp)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001038 seen.append(stamp)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001039
1040 if toremove:
1041 bb.note("There are %d recipes to be removed from sysroot %s, removing..." % (len(toremove), a))
1042
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001043 for r in toremove:
1044 (stamp, manifest, workdir) = r.split()
1045 for m in glob.glob(manifest + ".*"):
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001046 if m.endswith(".postrm"):
1047 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001048 sstate_clean_manifest(m, d)
1049 bb.utils.remove(stamp + "*")
1050 if removeworkdir:
1051 bb.utils.remove(workdir, recurse = True)
1052 lines.remove(r)
1053 with open(i, "w") as f:
1054 for l in lines:
1055 f.write(l)
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001056 if preservestamps:
1057 os.remove(preservestampfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001058}