blob: 63887b34f839ffa016c2917c95c64b7fef1e99f0 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001#
2# Packaging process
3#
4# Executive summary: This class iterates over the functions listed in PACKAGEFUNCS
5# Taking D and splitting it up into the packages listed in PACKAGES, placing the
6# resulting output in PKGDEST.
7#
8# There are the following default steps but PACKAGEFUNCS can be extended:
9#
Andrew Geisslerc9f78652020-09-18 14:11:35 -050010# a) package_convert_pr_autoinc - convert AUTOINC in PKGV to ${PRSERV_PV_AUTOINC}
Patrick Williamsc124f4f2015-09-15 14:41:29 -050011#
12# b) perform_packagecopy - Copy D into PKGD
13#
14# c) package_do_split_locales - Split out the locale files, updates FILES and PACKAGES
15#
16# d) split_and_strip_files - split the files into runtime and debug and strip them.
17# Debug files include debug info split, and associated sources that end up in -dbg packages
18#
19# e) fixup_perms - Fix up permissions in the package before we split it.
20#
21# f) populate_packages - Split the files in PKGD into separate packages in PKGDEST/<pkgname>
22# Also triggers the binary stripping code to put files in -dbg packages.
23#
24# g) package_do_filedeps - Collect perfile run-time dependency metadata
25# The data is stores in FILER{PROVIDES,DEPENDS}_file_pkg variables with
26# a list of affected files in FILER{PROVIDES,DEPENDS}FLIST_pkg
27#
28# h) package_do_shlibs - Look at the shared libraries generated and autotmatically add any
Brad Bishop316dfdd2018-06-25 12:45:53 -040029# dependencies found. Also stores the package name so anyone else using this library
Patrick Williamsc124f4f2015-09-15 14:41:29 -050030# knows which package to depend on.
31#
32# i) package_do_pkgconfig - Keep track of which packages need and provide which .pc files
33#
34# j) read_shlibdeps - Reads the stored shlibs information into the metadata
35#
36# k) package_depchains - Adds automatic dependencies to -dbg and -dev packages
37#
38# l) emit_pkgdata - saves the packaging data into PKGDATA_DIR for use in later
39# packaging steps
40
41inherit packagedata
Patrick Williamsc124f4f2015-09-15 14:41:29 -050042inherit chrpath
Brad Bishop96ff1982019-08-19 13:50:42 -040043inherit package_pkgdata
Patrick Williamsc124f4f2015-09-15 14:41:29 -050044inherit insane
45
46PKGD = "${WORKDIR}/package"
47PKGDEST = "${WORKDIR}/packages-split"
48
49LOCALE_SECTION ?= ''
50
51ALL_MULTILIB_PACKAGE_ARCHS = "${@all_multilib_tune_values(d, 'PACKAGE_ARCHS')}"
52
53# rpm is used for the per-file dependency identification
Brad Bishop316dfdd2018-06-25 12:45:53 -040054# dwarfsrcfiles is used to determine the list of debug source files
55PACKAGE_DEPENDS += "rpm-native dwarfsrcfiles-native"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050056
Brad Bishop6e60e8b2018-02-01 10:27:11 -050057
58# If your postinstall can execute at rootfs creation time rather than on
59# target but depends on a native/cross tool in order to execute, you need to
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080060# list that tool in PACKAGE_WRITE_DEPS. Target package dependencies belong
Brad Bishop6e60e8b2018-02-01 10:27:11 -050061# in the package dependencies as normal, this is just for native/cross support
62# tools at rootfs build time.
63PACKAGE_WRITE_DEPS ??= ""
64
Patrick Williamsc124f4f2015-09-15 14:41:29 -050065def legitimize_package_name(s):
66 """
67 Make sure package names are legitimate strings
68 """
69 import re
70
71 def fixutf(m):
72 cp = m.group(1)
73 if cp:
Patrick Williamsc0f7c042017-02-23 20:41:17 -060074 return ('\\u%s' % cp).encode('latin-1').decode('unicode_escape')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050075
76 # Handle unicode codepoints encoded as <U0123>, as in glibc locale files.
Brad Bishop19323692019-04-05 15:28:33 -040077 s = re.sub(r'<U([0-9A-Fa-f]{1,4})>', fixutf, s)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050078
79 # Remaining package name validity fixes
80 return s.lower().replace('_', '-').replace('@', '+').replace(',', '+').replace('/', '-')
81
82def do_split_packages(d, root, file_regex, output_pattern, description, postinst=None, recursive=False, hook=None, extra_depends=None, aux_files_pattern=None, postrm=None, allow_dirs=False, prepend=False, match_path=False, aux_files_pattern_verbatim=None, allow_links=False, summary=None):
83 """
84 Used in .bb files to split up dynamically generated subpackages of a
85 given package, usually plugins or modules.
86
87 Arguments:
88 root -- the path in which to search
89 file_regex -- regular expression to match searched files. Use
90 parentheses () to mark the part of this expression
91 that should be used to derive the module name (to be
92 substituted where %s is used in other function
93 arguments as noted below)
94 output_pattern -- pattern to use for the package names. Must include %s.
95 description -- description to set for each package. Must include %s.
96 postinst -- postinstall script to use for all packages (as a
97 string)
98 recursive -- True to perform a recursive search - default False
99 hook -- a hook function to be called for every match. The
100 function will be called with the following arguments
101 (in the order listed):
102 f: full path to the file/directory match
103 pkg: the package name
104 file_regex: as above
105 output_pattern: as above
106 modulename: the module name derived using file_regex
107 extra_depends -- extra runtime dependencies (RDEPENDS) to be set for
108 all packages. The default value of None causes a
109 dependency on the main package (${PN}) - if you do
110 not want this, pass '' for this parameter.
111 aux_files_pattern -- extra item(s) to be added to FILES for each
112 package. Can be a single string item or a list of
113 strings for multiple items. Must include %s.
114 postrm -- postrm script to use for all packages (as a string)
115 allow_dirs -- True allow directories to be matched - default False
116 prepend -- if True, prepend created packages to PACKAGES instead
117 of the default False which appends them
118 match_path -- match file_regex on the whole relative path to the
119 root rather than just the file name
120 aux_files_pattern_verbatim -- extra item(s) to be added to FILES for
121 each package, using the actual derived module name
122 rather than converting it to something legal for a
123 package name. Can be a single string item or a list
124 of strings for multiple items. Must include %s.
125 allow_links -- True to allow symlinks to be matched - default False
126 summary -- Summary to set for each package. Must include %s;
127 defaults to description if not set.
128
129 """
130
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500131 dvar = d.getVar('PKGD')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500132 root = d.expand(root)
133 output_pattern = d.expand(output_pattern)
134 extra_depends = d.expand(extra_depends)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500135
136 # If the root directory doesn't exist, don't error out later but silently do
137 # no splitting.
138 if not os.path.exists(dvar + root):
139 return []
140
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500141 ml = d.getVar("MLPREFIX")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500142 if ml:
143 if not output_pattern.startswith(ml):
144 output_pattern = ml + output_pattern
145
146 newdeps = []
147 for dep in (extra_depends or "").split():
148 if dep.startswith(ml):
149 newdeps.append(dep)
150 else:
151 newdeps.append(ml + dep)
152 if newdeps:
153 extra_depends = " ".join(newdeps)
154
155
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500156 packages = d.getVar('PACKAGES').split()
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600157 split_packages = set()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500158
159 if postinst:
160 postinst = '#!/bin/sh\n' + postinst + '\n'
161 if postrm:
162 postrm = '#!/bin/sh\n' + postrm + '\n'
163 if not recursive:
164 objs = os.listdir(dvar + root)
165 else:
166 objs = []
167 for walkroot, dirs, files in os.walk(dvar + root):
168 for file in files:
169 relpath = os.path.join(walkroot, file).replace(dvar + root + '/', '', 1)
170 if relpath:
171 objs.append(relpath)
172
173 if extra_depends == None:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500174 extra_depends = d.getVar("PN")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500175
176 if not summary:
177 summary = description
178
179 for o in sorted(objs):
180 import re, stat
181 if match_path:
182 m = re.match(file_regex, o)
183 else:
184 m = re.match(file_regex, os.path.basename(o))
185
186 if not m:
187 continue
188 f = os.path.join(dvar + root, o)
189 mode = os.lstat(f).st_mode
190 if not (stat.S_ISREG(mode) or (allow_links and stat.S_ISLNK(mode)) or (allow_dirs and stat.S_ISDIR(mode))):
191 continue
192 on = legitimize_package_name(m.group(1))
193 pkg = output_pattern % on
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600194 split_packages.add(pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500195 if not pkg in packages:
196 if prepend:
197 packages = [pkg] + packages
198 else:
199 packages.append(pkg)
Patrick Williams213cb262021-08-07 19:21:33 -0500200 oldfiles = d.getVar('FILES:' + pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500201 newfile = os.path.join(root, o)
202 # These names will be passed through glob() so if the filename actually
203 # contains * or ? (rare, but possible) we need to handle that specially
204 newfile = newfile.replace('*', '[*]')
205 newfile = newfile.replace('?', '[?]')
206 if not oldfiles:
207 the_files = [newfile]
208 if aux_files_pattern:
209 if type(aux_files_pattern) is list:
210 for fp in aux_files_pattern:
211 the_files.append(fp % on)
212 else:
213 the_files.append(aux_files_pattern % on)
214 if aux_files_pattern_verbatim:
215 if type(aux_files_pattern_verbatim) is list:
216 for fp in aux_files_pattern_verbatim:
217 the_files.append(fp % m.group(1))
218 else:
219 the_files.append(aux_files_pattern_verbatim % m.group(1))
Patrick Williams213cb262021-08-07 19:21:33 -0500220 d.setVar('FILES:' + pkg, " ".join(the_files))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500221 else:
Patrick Williams213cb262021-08-07 19:21:33 -0500222 d.setVar('FILES:' + pkg, oldfiles + " " + newfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500223 if extra_depends != '':
Patrick Williams213cb262021-08-07 19:21:33 -0500224 d.appendVar('RDEPENDS:' + pkg, ' ' + extra_depends)
225 if not d.getVar('DESCRIPTION:' + pkg):
226 d.setVar('DESCRIPTION:' + pkg, description % on)
227 if not d.getVar('SUMMARY:' + pkg):
228 d.setVar('SUMMARY:' + pkg, summary % on)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500229 if postinst:
Patrick Williams213cb262021-08-07 19:21:33 -0500230 d.setVar('pkg_postinst:' + pkg, postinst)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500231 if postrm:
Patrick Williams213cb262021-08-07 19:21:33 -0500232 d.setVar('pkg_postrm:' + pkg, postrm)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500233 if callable(hook):
234 hook(f, pkg, file_regex, output_pattern, m.group(1))
235
236 d.setVar('PACKAGES', ' '.join(packages))
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600237 return list(split_packages)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500238
239PACKAGE_DEPENDS += "file-native"
240
241python () {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500242 if d.getVar('PACKAGES') != '':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500243 deps = ""
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500244 for dep in (d.getVar('PACKAGE_DEPENDS') or "").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500245 deps += " %s:do_populate_sysroot" % dep
Andrew Geissler82c905d2020-04-13 13:39:40 -0500246 if d.getVar('PACKAGE_MINIDEBUGINFO') == '1':
247 deps += ' xz-native:do_populate_sysroot'
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500248 d.appendVarFlag('do_package', 'depends', deps)
249
250 # shlibs requires any DEPENDS to have already packaged for the *.list files
251 d.appendVarFlag('do_package', 'deptask', " do_packagedata")
252}
253
254# Get a list of files from file vars by searching files under current working directory
255# The list contains symlinks, directories and normal files.
256def files_from_filevars(filevars):
257 import os,glob
258 cpath = oe.cachedpath.CachedPath()
259 files = []
260 for f in filevars:
261 if os.path.isabs(f):
262 f = '.' + f
263 if not f.startswith("./"):
264 f = './' + f
265 globbed = glob.glob(f)
266 if globbed:
267 if [ f ] != globbed:
268 files += globbed
269 continue
270 files.append(f)
271
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600272 symlink_paths = []
273 for ind, f in enumerate(files):
274 # Handle directory symlinks. Truncate path to the lowest level symlink
275 parent = ''
276 for dirname in f.split('/')[:-1]:
277 parent = os.path.join(parent, dirname)
278 if dirname == '.':
279 continue
280 if cpath.islink(parent):
281 bb.warn("FILES contains file '%s' which resides under a "
282 "directory symlink. Please fix the recipe and use the "
283 "real path for the file." % f[1:])
284 symlink_paths.append(f)
285 files[ind] = parent
286 f = parent
287 break
288
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500289 if not cpath.islink(f):
290 if cpath.isdir(f):
291 newfiles = [ os.path.join(f,x) for x in os.listdir(f) ]
292 if newfiles:
293 files += newfiles
294
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600295 return files, symlink_paths
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500296
297# Called in package_<rpm,ipk,deb>.bbclass to get the correct list of configuration files
298def get_conffiles(pkg, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500299 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500300 root = os.path.join(pkgdest, pkg)
301 cwd = os.getcwd()
302 os.chdir(root)
303
Patrick Williams213cb262021-08-07 19:21:33 -0500304 conffiles = d.getVar('CONFFILES:%s' % pkg);
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500305 if conffiles == None:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500306 conffiles = d.getVar('CONFFILES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500307 if conffiles == None:
308 conffiles = ""
309 conffiles = conffiles.split()
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600310 conf_orig_list = files_from_filevars(conffiles)[0]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500311
312 # Remove links and directories from conf_orig_list to get conf_list which only contains normal files
313 conf_list = []
314 for f in conf_orig_list:
315 if os.path.isdir(f):
316 continue
317 if os.path.islink(f):
318 continue
319 if not os.path.exists(f):
320 continue
321 conf_list.append(f)
322
323 # Remove the leading './'
324 for i in range(0, len(conf_list)):
325 conf_list[i] = conf_list[i][1:]
326
327 os.chdir(cwd)
328 return conf_list
329
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500330def checkbuildpath(file, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500331 tmpdir = d.getVar('TMPDIR')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500332 with open(file) as f:
333 file_content = f.read()
334 if tmpdir in file_content:
335 return True
336
337 return False
338
Brad Bishop316dfdd2018-06-25 12:45:53 -0400339def parse_debugsources_from_dwarfsrcfiles_output(dwarfsrcfiles_output):
340 debugfiles = {}
341
342 for line in dwarfsrcfiles_output.splitlines():
343 if line.startswith("\t"):
344 debugfiles[os.path.normpath(line.split()[0])] = ""
345
346 return debugfiles.keys()
347
Brad Bishop19323692019-04-05 15:28:33 -0400348def source_info(file, d, fatal=True):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800349 import subprocess
350
351 cmd = ["dwarfsrcfiles", file]
352 try:
353 output = subprocess.check_output(cmd, universal_newlines=True, stderr=subprocess.STDOUT)
354 retval = 0
355 except subprocess.CalledProcessError as exc:
356 output = exc.output
357 retval = exc.returncode
358
Brad Bishop316dfdd2018-06-25 12:45:53 -0400359 # 255 means a specific file wasn't fully parsed to get the debug file list, which is not a fatal failure
360 if retval != 0 and retval != 255:
361 msg = "dwarfsrcfiles failed with exit code %s (cmd was %s)%s" % (retval, cmd, ":\n%s" % output if output else "")
362 if fatal:
363 bb.fatal(msg)
364 bb.note(msg)
365
366 debugsources = parse_debugsources_from_dwarfsrcfiles_output(output)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400367
Brad Bishop19323692019-04-05 15:28:33 -0400368 return list(debugsources)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400369
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000370def splitdebuginfo(file, dvar, dv, d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500371 # Function to split a single file into two components, one is the stripped
372 # target system binary, the other contains any debugging information. The
373 # two files are linked to reference each other.
374 #
Brad Bishop19323692019-04-05 15:28:33 -0400375 # return a mapping of files:debugsources
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500376
377 import stat
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800378 import subprocess
379
380 src = file[len(dvar):]
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000381 dest = dv["libdir"] + os.path.dirname(src) + dv["dir"] + "/" + os.path.basename(src) + dv["append"]
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800382 debugfile = dvar + dest
Brad Bishop19323692019-04-05 15:28:33 -0400383 sources = []
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800384
Andrew Geissler615f2f12022-07-15 14:00:58 -0500385 if file.endswith(".ko") and file.find("/lib/modules/") != -1:
386 if oe.package.is_kernel_module_signed(file):
387 bb.debug(1, "Skip strip on signed module %s" % file)
388 return (file, sources)
389
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800390 # Split the file...
391 bb.utils.mkdirhier(os.path.dirname(debugfile))
392 #bb.note("Split %s -> %s" % (file, debugfile))
393 # Only store off the hard link reference if we successfully split!
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500394
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500395 dvar = d.getVar('PKGD')
396 objcopy = d.getVar("OBJCOPY")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500397
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500398 newmode = None
399 if not os.access(file, os.W_OK) or os.access(file, os.R_OK):
400 origmode = os.stat(file)[stat.ST_MODE]
401 newmode = origmode | stat.S_IWRITE | stat.S_IREAD
402 os.chmod(file, newmode)
403
404 # We need to extract the debug src information here...
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000405 if dv["srcdir"]:
Brad Bishop19323692019-04-05 15:28:33 -0400406 sources = source_info(file, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500407
408 bb.utils.mkdirhier(os.path.dirname(debugfile))
409
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800410 subprocess.check_output([objcopy, '--only-keep-debug', file, debugfile], stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500411
412 # Set the debuglink to have the view of the file path on the target
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800413 subprocess.check_output([objcopy, '--add-gnu-debuglink', debugfile, file], stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500414
415 if newmode:
416 os.chmod(file, origmode)
417
Brad Bishop19323692019-04-05 15:28:33 -0400418 return (file, sources)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500419
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000420def splitstaticdebuginfo(file, dvar, dv, d):
Andrew Geissler82c905d2020-04-13 13:39:40 -0500421 # Unlike the function above, there is no way to split a static library
422 # two components. So to get similar results we will copy the unmodified
423 # static library (containing the debug symbols) into a new directory.
424 # We will then strip (preserving symbols) the static library in the
425 # typical location.
426 #
427 # return a mapping of files:debugsources
428
429 import stat
Andrew Geissler82c905d2020-04-13 13:39:40 -0500430
431 src = file[len(dvar):]
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000432 dest = dv["staticlibdir"] + os.path.dirname(src) + dv["staticdir"] + "/" + os.path.basename(src) + dv["staticappend"]
Andrew Geissler82c905d2020-04-13 13:39:40 -0500433 debugfile = dvar + dest
434 sources = []
435
436 # Copy the file...
437 bb.utils.mkdirhier(os.path.dirname(debugfile))
438 #bb.note("Copy %s -> %s" % (file, debugfile))
439
440 dvar = d.getVar('PKGD')
441
442 newmode = None
443 if not os.access(file, os.W_OK) or os.access(file, os.R_OK):
444 origmode = os.stat(file)[stat.ST_MODE]
445 newmode = origmode | stat.S_IWRITE | stat.S_IREAD
446 os.chmod(file, newmode)
447
448 # We need to extract the debug src information here...
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000449 if dv["srcdir"]:
Andrew Geissler82c905d2020-04-13 13:39:40 -0500450 sources = source_info(file, d)
451
452 bb.utils.mkdirhier(os.path.dirname(debugfile))
453
454 # Copy the unmodified item to the debug directory
455 shutil.copy2(file, debugfile)
456
457 if newmode:
458 os.chmod(file, origmode)
459
460 return (file, sources)
461
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000462def inject_minidebuginfo(file, dvar, dv, d):
Andrew Geissler82c905d2020-04-13 13:39:40 -0500463 # Extract just the symbols from debuginfo into minidebuginfo,
464 # compress it with xz and inject it back into the binary in a .gnu_debugdata section.
465 # https://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html
466
467 import subprocess
468
469 readelf = d.getVar('READELF')
470 nm = d.getVar('NM')
471 objcopy = d.getVar('OBJCOPY')
472
473 minidebuginfodir = d.expand('${WORKDIR}/minidebuginfo')
474
475 src = file[len(dvar):]
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000476 dest = dv["libdir"] + os.path.dirname(src) + dv["dir"] + "/" + os.path.basename(src) + dv["append"]
Andrew Geissler82c905d2020-04-13 13:39:40 -0500477 debugfile = dvar + dest
478 minidebugfile = minidebuginfodir + src + '.minidebug'
479 bb.utils.mkdirhier(os.path.dirname(minidebugfile))
480
481 # If we didn't produce debuginfo for any reason, we can't produce minidebuginfo either
482 # so skip it.
483 if not os.path.exists(debugfile):
484 bb.debug(1, 'ELF file {} has no debuginfo, skipping minidebuginfo injection'.format(file))
485 return
486
487 # Find non-allocated PROGBITS, NOTE, and NOBITS sections in the debuginfo.
488 # We will exclude all of these from minidebuginfo to save space.
489 remove_section_names = []
490 for line in subprocess.check_output([readelf, '-W', '-S', debugfile], universal_newlines=True).splitlines():
491 fields = line.split()
492 if len(fields) < 8:
493 continue
494 name = fields[0]
495 type = fields[1]
496 flags = fields[7]
497 # .debug_ sections will be removed by objcopy -S so no need to explicitly remove them
498 if name.startswith('.debug_'):
499 continue
500 if 'A' not in flags and type in ['PROGBITS', 'NOTE', 'NOBITS']:
501 remove_section_names.append(name)
502
503 # List dynamic symbols in the binary. We can exclude these from minidebuginfo
504 # because they are always present in the binary.
505 dynsyms = set()
506 for line in subprocess.check_output([nm, '-D', file, '--format=posix', '--defined-only'], universal_newlines=True).splitlines():
507 dynsyms.add(line.split()[0])
508
509 # Find all function symbols from debuginfo which aren't in the dynamic symbols table.
510 # These are the ones we want to keep in minidebuginfo.
511 keep_symbols_file = minidebugfile + '.symlist'
512 found_any_symbols = False
513 with open(keep_symbols_file, 'w') as f:
514 for line in subprocess.check_output([nm, debugfile, '--format=sysv', '--defined-only'], universal_newlines=True).splitlines():
515 fields = line.split('|')
516 if len(fields) < 7:
517 continue
518 name = fields[0].strip()
519 type = fields[3].strip()
520 if type == 'FUNC' and name not in dynsyms:
521 f.write('{}\n'.format(name))
522 found_any_symbols = True
523
524 if not found_any_symbols:
525 bb.debug(1, 'ELF file {} contains no symbols, skipping minidebuginfo injection'.format(file))
526 return
527
528 bb.utils.remove(minidebugfile)
529 bb.utils.remove(minidebugfile + '.xz')
530
531 subprocess.check_call([objcopy, '-S'] +
532 ['--remove-section={}'.format(s) for s in remove_section_names] +
533 ['--keep-symbols={}'.format(keep_symbols_file), debugfile, minidebugfile])
534
535 subprocess.check_call(['xz', '--keep', minidebugfile])
536
537 subprocess.check_call([objcopy, '--add-section', '.gnu_debugdata={}.xz'.format(minidebugfile), file])
538
Brad Bishop19323692019-04-05 15:28:33 -0400539def copydebugsources(debugsrcdir, sources, d):
Brad Bishop316dfdd2018-06-25 12:45:53 -0400540 # The debug src information written out to sourcefile is further processed
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500541 # and copied to the destination here.
542
543 import stat
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800544 import subprocess
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500545
Brad Bishop19323692019-04-05 15:28:33 -0400546 if debugsrcdir and sources:
547 sourcefile = d.expand("${WORKDIR}/debugsources.list")
548 bb.utils.remove(sourcefile)
549
550 # filenames are null-separated - this is an artefact of the previous use
551 # of rpm's debugedit, which was writing them out that way, and the code elsewhere
552 # is still assuming that.
553 debuglistoutput = '\0'.join(sources) + '\0'
554 with open(sourcefile, 'a') as sf:
555 sf.write(debuglistoutput)
556
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500557 dvar = d.getVar('PKGD')
558 strip = d.getVar("STRIP")
559 objcopy = d.getVar("OBJCOPY")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500560 workdir = d.getVar("WORKDIR")
Andrew Geissler615f2f12022-07-15 14:00:58 -0500561 sdir = d.getVar("S")
562 sparentdir = os.path.dirname(os.path.dirname(sdir))
563 sbasedir = os.path.basename(os.path.dirname(sdir)) + "/" + os.path.basename(sdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500564 workparentdir = os.path.dirname(os.path.dirname(workdir))
565 workbasedir = os.path.basename(os.path.dirname(workdir)) + "/" + os.path.basename(workdir)
566
Andrew Geissler615f2f12022-07-15 14:00:58 -0500567 # If S isnt based on WORKDIR we can infer our sources are located elsewhere,
568 # e.g. using externalsrc; use S as base for our dirs
569 if workdir in sdir:
570 basedir = workbasedir
571 parentdir = workparentdir
572 else:
573 basedir = sbasedir
574 parentdir = sparentdir
575
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500576 # If build path exists in sourcefile, it means toolchain did not use
577 # -fdebug-prefix-map to compile
578 if checkbuildpath(sourcefile, d):
Andrew Geissler615f2f12022-07-15 14:00:58 -0500579 localsrc_prefix = parentdir + "/"
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500580 else:
581 localsrc_prefix = "/usr/src/debug/"
582
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500583 nosuchdir = []
584 basepath = dvar
585 for p in debugsrcdir.split("/"):
586 basepath = basepath + "/" + p
587 if not cpath.exists(basepath):
588 nosuchdir.append(basepath)
589 bb.utils.mkdirhier(basepath)
590 cpath.updatecache(basepath)
591
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500592 # Ignore files from the recipe sysroots (target and native)
593 processdebugsrc = "LC_ALL=C ; sort -z -u '%s' | egrep -v -z '((<internal>|<built-in>)$|/.*recipe-sysroot.*/)' | "
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500594 # We need to ignore files that are not actually ours
595 # we do this by only paying attention to items from this package
596 processdebugsrc += "fgrep -zw '%s' | "
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500597 # Remove prefix in the source paths
598 processdebugsrc += "sed 's#%s##g' | "
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500599 processdebugsrc += "(cd '%s' ; cpio -pd0mlL --no-preserve-owner '%s%s' 2>/dev/null)"
600
Andrew Geissler615f2f12022-07-15 14:00:58 -0500601 cmd = processdebugsrc % (sourcefile, basedir, localsrc_prefix, parentdir, dvar, debugsrcdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800602 try:
603 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
604 except subprocess.CalledProcessError:
605 # Can "fail" if internal headers/transient sources are attempted
606 pass
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500607
608 # cpio seems to have a bug with -lL together and symbolic links are just copied, not dereferenced.
609 # Work around this by manually finding and copying any symbolic links that made it through.
Brad Bishop19323692019-04-05 15:28:33 -0400610 cmd = "find %s%s -type l -print0 -delete | sed s#%s%s/##g | (cd '%s' ; cpio -pd0mL --no-preserve-owner '%s%s')" % \
Andrew Geissler615f2f12022-07-15 14:00:58 -0500611 (dvar, debugsrcdir, dvar, debugsrcdir, parentdir, dvar, debugsrcdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800612 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500613
Andrew Geissler615f2f12022-07-15 14:00:58 -0500614
615 # debugsources.list may be polluted from the host if we used externalsrc,
616 # cpio uses copy-pass and may have just created a directory structure
617 # matching the one from the host, if thats the case move those files to
618 # debugsrcdir to avoid host contamination.
619 # Empty dir structure will be deleted in the next step.
620
621 # Same check as above for externalsrc
622 if workdir not in sdir:
623 if os.path.exists(dvar + debugsrcdir + sdir):
624 cmd = "mv %s%s%s/* %s%s" % (dvar, debugsrcdir, sdir, dvar,debugsrcdir)
625 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
626
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500627 # The copy by cpio may have resulted in some empty directories! Remove these
628 cmd = "find %s%s -empty -type d -delete" % (dvar, debugsrcdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800629 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500630
631 # Also remove debugsrcdir if its empty
632 for p in nosuchdir[::-1]:
633 if os.path.exists(p) and not os.listdir(p):
634 os.rmdir(p)
635
636#
637# Package data handling routines
638#
639
Andrew Geissler82c905d2020-04-13 13:39:40 -0500640def get_package_mapping (pkg, basepkg, d, depversions=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500641 import oe.packagedata
642
643 data = oe.packagedata.read_subpkgdata(pkg, d)
Patrick Williams213cb262021-08-07 19:21:33 -0500644 key = "PKG:%s" % pkg
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500645
646 if key in data:
Andrew Geissler595f6302022-01-24 19:11:47 +0000647 if bb.data.inherits_class('allarch', d) and bb.data.inherits_class('packagegroup', d) and pkg != data[key]:
648 bb.error("An allarch packagegroup shouldn't depend on packages which are dynamically renamed (%s to %s)" % (pkg, data[key]))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500649 # Have to avoid undoing the write_extra_pkgs(global_variants...)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800650 if bb.data.inherits_class('allarch', d) and not d.getVar('MULTILIB_VARIANTS') \
651 and data[key] == basepkg:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500652 return pkg
Andrew Geissler82c905d2020-04-13 13:39:40 -0500653 if depversions == []:
654 # Avoid returning a mapping if the renamed package rprovides its original name
Patrick Williams213cb262021-08-07 19:21:33 -0500655 rprovkey = "RPROVIDES:%s" % pkg
Andrew Geissler82c905d2020-04-13 13:39:40 -0500656 if rprovkey in data:
657 if pkg in bb.utils.explode_dep_versions2(data[rprovkey]):
658 bb.note("%s rprovides %s, not replacing the latter" % (data[key], pkg))
659 return pkg
660 # Do map to rewritten package name
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500661 return data[key]
662
663 return pkg
664
665def get_package_additional_metadata (pkg_type, d):
666 base_key = "PACKAGE_ADD_METADATA"
667 for key in ("%s_%s" % (base_key, pkg_type.upper()), base_key):
668 if d.getVar(key, False) is None:
669 continue
670 d.setVarFlag(key, "type", "list")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500671 if d.getVarFlag(key, "separator") is None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500672 d.setVarFlag(key, "separator", "\\n")
673 metadata_fields = [field.strip() for field in oe.data.typed_value(key, d)]
674 return "\n".join(metadata_fields).strip()
675
676def runtime_mapping_rename (varname, pkg, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500677 #bb.note("%s before: %s" % (varname, d.getVar(varname)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500678
679 new_depends = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500680 deps = bb.utils.explode_dep_versions2(d.getVar(varname) or "")
Andrew Geissler82c905d2020-04-13 13:39:40 -0500681 for depend, depversions in deps.items():
682 new_depend = get_package_mapping(depend, pkg, d, depversions)
683 if depend != new_depend:
684 bb.note("package name mapping done: %s -> %s" % (depend, new_depend))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500685 new_depends[new_depend] = deps[depend]
686
687 d.setVar(varname, bb.utils.join_deps(new_depends, commasep=False))
688
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500689 #bb.note("%s after: %s" % (varname, d.getVar(varname)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500690
691#
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500692# Used by do_packagedata (and possibly other routines post do_package)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500693#
694
Andrew Geisslerd5838332022-05-27 11:33:10 -0500695PRSERV_ACTIVE = "${@bool(d.getVar("PRSERV_HOST"))}"
696PRSERV_ACTIVE[vardepvalue] = "${PRSERV_ACTIVE}"
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500697package_get_auto_pr[vardepsexclude] = "BB_TASKDEPDATA"
Andrew Geisslerd5838332022-05-27 11:33:10 -0500698package_get_auto_pr[vardeps] += "PRSERV_ACTIVE"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500699python package_get_auto_pr() {
700 import oe.prservice
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500701
702 def get_do_package_hash(pn):
703 if d.getVar("BB_RUNTASK") != "do_package":
704 taskdepdata = d.getVar("BB_TASKDEPDATA", False)
705 for dep in taskdepdata:
706 if taskdepdata[dep][1] == "do_package" and taskdepdata[dep][0] == pn:
707 return taskdepdata[dep][6]
708 return None
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500709
710 # Support per recipe PRSERV_HOST
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500711 pn = d.getVar('PN')
712 host = d.getVar("PRSERV_HOST_" + pn)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500713 if not (host is None):
714 d.setVar("PRSERV_HOST", host)
715
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500716 pkgv = d.getVar("PKGV")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500717
718 # PR Server not active, handle AUTOINC
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500719 if not d.getVar('PRSERV_HOST'):
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500720 d.setVar("PRSERV_PV_AUTOINC", "0")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500721 return
722
723 auto_pr = None
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500724 pv = d.getVar("PV")
725 version = d.getVar("PRAUTOINX")
726 pkgarch = d.getVar("PACKAGE_ARCH")
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500727 checksum = get_do_package_hash(pn)
728
729 # If do_package isn't in the dependencies, we can't get the checksum...
730 if not checksum:
731 bb.warn('Task %s requested do_package unihash, but it was not available.' % d.getVar('BB_RUNTASK'))
732 #taskdepdata = d.getVar("BB_TASKDEPDATA", False)
733 #for dep in taskdepdata:
734 # bb.warn('%s:%s = %s' % (taskdepdata[dep][0], taskdepdata[dep][1], taskdepdata[dep][6]))
735 return
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500736
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500737 if d.getVar('PRSERV_LOCKDOWN'):
738 auto_pr = d.getVar('PRAUTO_' + version + '_' + pkgarch) or d.getVar('PRAUTO_' + version) or None
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500739 if auto_pr is None:
740 bb.fatal("Can NOT get PRAUTO from lockdown exported file")
741 d.setVar('PRAUTO',str(auto_pr))
742 return
743
744 try:
Andrew Geisslerd159c7f2021-09-02 21:05:58 -0500745 conn = oe.prservice.prserv_make_conn(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500746 if conn is not None:
747 if "AUTOINC" in pkgv:
748 srcpv = bb.fetch2.get_srcrev(d)
749 base_ver = "AUTOINC-%s" % version[:version.find(srcpv)]
750 value = conn.getPR(base_ver, pkgarch, srcpv)
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500751 d.setVar("PRSERV_PV_AUTOINC", str(value))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500752
753 auto_pr = conn.getPR(version, pkgarch, checksum)
Andrew Geisslerd159c7f2021-09-02 21:05:58 -0500754 conn.close()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500755 except Exception as e:
756 bb.fatal("Can NOT get PRAUTO, exception %s" % str(e))
757 if auto_pr is None:
758 bb.fatal("Can NOT get PRAUTO from remote PR service")
759 d.setVar('PRAUTO',str(auto_pr))
760}
761
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500762#
763# Package functions suitable for inclusion in PACKAGEFUNCS
764#
765
766python package_convert_pr_autoinc() {
767 pkgv = d.getVar("PKGV")
768
769 # Adjust pkgv as necessary...
770 if 'AUTOINC' in pkgv:
771 d.setVar("PKGV", pkgv.replace("AUTOINC", "${PRSERV_PV_AUTOINC}"))
772
773 # Change PRSERV_PV_AUTOINC and EXTENDPRAUTO usage to special values
774 d.setVar('PRSERV_PV_AUTOINC', '@PRSERV_PV_AUTOINC@')
775 d.setVar('EXTENDPRAUTO', '@EXTENDPRAUTO@')
776}
777
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500778LOCALEBASEPN ??= "${PN}"
779
780python package_do_split_locales() {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500781 if (d.getVar('PACKAGE_NO_LOCALE') == '1'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500782 bb.debug(1, "package requested not splitting locales")
783 return
784
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500785 packages = (d.getVar('PACKAGES') or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500786
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500787 datadir = d.getVar('datadir')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500788 if not datadir:
789 bb.note("datadir not defined")
790 return
791
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500792 dvar = d.getVar('PKGD')
793 pn = d.getVar('LOCALEBASEPN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500794
795 if pn + '-locale' in packages:
796 packages.remove(pn + '-locale')
797
798 localedir = os.path.join(dvar + datadir, 'locale')
799
800 if not cpath.isdir(localedir):
801 bb.debug(1, "No locale files in this package")
802 return
803
804 locales = os.listdir(localedir)
805
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500806 summary = d.getVar('SUMMARY') or pn
807 description = d.getVar('DESCRIPTION') or ""
808 locale_section = d.getVar('LOCALE_SECTION')
809 mlprefix = d.getVar('MLPREFIX') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500810 for l in sorted(locales):
811 ln = legitimize_package_name(l)
812 pkg = pn + '-locale-' + ln
813 packages.append(pkg)
Patrick Williams213cb262021-08-07 19:21:33 -0500814 d.setVar('FILES:' + pkg, os.path.join(datadir, 'locale', l))
815 d.setVar('RRECOMMENDS:' + pkg, '%svirtual-locale-%s' % (mlprefix, ln))
816 d.setVar('RPROVIDES:' + pkg, '%s-locale %s%s-translation' % (pn, mlprefix, ln))
817 d.setVar('SUMMARY:' + pkg, '%s - %s translations' % (summary, l))
818 d.setVar('DESCRIPTION:' + pkg, '%s This package contains language translation files for the %s locale.' % (description, l))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500819 if locale_section:
Patrick Williams213cb262021-08-07 19:21:33 -0500820 d.setVar('SECTION:' + pkg, locale_section)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500821
822 d.setVar('PACKAGES', ' '.join(packages))
823
824 # Disabled by RP 18/06/07
825 # Wildcards aren't supported in debian
826 # They break with ipkg since glibc-locale* will mean that
827 # glibc-localedata-translit* won't install as a dependency
828 # for some other package which breaks meta-toolchain
829 # Probably breaks since virtual-locale- isn't provided anywhere
Patrick Williams213cb262021-08-07 19:21:33 -0500830 #rdep = (d.getVar('RDEPENDS:%s' % pn) or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500831 #rdep.append('%s-locale*' % pn)
Patrick Williams213cb262021-08-07 19:21:33 -0500832 #d.setVar('RDEPENDS:%s' % pn, ' '.join(rdep))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500833}
834
835python perform_packagecopy () {
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800836 import subprocess
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600837 import shutil
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800838
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500839 dest = d.getVar('D')
840 dvar = d.getVar('PKGD')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500841
842 # Start by package population by taking a copy of the installed
843 # files to operate on
844 # Preserve sparse files and hard links
Patrick Williams03907ee2022-05-01 06:28:52 -0500845 cmd = 'tar --exclude=./sysroot-only -cf - -C %s -p -S . | tar -xf - -C %s' % (dest, dvar)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800846 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500847
848 # replace RPATHs for the nativesdk binaries, to make them relocatable
849 if bb.data.inherits_class('nativesdk', d) or bb.data.inherits_class('cross-canadian', d):
850 rpath_replace (dvar, d)
851}
852perform_packagecopy[cleandirs] = "${PKGD}"
853perform_packagecopy[dirs] = "${PKGD}"
854
855# We generate a master list of directories to process, we start by
856# seeding this list with reasonable defaults, then load from
857# the fs-perms.txt files
858python fixup_perms () {
859 import pwd, grp
860
861 # init using a string with the same format as a line as documented in
862 # the fs-perms.txt file
863 # <path> <mode> <uid> <gid> <walk> <fmode> <fuid> <fgid>
864 # <path> link <link target>
865 #
866 # __str__ can be used to print out an entry in the input format
867 #
868 # if fs_perms_entry.path is None:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400869 # an error occurred
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500870 # if fs_perms_entry.link, you can retrieve:
871 # fs_perms_entry.path = path
872 # fs_perms_entry.link = target of link
873 # if not fs_perms_entry.link, you can retrieve:
874 # fs_perms_entry.path = path
875 # fs_perms_entry.mode = expected dir mode or None
876 # fs_perms_entry.uid = expected uid or -1
877 # fs_perms_entry.gid = expected gid or -1
878 # fs_perms_entry.walk = 'true' or something else
879 # fs_perms_entry.fmode = expected file mode or None
880 # fs_perms_entry.fuid = expected file uid or -1
881 # fs_perms_entry_fgid = expected file gid or -1
882 class fs_perms_entry():
883 def __init__(self, line):
884 lsplit = line.split()
885 if len(lsplit) == 3 and lsplit[1].lower() == "link":
886 self._setlink(lsplit[0], lsplit[2])
887 elif len(lsplit) == 8:
888 self._setdir(lsplit[0], lsplit[1], lsplit[2], lsplit[3], lsplit[4], lsplit[5], lsplit[6], lsplit[7])
889 else:
890 msg = "Fixup Perms: invalid config line %s" % line
Andrew Geisslereff27472021-10-29 15:35:00 -0500891 oe.qa.handle_error("perm-config", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500892 self.path = None
893 self.link = None
894
895 def _setdir(self, path, mode, uid, gid, walk, fmode, fuid, fgid):
896 self.path = os.path.normpath(path)
897 self.link = None
898 self.mode = self._procmode(mode)
899 self.uid = self._procuid(uid)
900 self.gid = self._procgid(gid)
901 self.walk = walk.lower()
902 self.fmode = self._procmode(fmode)
903 self.fuid = self._procuid(fuid)
904 self.fgid = self._procgid(fgid)
905
906 def _setlink(self, path, link):
907 self.path = os.path.normpath(path)
908 self.link = link
909
910 def _procmode(self, mode):
911 if not mode or (mode and mode == "-"):
912 return None
913 else:
914 return int(mode,8)
915
916 # Note uid/gid -1 has special significance in os.lchown
917 def _procuid(self, uid):
918 if uid is None or uid == "-":
919 return -1
920 elif uid.isdigit():
921 return int(uid)
922 else:
923 return pwd.getpwnam(uid).pw_uid
924
925 def _procgid(self, gid):
926 if gid is None or gid == "-":
927 return -1
928 elif gid.isdigit():
929 return int(gid)
930 else:
931 return grp.getgrnam(gid).gr_gid
932
933 # Use for debugging the entries
934 def __str__(self):
935 if self.link:
936 return "%s link %s" % (self.path, self.link)
937 else:
938 mode = "-"
939 if self.mode:
940 mode = "0%o" % self.mode
941 fmode = "-"
942 if self.fmode:
943 fmode = "0%o" % self.fmode
944 uid = self._mapugid(self.uid)
945 gid = self._mapugid(self.gid)
946 fuid = self._mapugid(self.fuid)
947 fgid = self._mapugid(self.fgid)
948 return "%s %s %s %s %s %s %s %s" % (self.path, mode, uid, gid, self.walk, fmode, fuid, fgid)
949
950 def _mapugid(self, id):
951 if id is None or id == -1:
952 return "-"
953 else:
954 return "%d" % id
955
956 # Fix the permission, owner and group of path
957 def fix_perms(path, mode, uid, gid, dir):
958 if mode and not os.path.islink(path):
959 #bb.note("Fixup Perms: chmod 0%o %s" % (mode, dir))
960 os.chmod(path, mode)
961 # -1 is a special value that means don't change the uid/gid
962 # if they are BOTH -1, don't bother to lchown
963 if not (uid == -1 and gid == -1):
964 #bb.note("Fixup Perms: lchown %d:%d %s" % (uid, gid, dir))
965 os.lchown(path, uid, gid)
966
967 # Return a list of configuration files based on either the default
968 # files/fs-perms.txt or the contents of FILESYSTEM_PERMS_TABLES
969 # paths are resolved via BBPATH
970 def get_fs_perms_list(d):
971 str = ""
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500972 bbpath = d.getVar('BBPATH')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500973 fs_perms_tables = d.getVar('FILESYSTEM_PERMS_TABLES') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500974 for conf_file in fs_perms_tables.split():
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800975 confpath = bb.utils.which(bbpath, conf_file)
976 if confpath:
977 str += " %s" % bb.utils.which(bbpath, conf_file)
978 else:
979 bb.warn("cannot find %s specified in FILESYSTEM_PERMS_TABLES" % conf_file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500980 return str
981
982
983
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500984 dvar = d.getVar('PKGD')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500985
986 fs_perms_table = {}
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500987 fs_link_table = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500988
989 # By default all of the standard directories specified in
990 # bitbake.conf will get 0755 root:root.
991 target_path_vars = [ 'base_prefix',
992 'prefix',
993 'exec_prefix',
994 'base_bindir',
995 'base_sbindir',
996 'base_libdir',
997 'datadir',
998 'sysconfdir',
999 'servicedir',
1000 'sharedstatedir',
1001 'localstatedir',
1002 'infodir',
1003 'mandir',
1004 'docdir',
1005 'bindir',
1006 'sbindir',
1007 'libexecdir',
1008 'libdir',
1009 'includedir',
1010 'oldincludedir' ]
1011
1012 for path in target_path_vars:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001013 dir = d.getVar(path) or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001014 if dir == "":
1015 continue
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001016 fs_perms_table[dir] = fs_perms_entry(d.expand("%s 0755 root root false - - -" % (dir)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001017
1018 # Now we actually load from the configuration files
1019 for conf in get_fs_perms_list(d).split():
Brad Bishop64c979e2019-11-04 13:55:29 -05001020 if not os.path.exists(conf):
1021 continue
1022 with open(conf) as f:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001023 for line in f:
1024 if line.startswith('#'):
1025 continue
1026 lsplit = line.split()
1027 if len(lsplit) == 0:
1028 continue
1029 if len(lsplit) != 8 and not (len(lsplit) == 3 and lsplit[1].lower() == "link"):
1030 msg = "Fixup perms: %s invalid line: %s" % (conf, line)
Andrew Geisslereff27472021-10-29 15:35:00 -05001031 oe.qa.handle_error("perm-line", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001032 continue
1033 entry = fs_perms_entry(d.expand(line))
1034 if entry and entry.path:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001035 if entry.link:
1036 fs_link_table[entry.path] = entry
1037 if entry.path in fs_perms_table:
1038 fs_perms_table.pop(entry.path)
1039 else:
1040 fs_perms_table[entry.path] = entry
1041 if entry.path in fs_link_table:
1042 fs_link_table.pop(entry.path)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001043
1044 # Debug -- list out in-memory table
1045 #for dir in fs_perms_table:
1046 # bb.note("Fixup Perms: %s: %s" % (dir, str(fs_perms_table[dir])))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001047 #for link in fs_link_table:
1048 # bb.note("Fixup Perms: %s: %s" % (link, str(fs_link_table[link])))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001049
1050 # We process links first, so we can go back and fixup directory ownership
1051 # for any newly created directories
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001052 # Process in sorted order so /run gets created before /run/lock, etc.
1053 for entry in sorted(fs_link_table.values(), key=lambda x: x.link):
1054 link = entry.link
1055 dir = entry.path
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001056 origin = dvar + dir
1057 if not (cpath.exists(origin) and cpath.isdir(origin) and not cpath.islink(origin)):
1058 continue
1059
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001060 if link[0] == "/":
1061 target = dvar + link
1062 ptarget = link
1063 else:
1064 target = os.path.join(os.path.dirname(origin), link)
1065 ptarget = os.path.join(os.path.dirname(dir), link)
1066 if os.path.exists(target):
1067 msg = "Fixup Perms: Unable to correct directory link, target already exists: %s -> %s" % (dir, ptarget)
Andrew Geisslereff27472021-10-29 15:35:00 -05001068 oe.qa.handle_error("perm-link", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001069 continue
1070
1071 # Create path to move directory to, move it, and then setup the symlink
1072 bb.utils.mkdirhier(os.path.dirname(target))
1073 #bb.note("Fixup Perms: Rename %s -> %s" % (dir, ptarget))
Andrew Geisslerc926e172021-05-07 16:11:35 -05001074 bb.utils.rename(origin, target)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001075 #bb.note("Fixup Perms: Link %s -> %s" % (dir, link))
1076 os.symlink(link, origin)
1077
1078 for dir in fs_perms_table:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001079 origin = dvar + dir
1080 if not (cpath.exists(origin) and cpath.isdir(origin)):
1081 continue
1082
1083 fix_perms(origin, fs_perms_table[dir].mode, fs_perms_table[dir].uid, fs_perms_table[dir].gid, dir)
1084
1085 if fs_perms_table[dir].walk == 'true':
1086 for root, dirs, files in os.walk(origin):
1087 for dr in dirs:
1088 each_dir = os.path.join(root, dr)
1089 fix_perms(each_dir, fs_perms_table[dir].mode, fs_perms_table[dir].uid, fs_perms_table[dir].gid, dir)
1090 for f in files:
1091 each_file = os.path.join(root, f)
1092 fix_perms(each_file, fs_perms_table[dir].fmode, fs_perms_table[dir].fuid, fs_perms_table[dir].fgid, dir)
1093}
1094
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001095def package_debug_vars(d):
1096 # We default to '.debug' style
1097 if d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-file-directory':
1098 # Single debug-file-directory style debug info
1099 debug_vars = {
1100 "append": ".debug",
1101 "staticappend": "",
1102 "dir": "",
1103 "staticdir": "",
1104 "libdir": "/usr/lib/debug",
1105 "staticlibdir": "/usr/lib/debug-static",
1106 "srcdir": "/usr/src/debug",
1107 }
1108 elif d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-without-src':
1109 # Original OE-core, a.k.a. ".debug", style debug info, but without sources in /usr/src/debug
1110 debug_vars = {
1111 "append": "",
1112 "staticappend": "",
1113 "dir": "/.debug",
1114 "staticdir": "/.debug-static",
1115 "libdir": "",
1116 "staticlibdir": "",
1117 "srcdir": "",
1118 }
1119 elif d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-with-srcpkg':
1120 debug_vars = {
1121 "append": "",
1122 "staticappend": "",
1123 "dir": "/.debug",
1124 "staticdir": "/.debug-static",
1125 "libdir": "",
1126 "staticlibdir": "",
1127 "srcdir": "/usr/src/debug",
1128 }
1129 else:
1130 # Original OE-core, a.k.a. ".debug", style debug info
1131 debug_vars = {
1132 "append": "",
1133 "staticappend": "",
1134 "dir": "/.debug",
1135 "staticdir": "/.debug-static",
1136 "libdir": "",
1137 "staticlibdir": "",
1138 "srcdir": "/usr/src/debug",
1139 }
1140
1141 return debug_vars
1142
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001143python split_and_strip_files () {
1144 import stat, errno
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001145 import subprocess
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001146
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001147 dvar = d.getVar('PKGD')
1148 pn = d.getVar('PN')
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001149 hostos = d.getVar('HOST_OS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001150
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001151 oldcwd = os.getcwd()
1152 os.chdir(dvar)
1153
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001154 dv = package_debug_vars(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001155
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001156 #
1157 # First lets figure out all of the files we may have to process ... do this only once!
1158 #
1159 elffiles = {}
1160 symlinks = {}
Brad Bishop316dfdd2018-06-25 12:45:53 -04001161 staticlibs = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001162 inodes = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001163 libdir = os.path.abspath(dvar + os.sep + d.getVar("libdir"))
1164 baselibdir = os.path.abspath(dvar + os.sep + d.getVar("base_libdir"))
Brad Bishop316dfdd2018-06-25 12:45:53 -04001165 skipfiles = (d.getVar("INHIBIT_PACKAGE_STRIP_FILES") or "").split()
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001166 if (d.getVar('INHIBIT_PACKAGE_STRIP') != '1' or \
1167 d.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT') != '1'):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001168 checkelf = {}
1169 checkelflinks = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001170 for root, dirs, files in cpath.walk(dvar):
1171 for f in files:
1172 file = os.path.join(root, f)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001173
1174 # Skip debug files
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001175 if dv["append"] and file.endswith(dv["append"]):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001176 continue
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001177 if dv["dir"] and dv["dir"] in os.path.dirname(file[len(dvar):]):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001178 continue
1179
Brad Bishop316dfdd2018-06-25 12:45:53 -04001180 if file in skipfiles:
1181 continue
1182
Andrew Geissler82c905d2020-04-13 13:39:40 -05001183 if oe.package.is_static_lib(file):
1184 staticlibs.append(file)
1185 continue
1186
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001187 try:
1188 ltarget = cpath.realpath(file, dvar, False)
1189 s = cpath.lstat(ltarget)
1190 except OSError as e:
1191 (err, strerror) = e.args
1192 if err != errno.ENOENT:
1193 raise
1194 # Skip broken symlinks
1195 continue
1196 if not s:
1197 continue
Brad Bishop316dfdd2018-06-25 12:45:53 -04001198 # Check its an executable
Andrew Geissler595f6302022-01-24 19:11:47 +00001199 if (s[stat.ST_MODE] & stat.S_IXUSR) or (s[stat.ST_MODE] & stat.S_IXGRP) \
1200 or (s[stat.ST_MODE] & stat.S_IXOTH) \
1201 or ((file.startswith(libdir) or file.startswith(baselibdir)) \
1202 and (".so" in f or ".node" in f)) \
1203 or (f.startswith('vmlinux') or ".ko" in f):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001204
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001205 if cpath.islink(file):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001206 checkelflinks[file] = ltarget
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001207 continue
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001208 # Use a reference of device ID and inode number to identify files
1209 file_reference = "%d_%d" % (s.st_dev, s.st_ino)
1210 checkelf[file] = (file, file_reference)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001211
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001212 results = oe.utils.multiprocess_launch(oe.package.is_elf, checkelflinks.values(), d)
1213 results_map = {}
1214 for (ltarget, elf_file) in results:
1215 results_map[ltarget] = elf_file
1216 for file in checkelflinks:
1217 ltarget = checkelflinks[file]
1218 # If it's a symlink, and points to an ELF file, we capture the readlink target
1219 if results_map[ltarget]:
1220 target = os.readlink(file)
1221 #bb.note("Sym: %s (%d)" % (ltarget, results_map[ltarget]))
1222 symlinks[file] = target
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001223
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001224 results = oe.utils.multiprocess_launch(oe.package.is_elf, checkelf.keys(), d)
Brad Bishop15ae2502019-06-18 21:44:24 -04001225
1226 # Sort results by file path. This ensures that the files are always
1227 # processed in the same order, which is important to make sure builds
1228 # are reproducible when dealing with hardlinks
1229 results.sort(key=lambda x: x[0])
1230
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001231 for (file, elf_file) in results:
1232 # It's a file (or hardlink), not a link
1233 # ...but is it ELF, and is it already stripped?
1234 if elf_file & 1:
1235 if elf_file & 2:
Patrick Williams213cb262021-08-07 19:21:33 -05001236 if 'already-stripped' in (d.getVar('INSANE_SKIP:' + pn) or "").split():
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001237 bb.note("Skipping file %s from %s for already-stripped QA test" % (file[len(dvar):], pn))
1238 else:
1239 msg = "File '%s' from %s was already stripped, this will prevent future debugging!" % (file[len(dvar):], pn)
Andrew Geisslereff27472021-10-29 15:35:00 -05001240 oe.qa.handle_error("already-stripped", msg, d)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001241 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001242
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001243 # At this point we have an unstripped elf file. We need to:
1244 # a) Make sure any file we strip is not hardlinked to anything else outside this tree
1245 # b) Only strip any hardlinked file once (no races)
1246 # c) Track any hardlinks between files so that we can reconstruct matching debug file hardlinks
1247
1248 # Use a reference of device ID and inode number to identify files
1249 file_reference = checkelf[file][1]
1250 if file_reference in inodes:
1251 os.unlink(file)
1252 os.link(inodes[file_reference][0], file)
1253 inodes[file_reference].append(file)
1254 else:
1255 inodes[file_reference] = [file]
1256 # break hardlink
1257 bb.utils.break_hardlinks(file)
1258 elffiles[file] = elf_file
1259 # Modified the file so clear the cache
1260 cpath.updatecache(file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001261
Andrew Geissler5199d832021-09-24 16:47:35 -05001262 def strip_pkgd_prefix(f):
1263 nonlocal dvar
1264
1265 if f.startswith(dvar):
1266 return f[len(dvar):]
1267
1268 return f
1269
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001270 #
1271 # First lets process debug splitting
1272 #
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001273 if (d.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT') != '1'):
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001274 results = oe.utils.multiprocess_launch(splitdebuginfo, list(elffiles), d, extraargs=(dvar, dv, d))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001275
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001276 if dv["srcdir"] and not hostos.startswith("mingw"):
Andrew Geissler82c905d2020-04-13 13:39:40 -05001277 if (d.getVar('PACKAGE_DEBUG_STATIC_SPLIT') == '1'):
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001278 results = oe.utils.multiprocess_launch(splitstaticdebuginfo, staticlibs, d, extraargs=(dvar, dv, d))
Andrew Geissler82c905d2020-04-13 13:39:40 -05001279 else:
1280 for file in staticlibs:
1281 results.append( (file,source_info(file, d)) )
Brad Bishop19323692019-04-05 15:28:33 -04001282
Andrew Geissler5199d832021-09-24 16:47:35 -05001283 d.setVar("PKGDEBUGSOURCES", {strip_pkgd_prefix(f): sorted(s) for f, s in results})
1284
Brad Bishop19323692019-04-05 15:28:33 -04001285 sources = set()
1286 for r in results:
1287 sources.update(r[1])
Brad Bishop316dfdd2018-06-25 12:45:53 -04001288
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001289 # Hardlink our debug symbols to the other hardlink copies
1290 for ref in inodes:
1291 if len(inodes[ref]) == 1:
1292 continue
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001293
1294 target = inodes[ref][0][len(dvar):]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001295 for file in inodes[ref][1:]:
1296 src = file[len(dvar):]
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001297 dest = dv["libdir"] + os.path.dirname(src) + dv["dir"] + "/" + os.path.basename(target) + dv["append"]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001298 fpath = dvar + dest
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001299 ftarget = dvar + dv["libdir"] + os.path.dirname(target) + dv["dir"] + "/" + os.path.basename(target) + dv["append"]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001300 bb.utils.mkdirhier(os.path.dirname(fpath))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001301 # Only one hardlink of separated debug info file in each directory
1302 if not os.access(fpath, os.R_OK):
1303 #bb.note("Link %s -> %s" % (fpath, ftarget))
1304 os.link(ftarget, fpath)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001305
1306 # Create symlinks for all cases we were able to split symbols
1307 for file in symlinks:
1308 src = file[len(dvar):]
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001309 dest = dv["libdir"] + os.path.dirname(src) + dv["dir"] + "/" + os.path.basename(src) + dv["append"]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001310 fpath = dvar + dest
1311 # Skip it if the target doesn't exist
1312 try:
1313 s = os.stat(fpath)
1314 except OSError as e:
1315 (err, strerror) = e.args
1316 if err != errno.ENOENT:
1317 raise
1318 continue
1319
1320 ltarget = symlinks[file]
1321 lpath = os.path.dirname(ltarget)
1322 lbase = os.path.basename(ltarget)
1323 ftarget = ""
1324 if lpath and lpath != ".":
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001325 ftarget += lpath + dv["dir"] + "/"
1326 ftarget += lbase + dv["append"]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001327 if lpath.startswith(".."):
1328 ftarget = os.path.join("..", ftarget)
1329 bb.utils.mkdirhier(os.path.dirname(fpath))
1330 #bb.note("Symlink %s -> %s" % (fpath, ftarget))
1331 os.symlink(ftarget, fpath)
1332
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001333 # Process the dv["srcdir"] if requested...
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001334 # This copies and places the referenced sources for later debugging...
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001335 copydebugsources(dv["srcdir"], sources, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001336 #
1337 # End of debug splitting
1338 #
1339
1340 #
1341 # Now lets go back over things and strip them
1342 #
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001343 if (d.getVar('INHIBIT_PACKAGE_STRIP') != '1'):
1344 strip = d.getVar("STRIP")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001345 sfiles = []
1346 for file in elffiles:
1347 elf_file = int(elffiles[file])
1348 #bb.note("Strip %s" % file)
1349 sfiles.append((file, elf_file, strip))
Andrew Geissler82c905d2020-04-13 13:39:40 -05001350 if (d.getVar('PACKAGE_STRIP_STATIC') == '1' or d.getVar('PACKAGE_DEBUG_STATIC_SPLIT') == '1'):
1351 for f in staticlibs:
1352 sfiles.append((f, 16, strip))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001353
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001354 oe.utils.multiprocess_launch(oe.package.runstrip, sfiles, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001355
Andrew Geissler82c905d2020-04-13 13:39:40 -05001356 # Build "minidebuginfo" and reinject it back into the stripped binaries
1357 if d.getVar('PACKAGE_MINIDEBUGINFO') == '1':
1358 oe.utils.multiprocess_launch(inject_minidebuginfo, list(elffiles), d,
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001359 extraargs=(dvar, dv, d))
Andrew Geissler82c905d2020-04-13 13:39:40 -05001360
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001361 #
1362 # End of strip
1363 #
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001364 os.chdir(oldcwd)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001365}
1366
1367python populate_packages () {
1368 import glob, re
1369
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001370 workdir = d.getVar('WORKDIR')
1371 outdir = d.getVar('DEPLOY_DIR')
1372 dvar = d.getVar('PKGD')
Brad Bishop19323692019-04-05 15:28:33 -04001373 packages = d.getVar('PACKAGES').split()
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001374 pn = d.getVar('PN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001375
1376 bb.utils.mkdirhier(outdir)
1377 os.chdir(dvar)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001378
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001379 autodebug = not (d.getVar("NOAUTOPACKAGEDEBUG") or False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001380
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001381 split_source_package = (d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-with-srcpkg')
1382
Brad Bishop19323692019-04-05 15:28:33 -04001383 # If debug-with-srcpkg mode is enabled then add the source package if it
1384 # doesn't exist and add the source file contents to the source package.
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001385 if split_source_package:
1386 src_package_name = ('%s-src' % d.getVar('PN'))
Brad Bishop19323692019-04-05 15:28:33 -04001387 if not src_package_name in packages:
1388 packages.append(src_package_name)
Patrick Williams213cb262021-08-07 19:21:33 -05001389 d.setVar('FILES:%s' % src_package_name, '/usr/src/debug')
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001390
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001391 # Sanity check PACKAGES for duplicates
Brad Bishop316dfdd2018-06-25 12:45:53 -04001392 # Sanity should be moved to sanity.bbclass once we have the infrastructure
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001393 package_dict = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001394
Brad Bishop19323692019-04-05 15:28:33 -04001395 for i, pkg in enumerate(packages):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001396 if pkg in package_dict:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001397 msg = "%s is listed in PACKAGES multiple times, this leads to packaging errors." % pkg
Andrew Geisslereff27472021-10-29 15:35:00 -05001398 oe.qa.handle_error("packages-list", msg, d)
Brad Bishop19323692019-04-05 15:28:33 -04001399 # Ensure the source package gets the chance to pick up the source files
1400 # before the debug package by ordering it first in PACKAGES. Whether it
1401 # actually picks up any source files is controlled by
1402 # PACKAGE_DEBUG_SPLIT_STYLE.
1403 elif pkg.endswith("-src"):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001404 package_dict[pkg] = (10, i)
1405 elif autodebug and pkg.endswith("-dbg"):
1406 package_dict[pkg] = (30, i)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001407 else:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001408 package_dict[pkg] = (50, i)
Brad Bishop19323692019-04-05 15:28:33 -04001409 packages = sorted(package_dict.keys(), key=package_dict.get)
1410 d.setVar('PACKAGES', ' '.join(packages))
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001411 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001412
1413 seen = []
1414
1415 # os.mkdir masks the permissions with umask so we have to unset it first
1416 oldumask = os.umask(0)
1417
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001418 debug = []
1419 for root, dirs, files in cpath.walk(dvar):
1420 dir = root[len(dvar):]
1421 if not dir:
1422 dir = os.sep
1423 for f in (files + dirs):
1424 path = "." + os.path.join(dir, f)
Andrew Geissler82c905d2020-04-13 13:39:40 -05001425 if "/.debug/" in path or "/.debug-static/" in path or path.endswith("/.debug"):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001426 debug.append(path)
1427
Brad Bishop19323692019-04-05 15:28:33 -04001428 for pkg in packages:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001429 root = os.path.join(pkgdest, pkg)
1430 bb.utils.mkdirhier(root)
1431
Patrick Williams213cb262021-08-07 19:21:33 -05001432 filesvar = d.getVar('FILES:%s' % pkg) or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001433 if "//" in filesvar:
1434 msg = "FILES variable for package %s contains '//' which is invalid. Attempting to fix this but you should correct the metadata.\n" % pkg
Andrew Geisslereff27472021-10-29 15:35:00 -05001435 oe.qa.handle_error("files-invalid", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001436 filesvar.replace("//", "/")
1437
1438 origfiles = filesvar.split()
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001439 files, symlink_paths = files_from_filevars(origfiles)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001440
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001441 if autodebug and pkg.endswith("-dbg"):
1442 files.extend(debug)
1443
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001444 for file in files:
1445 if (not cpath.islink(file)) and (not cpath.exists(file)):
1446 continue
1447 if file in seen:
1448 continue
1449 seen.append(file)
1450
1451 def mkdir(src, dest, p):
1452 src = os.path.join(src, p)
1453 dest = os.path.join(dest, p)
1454 fstat = cpath.stat(src)
Brad Bishop96ff1982019-08-19 13:50:42 -04001455 os.mkdir(dest)
1456 os.chmod(dest, fstat.st_mode)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001457 os.chown(dest, fstat.st_uid, fstat.st_gid)
1458 if p not in seen:
1459 seen.append(p)
1460 cpath.updatecache(dest)
1461
1462 def mkdir_recurse(src, dest, paths):
1463 if cpath.exists(dest + '/' + paths):
1464 return
1465 while paths.startswith("./"):
1466 paths = paths[2:]
1467 p = "."
1468 for c in paths.split("/"):
1469 p = os.path.join(p, c)
1470 if not cpath.exists(os.path.join(dest, p)):
1471 mkdir(src, dest, p)
1472
1473 if cpath.isdir(file) and not cpath.islink(file):
1474 mkdir_recurse(dvar, root, file)
1475 continue
1476
1477 mkdir_recurse(dvar, root, os.path.dirname(file))
1478 fpath = os.path.join(root,file)
1479 if not cpath.islink(file):
1480 os.link(file, fpath)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001481 continue
1482 ret = bb.utils.copyfile(file, fpath)
1483 if ret is False or ret == 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001484 bb.fatal("File population failed")
1485
1486 # Check if symlink paths exist
1487 for file in symlink_paths:
1488 if not os.path.exists(os.path.join(root,file)):
1489 bb.fatal("File '%s' cannot be packaged into '%s' because its "
1490 "parent directory structure does not exist. One of "
1491 "its parent directories is a symlink whose target "
1492 "directory is not included in the package." %
1493 (file, pkg))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001494
1495 os.umask(oldumask)
1496 os.chdir(workdir)
1497
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001498 # Handle excluding packages with incompatible licenses
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001499 package_list = []
Brad Bishop19323692019-04-05 15:28:33 -04001500 for pkg in packages:
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001501 licenses = d.getVar('_exclude_incompatible-' + pkg)
Andrew Geissler82c905d2020-04-13 13:39:40 -05001502 if licenses:
1503 msg = "Excluding %s from packaging as it has incompatible license(s): %s" % (pkg, licenses)
Andrew Geisslereff27472021-10-29 15:35:00 -05001504 oe.qa.handle_error("incompatible-license", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001505 else:
1506 package_list.append(pkg)
1507 d.setVar('PACKAGES', ' '.join(package_list))
1508
1509 unshipped = []
1510 for root, dirs, files in cpath.walk(dvar):
1511 dir = root[len(dvar):]
1512 if not dir:
1513 dir = os.sep
1514 for f in (files + dirs):
1515 path = os.path.join(dir, f)
1516 if ('.' + path) not in seen:
1517 unshipped.append(path)
1518
1519 if unshipped != []:
1520 msg = pn + ": Files/directories were installed but not shipped in any package:"
Patrick Williams213cb262021-08-07 19:21:33 -05001521 if "installed-vs-shipped" in (d.getVar('INSANE_SKIP:' + pn) or "").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001522 bb.note("Package %s skipping QA tests: installed-vs-shipped" % pn)
1523 else:
1524 for f in unshipped:
1525 msg = msg + "\n " + f
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001526 msg = msg + "\nPlease set FILES such that these items are packaged. Alternatively if they are unneeded, avoid installing them or delete them within do_install.\n"
1527 msg = msg + "%s: %d installed and not shipped files." % (pn, len(unshipped))
Andrew Geisslereff27472021-10-29 15:35:00 -05001528 oe.qa.handle_error("installed-vs-shipped", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001529}
1530populate_packages[dirs] = "${D}"
1531
1532python package_fixsymlinks () {
1533 import errno
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001534 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001535 packages = d.getVar("PACKAGES", False).split()
1536
1537 dangling_links = {}
1538 pkg_files = {}
1539 for pkg in packages:
1540 dangling_links[pkg] = []
1541 pkg_files[pkg] = []
1542 inst_root = os.path.join(pkgdest, pkg)
1543 for path in pkgfiles[pkg]:
1544 rpath = path[len(inst_root):]
1545 pkg_files[pkg].append(rpath)
1546 rtarget = cpath.realpath(path, inst_root, True, assume_dir = True)
1547 if not cpath.lexists(rtarget):
1548 dangling_links[pkg].append(os.path.normpath(rtarget[len(inst_root):]))
1549
1550 newrdepends = {}
1551 for pkg in dangling_links:
1552 for l in dangling_links[pkg]:
1553 found = False
1554 bb.debug(1, "%s contains dangling link %s" % (pkg, l))
1555 for p in packages:
1556 if l in pkg_files[p]:
1557 found = True
1558 bb.debug(1, "target found in %s" % p)
1559 if p == pkg:
1560 break
1561 if pkg not in newrdepends:
1562 newrdepends[pkg] = []
1563 newrdepends[pkg].append(p)
1564 break
1565 if found == False:
1566 bb.note("%s contains dangling symlink to %s" % (pkg, l))
1567
1568 for pkg in newrdepends:
Patrick Williams213cb262021-08-07 19:21:33 -05001569 rdepends = bb.utils.explode_dep_versions2(d.getVar('RDEPENDS:' + pkg) or "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001570 for p in newrdepends[pkg]:
1571 if p not in rdepends:
1572 rdepends[p] = []
Patrick Williams213cb262021-08-07 19:21:33 -05001573 d.setVar('RDEPENDS:' + pkg, bb.utils.join_deps(rdepends, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001574}
1575
1576
1577python package_package_name_hook() {
1578 """
1579 A package_name_hook function can be used to rewrite the package names by
1580 changing PKG. For an example, see debian.bbclass.
1581 """
1582 pass
1583}
1584
1585EXPORT_FUNCTIONS package_name_hook
1586
1587
1588PKGDESTWORK = "${WORKDIR}/pkgdata"
1589
Andrew Geissler1e34c2d2020-05-29 16:02:59 -05001590PKGDATA_VARS = "PN PE PV PR PKGE PKGV PKGR LICENSE DESCRIPTION SUMMARY RDEPENDS RPROVIDES RRECOMMENDS RSUGGESTS RREPLACES RCONFLICTS SECTION PKG ALLOW_EMPTY FILES CONFFILES FILES_INFO PACKAGE_ADD_METADATA pkg_postinst pkg_postrm pkg_preinst pkg_prerm"
Brad Bishop15ae2502019-06-18 21:44:24 -04001591
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001592python emit_pkgdata() {
1593 from glob import glob
1594 import json
Andrew Geissler5199d832021-09-24 16:47:35 -05001595 import bb.compress.zstd
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001596
Brad Bishop316dfdd2018-06-25 12:45:53 -04001597 def process_postinst_on_target(pkg, mlprefix):
Patrick Williams213cb262021-08-07 19:21:33 -05001598 pkgval = d.getVar('PKG:%s' % pkg)
Brad Bishop96ff1982019-08-19 13:50:42 -04001599 if pkgval is None:
1600 pkgval = pkg
1601
Brad Bishop316dfdd2018-06-25 12:45:53 -04001602 defer_fragment = """
1603if [ -n "$D" ]; then
1604 $INTERCEPT_DIR/postinst_intercept delay_to_first_boot %s mlprefix=%s
1605 exit 0
1606fi
Brad Bishop96ff1982019-08-19 13:50:42 -04001607""" % (pkgval, mlprefix)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001608
Patrick Williams213cb262021-08-07 19:21:33 -05001609 postinst = d.getVar('pkg_postinst:%s' % pkg)
1610 postinst_ontarget = d.getVar('pkg_postinst_ontarget:%s' % pkg)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001611
1612 if postinst_ontarget:
1613 bb.debug(1, 'adding deferred pkg_postinst_ontarget() to pkg_postinst() for %s' % pkg)
1614 if not postinst:
1615 postinst = '#!/bin/sh\n'
1616 postinst += defer_fragment
1617 postinst += postinst_ontarget
Patrick Williams213cb262021-08-07 19:21:33 -05001618 d.setVar('pkg_postinst:%s' % pkg, postinst)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001619
1620 def add_set_e_to_scriptlets(pkg):
1621 for scriptlet_name in ('pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm'):
Patrick Williams213cb262021-08-07 19:21:33 -05001622 scriptlet = d.getVar('%s:%s' % (scriptlet_name, pkg))
Brad Bishop316dfdd2018-06-25 12:45:53 -04001623 if scriptlet:
1624 scriptlet_split = scriptlet.split('\n')
1625 if scriptlet_split[0].startswith("#!"):
1626 scriptlet = scriptlet_split[0] + "\nset -e\n" + "\n".join(scriptlet_split[1:])
1627 else:
1628 scriptlet = "set -e\n" + "\n".join(scriptlet_split[0:])
Patrick Williams213cb262021-08-07 19:21:33 -05001629 d.setVar('%s:%s' % (scriptlet_name, pkg), scriptlet)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001630
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001631 def write_if_exists(f, pkg, var):
1632 def encode(str):
1633 import codecs
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001634 c = codecs.getencoder("unicode_escape")
1635 return c(str)[0].decode("latin1")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001636
Patrick Williams213cb262021-08-07 19:21:33 -05001637 val = d.getVar('%s:%s' % (var, pkg))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001638 if val:
Patrick Williams213cb262021-08-07 19:21:33 -05001639 f.write('%s:%s: %s\n' % (var, pkg, encode(val)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001640 return val
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001641 val = d.getVar('%s' % (var))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001642 if val:
1643 f.write('%s: %s\n' % (var, encode(val)))
1644 return val
1645
1646 def write_extra_pkgs(variants, pn, packages, pkgdatadir):
1647 for variant in variants:
1648 with open("%s/%s-%s" % (pkgdatadir, variant, pn), 'w') as fd:
1649 fd.write("PACKAGES: %s\n" % ' '.join(
1650 map(lambda pkg: '%s-%s' % (variant, pkg), packages.split())))
1651
1652 def write_extra_runtime_pkgs(variants, packages, pkgdatadir):
1653 for variant in variants:
1654 for pkg in packages.split():
1655 ml_pkg = "%s-%s" % (variant, pkg)
1656 subdata_file = "%s/runtime/%s" % (pkgdatadir, ml_pkg)
1657 with open(subdata_file, 'w') as fd:
Patrick Williams213cb262021-08-07 19:21:33 -05001658 fd.write("PKG:%s: %s" % (ml_pkg, pkg))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001659
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001660 packages = d.getVar('PACKAGES')
1661 pkgdest = d.getVar('PKGDEST')
1662 pkgdatadir = d.getVar('PKGDESTWORK')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001663
Brad Bishop64c979e2019-11-04 13:55:29 -05001664 data_file = pkgdatadir + d.expand("/${PN}")
1665 with open(data_file, 'w') as fd:
1666 fd.write("PACKAGES: %s\n" % packages)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001667
Andrew Geissler5199d832021-09-24 16:47:35 -05001668 pkgdebugsource = d.getVar("PKGDEBUGSOURCES") or []
1669
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001670 pn = d.getVar('PN')
1671 global_variants = (d.getVar('MULTILIB_GLOBAL_VARIANTS') or "").split()
1672 variants = (d.getVar('MULTILIB_VARIANTS') or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001673
1674 if bb.data.inherits_class('kernel', d) or bb.data.inherits_class('module-base', d):
1675 write_extra_pkgs(variants, pn, packages, pkgdatadir)
1676
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001677 if bb.data.inherits_class('allarch', d) and not variants \
1678 and not bb.data.inherits_class('packagegroup', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001679 write_extra_pkgs(global_variants, pn, packages, pkgdatadir)
1680
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001681 workdir = d.getVar('WORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001682
1683 for pkg in packages.split():
Patrick Williams213cb262021-08-07 19:21:33 -05001684 pkgval = d.getVar('PKG:%s' % pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001685 if pkgval is None:
1686 pkgval = pkg
Patrick Williams213cb262021-08-07 19:21:33 -05001687 d.setVar('PKG:%s' % pkg, pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001688
Andrew Geissler5199d832021-09-24 16:47:35 -05001689 extended_data = {
1690 "files_info": {}
1691 }
1692
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001693 pkgdestpkg = os.path.join(pkgdest, pkg)
1694 files = {}
Andrew Geissler5199d832021-09-24 16:47:35 -05001695 files_extra = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001696 total_size = 0
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001697 seen = set()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001698 for f in pkgfiles[pkg]:
Andrew Geissler5199d832021-09-24 16:47:35 -05001699 fpath = os.sep + os.path.relpath(f, pkgdestpkg)
1700
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001701 fstat = os.lstat(f)
Andrew Geissler5199d832021-09-24 16:47:35 -05001702 files[fpath] = fstat.st_size
1703
1704 extended_data["files_info"].setdefault(fpath, {})
1705 extended_data["files_info"][fpath]['size'] = fstat.st_size
1706
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001707 if fstat.st_ino not in seen:
1708 seen.add(fstat.st_ino)
1709 total_size += fstat.st_size
Andrew Geissler5199d832021-09-24 16:47:35 -05001710
1711 if fpath in pkgdebugsource:
1712 extended_data["files_info"][fpath]['debugsrc'] = pkgdebugsource[fpath]
1713 del pkgdebugsource[fpath]
1714
Andrew Geisslerd159c7f2021-09-02 21:05:58 -05001715 d.setVar('FILES_INFO:' + pkg , json.dumps(files, sort_keys=True))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001716
Brad Bishop316dfdd2018-06-25 12:45:53 -04001717 process_postinst_on_target(pkg, d.getVar("MLPREFIX"))
1718 add_set_e_to_scriptlets(pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001719
Brad Bishop15ae2502019-06-18 21:44:24 -04001720 subdata_file = pkgdatadir + "/runtime/%s" % pkg
1721 with open(subdata_file, 'w') as sf:
1722 for var in (d.getVar('PKGDATA_VARS') or "").split():
1723 val = write_if_exists(sf, pkg, var)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001724
Brad Bishop15ae2502019-06-18 21:44:24 -04001725 write_if_exists(sf, pkg, 'FILERPROVIDESFLIST')
Andrew Geissler5199d832021-09-24 16:47:35 -05001726 for dfile in sorted((d.getVar('FILERPROVIDESFLIST:' + pkg) or "").split()):
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001727 write_if_exists(sf, pkg, 'FILERPROVIDES:' + dfile)
Brad Bishop15ae2502019-06-18 21:44:24 -04001728
1729 write_if_exists(sf, pkg, 'FILERDEPENDSFLIST')
Andrew Geissler5199d832021-09-24 16:47:35 -05001730 for dfile in sorted((d.getVar('FILERDEPENDSFLIST:' + pkg) or "").split()):
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001731 write_if_exists(sf, pkg, 'FILERDEPENDS:' + dfile)
Brad Bishop15ae2502019-06-18 21:44:24 -04001732
Andrew Geisslerd159c7f2021-09-02 21:05:58 -05001733 sf.write('%s:%s: %d\n' % ('PKGSIZE', pkg, total_size))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001734
Andrew Geissler5199d832021-09-24 16:47:35 -05001735 subdata_extended_file = pkgdatadir + "/extended/%s.json.zstd" % pkg
1736 num_threads = int(d.getVar("BB_NUMBER_THREADS"))
1737 with bb.compress.zstd.open(subdata_extended_file, "wt", encoding="utf-8", num_threads=num_threads) as f:
1738 json.dump(extended_data, f, sort_keys=True, separators=(",", ":"))
1739
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001740 # Symlinks needed for rprovides lookup
Patrick Williams213cb262021-08-07 19:21:33 -05001741 rprov = d.getVar('RPROVIDES:%s' % pkg) or d.getVar('RPROVIDES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001742 if rprov:
Andrew Geisslerc9f78652020-09-18 14:11:35 -05001743 for p in bb.utils.explode_deps(rprov):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001744 subdata_sym = pkgdatadir + "/runtime-rprovides/%s/%s" % (p, pkg)
1745 bb.utils.mkdirhier(os.path.dirname(subdata_sym))
1746 oe.path.symlink("../../runtime/%s" % pkg, subdata_sym, True)
1747
Patrick Williams213cb262021-08-07 19:21:33 -05001748 allow_empty = d.getVar('ALLOW_EMPTY:%s' % pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001749 if not allow_empty:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001750 allow_empty = d.getVar('ALLOW_EMPTY')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001751 root = "%s/%s" % (pkgdest, pkg)
1752 os.chdir(root)
1753 g = glob('*')
1754 if g or allow_empty == "1":
1755 # Symlinks needed for reverse lookups (from the final package name)
1756 subdata_sym = pkgdatadir + "/runtime-reverse/%s" % pkgval
1757 oe.path.symlink("../runtime/%s" % pkg, subdata_sym, True)
1758
1759 packagedfile = pkgdatadir + '/runtime/%s.packaged' % pkg
1760 open(packagedfile, 'w').close()
1761
1762 if bb.data.inherits_class('kernel', d) or bb.data.inherits_class('module-base', d):
1763 write_extra_runtime_pkgs(variants, packages, pkgdatadir)
1764
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001765 if bb.data.inherits_class('allarch', d) and not variants \
1766 and not bb.data.inherits_class('packagegroup', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001767 write_extra_runtime_pkgs(global_variants, packages, pkgdatadir)
1768
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001769}
Andrew Geissler5199d832021-09-24 16:47:35 -05001770emit_pkgdata[dirs] = "${PKGDESTWORK}/runtime ${PKGDESTWORK}/runtime-reverse ${PKGDESTWORK}/runtime-rprovides ${PKGDESTWORK}/extended"
1771emit_pkgdata[vardepsexclude] = "BB_NUMBER_THREADS"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001772
1773ldconfig_postinst_fragment() {
1774if [ x"$D" = "x" ]; then
1775 if [ -x /sbin/ldconfig ]; then /sbin/ldconfig ; fi
1776fi
1777}
1778
Andrew Geissler90fd73c2021-03-05 15:25:55 -06001779RPMDEPS = "${STAGING_LIBDIR_NATIVE}/rpm/rpmdeps --alldeps --define '__font_provides %{nil}'"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001780
1781# Collect perfile run-time dependency metadata
1782# Output:
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001783# FILERPROVIDESFLIST:pkg - list of all files w/ deps
1784# FILERPROVIDES:filepath:pkg - per file dep
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001785#
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001786# FILERDEPENDSFLIST:pkg - list of all files w/ deps
1787# FILERDEPENDS:filepath:pkg - per file dep
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001788
1789python package_do_filedeps() {
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001790 if d.getVar('SKIP_FILEDEPS') == '1':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001791 return
1792
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001793 pkgdest = d.getVar('PKGDEST')
1794 packages = d.getVar('PACKAGES')
1795 rpmdeps = d.getVar('RPMDEPS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001796
1797 def chunks(files, n):
1798 return [files[i:i+n] for i in range(0, len(files), n)]
1799
1800 pkglist = []
1801 for pkg in packages.split():
Patrick Williams213cb262021-08-07 19:21:33 -05001802 if d.getVar('SKIP_FILEDEPS:' + pkg) == '1':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001803 continue
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001804 if pkg.endswith('-dbg') or pkg.endswith('-doc') or pkg.find('-locale-') != -1 or pkg.find('-localedata-') != -1 or pkg.find('-gconv-') != -1 or pkg.find('-charmap-') != -1 or pkg.startswith('kernel-module-') or pkg.endswith('-src'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001805 continue
1806 for files in chunks(pkgfiles[pkg], 100):
1807 pkglist.append((pkg, files, rpmdeps, pkgdest))
1808
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001809 processed = oe.utils.multiprocess_launch(oe.package.filedeprunner, pkglist, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001810
1811 provides_files = {}
1812 requires_files = {}
1813
1814 for result in processed:
1815 (pkg, provides, requires) = result
1816
1817 if pkg not in provides_files:
1818 provides_files[pkg] = []
1819 if pkg not in requires_files:
1820 requires_files[pkg] = []
1821
Brad Bishop19323692019-04-05 15:28:33 -04001822 for file in sorted(provides):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001823 provides_files[pkg].append(file)
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001824 key = "FILERPROVIDES:" + file + ":" + pkg
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001825 d.appendVar(key, " " + " ".join(provides[file]))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001826
Brad Bishop19323692019-04-05 15:28:33 -04001827 for file in sorted(requires):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001828 requires_files[pkg].append(file)
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001829 key = "FILERDEPENDS:" + file + ":" + pkg
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001830 d.appendVar(key, " " + " ".join(requires[file]))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001831
1832 for pkg in requires_files:
Andrew Geissler5199d832021-09-24 16:47:35 -05001833 d.setVar("FILERDEPENDSFLIST:" + pkg, " ".join(sorted(requires_files[pkg])))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001834 for pkg in provides_files:
Andrew Geissler5199d832021-09-24 16:47:35 -05001835 d.setVar("FILERPROVIDESFLIST:" + pkg, " ".join(sorted(provides_files[pkg])))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001836}
1837
Brad Bishop96ff1982019-08-19 13:50:42 -04001838SHLIBSDIRS = "${WORKDIR_PKGDATA}/${MLPREFIX}shlibs2"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001839SHLIBSWORKDIR = "${PKGDESTWORK}/${MLPREFIX}shlibs2"
1840
1841python package_do_shlibs() {
Brad Bishop00e122a2019-10-05 11:10:57 -04001842 import itertools
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001843 import re, pipes
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001844 import subprocess
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001845
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001846 exclude_shlibs = d.getVar('EXCLUDE_FROM_SHLIBS', False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001847 if exclude_shlibs:
1848 bb.note("not generating shlibs")
1849 return
1850
Brad Bishop19323692019-04-05 15:28:33 -04001851 lib_re = re.compile(r"^.*\.so")
1852 libdir_re = re.compile(r".*/%s$" % d.getVar('baselib'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001853
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001854 packages = d.getVar('PACKAGES')
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001855
1856 shlib_pkgs = []
1857 exclusion_list = d.getVar("EXCLUDE_PACKAGES_FROM_SHLIBS")
1858 if exclusion_list:
1859 for pkg in packages.split():
1860 if pkg not in exclusion_list.split():
1861 shlib_pkgs.append(pkg)
1862 else:
1863 bb.note("not generating shlibs for %s" % pkg)
1864 else:
1865 shlib_pkgs = packages.split()
1866
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001867 hostos = d.getVar('HOST_OS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001868
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001869 workdir = d.getVar('WORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001870
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001871 ver = d.getVar('PKGV')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001872 if not ver:
1873 msg = "PKGV not defined"
Andrew Geisslereff27472021-10-29 15:35:00 -05001874 oe.qa.handle_error("pkgv-undefined", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001875 return
1876
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001877 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001878
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001879 shlibswork_dir = d.getVar('SHLIBSWORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001880
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001881 def linux_so(file, pkg, pkgver, d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001882 needs_ldconfig = False
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001883 needed = set()
1884 sonames = set()
1885 renames = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001886 ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '')
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001887 cmd = d.getVar('OBJDUMP') + " -p " + pipes.quote(file) + " 2>/dev/null"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001888 fd = os.popen(cmd)
1889 lines = fd.readlines()
1890 fd.close()
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001891 rpath = tuple()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001892 for l in lines:
Brad Bishop19323692019-04-05 15:28:33 -04001893 m = re.match(r"\s+RPATH\s+([^\s]*)", l)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001894 if m:
1895 rpaths = m.group(1).replace("$ORIGIN", ldir).split(":")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001896 rpath = tuple(map(os.path.normpath, rpaths))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001897 for l in lines:
Brad Bishop19323692019-04-05 15:28:33 -04001898 m = re.match(r"\s+NEEDED\s+([^\s]*)", l)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001899 if m:
1900 dep = m.group(1)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001901 if dep not in needed:
1902 needed.add((dep, file, rpath))
Brad Bishop19323692019-04-05 15:28:33 -04001903 m = re.match(r"\s+SONAME\s+([^\s]*)", l)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001904 if m:
1905 this_soname = m.group(1)
1906 prov = (this_soname, ldir, pkgver)
1907 if not prov in sonames:
1908 # if library is private (only used by package) then do not build shlib for it
Brad Bishop79641f22019-09-10 07:20:22 -04001909 import fnmatch
1910 if not private_libs or len([i for i in private_libs if fnmatch.fnmatch(this_soname, i)]) == 0:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001911 sonames.add(prov)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001912 if libdir_re.match(os.path.dirname(file)):
1913 needs_ldconfig = True
Andrew Geissler595f6302022-01-24 19:11:47 +00001914 if needs_ldconfig and snap_symlinks and (os.path.basename(file) != this_soname):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001915 renames.append((file, os.path.join(os.path.dirname(file), this_soname)))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001916 return (needs_ldconfig, needed, sonames, renames)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001917
1918 def darwin_so(file, needed, sonames, renames, pkgver):
1919 if not os.path.exists(file):
1920 return
1921 ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '')
1922
1923 def get_combinations(base):
1924 #
1925 # Given a base library name, find all combinations of this split by "." and "-"
1926 #
1927 combos = []
1928 options = base.split(".")
1929 for i in range(1, len(options) + 1):
1930 combos.append(".".join(options[0:i]))
1931 options = base.split("-")
1932 for i in range(1, len(options) + 1):
1933 combos.append("-".join(options[0:i]))
1934 return combos
1935
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001936 if (file.endswith('.dylib') or file.endswith('.so')) and not pkg.endswith('-dev') and not pkg.endswith('-dbg') and not pkg.endswith('-src'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001937 # Drop suffix
1938 name = os.path.basename(file).rsplit(".",1)[0]
1939 # Find all combinations
1940 combos = get_combinations(name)
1941 for combo in combos:
1942 if not combo in sonames:
1943 prov = (combo, ldir, pkgver)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001944 sonames.add(prov)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001945 if file.endswith('.dylib') or file.endswith('.so'):
1946 rpath = []
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001947 p = subprocess.Popen([d.expand("${HOST_PREFIX}otool"), '-l', file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001948 out, err = p.communicate()
1949 # If returned successfully, process stdout for results
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001950 if p.returncode == 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001951 for l in out.split("\n"):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001952 l = l.strip()
1953 if l.startswith('path '):
1954 rpath.append(l.split()[1])
1955
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001956 p = subprocess.Popen([d.expand("${HOST_PREFIX}otool"), '-L', file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001957 out, err = p.communicate()
1958 # If returned successfully, process stdout for results
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001959 if p.returncode == 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001960 for l in out.split("\n"):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001961 l = l.strip()
1962 if not l or l.endswith(":"):
1963 continue
1964 if "is not an object file" in l:
1965 continue
1966 name = os.path.basename(l.split()[0]).rsplit(".", 1)[0]
1967 if name and name not in needed[pkg]:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001968 needed[pkg].add((name, file, tuple()))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001969
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001970 def mingw_dll(file, needed, sonames, renames, pkgver):
1971 if not os.path.exists(file):
1972 return
1973
1974 if file.endswith(".dll"):
1975 # assume all dlls are shared objects provided by the package
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001976 sonames.add((os.path.basename(file), os.path.dirname(file).replace(pkgdest + "/" + pkg, ''), pkgver))
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001977
1978 if (file.endswith(".dll") or file.endswith(".exe")):
1979 # use objdump to search for "DLL Name: .*\.dll"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001980 p = subprocess.Popen([d.expand("${HOST_PREFIX}objdump"), "-p", file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001981 out, err = p.communicate()
1982 # process the output, grabbing all .dll names
1983 if p.returncode == 0:
Brad Bishop19323692019-04-05 15:28:33 -04001984 for m in re.finditer(r"DLL Name: (.*?\.dll)$", out.decode(), re.MULTILINE | re.IGNORECASE):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001985 dllname = m.group(1)
1986 if dllname:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001987 needed[pkg].add((dllname, file, tuple()))
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001988
1989 if d.getVar('PACKAGE_SNAP_LIB_SYMLINKS') == "1":
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001990 snap_symlinks = True
1991 else:
1992 snap_symlinks = False
1993
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001994 needed = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001995
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001996 shlib_provider = oe.package.read_shlib_providers(d)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001997
1998 for pkg in shlib_pkgs:
Patrick Williams213cb262021-08-07 19:21:33 -05001999 private_libs = d.getVar('PRIVATE_LIBS:' + pkg) or d.getVar('PRIVATE_LIBS') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002000 private_libs = private_libs.split()
2001 needs_ldconfig = False
2002 bb.debug(2, "calculating shlib provides for %s" % pkg)
2003
Patrick Williams213cb262021-08-07 19:21:33 -05002004 pkgver = d.getVar('PKGV:' + pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002005 if not pkgver:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002006 pkgver = d.getVar('PV_' + pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002007 if not pkgver:
2008 pkgver = ver
2009
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08002010 needed[pkg] = set()
2011 sonames = set()
2012 renames = []
2013 linuxlist = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002014 for file in pkgfiles[pkg]:
2015 soname = None
2016 if cpath.islink(file):
2017 continue
Andrew Geisslerb7d28612020-07-24 16:15:54 -05002018 if hostos == "darwin" or hostos == "darwin8":
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002019 darwin_so(file, needed, sonames, renames, pkgver)
Andrew Geisslerb7d28612020-07-24 16:15:54 -05002020 elif hostos.startswith("mingw"):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002021 mingw_dll(file, needed, sonames, renames, pkgver)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002022 elif os.access(file, os.X_OK) or lib_re.match(file):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08002023 linuxlist.append(file)
2024
2025 if linuxlist:
2026 results = oe.utils.multiprocess_launch(linux_so, linuxlist, d, extraargs=(pkg, pkgver, d))
2027 for r in results:
2028 ldconfig = r[0]
2029 needed[pkg] |= r[1]
2030 sonames |= r[2]
2031 renames.extend(r[3])
2032 needs_ldconfig = needs_ldconfig or ldconfig
2033
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002034 for (old, new) in renames:
2035 bb.note("Renaming %s to %s" % (old, new))
Andrew Geisslerc926e172021-05-07 16:11:35 -05002036 bb.utils.rename(old, new)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002037 pkgfiles[pkg].remove(old)
Brad Bishop64c979e2019-11-04 13:55:29 -05002038
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002039 shlibs_file = os.path.join(shlibswork_dir, pkg + ".list")
2040 if len(sonames):
Brad Bishop64c979e2019-11-04 13:55:29 -05002041 with open(shlibs_file, 'w') as fd:
Andrew Geissler635e0e42020-08-21 15:58:33 -05002042 for s in sorted(sonames):
Brad Bishop64c979e2019-11-04 13:55:29 -05002043 if s[0] in shlib_provider and s[1] in shlib_provider[s[0]]:
2044 (old_pkg, old_pkgver) = shlib_provider[s[0]][s[1]]
2045 if old_pkg != pkg:
2046 bb.warn('%s-%s was registered as shlib provider for %s, changing it to %s-%s because it was built later' % (old_pkg, old_pkgver, s[0], pkg, pkgver))
2047 bb.debug(1, 'registering %s-%s as shlib provider for %s' % (pkg, pkgver, s[0]))
2048 fd.write(s[0] + ':' + s[1] + ':' + s[2] + '\n')
2049 if s[0] not in shlib_provider:
2050 shlib_provider[s[0]] = {}
2051 shlib_provider[s[0]][s[1]] = (pkg, pkgver)
Brad Bishop1d80a2e2019-11-15 16:35:03 -05002052 if needs_ldconfig:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002053 bb.debug(1, 'adding ldconfig call to postinst for %s' % pkg)
Patrick Williams213cb262021-08-07 19:21:33 -05002054 postinst = d.getVar('pkg_postinst:%s' % pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002055 if not postinst:
2056 postinst = '#!/bin/sh\n'
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002057 postinst += d.getVar('ldconfig_postinst_fragment')
Patrick Williams213cb262021-08-07 19:21:33 -05002058 d.setVar('pkg_postinst:%s' % pkg, postinst)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002059 bb.debug(1, 'LIBNAMES: pkg %s sonames %s' % (pkg, sonames))
2060
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002061 assumed_libs = d.getVar('ASSUME_SHLIBS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002062 if assumed_libs:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002063 libdir = d.getVar("libdir")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002064 for e in assumed_libs.split():
2065 l, dep_pkg = e.split(":")
2066 lib_ver = None
2067 dep_pkg = dep_pkg.rsplit("_", 1)
2068 if len(dep_pkg) == 2:
2069 lib_ver = dep_pkg[1]
2070 dep_pkg = dep_pkg[0]
2071 if l not in shlib_provider:
2072 shlib_provider[l] = {}
2073 shlib_provider[l][libdir] = (dep_pkg, lib_ver)
2074
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002075 libsearchpath = [d.getVar('libdir'), d.getVar('base_libdir')]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002076
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08002077 for pkg in shlib_pkgs:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002078 bb.debug(2, "calculating shlib requirements for %s" % pkg)
2079
Patrick Williams213cb262021-08-07 19:21:33 -05002080 private_libs = d.getVar('PRIVATE_LIBS:' + pkg) or d.getVar('PRIVATE_LIBS') or ""
Brad Bishop316dfdd2018-06-25 12:45:53 -04002081 private_libs = private_libs.split()
2082
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002083 deps = list()
2084 for n in needed[pkg]:
2085 # if n is in private libraries, don't try to search provider for it
2086 # this could cause problem in case some abc.bb provides private
2087 # /opt/abc/lib/libfoo.so.1 and contains /usr/bin/abc depending on system library libfoo.so.1
2088 # but skipping it is still better alternative than providing own
2089 # version and then adding runtime dependency for the same system library
Brad Bishop79641f22019-09-10 07:20:22 -04002090 import fnmatch
2091 if private_libs and len([i for i in private_libs if fnmatch.fnmatch(n[0], i)]) > 0:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002092 bb.debug(2, '%s: Dependency %s covered by PRIVATE_LIBS' % (pkg, n[0]))
2093 continue
2094 if n[0] in shlib_provider.keys():
Brad Bishop00e122a2019-10-05 11:10:57 -04002095 shlib_provider_map = shlib_provider[n[0]]
2096 matches = set()
2097 for p in itertools.chain(list(n[2]), sorted(shlib_provider_map.keys()), libsearchpath):
2098 if p in shlib_provider_map:
2099 matches.add(p)
2100 if len(matches) > 1:
2101 matchpkgs = ', '.join([shlib_provider_map[match][0] for match in matches])
2102 bb.error("%s: Multiple shlib providers for %s: %s (used by files: %s)" % (pkg, n[0], matchpkgs, n[1]))
2103 elif len(matches) == 1:
2104 (dep_pkg, ver_needed) = shlib_provider_map[matches.pop()]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002105
2106 bb.debug(2, '%s: Dependency %s requires package %s (used by files: %s)' % (pkg, n[0], dep_pkg, n[1]))
2107
2108 if dep_pkg == pkg:
2109 continue
2110
2111 if ver_needed:
2112 dep = "%s (>= %s)" % (dep_pkg, ver_needed)
2113 else:
2114 dep = dep_pkg
2115 if not dep in deps:
2116 deps.append(dep)
2117 continue
2118 bb.note("Couldn't find shared library provider for %s, used by files: %s" % (n[0], n[1]))
2119
2120 deps_file = os.path.join(pkgdest, pkg + ".shlibdeps")
2121 if os.path.exists(deps_file):
2122 os.remove(deps_file)
Brad Bishop64c979e2019-11-04 13:55:29 -05002123 if deps:
2124 with open(deps_file, 'w') as fd:
2125 for dep in sorted(deps):
2126 fd.write(dep + '\n')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002127}
2128
2129python package_do_pkgconfig () {
2130 import re
2131
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002132 packages = d.getVar('PACKAGES')
2133 workdir = d.getVar('WORKDIR')
2134 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002135
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002136 shlibs_dirs = d.getVar('SHLIBSDIRS').split()
2137 shlibswork_dir = d.getVar('SHLIBSWORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002138
Brad Bishop19323692019-04-05 15:28:33 -04002139 pc_re = re.compile(r'(.*)\.pc$')
2140 var_re = re.compile(r'(.*)=(.*)')
2141 field_re = re.compile(r'(.*): (.*)')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002142
2143 pkgconfig_provided = {}
2144 pkgconfig_needed = {}
2145 for pkg in packages.split():
2146 pkgconfig_provided[pkg] = []
2147 pkgconfig_needed[pkg] = []
Patrick Williams93c203f2021-10-06 16:15:23 -05002148 for file in sorted(pkgfiles[pkg]):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002149 m = pc_re.match(file)
2150 if m:
2151 pd = bb.data.init()
2152 name = m.group(1)
Patrick Williams93c203f2021-10-06 16:15:23 -05002153 pkgconfig_provided[pkg].append(os.path.basename(name))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002154 if not os.access(file, os.R_OK):
2155 continue
Brad Bishop64c979e2019-11-04 13:55:29 -05002156 with open(file, 'r') as f:
2157 lines = f.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002158 for l in lines:
2159 m = var_re.match(l)
2160 if m:
2161 name = m.group(1)
2162 val = m.group(2)
2163 pd.setVar(name, pd.expand(val))
2164 continue
2165 m = field_re.match(l)
2166 if m:
2167 hdr = m.group(1)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002168 exp = pd.expand(m.group(2))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002169 if hdr == 'Requires':
2170 pkgconfig_needed[pkg] += exp.replace(',', ' ').split()
2171
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002172 for pkg in packages.split():
2173 pkgs_file = os.path.join(shlibswork_dir, pkg + ".pclist")
2174 if pkgconfig_provided[pkg] != []:
Brad Bishop64c979e2019-11-04 13:55:29 -05002175 with open(pkgs_file, 'w') as f:
Patrick Williams93c203f2021-10-06 16:15:23 -05002176 for p in sorted(pkgconfig_provided[pkg]):
Brad Bishop64c979e2019-11-04 13:55:29 -05002177 f.write('%s\n' % p)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002178
2179 # Go from least to most specific since the last one found wins
2180 for dir in reversed(shlibs_dirs):
2181 if not os.path.exists(dir):
2182 continue
Brad Bishop08902b02019-08-20 09:16:51 -04002183 for file in sorted(os.listdir(dir)):
Brad Bishop19323692019-04-05 15:28:33 -04002184 m = re.match(r'^(.*)\.pclist$', file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002185 if m:
2186 pkg = m.group(1)
Brad Bishop64c979e2019-11-04 13:55:29 -05002187 with open(os.path.join(dir, file)) as fd:
2188 lines = fd.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002189 pkgconfig_provided[pkg] = []
2190 for l in lines:
2191 pkgconfig_provided[pkg].append(l.rstrip())
2192
2193 for pkg in packages.split():
2194 deps = []
2195 for n in pkgconfig_needed[pkg]:
2196 found = False
2197 for k in pkgconfig_provided.keys():
2198 if n in pkgconfig_provided[k]:
2199 if k != pkg and not (k in deps):
2200 deps.append(k)
2201 found = True
2202 if found == False:
2203 bb.note("couldn't find pkgconfig module '%s' in any package" % n)
2204 deps_file = os.path.join(pkgdest, pkg + ".pcdeps")
2205 if len(deps):
Brad Bishop64c979e2019-11-04 13:55:29 -05002206 with open(deps_file, 'w') as fd:
2207 for dep in deps:
2208 fd.write(dep + '\n')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002209}
2210
2211def read_libdep_files(d):
2212 pkglibdeps = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002213 packages = d.getVar('PACKAGES').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002214 for pkg in packages:
2215 pkglibdeps[pkg] = {}
2216 for extension in ".shlibdeps", ".pcdeps", ".clilibdeps":
2217 depsfile = d.expand("${PKGDEST}/" + pkg + extension)
2218 if os.access(depsfile, os.R_OK):
Brad Bishop64c979e2019-11-04 13:55:29 -05002219 with open(depsfile) as fd:
2220 lines = fd.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002221 for l in lines:
2222 l.rstrip()
2223 deps = bb.utils.explode_dep_versions2(l)
2224 for dep in deps:
2225 if not dep in pkglibdeps[pkg]:
2226 pkglibdeps[pkg][dep] = deps[dep]
2227 return pkglibdeps
2228
2229python read_shlibdeps () {
2230 pkglibdeps = read_libdep_files(d)
2231
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002232 packages = d.getVar('PACKAGES').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002233 for pkg in packages:
Patrick Williams213cb262021-08-07 19:21:33 -05002234 rdepends = bb.utils.explode_dep_versions2(d.getVar('RDEPENDS:' + pkg) or "")
Brad Bishop19323692019-04-05 15:28:33 -04002235 for dep in sorted(pkglibdeps[pkg]):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002236 # Add the dep if it's not already there, or if no comparison is set
2237 if dep not in rdepends:
2238 rdepends[dep] = []
2239 for v in pkglibdeps[pkg][dep]:
2240 if v not in rdepends[dep]:
2241 rdepends[dep].append(v)
Patrick Williams213cb262021-08-07 19:21:33 -05002242 d.setVar('RDEPENDS:' + pkg, bb.utils.join_deps(rdepends, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002243}
2244
2245python package_depchains() {
2246 """
2247 For a given set of prefix and postfix modifiers, make those packages
2248 RRECOMMENDS on the corresponding packages for its RDEPENDS.
2249
2250 Example: If package A depends upon package B, and A's .bb emits an
2251 A-dev package, this would make A-dev Recommends: B-dev.
2252
2253 If only one of a given suffix is specified, it will take the RRECOMMENDS
2254 based on the RDEPENDS of *all* other packages. If more than one of a given
2255 suffix is specified, its will only use the RDEPENDS of the single parent
2256 package.
2257 """
2258
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002259 packages = d.getVar('PACKAGES')
2260 postfixes = (d.getVar('DEPCHAIN_POST') or '').split()
2261 prefixes = (d.getVar('DEPCHAIN_PRE') or '').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002262
2263 def pkg_adddeprrecs(pkg, base, suffix, getname, depends, d):
2264
2265 #bb.note('depends for %s is %s' % (base, depends))
Patrick Williams213cb262021-08-07 19:21:33 -05002266 rreclist = bb.utils.explode_dep_versions2(d.getVar('RRECOMMENDS:' + pkg) or "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002267
Brad Bishop19323692019-04-05 15:28:33 -04002268 for depend in sorted(depends):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002269 if depend.find('-native') != -1 or depend.find('-cross') != -1 or depend.startswith('virtual/'):
2270 #bb.note("Skipping %s" % depend)
2271 continue
2272 if depend.endswith('-dev'):
2273 depend = depend[:-4]
2274 if depend.endswith('-dbg'):
2275 depend = depend[:-4]
2276 pkgname = getname(depend, suffix)
2277 #bb.note("Adding %s for %s" % (pkgname, depend))
2278 if pkgname not in rreclist and pkgname != pkg:
2279 rreclist[pkgname] = []
2280
Patrick Williams213cb262021-08-07 19:21:33 -05002281 #bb.note('setting: RRECOMMENDS:%s=%s' % (pkg, ' '.join(rreclist)))
2282 d.setVar('RRECOMMENDS:%s' % pkg, bb.utils.join_deps(rreclist, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002283
2284 def pkg_addrrecs(pkg, base, suffix, getname, rdepends, d):
2285
2286 #bb.note('rdepends for %s is %s' % (base, rdepends))
Patrick Williams213cb262021-08-07 19:21:33 -05002287 rreclist = bb.utils.explode_dep_versions2(d.getVar('RRECOMMENDS:' + pkg) or "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002288
Brad Bishop19323692019-04-05 15:28:33 -04002289 for depend in sorted(rdepends):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002290 if depend.find('virtual-locale-') != -1:
2291 #bb.note("Skipping %s" % depend)
2292 continue
2293 if depend.endswith('-dev'):
2294 depend = depend[:-4]
2295 if depend.endswith('-dbg'):
2296 depend = depend[:-4]
2297 pkgname = getname(depend, suffix)
2298 #bb.note("Adding %s for %s" % (pkgname, depend))
2299 if pkgname not in rreclist and pkgname != pkg:
2300 rreclist[pkgname] = []
2301
Patrick Williams213cb262021-08-07 19:21:33 -05002302 #bb.note('setting: RRECOMMENDS:%s=%s' % (pkg, ' '.join(rreclist)))
2303 d.setVar('RRECOMMENDS:%s' % pkg, bb.utils.join_deps(rreclist, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002304
2305 def add_dep(list, dep):
2306 if dep not in list:
2307 list.append(dep)
2308
2309 depends = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002310 for dep in bb.utils.explode_deps(d.getVar('DEPENDS') or ""):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002311 add_dep(depends, dep)
2312
2313 rdepends = []
2314 for pkg in packages.split():
Patrick Williams213cb262021-08-07 19:21:33 -05002315 for dep in bb.utils.explode_deps(d.getVar('RDEPENDS:' + pkg) or ""):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002316 add_dep(rdepends, dep)
2317
2318 #bb.note('rdepends is %s' % rdepends)
2319
2320 def post_getname(name, suffix):
2321 return '%s%s' % (name, suffix)
2322 def pre_getname(name, suffix):
2323 return '%s%s' % (suffix, name)
2324
2325 pkgs = {}
2326 for pkg in packages.split():
2327 for postfix in postfixes:
2328 if pkg.endswith(postfix):
2329 if not postfix in pkgs:
2330 pkgs[postfix] = {}
2331 pkgs[postfix][pkg] = (pkg[:-len(postfix)], post_getname)
2332
2333 for prefix in prefixes:
2334 if pkg.startswith(prefix):
2335 if not prefix in pkgs:
2336 pkgs[prefix] = {}
2337 pkgs[prefix][pkg] = (pkg[:-len(prefix)], pre_getname)
2338
2339 if "-dbg" in pkgs:
2340 pkglibdeps = read_libdep_files(d)
2341 pkglibdeplist = []
2342 for pkg in pkglibdeps:
2343 for k in pkglibdeps[pkg]:
2344 add_dep(pkglibdeplist, k)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002345 dbgdefaultdeps = ((d.getVar('DEPCHAIN_DBGDEFAULTDEPS') == '1') or (bb.data.inherits_class('packagegroup', d)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002346
2347 for suffix in pkgs:
2348 for pkg in pkgs[suffix]:
Patrick Williams213cb262021-08-07 19:21:33 -05002349 if d.getVarFlag('RRECOMMENDS:' + pkg, 'nodeprrecs'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002350 continue
2351 (base, func) = pkgs[suffix][pkg]
2352 if suffix == "-dev":
2353 pkg_adddeprrecs(pkg, base, suffix, func, depends, d)
2354 elif suffix == "-dbg":
2355 if not dbgdefaultdeps:
2356 pkg_addrrecs(pkg, base, suffix, func, pkglibdeplist, d)
2357 continue
2358 if len(pkgs[suffix]) == 1:
2359 pkg_addrrecs(pkg, base, suffix, func, rdepends, d)
2360 else:
2361 rdeps = []
Patrick Williams213cb262021-08-07 19:21:33 -05002362 for dep in bb.utils.explode_deps(d.getVar('RDEPENDS:' + base) or ""):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002363 add_dep(rdeps, dep)
2364 pkg_addrrecs(pkg, base, suffix, func, rdeps, d)
2365}
2366
2367# Since bitbake can't determine which variables are accessed during package
2368# iteration, we need to list them here:
Andrew Geissler1e34c2d2020-05-29 16:02:59 -05002369PACKAGEVARS = "FILES RDEPENDS RRECOMMENDS SUMMARY DESCRIPTION RSUGGESTS RPROVIDES RCONFLICTS PKG ALLOW_EMPTY pkg_postinst pkg_postrm pkg_postinst_ontarget INITSCRIPT_NAME INITSCRIPT_PARAMS DEBIAN_NOAUTONAME ALTERNATIVE PKGE PKGV PKGR USERADD_PARAM GROUPADD_PARAM CONFFILES SYSTEMD_SERVICE LICENSE SECTION pkg_preinst pkg_prerm RREPLACES GROUPMEMS_PARAM SYSTEMD_AUTO_ENABLE SKIP_FILEDEPS PRIVATE_LIBS PACKAGE_ADD_METADATA"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002370
Andrew Geissler82c905d2020-04-13 13:39:40 -05002371def gen_packagevar(d, pkgvars="PACKAGEVARS"):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002372 ret = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002373 pkgs = (d.getVar("PACKAGES") or "").split()
Andrew Geissler82c905d2020-04-13 13:39:40 -05002374 vars = (d.getVar(pkgvars) or "").split()
2375 for v in vars:
2376 ret.append(v)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002377 for p in pkgs:
2378 for v in vars:
Patrick Williams213cb262021-08-07 19:21:33 -05002379 ret.append(v + ":" + p)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002380
2381 # Ensure that changes to INCOMPATIBLE_LICENSE re-run do_package for
2382 # affected recipes.
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00002383 ret.append('_exclude_incompatible-%s' % p)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002384 return " ".join(ret)
2385
2386PACKAGE_PREPROCESS_FUNCS ?= ""
2387# Functions for setting up PKGD
2388PACKAGEBUILDPKGD ?= " \
Brad Bishop96ff1982019-08-19 13:50:42 -04002389 package_prepare_pkgdata \
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002390 perform_packagecopy \
2391 ${PACKAGE_PREPROCESS_FUNCS} \
2392 split_and_strip_files \
2393 fixup_perms \
2394 "
2395# Functions which split PKGD up into separate packages
2396PACKAGESPLITFUNCS ?= " \
2397 package_do_split_locales \
2398 populate_packages"
2399# Functions which process metadata based on split packages
2400PACKAGEFUNCS += " \
2401 package_fixsymlinks \
2402 package_name_hook \
2403 package_do_filedeps \
2404 package_do_shlibs \
2405 package_do_pkgconfig \
2406 read_shlibdeps \
2407 package_depchains \
2408 emit_pkgdata"
2409
2410python do_package () {
2411 # Change the following version to cause sstate to invalidate the package
2412 # cache. This is useful if an item this class depends on changes in a
2413 # way that the output of this class changes. rpmdeps is a good example
2414 # as any change to rpmdeps requires this to be rerun.
Andrew Geissler6ce62a22020-11-30 19:58:47 -06002415 # PACKAGE_BBCLASS_VERSION = "4"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002416
2417 # Init cachedpath
2418 global cpath
2419 cpath = oe.cachedpath.CachedPath()
2420
2421 ###########################################################################
2422 # Sanity test the setup
2423 ###########################################################################
2424
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002425 packages = (d.getVar('PACKAGES') or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002426 if len(packages) < 1:
2427 bb.debug(1, "No packages to build, skipping do_package")
2428 return
2429
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002430 workdir = d.getVar('WORKDIR')
2431 outdir = d.getVar('DEPLOY_DIR')
2432 dest = d.getVar('D')
2433 dvar = d.getVar('PKGD')
2434 pn = d.getVar('PN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002435
2436 if not workdir or not outdir or not dest or not dvar or not pn:
2437 msg = "WORKDIR, DEPLOY_DIR, D, PN and PKGD all must be defined, unable to package"
Andrew Geisslereff27472021-10-29 15:35:00 -05002438 oe.qa.handle_error("var-undefined", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002439 return
2440
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002441 bb.build.exec_func("package_convert_pr_autoinc", d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002442
2443 ###########################################################################
2444 # Optimisations
2445 ###########################################################################
2446
2447 # Continually expanding complex expressions is inefficient, particularly
2448 # when we write to the datastore and invalidate the expansion cache. This
2449 # code pre-expands some frequently used variables
2450
2451 def expandVar(x, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002452 d.setVar(x, d.getVar(x))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002453
2454 for x in 'PN', 'PV', 'BPN', 'TARGET_SYS', 'EXTENDPRAUTO':
2455 expandVar(x, d)
2456
2457 ###########################################################################
2458 # Setup PKGD (from D)
2459 ###########################################################################
2460
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002461 for f in (d.getVar('PACKAGEBUILDPKGD') or '').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002462 bb.build.exec_func(f, d)
2463
2464 ###########################################################################
2465 # Split up PKGD into PKGDEST
2466 ###########################################################################
2467
2468 cpath = oe.cachedpath.CachedPath()
2469
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002470 for f in (d.getVar('PACKAGESPLITFUNCS') or '').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002471 bb.build.exec_func(f, d)
2472
2473 ###########################################################################
2474 # Process PKGDEST
2475 ###########################################################################
2476
2477 # Build global list of files in each split package
2478 global pkgfiles
2479 pkgfiles = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002480 packages = d.getVar('PACKAGES').split()
2481 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002482 for pkg in packages:
2483 pkgfiles[pkg] = []
2484 for walkroot, dirs, files in cpath.walk(pkgdest + "/" + pkg):
2485 for file in files:
2486 pkgfiles[pkg].append(walkroot + os.sep + file)
2487
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002488 for f in (d.getVar('PACKAGEFUNCS') or '').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002489 bb.build.exec_func(f, d)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05002490
Andrew Geisslereff27472021-10-29 15:35:00 -05002491 oe.qa.exit_if_errors(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002492}
2493
Andrew Geissler9aee5002022-03-30 16:27:02 +00002494do_package[dirs] = "${SHLIBSWORKDIR} ${D}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002495do_package[vardeps] += "${PACKAGEBUILDPKGD} ${PACKAGESPLITFUNCS} ${PACKAGEFUNCS} ${@gen_packagevar(d)}"
2496addtask package after do_install
2497
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002498SSTATETASKS += "do_package"
2499do_package[cleandirs] = "${PKGDEST} ${PKGDESTWORK}"
2500do_package[sstate-plaindirs] = "${PKGD} ${PKGDEST} ${PKGDESTWORK}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002501do_package_setscene[dirs] = "${STAGING_DIR}"
2502
2503python do_package_setscene () {
2504 sstate_setscene(d)
2505}
2506addtask do_package_setscene
2507
Brad Bishopc68388fc2019-08-26 01:33:31 -04002508# Copy from PKGDESTWORK to tempdirectory as tempdirectory can be cleaned at both
2509# do_package_setscene and do_packagedata_setscene leading to races
2510python do_packagedata () {
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002511 bb.build.exec_func("package_get_auto_pr", d)
2512
Brad Bishopc68388fc2019-08-26 01:33:31 -04002513 src = d.expand("${PKGDESTWORK}")
2514 dest = d.expand("${WORKDIR}/pkgdata-pdata-input")
2515 oe.path.copyhardlinktree(src, dest)
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002516
2517 bb.build.exec_func("packagedata_translate_pr_autoinc", d)
2518}
Andrew Geisslerd1e89492021-02-12 15:35:20 -06002519do_packagedata[cleandirs] += "${WORKDIR}/pkgdata-pdata-input"
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002520
2521# Translate the EXTENDPRAUTO and AUTOINC to the final values
2522packagedata_translate_pr_autoinc() {
2523 find ${WORKDIR}/pkgdata-pdata-input -type f | xargs --no-run-if-empty \
2524 sed -e 's,@PRSERV_PV_AUTOINC@,${PRSERV_PV_AUTOINC},g' \
2525 -e 's,@EXTENDPRAUTO@,${EXTENDPRAUTO},g' -i
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002526}
2527
2528addtask packagedata before do_build after do_package
2529
2530SSTATETASKS += "do_packagedata"
Brad Bishopc68388fc2019-08-26 01:33:31 -04002531do_packagedata[sstate-inputdirs] = "${WORKDIR}/pkgdata-pdata-input"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002532do_packagedata[sstate-outputdirs] = "${PKGDATA_DIR}"
Brad Bishop316dfdd2018-06-25 12:45:53 -04002533do_packagedata[stamp-extra-info] = "${MACHINE_ARCH}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002534
2535python do_packagedata_setscene () {
2536 sstate_setscene(d)
2537}
2538addtask do_packagedata_setscene
2539
2540#
2541# Helper functions for the package writing classes
2542#
2543
2544def mapping_rename_hook(d):
2545 """
2546 Rewrite variables to account for package renaming in things
2547 like debian.bbclass or manual PKG variable name changes
2548 """
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002549 pkg = d.getVar("PKG")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002550 runtime_mapping_rename("RDEPENDS", pkg, d)
2551 runtime_mapping_rename("RRECOMMENDS", pkg, d)
2552 runtime_mapping_rename("RSUGGESTS", pkg, d)