summaryrefslogtreecommitdiffstats
path: root/meta
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2020-08-11 21:50:14 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2020-08-15 11:44:20 +0100
commitf31ed30c114cf85e35afdbd84668d1e49fb589c4 (patch)
treee9256da8631218d5dd45d380115d9377f6d1148b /meta
parent0e15931688322f9422c4f128965f050b6e030c29 (diff)
downloadpoky-f31ed30c114cf85e35afdbd84668d1e49fb589c4.tar.gz
packagefeed-stability: Remove as obsolete
This class had great ideas and potential but now we have hash equivalence and reproducibility, its effectively obsolete. I'm not aware of any serious use of the class, we certainly don't get bug reports or patches so remove it and focus on those other areas. (From OE-Core rev: a7f7fc07fa9a95bb0294fa4398a0e56e80a7e148) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta')
-rw-r--r--meta/classes/packagefeed-stability.bbclass252
1 files changed, 0 insertions, 252 deletions
diff --git a/meta/classes/packagefeed-stability.bbclass b/meta/classes/packagefeed-stability.bbclass
deleted file mode 100644
index 5648602564..0000000000
--- a/meta/classes/packagefeed-stability.bbclass
+++ /dev/null
@@ -1,252 +0,0 @@
1# Class to avoid copying packages into the feed if they haven't materially changed
2#
3# Copyright (C) 2015 Intel Corporation
4# Released under the MIT license (see COPYING.MIT for details)
5#
6# This class effectively intercepts packages as they are written out by
7# do_package_write_*, causing them to be written into a different
8# directory where we can compare them to whatever older packages might
9# be in the "real" package feed directory, and avoid copying the new
10# package to the feed if it has not materially changed. The idea is to
11# avoid unnecessary churn in the packages when dependencies trigger task
12# reexecution (and thus repackaging). Enabling the class is simple:
13#
14# INHERIT += "packagefeed-stability"
15#
16# Caveats:
17# 1) Latest PR values in the build system may not match those in packages
18# seen on the target (naturally)
19# 2) If you rebuild from sstate without the existing package feed present,
20# you will lose the "state" of the package feed i.e. the preserved old
21# package versions. Not the end of the world, but would negate the
22# entire purpose of this class.
23#
24# Note that running -c cleanall on a recipe will purposely delete the old
25# package files so they will definitely be copied the next time.
26
27python() {
28 if bb.data.inherits_class('native', d) or bb.data.inherits_class('cross', d):
29 return
30 # Package backend agnostic intercept
31 # This assumes that the package_write task is called package_write_<pkgtype>
32 # and that the directory in which packages should be written is
33 # pointed to by the variable DEPLOY_DIR_<PKGTYPE>
34 for pkgclass in (d.getVar('PACKAGE_CLASSES') or '').split():
35 if pkgclass.startswith('package_'):
36 pkgtype = pkgclass.split('_', 1)[1]
37 pkgwritefunc = 'do_package_write_%s' % pkgtype
38 sstate_outputdirs = d.getVarFlag(pkgwritefunc, 'sstate-outputdirs', False)
39 deploydirvar = 'DEPLOY_DIR_%s' % pkgtype.upper()
40 deploydirvarref = '${' + deploydirvar + '}'
41 pkgcomparefunc = 'do_package_compare_%s' % pkgtype
42
43 if bb.data.inherits_class('image', d):
44 d.appendVarFlag('do_rootfs', 'recrdeptask', ' ' + pkgcomparefunc)
45
46 if bb.data.inherits_class('populate_sdk_base', d):
47 d.appendVarFlag('do_populate_sdk', 'recrdeptask', ' ' + pkgcomparefunc)
48
49 if bb.data.inherits_class('populate_sdk_ext', d):
50 d.appendVarFlag('do_populate_sdk_ext', 'recrdeptask', ' ' + pkgcomparefunc)
51
52 d.appendVarFlag('do_build', 'recrdeptask', ' ' + pkgcomparefunc)
53
54 if d.getVarFlag(pkgwritefunc, 'noexec') or not d.getVarFlag(pkgwritefunc, 'task'):
55 # Packaging is disabled for this recipe, we shouldn't do anything
56 continue
57
58 if deploydirvarref in sstate_outputdirs:
59 deplor_dir_pkgtype = d.expand(deploydirvarref + '-prediff')
60 # Set intermediate output directory
61 d.setVarFlag(pkgwritefunc, 'sstate-outputdirs', sstate_outputdirs.replace(deploydirvarref, deplor_dir_pkgtype))
62 # Update SSTATE_DUPWHITELIST to avoid shared location conflicted error
63 d.appendVar('SSTATE_DUPWHITELIST', ' %s' % deplor_dir_pkgtype)
64
65 d.setVar(pkgcomparefunc, d.getVar('do_package_compare', False))
66 d.setVarFlags(pkgcomparefunc, d.getVarFlags('do_package_compare', False))
67 d.appendVarFlag(pkgcomparefunc, 'depends', ' build-compare-native:do_populate_sysroot')
68 bb.build.addtask(pkgcomparefunc, 'do_build', 'do_packagedata ' + pkgwritefunc, d)
69}
70
71# This isn't the real task function - it's a template that we use in the
72# anonymous python code above
73fakeroot python do_package_compare () {
74 currenttask = d.getVar('BB_CURRENTTASK')
75 pkgtype = currenttask.rsplit('_', 1)[1]
76 package_compare_impl(pkgtype, d)
77}
78
79def package_compare_impl(pkgtype, d):
80 import errno
81 import fnmatch
82 import glob
83 import subprocess
84 import oe.sstatesig
85
86 pn = d.getVar('PN')
87 deploydir = d.getVar('DEPLOY_DIR_%s' % pkgtype.upper())
88 prepath = deploydir + '-prediff/'
89
90 # Find out PKGR values are
91 pkgdatadir = d.getVar('PKGDATA_DIR')
92 packages = []
93 try:
94 with open(os.path.join(pkgdatadir, pn), 'r') as f:
95 for line in f:
96 if line.startswith('PACKAGES:'):
97 packages = line.split(':', 1)[1].split()
98 break
99 except IOError as e:
100 if e.errno == errno.ENOENT:
101 pass
102
103 if not packages:
104 bb.debug(2, '%s: no packages, nothing to do' % pn)
105 return
106
107 pkgrvalues = {}
108 rpkgnames = {}
109 rdepends = {}
110 pkgvvalues = {}
111 for pkg in packages:
112 with open(os.path.join(pkgdatadir, 'runtime', pkg), 'r') as f:
113 for line in f:
114 if line.startswith('PKGR:'):
115 pkgrvalues[pkg] = line.split(':', 1)[1].strip()
116 if line.startswith('PKGV:'):
117 pkgvvalues[pkg] = line.split(':', 1)[1].strip()
118 elif line.startswith('PKG_%s:' % pkg):
119 rpkgnames[pkg] = line.split(':', 1)[1].strip()
120 elif line.startswith('RDEPENDS_%s:' % pkg):
121 rdepends[pkg] = line.split(':', 1)[1].strip()
122
123 # Prepare a list of the runtime package names for packages that were
124 # actually produced
125 rpkglist = []
126 for pkg, rpkg in rpkgnames.items():
127 if os.path.exists(os.path.join(pkgdatadir, 'runtime', pkg + '.packaged')):
128 rpkglist.append((rpkg, pkg))
129 rpkglist.sort(key=lambda x: len(x[0]), reverse=True)
130
131 pvu = d.getVar('PV', False)
132 if '$' + '{SRCPV}' in pvu:
133 pvprefix = pvu.split('$' + '{SRCPV}', 1)[0]
134 else:
135 pvprefix = None
136
137 pkgwritetask = 'package_write_%s' % pkgtype
138 files = []
139 docopy = False
140 manifest, _ = oe.sstatesig.sstate_get_manifest_filename(pkgwritetask, d)
141 mlprefix = d.getVar('MLPREFIX')
142 # Copy recipe's all packages if one of the packages are different to make
143 # they have the same PR.
144 with open(manifest, 'r') as f:
145 for line in f:
146 if line.startswith(prepath):
147 srcpath = line.rstrip()
148 if os.path.isfile(srcpath):
149 destpath = os.path.join(deploydir, os.path.relpath(srcpath, prepath))
150
151 # This is crude but should work assuming the output
152 # package file name starts with the package name
153 # and rpkglist is sorted by length (descending)
154 pkgbasename = os.path.basename(destpath)
155 pkgname = None
156 for rpkg, pkg in rpkglist:
157 if mlprefix and pkgtype == 'rpm' and rpkg.startswith(mlprefix):
158 rpkg = rpkg[len(mlprefix):]
159 if pkgbasename.startswith(rpkg):
160 pkgr = pkgrvalues[pkg]
161 destpathspec = destpath.replace(pkgr, '*')
162 if pvprefix:
163 pkgv = pkgvvalues[pkg]
164 if pkgv.startswith(pvprefix):
165 pkgvsuffix = pkgv[len(pvprefix):]
166 if '+' in pkgvsuffix:
167 newpkgv = pvprefix + '*+' + pkgvsuffix.split('+', 1)[1]
168 destpathspec = destpathspec.replace(pkgv, newpkgv)
169 pkgname = pkg
170 break
171 else:
172 bb.warn('Unable to map %s back to package' % pkgbasename)
173 destpathspec = destpath
174
175 oldfile = None
176 if not docopy:
177 oldfiles = glob.glob(destpathspec)
178 if oldfiles:
179 oldfile = oldfiles[-1]
180 result = subprocess.call(['pkg-diff.sh', oldfile, srcpath])
181 if result != 0:
182 docopy = True
183 bb.note("%s and %s are different, will copy packages" % (oldfile, srcpath))
184 else:
185 docopy = True
186 bb.note("No old packages found for %s, will copy packages" % pkgname)
187
188 files.append((pkgname, pkgbasename, srcpath, destpath))
189
190 # Remove all the old files and copy again if docopy
191 if docopy:
192 bb.note('Copying packages for recipe %s' % pn)
193 pcmanifest = os.path.join(prepath, d.expand('pkg-compare-manifest-${MULTIMACH_TARGET_SYS}-${PN}'))
194 try:
195 with open(pcmanifest, 'r') as f:
196 for line in f:
197 fn = line.rstrip()
198 if fn:
199 try:
200 os.remove(fn)
201 bb.note('Removed old package %s' % fn)
202 except OSError as e:
203 if e.errno == errno.ENOENT:
204 pass
205 except IOError as e:
206 if e.errno == errno.ENOENT:
207 pass
208
209 # Create new manifest
210 with open(pcmanifest, 'w') as f:
211 for pkgname, pkgbasename, srcpath, destpath in files:
212 destdir = os.path.dirname(destpath)
213 bb.utils.mkdirhier(destdir)
214 # Remove allarch rpm pkg if it is already existed (for
215 # multilib), they're identical in theory, but sstate.bbclass
216 # copies it again, so keep align with that.
217 if os.path.exists(destpath) and pkgtype == 'rpm' \
218 and d.getVar('PACKAGE_ARCH') == 'all':
219 os.unlink(destpath)
220 if (os.stat(srcpath).st_dev == os.stat(destdir).st_dev):
221 # Use a hard link to save space
222 os.link(srcpath, destpath)
223 else:
224 shutil.copyfile(srcpath, destpath)
225 f.write('%s\n' % destpath)
226 else:
227 bb.note('Not copying packages for recipe %s' % pn)
228
229do_cleansstate[postfuncs] += "pfs_cleanpkgs"
230python pfs_cleanpkgs () {
231 import errno
232 for pkgclass in (d.getVar('PACKAGE_CLASSES') or '').split():
233 if pkgclass.startswith('package_'):
234 pkgtype = pkgclass.split('_', 1)[1]
235 deploydir = d.getVar('DEPLOY_DIR_%s' % pkgtype.upper())
236 prepath = deploydir + '-prediff'
237 pcmanifest = os.path.join(prepath, d.expand('pkg-compare-manifest-${MULTIMACH_TARGET_SYS}-${PN}'))
238 try:
239 with open(pcmanifest, 'r') as f:
240 for line in f:
241 fn = line.rstrip()
242 if fn:
243 try:
244 os.remove(fn)
245 except OSError as e:
246 if e.errno == errno.ENOENT:
247 pass
248 os.remove(pcmanifest)
249 except IOError as e:
250 if e.errno == errno.ENOENT:
251 pass
252}