blob: 92eba988929820b0dc75c6b58a465a440119abca [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
Brad Bishop19323692019-04-05 15:28:33 -0400370def splitdebuginfo(file, dvar, debugdir, debuglibdir, debugappend, debugsrcdir, 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):]
381 dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(src) + debugappend
382 debugfile = dvar + dest
Brad Bishop19323692019-04-05 15:28:33 -0400383 sources = []
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800384
385 # Split the file...
386 bb.utils.mkdirhier(os.path.dirname(debugfile))
387 #bb.note("Split %s -> %s" % (file, debugfile))
388 # Only store off the hard link reference if we successfully split!
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500389
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500390 dvar = d.getVar('PKGD')
391 objcopy = d.getVar("OBJCOPY")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500392
393 # We ignore kernel modules, we don't generate debug info files.
394 if file.find("/lib/modules/") != -1 and file.endswith(".ko"):
Brad Bishop19323692019-04-05 15:28:33 -0400395 return (file, sources)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500396
397 newmode = None
398 if not os.access(file, os.W_OK) or os.access(file, os.R_OK):
399 origmode = os.stat(file)[stat.ST_MODE]
400 newmode = origmode | stat.S_IWRITE | stat.S_IREAD
401 os.chmod(file, newmode)
402
403 # We need to extract the debug src information here...
404 if debugsrcdir:
Brad Bishop19323692019-04-05 15:28:33 -0400405 sources = source_info(file, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500406
407 bb.utils.mkdirhier(os.path.dirname(debugfile))
408
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800409 subprocess.check_output([objcopy, '--only-keep-debug', file, debugfile], stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500410
411 # Set the debuglink to have the view of the file path on the target
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800412 subprocess.check_output([objcopy, '--add-gnu-debuglink', debugfile, file], stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500413
414 if newmode:
415 os.chmod(file, origmode)
416
Brad Bishop19323692019-04-05 15:28:33 -0400417 return (file, sources)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500418
Andrew Geissler82c905d2020-04-13 13:39:40 -0500419def splitstaticdebuginfo(file, dvar, debugstaticdir, debugstaticlibdir, debugstaticappend, debugsrcdir, d):
420 # Unlike the function above, there is no way to split a static library
421 # two components. So to get similar results we will copy the unmodified
422 # static library (containing the debug symbols) into a new directory.
423 # We will then strip (preserving symbols) the static library in the
424 # typical location.
425 #
426 # return a mapping of files:debugsources
427
428 import stat
429 import shutil
430
431 src = file[len(dvar):]
432 dest = debugstaticlibdir + os.path.dirname(src) + debugstaticdir + "/" + os.path.basename(src) + debugstaticappend
433 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...
449 if debugsrcdir:
450 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
462def inject_minidebuginfo(file, dvar, debugdir, debuglibdir, debugappend, debugsrcdir, d):
463 # 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):]
476 dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(src) + debugappend
477 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")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500561 workparentdir = os.path.dirname(os.path.dirname(workdir))
562 workbasedir = os.path.basename(os.path.dirname(workdir)) + "/" + os.path.basename(workdir)
563
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500564 # If build path exists in sourcefile, it means toolchain did not use
565 # -fdebug-prefix-map to compile
566 if checkbuildpath(sourcefile, d):
567 localsrc_prefix = workparentdir + "/"
568 else:
569 localsrc_prefix = "/usr/src/debug/"
570
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500571 nosuchdir = []
572 basepath = dvar
573 for p in debugsrcdir.split("/"):
574 basepath = basepath + "/" + p
575 if not cpath.exists(basepath):
576 nosuchdir.append(basepath)
577 bb.utils.mkdirhier(basepath)
578 cpath.updatecache(basepath)
579
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500580 # Ignore files from the recipe sysroots (target and native)
581 processdebugsrc = "LC_ALL=C ; sort -z -u '%s' | egrep -v -z '((<internal>|<built-in>)$|/.*recipe-sysroot.*/)' | "
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500582 # We need to ignore files that are not actually ours
583 # we do this by only paying attention to items from this package
584 processdebugsrc += "fgrep -zw '%s' | "
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500585 # Remove prefix in the source paths
586 processdebugsrc += "sed 's#%s##g' | "
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500587 processdebugsrc += "(cd '%s' ; cpio -pd0mlL --no-preserve-owner '%s%s' 2>/dev/null)"
588
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500589 cmd = processdebugsrc % (sourcefile, workbasedir, localsrc_prefix, workparentdir, dvar, debugsrcdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800590 try:
591 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
592 except subprocess.CalledProcessError:
593 # Can "fail" if internal headers/transient sources are attempted
594 pass
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500595
596 # cpio seems to have a bug with -lL together and symbolic links are just copied, not dereferenced.
597 # Work around this by manually finding and copying any symbolic links that made it through.
Brad Bishop19323692019-04-05 15:28:33 -0400598 cmd = "find %s%s -type l -print0 -delete | sed s#%s%s/##g | (cd '%s' ; cpio -pd0mL --no-preserve-owner '%s%s')" % \
599 (dvar, debugsrcdir, dvar, debugsrcdir, workparentdir, dvar, debugsrcdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800600 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500601
602 # The copy by cpio may have resulted in some empty directories! Remove these
603 cmd = "find %s%s -empty -type d -delete" % (dvar, debugsrcdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800604 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500605
606 # Also remove debugsrcdir if its empty
607 for p in nosuchdir[::-1]:
608 if os.path.exists(p) and not os.listdir(p):
609 os.rmdir(p)
610
611#
612# Package data handling routines
613#
614
Andrew Geissler82c905d2020-04-13 13:39:40 -0500615def get_package_mapping (pkg, basepkg, d, depversions=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500616 import oe.packagedata
617
618 data = oe.packagedata.read_subpkgdata(pkg, d)
Patrick Williams213cb262021-08-07 19:21:33 -0500619 key = "PKG:%s" % pkg
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500620
621 if key in data:
622 # Have to avoid undoing the write_extra_pkgs(global_variants...)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800623 if bb.data.inherits_class('allarch', d) and not d.getVar('MULTILIB_VARIANTS') \
624 and data[key] == basepkg:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500625 return pkg
Andrew Geissler82c905d2020-04-13 13:39:40 -0500626 if depversions == []:
627 # Avoid returning a mapping if the renamed package rprovides its original name
Patrick Williams213cb262021-08-07 19:21:33 -0500628 rprovkey = "RPROVIDES:%s" % pkg
Andrew Geissler82c905d2020-04-13 13:39:40 -0500629 if rprovkey in data:
630 if pkg in bb.utils.explode_dep_versions2(data[rprovkey]):
631 bb.note("%s rprovides %s, not replacing the latter" % (data[key], pkg))
632 return pkg
633 # Do map to rewritten package name
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500634 return data[key]
635
636 return pkg
637
638def get_package_additional_metadata (pkg_type, d):
639 base_key = "PACKAGE_ADD_METADATA"
640 for key in ("%s_%s" % (base_key, pkg_type.upper()), base_key):
641 if d.getVar(key, False) is None:
642 continue
643 d.setVarFlag(key, "type", "list")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500644 if d.getVarFlag(key, "separator") is None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500645 d.setVarFlag(key, "separator", "\\n")
646 metadata_fields = [field.strip() for field in oe.data.typed_value(key, d)]
647 return "\n".join(metadata_fields).strip()
648
649def runtime_mapping_rename (varname, pkg, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500650 #bb.note("%s before: %s" % (varname, d.getVar(varname)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500651
652 new_depends = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500653 deps = bb.utils.explode_dep_versions2(d.getVar(varname) or "")
Andrew Geissler82c905d2020-04-13 13:39:40 -0500654 for depend, depversions in deps.items():
655 new_depend = get_package_mapping(depend, pkg, d, depversions)
656 if depend != new_depend:
657 bb.note("package name mapping done: %s -> %s" % (depend, new_depend))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500658 new_depends[new_depend] = deps[depend]
659
660 d.setVar(varname, bb.utils.join_deps(new_depends, commasep=False))
661
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500662 #bb.note("%s after: %s" % (varname, d.getVar(varname)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500663
664#
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500665# Used by do_packagedata (and possibly other routines post do_package)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500666#
667
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500668package_get_auto_pr[vardepsexclude] = "BB_TASKDEPDATA"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500669python package_get_auto_pr() {
670 import oe.prservice
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500671
672 def get_do_package_hash(pn):
673 if d.getVar("BB_RUNTASK") != "do_package":
674 taskdepdata = d.getVar("BB_TASKDEPDATA", False)
675 for dep in taskdepdata:
676 if taskdepdata[dep][1] == "do_package" and taskdepdata[dep][0] == pn:
677 return taskdepdata[dep][6]
678 return None
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500679
680 # Support per recipe PRSERV_HOST
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500681 pn = d.getVar('PN')
682 host = d.getVar("PRSERV_HOST_" + pn)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500683 if not (host is None):
684 d.setVar("PRSERV_HOST", host)
685
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500686 pkgv = d.getVar("PKGV")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500687
688 # PR Server not active, handle AUTOINC
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500689 if not d.getVar('PRSERV_HOST'):
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500690 d.setVar("PRSERV_PV_AUTOINC", "0")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500691 return
692
693 auto_pr = None
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500694 pv = d.getVar("PV")
695 version = d.getVar("PRAUTOINX")
696 pkgarch = d.getVar("PACKAGE_ARCH")
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500697 checksum = get_do_package_hash(pn)
698
699 # If do_package isn't in the dependencies, we can't get the checksum...
700 if not checksum:
701 bb.warn('Task %s requested do_package unihash, but it was not available.' % d.getVar('BB_RUNTASK'))
702 #taskdepdata = d.getVar("BB_TASKDEPDATA", False)
703 #for dep in taskdepdata:
704 # bb.warn('%s:%s = %s' % (taskdepdata[dep][0], taskdepdata[dep][1], taskdepdata[dep][6]))
705 return
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500706
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500707 if d.getVar('PRSERV_LOCKDOWN'):
708 auto_pr = d.getVar('PRAUTO_' + version + '_' + pkgarch) or d.getVar('PRAUTO_' + version) or None
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500709 if auto_pr is None:
710 bb.fatal("Can NOT get PRAUTO from lockdown exported file")
711 d.setVar('PRAUTO',str(auto_pr))
712 return
713
714 try:
Andrew Geisslerd159c7f2021-09-02 21:05:58 -0500715 conn = oe.prservice.prserv_make_conn(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500716 if conn is not None:
717 if "AUTOINC" in pkgv:
718 srcpv = bb.fetch2.get_srcrev(d)
719 base_ver = "AUTOINC-%s" % version[:version.find(srcpv)]
720 value = conn.getPR(base_ver, pkgarch, srcpv)
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500721 d.setVar("PRSERV_PV_AUTOINC", str(value))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500722
723 auto_pr = conn.getPR(version, pkgarch, checksum)
Andrew Geisslerd159c7f2021-09-02 21:05:58 -0500724 conn.close()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500725 except Exception as e:
726 bb.fatal("Can NOT get PRAUTO, exception %s" % str(e))
727 if auto_pr is None:
728 bb.fatal("Can NOT get PRAUTO from remote PR service")
729 d.setVar('PRAUTO',str(auto_pr))
730}
731
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500732#
733# Package functions suitable for inclusion in PACKAGEFUNCS
734#
735
736python package_convert_pr_autoinc() {
737 pkgv = d.getVar("PKGV")
738
739 # Adjust pkgv as necessary...
740 if 'AUTOINC' in pkgv:
741 d.setVar("PKGV", pkgv.replace("AUTOINC", "${PRSERV_PV_AUTOINC}"))
742
743 # Change PRSERV_PV_AUTOINC and EXTENDPRAUTO usage to special values
744 d.setVar('PRSERV_PV_AUTOINC', '@PRSERV_PV_AUTOINC@')
745 d.setVar('EXTENDPRAUTO', '@EXTENDPRAUTO@')
746}
747
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500748LOCALEBASEPN ??= "${PN}"
749
750python package_do_split_locales() {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500751 if (d.getVar('PACKAGE_NO_LOCALE') == '1'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500752 bb.debug(1, "package requested not splitting locales")
753 return
754
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500755 packages = (d.getVar('PACKAGES') or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500756
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500757 datadir = d.getVar('datadir')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500758 if not datadir:
759 bb.note("datadir not defined")
760 return
761
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500762 dvar = d.getVar('PKGD')
763 pn = d.getVar('LOCALEBASEPN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500764
765 if pn + '-locale' in packages:
766 packages.remove(pn + '-locale')
767
768 localedir = os.path.join(dvar + datadir, 'locale')
769
770 if not cpath.isdir(localedir):
771 bb.debug(1, "No locale files in this package")
772 return
773
774 locales = os.listdir(localedir)
775
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500776 summary = d.getVar('SUMMARY') or pn
777 description = d.getVar('DESCRIPTION') or ""
778 locale_section = d.getVar('LOCALE_SECTION')
779 mlprefix = d.getVar('MLPREFIX') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500780 for l in sorted(locales):
781 ln = legitimize_package_name(l)
782 pkg = pn + '-locale-' + ln
783 packages.append(pkg)
Patrick Williams213cb262021-08-07 19:21:33 -0500784 d.setVar('FILES:' + pkg, os.path.join(datadir, 'locale', l))
785 d.setVar('RRECOMMENDS:' + pkg, '%svirtual-locale-%s' % (mlprefix, ln))
786 d.setVar('RPROVIDES:' + pkg, '%s-locale %s%s-translation' % (pn, mlprefix, ln))
787 d.setVar('SUMMARY:' + pkg, '%s - %s translations' % (summary, l))
788 d.setVar('DESCRIPTION:' + pkg, '%s This package contains language translation files for the %s locale.' % (description, l))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500789 if locale_section:
Patrick Williams213cb262021-08-07 19:21:33 -0500790 d.setVar('SECTION:' + pkg, locale_section)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500791
792 d.setVar('PACKAGES', ' '.join(packages))
793
794 # Disabled by RP 18/06/07
795 # Wildcards aren't supported in debian
796 # They break with ipkg since glibc-locale* will mean that
797 # glibc-localedata-translit* won't install as a dependency
798 # for some other package which breaks meta-toolchain
799 # Probably breaks since virtual-locale- isn't provided anywhere
Patrick Williams213cb262021-08-07 19:21:33 -0500800 #rdep = (d.getVar('RDEPENDS:%s' % pn) or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500801 #rdep.append('%s-locale*' % pn)
Patrick Williams213cb262021-08-07 19:21:33 -0500802 #d.setVar('RDEPENDS:%s' % pn, ' '.join(rdep))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500803}
804
805python perform_packagecopy () {
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800806 import subprocess
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600807 import shutil
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800808
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500809 dest = d.getVar('D')
810 dvar = d.getVar('PKGD')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500811
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600812 # Remove ${D}/sysroot-only if present
813 sysroot_only = os.path.join(dest, 'sysroot-only')
814 if cpath.exists(sysroot_only) and cpath.isdir(sysroot_only):
815 shutil.rmtree(sysroot_only)
816
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500817 # Start by package population by taking a copy of the installed
818 # files to operate on
819 # Preserve sparse files and hard links
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800820 cmd = 'tar -cf - -C %s -p -S . | tar -xf - -C %s' % (dest, dvar)
821 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500822
823 # replace RPATHs for the nativesdk binaries, to make them relocatable
824 if bb.data.inherits_class('nativesdk', d) or bb.data.inherits_class('cross-canadian', d):
825 rpath_replace (dvar, d)
826}
827perform_packagecopy[cleandirs] = "${PKGD}"
828perform_packagecopy[dirs] = "${PKGD}"
829
830# We generate a master list of directories to process, we start by
831# seeding this list with reasonable defaults, then load from
832# the fs-perms.txt files
833python fixup_perms () {
834 import pwd, grp
835
836 # init using a string with the same format as a line as documented in
837 # the fs-perms.txt file
838 # <path> <mode> <uid> <gid> <walk> <fmode> <fuid> <fgid>
839 # <path> link <link target>
840 #
841 # __str__ can be used to print out an entry in the input format
842 #
843 # if fs_perms_entry.path is None:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400844 # an error occurred
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500845 # if fs_perms_entry.link, you can retrieve:
846 # fs_perms_entry.path = path
847 # fs_perms_entry.link = target of link
848 # if not fs_perms_entry.link, you can retrieve:
849 # fs_perms_entry.path = path
850 # fs_perms_entry.mode = expected dir mode or None
851 # fs_perms_entry.uid = expected uid or -1
852 # fs_perms_entry.gid = expected gid or -1
853 # fs_perms_entry.walk = 'true' or something else
854 # fs_perms_entry.fmode = expected file mode or None
855 # fs_perms_entry.fuid = expected file uid or -1
856 # fs_perms_entry_fgid = expected file gid or -1
857 class fs_perms_entry():
858 def __init__(self, line):
859 lsplit = line.split()
860 if len(lsplit) == 3 and lsplit[1].lower() == "link":
861 self._setlink(lsplit[0], lsplit[2])
862 elif len(lsplit) == 8:
863 self._setdir(lsplit[0], lsplit[1], lsplit[2], lsplit[3], lsplit[4], lsplit[5], lsplit[6], lsplit[7])
864 else:
865 msg = "Fixup Perms: invalid config line %s" % line
Andrew Geisslereff27472021-10-29 15:35:00 -0500866 oe.qa.handle_error("perm-config", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500867 self.path = None
868 self.link = None
869
870 def _setdir(self, path, mode, uid, gid, walk, fmode, fuid, fgid):
871 self.path = os.path.normpath(path)
872 self.link = None
873 self.mode = self._procmode(mode)
874 self.uid = self._procuid(uid)
875 self.gid = self._procgid(gid)
876 self.walk = walk.lower()
877 self.fmode = self._procmode(fmode)
878 self.fuid = self._procuid(fuid)
879 self.fgid = self._procgid(fgid)
880
881 def _setlink(self, path, link):
882 self.path = os.path.normpath(path)
883 self.link = link
884
885 def _procmode(self, mode):
886 if not mode or (mode and mode == "-"):
887 return None
888 else:
889 return int(mode,8)
890
891 # Note uid/gid -1 has special significance in os.lchown
892 def _procuid(self, uid):
893 if uid is None or uid == "-":
894 return -1
895 elif uid.isdigit():
896 return int(uid)
897 else:
898 return pwd.getpwnam(uid).pw_uid
899
900 def _procgid(self, gid):
901 if gid is None or gid == "-":
902 return -1
903 elif gid.isdigit():
904 return int(gid)
905 else:
906 return grp.getgrnam(gid).gr_gid
907
908 # Use for debugging the entries
909 def __str__(self):
910 if self.link:
911 return "%s link %s" % (self.path, self.link)
912 else:
913 mode = "-"
914 if self.mode:
915 mode = "0%o" % self.mode
916 fmode = "-"
917 if self.fmode:
918 fmode = "0%o" % self.fmode
919 uid = self._mapugid(self.uid)
920 gid = self._mapugid(self.gid)
921 fuid = self._mapugid(self.fuid)
922 fgid = self._mapugid(self.fgid)
923 return "%s %s %s %s %s %s %s %s" % (self.path, mode, uid, gid, self.walk, fmode, fuid, fgid)
924
925 def _mapugid(self, id):
926 if id is None or id == -1:
927 return "-"
928 else:
929 return "%d" % id
930
931 # Fix the permission, owner and group of path
932 def fix_perms(path, mode, uid, gid, dir):
933 if mode and not os.path.islink(path):
934 #bb.note("Fixup Perms: chmod 0%o %s" % (mode, dir))
935 os.chmod(path, mode)
936 # -1 is a special value that means don't change the uid/gid
937 # if they are BOTH -1, don't bother to lchown
938 if not (uid == -1 and gid == -1):
939 #bb.note("Fixup Perms: lchown %d:%d %s" % (uid, gid, dir))
940 os.lchown(path, uid, gid)
941
942 # Return a list of configuration files based on either the default
943 # files/fs-perms.txt or the contents of FILESYSTEM_PERMS_TABLES
944 # paths are resolved via BBPATH
945 def get_fs_perms_list(d):
946 str = ""
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500947 bbpath = d.getVar('BBPATH')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500948 fs_perms_tables = d.getVar('FILESYSTEM_PERMS_TABLES') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500949 for conf_file in fs_perms_tables.split():
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800950 confpath = bb.utils.which(bbpath, conf_file)
951 if confpath:
952 str += " %s" % bb.utils.which(bbpath, conf_file)
953 else:
954 bb.warn("cannot find %s specified in FILESYSTEM_PERMS_TABLES" % conf_file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500955 return str
956
957
958
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500959 dvar = d.getVar('PKGD')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500960
961 fs_perms_table = {}
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500962 fs_link_table = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500963
964 # By default all of the standard directories specified in
965 # bitbake.conf will get 0755 root:root.
966 target_path_vars = [ 'base_prefix',
967 'prefix',
968 'exec_prefix',
969 'base_bindir',
970 'base_sbindir',
971 'base_libdir',
972 'datadir',
973 'sysconfdir',
974 'servicedir',
975 'sharedstatedir',
976 'localstatedir',
977 'infodir',
978 'mandir',
979 'docdir',
980 'bindir',
981 'sbindir',
982 'libexecdir',
983 'libdir',
984 'includedir',
985 'oldincludedir' ]
986
987 for path in target_path_vars:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500988 dir = d.getVar(path) or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500989 if dir == "":
990 continue
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500991 fs_perms_table[dir] = fs_perms_entry(d.expand("%s 0755 root root false - - -" % (dir)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500992
993 # Now we actually load from the configuration files
994 for conf in get_fs_perms_list(d).split():
Brad Bishop64c979e2019-11-04 13:55:29 -0500995 if not os.path.exists(conf):
996 continue
997 with open(conf) as f:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500998 for line in f:
999 if line.startswith('#'):
1000 continue
1001 lsplit = line.split()
1002 if len(lsplit) == 0:
1003 continue
1004 if len(lsplit) != 8 and not (len(lsplit) == 3 and lsplit[1].lower() == "link"):
1005 msg = "Fixup perms: %s invalid line: %s" % (conf, line)
Andrew Geisslereff27472021-10-29 15:35:00 -05001006 oe.qa.handle_error("perm-line", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001007 continue
1008 entry = fs_perms_entry(d.expand(line))
1009 if entry and entry.path:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001010 if entry.link:
1011 fs_link_table[entry.path] = entry
1012 if entry.path in fs_perms_table:
1013 fs_perms_table.pop(entry.path)
1014 else:
1015 fs_perms_table[entry.path] = entry
1016 if entry.path in fs_link_table:
1017 fs_link_table.pop(entry.path)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001018
1019 # Debug -- list out in-memory table
1020 #for dir in fs_perms_table:
1021 # bb.note("Fixup Perms: %s: %s" % (dir, str(fs_perms_table[dir])))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001022 #for link in fs_link_table:
1023 # bb.note("Fixup Perms: %s: %s" % (link, str(fs_link_table[link])))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001024
1025 # We process links first, so we can go back and fixup directory ownership
1026 # for any newly created directories
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001027 # Process in sorted order so /run gets created before /run/lock, etc.
1028 for entry in sorted(fs_link_table.values(), key=lambda x: x.link):
1029 link = entry.link
1030 dir = entry.path
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001031 origin = dvar + dir
1032 if not (cpath.exists(origin) and cpath.isdir(origin) and not cpath.islink(origin)):
1033 continue
1034
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001035 if link[0] == "/":
1036 target = dvar + link
1037 ptarget = link
1038 else:
1039 target = os.path.join(os.path.dirname(origin), link)
1040 ptarget = os.path.join(os.path.dirname(dir), link)
1041 if os.path.exists(target):
1042 msg = "Fixup Perms: Unable to correct directory link, target already exists: %s -> %s" % (dir, ptarget)
Andrew Geisslereff27472021-10-29 15:35:00 -05001043 oe.qa.handle_error("perm-link", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001044 continue
1045
1046 # Create path to move directory to, move it, and then setup the symlink
1047 bb.utils.mkdirhier(os.path.dirname(target))
1048 #bb.note("Fixup Perms: Rename %s -> %s" % (dir, ptarget))
Andrew Geisslerc926e172021-05-07 16:11:35 -05001049 bb.utils.rename(origin, target)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001050 #bb.note("Fixup Perms: Link %s -> %s" % (dir, link))
1051 os.symlink(link, origin)
1052
1053 for dir in fs_perms_table:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001054 origin = dvar + dir
1055 if not (cpath.exists(origin) and cpath.isdir(origin)):
1056 continue
1057
1058 fix_perms(origin, fs_perms_table[dir].mode, fs_perms_table[dir].uid, fs_perms_table[dir].gid, dir)
1059
1060 if fs_perms_table[dir].walk == 'true':
1061 for root, dirs, files in os.walk(origin):
1062 for dr in dirs:
1063 each_dir = os.path.join(root, dr)
1064 fix_perms(each_dir, fs_perms_table[dir].mode, fs_perms_table[dir].uid, fs_perms_table[dir].gid, dir)
1065 for f in files:
1066 each_file = os.path.join(root, f)
1067 fix_perms(each_file, fs_perms_table[dir].fmode, fs_perms_table[dir].fuid, fs_perms_table[dir].fgid, dir)
1068}
1069
1070python split_and_strip_files () {
1071 import stat, errno
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001072 import subprocess
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001073
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001074 dvar = d.getVar('PKGD')
1075 pn = d.getVar('PN')
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001076 hostos = d.getVar('HOST_OS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001077
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001078 oldcwd = os.getcwd()
1079 os.chdir(dvar)
1080
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001081 # We default to '.debug' style
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001082 if d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-file-directory':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001083 # Single debug-file-directory style debug info
1084 debugappend = ".debug"
Andrew Geissler82c905d2020-04-13 13:39:40 -05001085 debugstaticappend = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001086 debugdir = ""
Andrew Geissler82c905d2020-04-13 13:39:40 -05001087 debugstaticdir = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001088 debuglibdir = "/usr/lib/debug"
Andrew Geissler82c905d2020-04-13 13:39:40 -05001089 debugstaticlibdir = "/usr/lib/debug-static"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001090 debugsrcdir = "/usr/src/debug"
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001091 elif d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-without-src':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001092 # Original OE-core, a.k.a. ".debug", style debug info, but without sources in /usr/src/debug
1093 debugappend = ""
Andrew Geissler82c905d2020-04-13 13:39:40 -05001094 debugstaticappend = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001095 debugdir = "/.debug"
Andrew Geissler82c905d2020-04-13 13:39:40 -05001096 debugstaticdir = "/.debug-static"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001097 debuglibdir = ""
Andrew Geissler82c905d2020-04-13 13:39:40 -05001098 debugstaticlibdir = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001099 debugsrcdir = ""
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001100 elif d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-with-srcpkg':
1101 debugappend = ""
Andrew Geissler82c905d2020-04-13 13:39:40 -05001102 debugstaticappend = ""
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001103 debugdir = "/.debug"
Andrew Geissler82c905d2020-04-13 13:39:40 -05001104 debugstaticdir = "/.debug-static"
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001105 debuglibdir = ""
Andrew Geissler82c905d2020-04-13 13:39:40 -05001106 debugstaticlibdir = ""
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001107 debugsrcdir = "/usr/src/debug"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001108 else:
1109 # Original OE-core, a.k.a. ".debug", style debug info
1110 debugappend = ""
Andrew Geissler82c905d2020-04-13 13:39:40 -05001111 debugstaticappend = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001112 debugdir = "/.debug"
Andrew Geissler82c905d2020-04-13 13:39:40 -05001113 debugstaticdir = "/.debug-static"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001114 debuglibdir = ""
Andrew Geissler82c905d2020-04-13 13:39:40 -05001115 debugstaticlibdir = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001116 debugsrcdir = "/usr/src/debug"
1117
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001118 #
1119 # First lets figure out all of the files we may have to process ... do this only once!
1120 #
1121 elffiles = {}
1122 symlinks = {}
1123 kernmods = []
Brad Bishop316dfdd2018-06-25 12:45:53 -04001124 staticlibs = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001125 inodes = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001126 libdir = os.path.abspath(dvar + os.sep + d.getVar("libdir"))
1127 baselibdir = os.path.abspath(dvar + os.sep + d.getVar("base_libdir"))
Brad Bishop316dfdd2018-06-25 12:45:53 -04001128 skipfiles = (d.getVar("INHIBIT_PACKAGE_STRIP_FILES") or "").split()
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001129 if (d.getVar('INHIBIT_PACKAGE_STRIP') != '1' or \
1130 d.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT') != '1'):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001131 checkelf = {}
1132 checkelflinks = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001133 for root, dirs, files in cpath.walk(dvar):
1134 for f in files:
1135 file = os.path.join(root, f)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001136
1137 # Skip debug files
1138 if debugappend and file.endswith(debugappend):
1139 continue
1140 if debugdir and debugdir in os.path.dirname(file[len(dvar):]):
1141 continue
1142
Brad Bishop316dfdd2018-06-25 12:45:53 -04001143 if file in skipfiles:
1144 continue
1145
Andrew Geissler82c905d2020-04-13 13:39:40 -05001146 if file.endswith(".ko") and file.find("/lib/modules/") != -1:
1147 kernmods.append(file)
1148 continue
1149 if oe.package.is_static_lib(file):
1150 staticlibs.append(file)
1151 continue
1152
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001153 try:
1154 ltarget = cpath.realpath(file, dvar, False)
1155 s = cpath.lstat(ltarget)
1156 except OSError as e:
1157 (err, strerror) = e.args
1158 if err != errno.ENOENT:
1159 raise
1160 # Skip broken symlinks
1161 continue
1162 if not s:
1163 continue
Brad Bishop316dfdd2018-06-25 12:45:53 -04001164 # Check its an executable
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001165 if (s[stat.ST_MODE] & stat.S_IXUSR) or (s[stat.ST_MODE] & stat.S_IXGRP) or (s[stat.ST_MODE] & stat.S_IXOTH) \
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001166 or ((file.startswith(libdir) or file.startswith(baselibdir)) and (".so" in f or ".node" in f)):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001167
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001168 if cpath.islink(file):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001169 checkelflinks[file] = ltarget
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001170 continue
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001171 # Use a reference of device ID and inode number to identify files
1172 file_reference = "%d_%d" % (s.st_dev, s.st_ino)
1173 checkelf[file] = (file, file_reference)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001174
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001175 results = oe.utils.multiprocess_launch(oe.package.is_elf, checkelflinks.values(), d)
1176 results_map = {}
1177 for (ltarget, elf_file) in results:
1178 results_map[ltarget] = elf_file
1179 for file in checkelflinks:
1180 ltarget = checkelflinks[file]
1181 # If it's a symlink, and points to an ELF file, we capture the readlink target
1182 if results_map[ltarget]:
1183 target = os.readlink(file)
1184 #bb.note("Sym: %s (%d)" % (ltarget, results_map[ltarget]))
1185 symlinks[file] = target
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001186
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001187 results = oe.utils.multiprocess_launch(oe.package.is_elf, checkelf.keys(), d)
Brad Bishop15ae2502019-06-18 21:44:24 -04001188
1189 # Sort results by file path. This ensures that the files are always
1190 # processed in the same order, which is important to make sure builds
1191 # are reproducible when dealing with hardlinks
1192 results.sort(key=lambda x: x[0])
1193
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001194 for (file, elf_file) in results:
1195 # It's a file (or hardlink), not a link
1196 # ...but is it ELF, and is it already stripped?
1197 if elf_file & 1:
1198 if elf_file & 2:
Patrick Williams213cb262021-08-07 19:21:33 -05001199 if 'already-stripped' in (d.getVar('INSANE_SKIP:' + pn) or "").split():
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001200 bb.note("Skipping file %s from %s for already-stripped QA test" % (file[len(dvar):], pn))
1201 else:
1202 msg = "File '%s' from %s was already stripped, this will prevent future debugging!" % (file[len(dvar):], pn)
Andrew Geisslereff27472021-10-29 15:35:00 -05001203 oe.qa.handle_error("already-stripped", msg, d)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001204 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001205
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001206 # At this point we have an unstripped elf file. We need to:
1207 # a) Make sure any file we strip is not hardlinked to anything else outside this tree
1208 # b) Only strip any hardlinked file once (no races)
1209 # c) Track any hardlinks between files so that we can reconstruct matching debug file hardlinks
1210
1211 # Use a reference of device ID and inode number to identify files
1212 file_reference = checkelf[file][1]
1213 if file_reference in inodes:
1214 os.unlink(file)
1215 os.link(inodes[file_reference][0], file)
1216 inodes[file_reference].append(file)
1217 else:
1218 inodes[file_reference] = [file]
1219 # break hardlink
1220 bb.utils.break_hardlinks(file)
1221 elffiles[file] = elf_file
1222 # Modified the file so clear the cache
1223 cpath.updatecache(file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001224
Andrew Geissler5199d832021-09-24 16:47:35 -05001225 def strip_pkgd_prefix(f):
1226 nonlocal dvar
1227
1228 if f.startswith(dvar):
1229 return f[len(dvar):]
1230
1231 return f
1232
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001233 #
1234 # First lets process debug splitting
1235 #
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001236 if (d.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT') != '1'):
Brad Bishop19323692019-04-05 15:28:33 -04001237 results = oe.utils.multiprocess_launch(splitdebuginfo, list(elffiles), d, extraargs=(dvar, debugdir, debuglibdir, debugappend, debugsrcdir, d))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001238
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001239 if debugsrcdir and not hostos.startswith("mingw"):
Andrew Geissler82c905d2020-04-13 13:39:40 -05001240 if (d.getVar('PACKAGE_DEBUG_STATIC_SPLIT') == '1'):
1241 results = oe.utils.multiprocess_launch(splitstaticdebuginfo, staticlibs, d, extraargs=(dvar, debugstaticdir, debugstaticlibdir, debugstaticappend, debugsrcdir, d))
1242 else:
1243 for file in staticlibs:
1244 results.append( (file,source_info(file, d)) )
Brad Bishop19323692019-04-05 15:28:33 -04001245
Andrew Geissler5199d832021-09-24 16:47:35 -05001246 d.setVar("PKGDEBUGSOURCES", {strip_pkgd_prefix(f): sorted(s) for f, s in results})
1247
Brad Bishop19323692019-04-05 15:28:33 -04001248 sources = set()
1249 for r in results:
1250 sources.update(r[1])
Brad Bishop316dfdd2018-06-25 12:45:53 -04001251
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001252 # Hardlink our debug symbols to the other hardlink copies
1253 for ref in inodes:
1254 if len(inodes[ref]) == 1:
1255 continue
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001256
1257 target = inodes[ref][0][len(dvar):]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001258 for file in inodes[ref][1:]:
1259 src = file[len(dvar):]
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001260 dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(target) + debugappend
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001261 fpath = dvar + dest
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001262 ftarget = dvar + debuglibdir + os.path.dirname(target) + debugdir + "/" + os.path.basename(target) + debugappend
1263 bb.utils.mkdirhier(os.path.dirname(fpath))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001264 # Only one hardlink of separated debug info file in each directory
1265 if not os.access(fpath, os.R_OK):
1266 #bb.note("Link %s -> %s" % (fpath, ftarget))
1267 os.link(ftarget, fpath)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001268
1269 # Create symlinks for all cases we were able to split symbols
1270 for file in symlinks:
1271 src = file[len(dvar):]
1272 dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(src) + debugappend
1273 fpath = dvar + dest
1274 # Skip it if the target doesn't exist
1275 try:
1276 s = os.stat(fpath)
1277 except OSError as e:
1278 (err, strerror) = e.args
1279 if err != errno.ENOENT:
1280 raise
1281 continue
1282
1283 ltarget = symlinks[file]
1284 lpath = os.path.dirname(ltarget)
1285 lbase = os.path.basename(ltarget)
1286 ftarget = ""
1287 if lpath and lpath != ".":
1288 ftarget += lpath + debugdir + "/"
1289 ftarget += lbase + debugappend
1290 if lpath.startswith(".."):
1291 ftarget = os.path.join("..", ftarget)
1292 bb.utils.mkdirhier(os.path.dirname(fpath))
1293 #bb.note("Symlink %s -> %s" % (fpath, ftarget))
1294 os.symlink(ftarget, fpath)
1295
1296 # Process the debugsrcdir if requested...
1297 # This copies and places the referenced sources for later debugging...
Brad Bishop19323692019-04-05 15:28:33 -04001298 copydebugsources(debugsrcdir, sources, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001299 #
1300 # End of debug splitting
1301 #
1302
1303 #
1304 # Now lets go back over things and strip them
1305 #
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001306 if (d.getVar('INHIBIT_PACKAGE_STRIP') != '1'):
1307 strip = d.getVar("STRIP")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001308 sfiles = []
1309 for file in elffiles:
1310 elf_file = int(elffiles[file])
1311 #bb.note("Strip %s" % file)
1312 sfiles.append((file, elf_file, strip))
1313 for f in kernmods:
1314 sfiles.append((f, 16, strip))
Andrew Geissler82c905d2020-04-13 13:39:40 -05001315 if (d.getVar('PACKAGE_STRIP_STATIC') == '1' or d.getVar('PACKAGE_DEBUG_STATIC_SPLIT') == '1'):
1316 for f in staticlibs:
1317 sfiles.append((f, 16, strip))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001318
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001319 oe.utils.multiprocess_launch(oe.package.runstrip, sfiles, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001320
Andrew Geissler82c905d2020-04-13 13:39:40 -05001321 # Build "minidebuginfo" and reinject it back into the stripped binaries
1322 if d.getVar('PACKAGE_MINIDEBUGINFO') == '1':
1323 oe.utils.multiprocess_launch(inject_minidebuginfo, list(elffiles), d,
1324 extraargs=(dvar, debugdir, debuglibdir, debugappend, debugsrcdir, d))
1325
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001326 #
1327 # End of strip
1328 #
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001329 os.chdir(oldcwd)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001330}
1331
1332python populate_packages () {
1333 import glob, re
1334
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001335 workdir = d.getVar('WORKDIR')
1336 outdir = d.getVar('DEPLOY_DIR')
1337 dvar = d.getVar('PKGD')
Brad Bishop19323692019-04-05 15:28:33 -04001338 packages = d.getVar('PACKAGES').split()
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001339 pn = d.getVar('PN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001340
1341 bb.utils.mkdirhier(outdir)
1342 os.chdir(dvar)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001343
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001344 autodebug = not (d.getVar("NOAUTOPACKAGEDEBUG") or False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001345
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001346 split_source_package = (d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-with-srcpkg')
1347
Brad Bishop19323692019-04-05 15:28:33 -04001348 # If debug-with-srcpkg mode is enabled then add the source package if it
1349 # doesn't exist and add the source file contents to the source package.
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001350 if split_source_package:
1351 src_package_name = ('%s-src' % d.getVar('PN'))
Brad Bishop19323692019-04-05 15:28:33 -04001352 if not src_package_name in packages:
1353 packages.append(src_package_name)
Patrick Williams213cb262021-08-07 19:21:33 -05001354 d.setVar('FILES:%s' % src_package_name, '/usr/src/debug')
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001355
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001356 # Sanity check PACKAGES for duplicates
Brad Bishop316dfdd2018-06-25 12:45:53 -04001357 # Sanity should be moved to sanity.bbclass once we have the infrastructure
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001358 package_dict = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001359
Brad Bishop19323692019-04-05 15:28:33 -04001360 for i, pkg in enumerate(packages):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001361 if pkg in package_dict:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001362 msg = "%s is listed in PACKAGES multiple times, this leads to packaging errors." % pkg
Andrew Geisslereff27472021-10-29 15:35:00 -05001363 oe.qa.handle_error("packages-list", msg, d)
Brad Bishop19323692019-04-05 15:28:33 -04001364 # Ensure the source package gets the chance to pick up the source files
1365 # before the debug package by ordering it first in PACKAGES. Whether it
1366 # actually picks up any source files is controlled by
1367 # PACKAGE_DEBUG_SPLIT_STYLE.
1368 elif pkg.endswith("-src"):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001369 package_dict[pkg] = (10, i)
1370 elif autodebug and pkg.endswith("-dbg"):
1371 package_dict[pkg] = (30, i)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001372 else:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001373 package_dict[pkg] = (50, i)
Brad Bishop19323692019-04-05 15:28:33 -04001374 packages = sorted(package_dict.keys(), key=package_dict.get)
1375 d.setVar('PACKAGES', ' '.join(packages))
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001376 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001377
1378 seen = []
1379
1380 # os.mkdir masks the permissions with umask so we have to unset it first
1381 oldumask = os.umask(0)
1382
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001383 debug = []
1384 for root, dirs, files in cpath.walk(dvar):
1385 dir = root[len(dvar):]
1386 if not dir:
1387 dir = os.sep
1388 for f in (files + dirs):
1389 path = "." + os.path.join(dir, f)
Andrew Geissler82c905d2020-04-13 13:39:40 -05001390 if "/.debug/" in path or "/.debug-static/" in path or path.endswith("/.debug"):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001391 debug.append(path)
1392
Brad Bishop19323692019-04-05 15:28:33 -04001393 for pkg in packages:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001394 root = os.path.join(pkgdest, pkg)
1395 bb.utils.mkdirhier(root)
1396
Patrick Williams213cb262021-08-07 19:21:33 -05001397 filesvar = d.getVar('FILES:%s' % pkg) or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001398 if "//" in filesvar:
1399 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 -05001400 oe.qa.handle_error("files-invalid", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001401 filesvar.replace("//", "/")
1402
1403 origfiles = filesvar.split()
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001404 files, symlink_paths = files_from_filevars(origfiles)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001405
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001406 if autodebug and pkg.endswith("-dbg"):
1407 files.extend(debug)
1408
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001409 for file in files:
1410 if (not cpath.islink(file)) and (not cpath.exists(file)):
1411 continue
1412 if file in seen:
1413 continue
1414 seen.append(file)
1415
1416 def mkdir(src, dest, p):
1417 src = os.path.join(src, p)
1418 dest = os.path.join(dest, p)
1419 fstat = cpath.stat(src)
Brad Bishop96ff1982019-08-19 13:50:42 -04001420 os.mkdir(dest)
1421 os.chmod(dest, fstat.st_mode)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001422 os.chown(dest, fstat.st_uid, fstat.st_gid)
1423 if p not in seen:
1424 seen.append(p)
1425 cpath.updatecache(dest)
1426
1427 def mkdir_recurse(src, dest, paths):
1428 if cpath.exists(dest + '/' + paths):
1429 return
1430 while paths.startswith("./"):
1431 paths = paths[2:]
1432 p = "."
1433 for c in paths.split("/"):
1434 p = os.path.join(p, c)
1435 if not cpath.exists(os.path.join(dest, p)):
1436 mkdir(src, dest, p)
1437
1438 if cpath.isdir(file) and not cpath.islink(file):
1439 mkdir_recurse(dvar, root, file)
1440 continue
1441
1442 mkdir_recurse(dvar, root, os.path.dirname(file))
1443 fpath = os.path.join(root,file)
1444 if not cpath.islink(file):
1445 os.link(file, fpath)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001446 continue
1447 ret = bb.utils.copyfile(file, fpath)
1448 if ret is False or ret == 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001449 bb.fatal("File population failed")
1450
1451 # Check if symlink paths exist
1452 for file in symlink_paths:
1453 if not os.path.exists(os.path.join(root,file)):
1454 bb.fatal("File '%s' cannot be packaged into '%s' because its "
1455 "parent directory structure does not exist. One of "
1456 "its parent directories is a symlink whose target "
1457 "directory is not included in the package." %
1458 (file, pkg))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001459
1460 os.umask(oldumask)
1461 os.chdir(workdir)
1462
1463 # Handle LICENSE_EXCLUSION
1464 package_list = []
Brad Bishop19323692019-04-05 15:28:33 -04001465 for pkg in packages:
Andrew Geissler82c905d2020-04-13 13:39:40 -05001466 licenses = d.getVar('LICENSE_EXCLUSION-' + pkg)
1467 if licenses:
1468 msg = "Excluding %s from packaging as it has incompatible license(s): %s" % (pkg, licenses)
Andrew Geisslereff27472021-10-29 15:35:00 -05001469 oe.qa.handle_error("incompatible-license", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001470 else:
1471 package_list.append(pkg)
1472 d.setVar('PACKAGES', ' '.join(package_list))
1473
1474 unshipped = []
1475 for root, dirs, files in cpath.walk(dvar):
1476 dir = root[len(dvar):]
1477 if not dir:
1478 dir = os.sep
1479 for f in (files + dirs):
1480 path = os.path.join(dir, f)
1481 if ('.' + path) not in seen:
1482 unshipped.append(path)
1483
1484 if unshipped != []:
1485 msg = pn + ": Files/directories were installed but not shipped in any package:"
Patrick Williams213cb262021-08-07 19:21:33 -05001486 if "installed-vs-shipped" in (d.getVar('INSANE_SKIP:' + pn) or "").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001487 bb.note("Package %s skipping QA tests: installed-vs-shipped" % pn)
1488 else:
1489 for f in unshipped:
1490 msg = msg + "\n " + f
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001491 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"
1492 msg = msg + "%s: %d installed and not shipped files." % (pn, len(unshipped))
Andrew Geisslereff27472021-10-29 15:35:00 -05001493 oe.qa.handle_error("installed-vs-shipped", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001494}
1495populate_packages[dirs] = "${D}"
1496
1497python package_fixsymlinks () {
1498 import errno
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001499 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001500 packages = d.getVar("PACKAGES", False).split()
1501
1502 dangling_links = {}
1503 pkg_files = {}
1504 for pkg in packages:
1505 dangling_links[pkg] = []
1506 pkg_files[pkg] = []
1507 inst_root = os.path.join(pkgdest, pkg)
1508 for path in pkgfiles[pkg]:
1509 rpath = path[len(inst_root):]
1510 pkg_files[pkg].append(rpath)
1511 rtarget = cpath.realpath(path, inst_root, True, assume_dir = True)
1512 if not cpath.lexists(rtarget):
1513 dangling_links[pkg].append(os.path.normpath(rtarget[len(inst_root):]))
1514
1515 newrdepends = {}
1516 for pkg in dangling_links:
1517 for l in dangling_links[pkg]:
1518 found = False
1519 bb.debug(1, "%s contains dangling link %s" % (pkg, l))
1520 for p in packages:
1521 if l in pkg_files[p]:
1522 found = True
1523 bb.debug(1, "target found in %s" % p)
1524 if p == pkg:
1525 break
1526 if pkg not in newrdepends:
1527 newrdepends[pkg] = []
1528 newrdepends[pkg].append(p)
1529 break
1530 if found == False:
1531 bb.note("%s contains dangling symlink to %s" % (pkg, l))
1532
1533 for pkg in newrdepends:
Patrick Williams213cb262021-08-07 19:21:33 -05001534 rdepends = bb.utils.explode_dep_versions2(d.getVar('RDEPENDS:' + pkg) or "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001535 for p in newrdepends[pkg]:
1536 if p not in rdepends:
1537 rdepends[p] = []
Patrick Williams213cb262021-08-07 19:21:33 -05001538 d.setVar('RDEPENDS:' + pkg, bb.utils.join_deps(rdepends, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001539}
1540
1541
1542python package_package_name_hook() {
1543 """
1544 A package_name_hook function can be used to rewrite the package names by
1545 changing PKG. For an example, see debian.bbclass.
1546 """
1547 pass
1548}
1549
1550EXPORT_FUNCTIONS package_name_hook
1551
1552
1553PKGDESTWORK = "${WORKDIR}/pkgdata"
1554
Andrew Geissler1e34c2d2020-05-29 16:02:59 -05001555PKGDATA_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 -04001556
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001557python emit_pkgdata() {
1558 from glob import glob
1559 import json
Andrew Geissler5199d832021-09-24 16:47:35 -05001560 import bb.compress.zstd
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001561
Brad Bishop316dfdd2018-06-25 12:45:53 -04001562 def process_postinst_on_target(pkg, mlprefix):
Patrick Williams213cb262021-08-07 19:21:33 -05001563 pkgval = d.getVar('PKG:%s' % pkg)
Brad Bishop96ff1982019-08-19 13:50:42 -04001564 if pkgval is None:
1565 pkgval = pkg
1566
Brad Bishop316dfdd2018-06-25 12:45:53 -04001567 defer_fragment = """
1568if [ -n "$D" ]; then
1569 $INTERCEPT_DIR/postinst_intercept delay_to_first_boot %s mlprefix=%s
1570 exit 0
1571fi
Brad Bishop96ff1982019-08-19 13:50:42 -04001572""" % (pkgval, mlprefix)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001573
Patrick Williams213cb262021-08-07 19:21:33 -05001574 postinst = d.getVar('pkg_postinst:%s' % pkg)
1575 postinst_ontarget = d.getVar('pkg_postinst_ontarget:%s' % pkg)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001576
1577 if postinst_ontarget:
1578 bb.debug(1, 'adding deferred pkg_postinst_ontarget() to pkg_postinst() for %s' % pkg)
1579 if not postinst:
1580 postinst = '#!/bin/sh\n'
1581 postinst += defer_fragment
1582 postinst += postinst_ontarget
Patrick Williams213cb262021-08-07 19:21:33 -05001583 d.setVar('pkg_postinst:%s' % pkg, postinst)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001584
1585 def add_set_e_to_scriptlets(pkg):
1586 for scriptlet_name in ('pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm'):
Patrick Williams213cb262021-08-07 19:21:33 -05001587 scriptlet = d.getVar('%s:%s' % (scriptlet_name, pkg))
Brad Bishop316dfdd2018-06-25 12:45:53 -04001588 if scriptlet:
1589 scriptlet_split = scriptlet.split('\n')
1590 if scriptlet_split[0].startswith("#!"):
1591 scriptlet = scriptlet_split[0] + "\nset -e\n" + "\n".join(scriptlet_split[1:])
1592 else:
1593 scriptlet = "set -e\n" + "\n".join(scriptlet_split[0:])
Patrick Williams213cb262021-08-07 19:21:33 -05001594 d.setVar('%s:%s' % (scriptlet_name, pkg), scriptlet)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001595
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001596 def write_if_exists(f, pkg, var):
1597 def encode(str):
1598 import codecs
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001599 c = codecs.getencoder("unicode_escape")
1600 return c(str)[0].decode("latin1")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001601
Patrick Williams213cb262021-08-07 19:21:33 -05001602 val = d.getVar('%s:%s' % (var, pkg))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001603 if val:
Patrick Williams213cb262021-08-07 19:21:33 -05001604 f.write('%s:%s: %s\n' % (var, pkg, encode(val)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001605 return val
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001606 val = d.getVar('%s' % (var))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001607 if val:
1608 f.write('%s: %s\n' % (var, encode(val)))
1609 return val
1610
1611 def write_extra_pkgs(variants, pn, packages, pkgdatadir):
1612 for variant in variants:
1613 with open("%s/%s-%s" % (pkgdatadir, variant, pn), 'w') as fd:
1614 fd.write("PACKAGES: %s\n" % ' '.join(
1615 map(lambda pkg: '%s-%s' % (variant, pkg), packages.split())))
1616
1617 def write_extra_runtime_pkgs(variants, packages, pkgdatadir):
1618 for variant in variants:
1619 for pkg in packages.split():
1620 ml_pkg = "%s-%s" % (variant, pkg)
1621 subdata_file = "%s/runtime/%s" % (pkgdatadir, ml_pkg)
1622 with open(subdata_file, 'w') as fd:
Patrick Williams213cb262021-08-07 19:21:33 -05001623 fd.write("PKG:%s: %s" % (ml_pkg, pkg))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001624
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001625 packages = d.getVar('PACKAGES')
1626 pkgdest = d.getVar('PKGDEST')
1627 pkgdatadir = d.getVar('PKGDESTWORK')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001628
Brad Bishop64c979e2019-11-04 13:55:29 -05001629 data_file = pkgdatadir + d.expand("/${PN}")
1630 with open(data_file, 'w') as fd:
1631 fd.write("PACKAGES: %s\n" % packages)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001632
Andrew Geissler5199d832021-09-24 16:47:35 -05001633 pkgdebugsource = d.getVar("PKGDEBUGSOURCES") or []
1634
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001635 pn = d.getVar('PN')
1636 global_variants = (d.getVar('MULTILIB_GLOBAL_VARIANTS') or "").split()
1637 variants = (d.getVar('MULTILIB_VARIANTS') or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001638
1639 if bb.data.inherits_class('kernel', d) or bb.data.inherits_class('module-base', d):
1640 write_extra_pkgs(variants, pn, packages, pkgdatadir)
1641
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001642 if bb.data.inherits_class('allarch', d) and not variants \
1643 and not bb.data.inherits_class('packagegroup', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001644 write_extra_pkgs(global_variants, pn, packages, pkgdatadir)
1645
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001646 workdir = d.getVar('WORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001647
1648 for pkg in packages.split():
Patrick Williams213cb262021-08-07 19:21:33 -05001649 pkgval = d.getVar('PKG:%s' % pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001650 if pkgval is None:
1651 pkgval = pkg
Patrick Williams213cb262021-08-07 19:21:33 -05001652 d.setVar('PKG:%s' % pkg, pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001653
Andrew Geissler5199d832021-09-24 16:47:35 -05001654 extended_data = {
1655 "files_info": {}
1656 }
1657
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001658 pkgdestpkg = os.path.join(pkgdest, pkg)
1659 files = {}
Andrew Geissler5199d832021-09-24 16:47:35 -05001660 files_extra = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001661 total_size = 0
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001662 seen = set()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001663 for f in pkgfiles[pkg]:
Andrew Geissler5199d832021-09-24 16:47:35 -05001664 fpath = os.sep + os.path.relpath(f, pkgdestpkg)
1665
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001666 fstat = os.lstat(f)
Andrew Geissler5199d832021-09-24 16:47:35 -05001667 files[fpath] = fstat.st_size
1668
1669 extended_data["files_info"].setdefault(fpath, {})
1670 extended_data["files_info"][fpath]['size'] = fstat.st_size
1671
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001672 if fstat.st_ino not in seen:
1673 seen.add(fstat.st_ino)
1674 total_size += fstat.st_size
Andrew Geissler5199d832021-09-24 16:47:35 -05001675
1676 if fpath in pkgdebugsource:
1677 extended_data["files_info"][fpath]['debugsrc'] = pkgdebugsource[fpath]
1678 del pkgdebugsource[fpath]
1679
Andrew Geisslerd159c7f2021-09-02 21:05:58 -05001680 d.setVar('FILES_INFO:' + pkg , json.dumps(files, sort_keys=True))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001681
Brad Bishop316dfdd2018-06-25 12:45:53 -04001682 process_postinst_on_target(pkg, d.getVar("MLPREFIX"))
1683 add_set_e_to_scriptlets(pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001684
Brad Bishop15ae2502019-06-18 21:44:24 -04001685 subdata_file = pkgdatadir + "/runtime/%s" % pkg
1686 with open(subdata_file, 'w') as sf:
1687 for var in (d.getVar('PKGDATA_VARS') or "").split():
1688 val = write_if_exists(sf, pkg, var)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001689
Brad Bishop15ae2502019-06-18 21:44:24 -04001690 write_if_exists(sf, pkg, 'FILERPROVIDESFLIST')
Andrew Geissler5199d832021-09-24 16:47:35 -05001691 for dfile in sorted((d.getVar('FILERPROVIDESFLIST:' + pkg) or "").split()):
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001692 write_if_exists(sf, pkg, 'FILERPROVIDES:' + dfile)
Brad Bishop15ae2502019-06-18 21:44:24 -04001693
1694 write_if_exists(sf, pkg, 'FILERDEPENDSFLIST')
Andrew Geissler5199d832021-09-24 16:47:35 -05001695 for dfile in sorted((d.getVar('FILERDEPENDSFLIST:' + pkg) or "").split()):
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001696 write_if_exists(sf, pkg, 'FILERDEPENDS:' + dfile)
Brad Bishop15ae2502019-06-18 21:44:24 -04001697
Andrew Geisslerd159c7f2021-09-02 21:05:58 -05001698 sf.write('%s:%s: %d\n' % ('PKGSIZE', pkg, total_size))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001699
Andrew Geissler5199d832021-09-24 16:47:35 -05001700 subdata_extended_file = pkgdatadir + "/extended/%s.json.zstd" % pkg
1701 num_threads = int(d.getVar("BB_NUMBER_THREADS"))
1702 with bb.compress.zstd.open(subdata_extended_file, "wt", encoding="utf-8", num_threads=num_threads) as f:
1703 json.dump(extended_data, f, sort_keys=True, separators=(",", ":"))
1704
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001705 # Symlinks needed for rprovides lookup
Patrick Williams213cb262021-08-07 19:21:33 -05001706 rprov = d.getVar('RPROVIDES:%s' % pkg) or d.getVar('RPROVIDES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001707 if rprov:
Andrew Geisslerc9f78652020-09-18 14:11:35 -05001708 for p in bb.utils.explode_deps(rprov):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001709 subdata_sym = pkgdatadir + "/runtime-rprovides/%s/%s" % (p, pkg)
1710 bb.utils.mkdirhier(os.path.dirname(subdata_sym))
1711 oe.path.symlink("../../runtime/%s" % pkg, subdata_sym, True)
1712
Patrick Williams213cb262021-08-07 19:21:33 -05001713 allow_empty = d.getVar('ALLOW_EMPTY:%s' % pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001714 if not allow_empty:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001715 allow_empty = d.getVar('ALLOW_EMPTY')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001716 root = "%s/%s" % (pkgdest, pkg)
1717 os.chdir(root)
1718 g = glob('*')
1719 if g or allow_empty == "1":
1720 # Symlinks needed for reverse lookups (from the final package name)
1721 subdata_sym = pkgdatadir + "/runtime-reverse/%s" % pkgval
1722 oe.path.symlink("../runtime/%s" % pkg, subdata_sym, True)
1723
1724 packagedfile = pkgdatadir + '/runtime/%s.packaged' % pkg
1725 open(packagedfile, 'w').close()
1726
1727 if bb.data.inherits_class('kernel', d) or bb.data.inherits_class('module-base', d):
1728 write_extra_runtime_pkgs(variants, packages, pkgdatadir)
1729
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001730 if bb.data.inherits_class('allarch', d) and not variants \
1731 and not bb.data.inherits_class('packagegroup', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001732 write_extra_runtime_pkgs(global_variants, packages, pkgdatadir)
1733
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001734}
Andrew Geissler5199d832021-09-24 16:47:35 -05001735emit_pkgdata[dirs] = "${PKGDESTWORK}/runtime ${PKGDESTWORK}/runtime-reverse ${PKGDESTWORK}/runtime-rprovides ${PKGDESTWORK}/extended"
1736emit_pkgdata[vardepsexclude] = "BB_NUMBER_THREADS"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001737
1738ldconfig_postinst_fragment() {
1739if [ x"$D" = "x" ]; then
1740 if [ -x /sbin/ldconfig ]; then /sbin/ldconfig ; fi
1741fi
1742}
1743
Andrew Geissler90fd73c2021-03-05 15:25:55 -06001744RPMDEPS = "${STAGING_LIBDIR_NATIVE}/rpm/rpmdeps --alldeps --define '__font_provides %{nil}'"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001745
1746# Collect perfile run-time dependency metadata
1747# Output:
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001748# FILERPROVIDESFLIST:pkg - list of all files w/ deps
1749# FILERPROVIDES:filepath:pkg - per file dep
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001750#
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001751# FILERDEPENDSFLIST:pkg - list of all files w/ deps
1752# FILERDEPENDS:filepath:pkg - per file dep
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001753
1754python package_do_filedeps() {
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001755 if d.getVar('SKIP_FILEDEPS') == '1':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001756 return
1757
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001758 pkgdest = d.getVar('PKGDEST')
1759 packages = d.getVar('PACKAGES')
1760 rpmdeps = d.getVar('RPMDEPS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001761
1762 def chunks(files, n):
1763 return [files[i:i+n] for i in range(0, len(files), n)]
1764
1765 pkglist = []
1766 for pkg in packages.split():
Patrick Williams213cb262021-08-07 19:21:33 -05001767 if d.getVar('SKIP_FILEDEPS:' + pkg) == '1':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001768 continue
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001769 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 -05001770 continue
1771 for files in chunks(pkgfiles[pkg], 100):
1772 pkglist.append((pkg, files, rpmdeps, pkgdest))
1773
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001774 processed = oe.utils.multiprocess_launch(oe.package.filedeprunner, pkglist, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001775
1776 provides_files = {}
1777 requires_files = {}
1778
1779 for result in processed:
1780 (pkg, provides, requires) = result
1781
1782 if pkg not in provides_files:
1783 provides_files[pkg] = []
1784 if pkg not in requires_files:
1785 requires_files[pkg] = []
1786
Brad Bishop19323692019-04-05 15:28:33 -04001787 for file in sorted(provides):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001788 provides_files[pkg].append(file)
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001789 key = "FILERPROVIDES:" + file + ":" + pkg
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001790 d.appendVar(key, " " + " ".join(provides[file]))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001791
Brad Bishop19323692019-04-05 15:28:33 -04001792 for file in sorted(requires):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001793 requires_files[pkg].append(file)
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001794 key = "FILERDEPENDS:" + file + ":" + pkg
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001795 d.appendVar(key, " " + " ".join(requires[file]))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001796
1797 for pkg in requires_files:
Andrew Geissler5199d832021-09-24 16:47:35 -05001798 d.setVar("FILERDEPENDSFLIST:" + pkg, " ".join(sorted(requires_files[pkg])))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001799 for pkg in provides_files:
Andrew Geissler5199d832021-09-24 16:47:35 -05001800 d.setVar("FILERPROVIDESFLIST:" + pkg, " ".join(sorted(provides_files[pkg])))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001801}
1802
Brad Bishop96ff1982019-08-19 13:50:42 -04001803SHLIBSDIRS = "${WORKDIR_PKGDATA}/${MLPREFIX}shlibs2"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001804SHLIBSWORKDIR = "${PKGDESTWORK}/${MLPREFIX}shlibs2"
1805
1806python package_do_shlibs() {
Brad Bishop00e122a2019-10-05 11:10:57 -04001807 import itertools
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001808 import re, pipes
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001809 import subprocess
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001810
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001811 exclude_shlibs = d.getVar('EXCLUDE_FROM_SHLIBS', False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001812 if exclude_shlibs:
1813 bb.note("not generating shlibs")
1814 return
1815
Brad Bishop19323692019-04-05 15:28:33 -04001816 lib_re = re.compile(r"^.*\.so")
1817 libdir_re = re.compile(r".*/%s$" % d.getVar('baselib'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001818
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001819 packages = d.getVar('PACKAGES')
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001820
1821 shlib_pkgs = []
1822 exclusion_list = d.getVar("EXCLUDE_PACKAGES_FROM_SHLIBS")
1823 if exclusion_list:
1824 for pkg in packages.split():
1825 if pkg not in exclusion_list.split():
1826 shlib_pkgs.append(pkg)
1827 else:
1828 bb.note("not generating shlibs for %s" % pkg)
1829 else:
1830 shlib_pkgs = packages.split()
1831
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001832 hostos = d.getVar('HOST_OS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001833
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001834 workdir = d.getVar('WORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001835
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001836 ver = d.getVar('PKGV')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001837 if not ver:
1838 msg = "PKGV not defined"
Andrew Geisslereff27472021-10-29 15:35:00 -05001839 oe.qa.handle_error("pkgv-undefined", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001840 return
1841
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001842 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001843
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001844 shlibswork_dir = d.getVar('SHLIBSWORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001845
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001846 def linux_so(file, pkg, pkgver, d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001847 needs_ldconfig = False
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001848 needed = set()
1849 sonames = set()
1850 renames = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001851 ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '')
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001852 cmd = d.getVar('OBJDUMP') + " -p " + pipes.quote(file) + " 2>/dev/null"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001853 fd = os.popen(cmd)
1854 lines = fd.readlines()
1855 fd.close()
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001856 rpath = tuple()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001857 for l in lines:
Brad Bishop19323692019-04-05 15:28:33 -04001858 m = re.match(r"\s+RPATH\s+([^\s]*)", l)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001859 if m:
1860 rpaths = m.group(1).replace("$ORIGIN", ldir).split(":")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001861 rpath = tuple(map(os.path.normpath, rpaths))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001862 for l in lines:
Brad Bishop19323692019-04-05 15:28:33 -04001863 m = re.match(r"\s+NEEDED\s+([^\s]*)", l)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001864 if m:
1865 dep = m.group(1)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001866 if dep not in needed:
1867 needed.add((dep, file, rpath))
Brad Bishop19323692019-04-05 15:28:33 -04001868 m = re.match(r"\s+SONAME\s+([^\s]*)", l)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001869 if m:
1870 this_soname = m.group(1)
1871 prov = (this_soname, ldir, pkgver)
1872 if not prov in sonames:
1873 # if library is private (only used by package) then do not build shlib for it
Brad Bishop79641f22019-09-10 07:20:22 -04001874 import fnmatch
1875 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 -08001876 sonames.add(prov)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001877 if libdir_re.match(os.path.dirname(file)):
1878 needs_ldconfig = True
1879 if snap_symlinks and (os.path.basename(file) != this_soname):
1880 renames.append((file, os.path.join(os.path.dirname(file), this_soname)))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001881 return (needs_ldconfig, needed, sonames, renames)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001882
1883 def darwin_so(file, needed, sonames, renames, pkgver):
1884 if not os.path.exists(file):
1885 return
1886 ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '')
1887
1888 def get_combinations(base):
1889 #
1890 # Given a base library name, find all combinations of this split by "." and "-"
1891 #
1892 combos = []
1893 options = base.split(".")
1894 for i in range(1, len(options) + 1):
1895 combos.append(".".join(options[0:i]))
1896 options = base.split("-")
1897 for i in range(1, len(options) + 1):
1898 combos.append("-".join(options[0:i]))
1899 return combos
1900
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001901 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 -05001902 # Drop suffix
1903 name = os.path.basename(file).rsplit(".",1)[0]
1904 # Find all combinations
1905 combos = get_combinations(name)
1906 for combo in combos:
1907 if not combo in sonames:
1908 prov = (combo, ldir, pkgver)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001909 sonames.add(prov)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001910 if file.endswith('.dylib') or file.endswith('.so'):
1911 rpath = []
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001912 p = subprocess.Popen([d.expand("${HOST_PREFIX}otool"), '-l', file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001913 out, err = p.communicate()
1914 # If returned successfully, process stdout for results
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001915 if p.returncode == 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001916 for l in out.split("\n"):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001917 l = l.strip()
1918 if l.startswith('path '):
1919 rpath.append(l.split()[1])
1920
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001921 p = subprocess.Popen([d.expand("${HOST_PREFIX}otool"), '-L', file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001922 out, err = p.communicate()
1923 # If returned successfully, process stdout for results
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001924 if p.returncode == 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001925 for l in out.split("\n"):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001926 l = l.strip()
1927 if not l or l.endswith(":"):
1928 continue
1929 if "is not an object file" in l:
1930 continue
1931 name = os.path.basename(l.split()[0]).rsplit(".", 1)[0]
1932 if name and name not in needed[pkg]:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001933 needed[pkg].add((name, file, tuple()))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001934
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001935 def mingw_dll(file, needed, sonames, renames, pkgver):
1936 if not os.path.exists(file):
1937 return
1938
1939 if file.endswith(".dll"):
1940 # assume all dlls are shared objects provided by the package
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001941 sonames.add((os.path.basename(file), os.path.dirname(file).replace(pkgdest + "/" + pkg, ''), pkgver))
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001942
1943 if (file.endswith(".dll") or file.endswith(".exe")):
1944 # use objdump to search for "DLL Name: .*\.dll"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001945 p = subprocess.Popen([d.expand("${HOST_PREFIX}objdump"), "-p", file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001946 out, err = p.communicate()
1947 # process the output, grabbing all .dll names
1948 if p.returncode == 0:
Brad Bishop19323692019-04-05 15:28:33 -04001949 for m in re.finditer(r"DLL Name: (.*?\.dll)$", out.decode(), re.MULTILINE | re.IGNORECASE):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001950 dllname = m.group(1)
1951 if dllname:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001952 needed[pkg].add((dllname, file, tuple()))
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001953
1954 if d.getVar('PACKAGE_SNAP_LIB_SYMLINKS') == "1":
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001955 snap_symlinks = True
1956 else:
1957 snap_symlinks = False
1958
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001959 needed = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001960
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001961 shlib_provider = oe.package.read_shlib_providers(d)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001962
1963 for pkg in shlib_pkgs:
Patrick Williams213cb262021-08-07 19:21:33 -05001964 private_libs = d.getVar('PRIVATE_LIBS:' + pkg) or d.getVar('PRIVATE_LIBS') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001965 private_libs = private_libs.split()
1966 needs_ldconfig = False
1967 bb.debug(2, "calculating shlib provides for %s" % pkg)
1968
Patrick Williams213cb262021-08-07 19:21:33 -05001969 pkgver = d.getVar('PKGV:' + pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001970 if not pkgver:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001971 pkgver = d.getVar('PV_' + pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001972 if not pkgver:
1973 pkgver = ver
1974
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001975 needed[pkg] = set()
1976 sonames = set()
1977 renames = []
1978 linuxlist = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001979 for file in pkgfiles[pkg]:
1980 soname = None
1981 if cpath.islink(file):
1982 continue
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001983 if hostos == "darwin" or hostos == "darwin8":
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001984 darwin_so(file, needed, sonames, renames, pkgver)
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001985 elif hostos.startswith("mingw"):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001986 mingw_dll(file, needed, sonames, renames, pkgver)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001987 elif os.access(file, os.X_OK) or lib_re.match(file):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001988 linuxlist.append(file)
1989
1990 if linuxlist:
1991 results = oe.utils.multiprocess_launch(linux_so, linuxlist, d, extraargs=(pkg, pkgver, d))
1992 for r in results:
1993 ldconfig = r[0]
1994 needed[pkg] |= r[1]
1995 sonames |= r[2]
1996 renames.extend(r[3])
1997 needs_ldconfig = needs_ldconfig or ldconfig
1998
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001999 for (old, new) in renames:
2000 bb.note("Renaming %s to %s" % (old, new))
Andrew Geisslerc926e172021-05-07 16:11:35 -05002001 bb.utils.rename(old, new)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002002 pkgfiles[pkg].remove(old)
Brad Bishop64c979e2019-11-04 13:55:29 -05002003
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002004 shlibs_file = os.path.join(shlibswork_dir, pkg + ".list")
2005 if len(sonames):
Brad Bishop64c979e2019-11-04 13:55:29 -05002006 with open(shlibs_file, 'w') as fd:
Andrew Geissler635e0e42020-08-21 15:58:33 -05002007 for s in sorted(sonames):
Brad Bishop64c979e2019-11-04 13:55:29 -05002008 if s[0] in shlib_provider and s[1] in shlib_provider[s[0]]:
2009 (old_pkg, old_pkgver) = shlib_provider[s[0]][s[1]]
2010 if old_pkg != pkg:
2011 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))
2012 bb.debug(1, 'registering %s-%s as shlib provider for %s' % (pkg, pkgver, s[0]))
2013 fd.write(s[0] + ':' + s[1] + ':' + s[2] + '\n')
2014 if s[0] not in shlib_provider:
2015 shlib_provider[s[0]] = {}
2016 shlib_provider[s[0]][s[1]] = (pkg, pkgver)
Brad Bishop1d80a2e2019-11-15 16:35:03 -05002017 if needs_ldconfig:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002018 bb.debug(1, 'adding ldconfig call to postinst for %s' % pkg)
Patrick Williams213cb262021-08-07 19:21:33 -05002019 postinst = d.getVar('pkg_postinst:%s' % pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002020 if not postinst:
2021 postinst = '#!/bin/sh\n'
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002022 postinst += d.getVar('ldconfig_postinst_fragment')
Patrick Williams213cb262021-08-07 19:21:33 -05002023 d.setVar('pkg_postinst:%s' % pkg, postinst)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002024 bb.debug(1, 'LIBNAMES: pkg %s sonames %s' % (pkg, sonames))
2025
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002026 assumed_libs = d.getVar('ASSUME_SHLIBS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002027 if assumed_libs:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002028 libdir = d.getVar("libdir")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002029 for e in assumed_libs.split():
2030 l, dep_pkg = e.split(":")
2031 lib_ver = None
2032 dep_pkg = dep_pkg.rsplit("_", 1)
2033 if len(dep_pkg) == 2:
2034 lib_ver = dep_pkg[1]
2035 dep_pkg = dep_pkg[0]
2036 if l not in shlib_provider:
2037 shlib_provider[l] = {}
2038 shlib_provider[l][libdir] = (dep_pkg, lib_ver)
2039
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002040 libsearchpath = [d.getVar('libdir'), d.getVar('base_libdir')]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002041
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08002042 for pkg in shlib_pkgs:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002043 bb.debug(2, "calculating shlib requirements for %s" % pkg)
2044
Patrick Williams213cb262021-08-07 19:21:33 -05002045 private_libs = d.getVar('PRIVATE_LIBS:' + pkg) or d.getVar('PRIVATE_LIBS') or ""
Brad Bishop316dfdd2018-06-25 12:45:53 -04002046 private_libs = private_libs.split()
2047
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002048 deps = list()
2049 for n in needed[pkg]:
2050 # if n is in private libraries, don't try to search provider for it
2051 # this could cause problem in case some abc.bb provides private
2052 # /opt/abc/lib/libfoo.so.1 and contains /usr/bin/abc depending on system library libfoo.so.1
2053 # but skipping it is still better alternative than providing own
2054 # version and then adding runtime dependency for the same system library
Brad Bishop79641f22019-09-10 07:20:22 -04002055 import fnmatch
2056 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 -05002057 bb.debug(2, '%s: Dependency %s covered by PRIVATE_LIBS' % (pkg, n[0]))
2058 continue
2059 if n[0] in shlib_provider.keys():
Brad Bishop00e122a2019-10-05 11:10:57 -04002060 shlib_provider_map = shlib_provider[n[0]]
2061 matches = set()
2062 for p in itertools.chain(list(n[2]), sorted(shlib_provider_map.keys()), libsearchpath):
2063 if p in shlib_provider_map:
2064 matches.add(p)
2065 if len(matches) > 1:
2066 matchpkgs = ', '.join([shlib_provider_map[match][0] for match in matches])
2067 bb.error("%s: Multiple shlib providers for %s: %s (used by files: %s)" % (pkg, n[0], matchpkgs, n[1]))
2068 elif len(matches) == 1:
2069 (dep_pkg, ver_needed) = shlib_provider_map[matches.pop()]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002070
2071 bb.debug(2, '%s: Dependency %s requires package %s (used by files: %s)' % (pkg, n[0], dep_pkg, n[1]))
2072
2073 if dep_pkg == pkg:
2074 continue
2075
2076 if ver_needed:
2077 dep = "%s (>= %s)" % (dep_pkg, ver_needed)
2078 else:
2079 dep = dep_pkg
2080 if not dep in deps:
2081 deps.append(dep)
2082 continue
2083 bb.note("Couldn't find shared library provider for %s, used by files: %s" % (n[0], n[1]))
2084
2085 deps_file = os.path.join(pkgdest, pkg + ".shlibdeps")
2086 if os.path.exists(deps_file):
2087 os.remove(deps_file)
Brad Bishop64c979e2019-11-04 13:55:29 -05002088 if deps:
2089 with open(deps_file, 'w') as fd:
2090 for dep in sorted(deps):
2091 fd.write(dep + '\n')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002092}
2093
2094python package_do_pkgconfig () {
2095 import re
2096
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002097 packages = d.getVar('PACKAGES')
2098 workdir = d.getVar('WORKDIR')
2099 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002100
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002101 shlibs_dirs = d.getVar('SHLIBSDIRS').split()
2102 shlibswork_dir = d.getVar('SHLIBSWORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002103
Brad Bishop19323692019-04-05 15:28:33 -04002104 pc_re = re.compile(r'(.*)\.pc$')
2105 var_re = re.compile(r'(.*)=(.*)')
2106 field_re = re.compile(r'(.*): (.*)')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002107
2108 pkgconfig_provided = {}
2109 pkgconfig_needed = {}
2110 for pkg in packages.split():
2111 pkgconfig_provided[pkg] = []
2112 pkgconfig_needed[pkg] = []
Patrick Williams93c203f2021-10-06 16:15:23 -05002113 for file in sorted(pkgfiles[pkg]):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002114 m = pc_re.match(file)
2115 if m:
2116 pd = bb.data.init()
2117 name = m.group(1)
Patrick Williams93c203f2021-10-06 16:15:23 -05002118 pkgconfig_provided[pkg].append(os.path.basename(name))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002119 if not os.access(file, os.R_OK):
2120 continue
Brad Bishop64c979e2019-11-04 13:55:29 -05002121 with open(file, 'r') as f:
2122 lines = f.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002123 for l in lines:
2124 m = var_re.match(l)
2125 if m:
2126 name = m.group(1)
2127 val = m.group(2)
2128 pd.setVar(name, pd.expand(val))
2129 continue
2130 m = field_re.match(l)
2131 if m:
2132 hdr = m.group(1)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002133 exp = pd.expand(m.group(2))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002134 if hdr == 'Requires':
2135 pkgconfig_needed[pkg] += exp.replace(',', ' ').split()
2136
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002137 for pkg in packages.split():
2138 pkgs_file = os.path.join(shlibswork_dir, pkg + ".pclist")
2139 if pkgconfig_provided[pkg] != []:
Brad Bishop64c979e2019-11-04 13:55:29 -05002140 with open(pkgs_file, 'w') as f:
Patrick Williams93c203f2021-10-06 16:15:23 -05002141 for p in sorted(pkgconfig_provided[pkg]):
Brad Bishop64c979e2019-11-04 13:55:29 -05002142 f.write('%s\n' % p)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002143
2144 # Go from least to most specific since the last one found wins
2145 for dir in reversed(shlibs_dirs):
2146 if not os.path.exists(dir):
2147 continue
Brad Bishop08902b02019-08-20 09:16:51 -04002148 for file in sorted(os.listdir(dir)):
Brad Bishop19323692019-04-05 15:28:33 -04002149 m = re.match(r'^(.*)\.pclist$', file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002150 if m:
2151 pkg = m.group(1)
Brad Bishop64c979e2019-11-04 13:55:29 -05002152 with open(os.path.join(dir, file)) as fd:
2153 lines = fd.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002154 pkgconfig_provided[pkg] = []
2155 for l in lines:
2156 pkgconfig_provided[pkg].append(l.rstrip())
2157
2158 for pkg in packages.split():
2159 deps = []
2160 for n in pkgconfig_needed[pkg]:
2161 found = False
2162 for k in pkgconfig_provided.keys():
2163 if n in pkgconfig_provided[k]:
2164 if k != pkg and not (k in deps):
2165 deps.append(k)
2166 found = True
2167 if found == False:
2168 bb.note("couldn't find pkgconfig module '%s' in any package" % n)
2169 deps_file = os.path.join(pkgdest, pkg + ".pcdeps")
2170 if len(deps):
Brad Bishop64c979e2019-11-04 13:55:29 -05002171 with open(deps_file, 'w') as fd:
2172 for dep in deps:
2173 fd.write(dep + '\n')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002174}
2175
2176def read_libdep_files(d):
2177 pkglibdeps = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002178 packages = d.getVar('PACKAGES').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002179 for pkg in packages:
2180 pkglibdeps[pkg] = {}
2181 for extension in ".shlibdeps", ".pcdeps", ".clilibdeps":
2182 depsfile = d.expand("${PKGDEST}/" + pkg + extension)
2183 if os.access(depsfile, os.R_OK):
Brad Bishop64c979e2019-11-04 13:55:29 -05002184 with open(depsfile) as fd:
2185 lines = fd.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002186 for l in lines:
2187 l.rstrip()
2188 deps = bb.utils.explode_dep_versions2(l)
2189 for dep in deps:
2190 if not dep in pkglibdeps[pkg]:
2191 pkglibdeps[pkg][dep] = deps[dep]
2192 return pkglibdeps
2193
2194python read_shlibdeps () {
2195 pkglibdeps = read_libdep_files(d)
2196
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002197 packages = d.getVar('PACKAGES').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002198 for pkg in packages:
Patrick Williams213cb262021-08-07 19:21:33 -05002199 rdepends = bb.utils.explode_dep_versions2(d.getVar('RDEPENDS:' + pkg) or "")
Brad Bishop19323692019-04-05 15:28:33 -04002200 for dep in sorted(pkglibdeps[pkg]):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002201 # Add the dep if it's not already there, or if no comparison is set
2202 if dep not in rdepends:
2203 rdepends[dep] = []
2204 for v in pkglibdeps[pkg][dep]:
2205 if v not in rdepends[dep]:
2206 rdepends[dep].append(v)
Patrick Williams213cb262021-08-07 19:21:33 -05002207 d.setVar('RDEPENDS:' + pkg, bb.utils.join_deps(rdepends, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002208}
2209
2210python package_depchains() {
2211 """
2212 For a given set of prefix and postfix modifiers, make those packages
2213 RRECOMMENDS on the corresponding packages for its RDEPENDS.
2214
2215 Example: If package A depends upon package B, and A's .bb emits an
2216 A-dev package, this would make A-dev Recommends: B-dev.
2217
2218 If only one of a given suffix is specified, it will take the RRECOMMENDS
2219 based on the RDEPENDS of *all* other packages. If more than one of a given
2220 suffix is specified, its will only use the RDEPENDS of the single parent
2221 package.
2222 """
2223
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002224 packages = d.getVar('PACKAGES')
2225 postfixes = (d.getVar('DEPCHAIN_POST') or '').split()
2226 prefixes = (d.getVar('DEPCHAIN_PRE') or '').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002227
2228 def pkg_adddeprrecs(pkg, base, suffix, getname, depends, d):
2229
2230 #bb.note('depends for %s is %s' % (base, depends))
Patrick Williams213cb262021-08-07 19:21:33 -05002231 rreclist = bb.utils.explode_dep_versions2(d.getVar('RRECOMMENDS:' + pkg) or "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002232
Brad Bishop19323692019-04-05 15:28:33 -04002233 for depend in sorted(depends):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002234 if depend.find('-native') != -1 or depend.find('-cross') != -1 or depend.startswith('virtual/'):
2235 #bb.note("Skipping %s" % depend)
2236 continue
2237 if depend.endswith('-dev'):
2238 depend = depend[:-4]
2239 if depend.endswith('-dbg'):
2240 depend = depend[:-4]
2241 pkgname = getname(depend, suffix)
2242 #bb.note("Adding %s for %s" % (pkgname, depend))
2243 if pkgname not in rreclist and pkgname != pkg:
2244 rreclist[pkgname] = []
2245
Patrick Williams213cb262021-08-07 19:21:33 -05002246 #bb.note('setting: RRECOMMENDS:%s=%s' % (pkg, ' '.join(rreclist)))
2247 d.setVar('RRECOMMENDS:%s' % pkg, bb.utils.join_deps(rreclist, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002248
2249 def pkg_addrrecs(pkg, base, suffix, getname, rdepends, d):
2250
2251 #bb.note('rdepends for %s is %s' % (base, rdepends))
Patrick Williams213cb262021-08-07 19:21:33 -05002252 rreclist = bb.utils.explode_dep_versions2(d.getVar('RRECOMMENDS:' + pkg) or "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002253
Brad Bishop19323692019-04-05 15:28:33 -04002254 for depend in sorted(rdepends):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002255 if depend.find('virtual-locale-') != -1:
2256 #bb.note("Skipping %s" % depend)
2257 continue
2258 if depend.endswith('-dev'):
2259 depend = depend[:-4]
2260 if depend.endswith('-dbg'):
2261 depend = depend[:-4]
2262 pkgname = getname(depend, suffix)
2263 #bb.note("Adding %s for %s" % (pkgname, depend))
2264 if pkgname not in rreclist and pkgname != pkg:
2265 rreclist[pkgname] = []
2266
Patrick Williams213cb262021-08-07 19:21:33 -05002267 #bb.note('setting: RRECOMMENDS:%s=%s' % (pkg, ' '.join(rreclist)))
2268 d.setVar('RRECOMMENDS:%s' % pkg, bb.utils.join_deps(rreclist, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002269
2270 def add_dep(list, dep):
2271 if dep not in list:
2272 list.append(dep)
2273
2274 depends = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002275 for dep in bb.utils.explode_deps(d.getVar('DEPENDS') or ""):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002276 add_dep(depends, dep)
2277
2278 rdepends = []
2279 for pkg in packages.split():
Patrick Williams213cb262021-08-07 19:21:33 -05002280 for dep in bb.utils.explode_deps(d.getVar('RDEPENDS:' + pkg) or ""):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002281 add_dep(rdepends, dep)
2282
2283 #bb.note('rdepends is %s' % rdepends)
2284
2285 def post_getname(name, suffix):
2286 return '%s%s' % (name, suffix)
2287 def pre_getname(name, suffix):
2288 return '%s%s' % (suffix, name)
2289
2290 pkgs = {}
2291 for pkg in packages.split():
2292 for postfix in postfixes:
2293 if pkg.endswith(postfix):
2294 if not postfix in pkgs:
2295 pkgs[postfix] = {}
2296 pkgs[postfix][pkg] = (pkg[:-len(postfix)], post_getname)
2297
2298 for prefix in prefixes:
2299 if pkg.startswith(prefix):
2300 if not prefix in pkgs:
2301 pkgs[prefix] = {}
2302 pkgs[prefix][pkg] = (pkg[:-len(prefix)], pre_getname)
2303
2304 if "-dbg" in pkgs:
2305 pkglibdeps = read_libdep_files(d)
2306 pkglibdeplist = []
2307 for pkg in pkglibdeps:
2308 for k in pkglibdeps[pkg]:
2309 add_dep(pkglibdeplist, k)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002310 dbgdefaultdeps = ((d.getVar('DEPCHAIN_DBGDEFAULTDEPS') == '1') or (bb.data.inherits_class('packagegroup', d)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002311
2312 for suffix in pkgs:
2313 for pkg in pkgs[suffix]:
Patrick Williams213cb262021-08-07 19:21:33 -05002314 if d.getVarFlag('RRECOMMENDS:' + pkg, 'nodeprrecs'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002315 continue
2316 (base, func) = pkgs[suffix][pkg]
2317 if suffix == "-dev":
2318 pkg_adddeprrecs(pkg, base, suffix, func, depends, d)
2319 elif suffix == "-dbg":
2320 if not dbgdefaultdeps:
2321 pkg_addrrecs(pkg, base, suffix, func, pkglibdeplist, d)
2322 continue
2323 if len(pkgs[suffix]) == 1:
2324 pkg_addrrecs(pkg, base, suffix, func, rdepends, d)
2325 else:
2326 rdeps = []
Patrick Williams213cb262021-08-07 19:21:33 -05002327 for dep in bb.utils.explode_deps(d.getVar('RDEPENDS:' + base) or ""):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002328 add_dep(rdeps, dep)
2329 pkg_addrrecs(pkg, base, suffix, func, rdeps, d)
2330}
2331
2332# Since bitbake can't determine which variables are accessed during package
2333# iteration, we need to list them here:
Andrew Geissler1e34c2d2020-05-29 16:02:59 -05002334PACKAGEVARS = "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 -05002335
Andrew Geissler82c905d2020-04-13 13:39:40 -05002336def gen_packagevar(d, pkgvars="PACKAGEVARS"):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002337 ret = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002338 pkgs = (d.getVar("PACKAGES") or "").split()
Andrew Geissler82c905d2020-04-13 13:39:40 -05002339 vars = (d.getVar(pkgvars) or "").split()
2340 for v in vars:
2341 ret.append(v)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002342 for p in pkgs:
2343 for v in vars:
Patrick Williams213cb262021-08-07 19:21:33 -05002344 ret.append(v + ":" + p)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002345
2346 # Ensure that changes to INCOMPATIBLE_LICENSE re-run do_package for
2347 # affected recipes.
2348 ret.append('LICENSE_EXCLUSION-%s' % p)
2349 return " ".join(ret)
2350
2351PACKAGE_PREPROCESS_FUNCS ?= ""
2352# Functions for setting up PKGD
2353PACKAGEBUILDPKGD ?= " \
Brad Bishop96ff1982019-08-19 13:50:42 -04002354 package_prepare_pkgdata \
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002355 perform_packagecopy \
2356 ${PACKAGE_PREPROCESS_FUNCS} \
2357 split_and_strip_files \
2358 fixup_perms \
2359 "
2360# Functions which split PKGD up into separate packages
2361PACKAGESPLITFUNCS ?= " \
2362 package_do_split_locales \
2363 populate_packages"
2364# Functions which process metadata based on split packages
2365PACKAGEFUNCS += " \
2366 package_fixsymlinks \
2367 package_name_hook \
2368 package_do_filedeps \
2369 package_do_shlibs \
2370 package_do_pkgconfig \
2371 read_shlibdeps \
2372 package_depchains \
2373 emit_pkgdata"
2374
2375python do_package () {
2376 # Change the following version to cause sstate to invalidate the package
2377 # cache. This is useful if an item this class depends on changes in a
2378 # way that the output of this class changes. rpmdeps is a good example
2379 # as any change to rpmdeps requires this to be rerun.
Andrew Geissler6ce62a22020-11-30 19:58:47 -06002380 # PACKAGE_BBCLASS_VERSION = "4"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002381
2382 # Init cachedpath
2383 global cpath
2384 cpath = oe.cachedpath.CachedPath()
2385
2386 ###########################################################################
2387 # Sanity test the setup
2388 ###########################################################################
2389
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002390 packages = (d.getVar('PACKAGES') or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002391 if len(packages) < 1:
2392 bb.debug(1, "No packages to build, skipping do_package")
2393 return
2394
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002395 workdir = d.getVar('WORKDIR')
2396 outdir = d.getVar('DEPLOY_DIR')
2397 dest = d.getVar('D')
2398 dvar = d.getVar('PKGD')
2399 pn = d.getVar('PN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002400
2401 if not workdir or not outdir or not dest or not dvar or not pn:
2402 msg = "WORKDIR, DEPLOY_DIR, D, PN and PKGD all must be defined, unable to package"
Andrew Geisslereff27472021-10-29 15:35:00 -05002403 oe.qa.handle_error("var-undefined", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002404 return
2405
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002406 bb.build.exec_func("package_convert_pr_autoinc", d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002407
2408 ###########################################################################
2409 # Optimisations
2410 ###########################################################################
2411
2412 # Continually expanding complex expressions is inefficient, particularly
2413 # when we write to the datastore and invalidate the expansion cache. This
2414 # code pre-expands some frequently used variables
2415
2416 def expandVar(x, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002417 d.setVar(x, d.getVar(x))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002418
2419 for x in 'PN', 'PV', 'BPN', 'TARGET_SYS', 'EXTENDPRAUTO':
2420 expandVar(x, d)
2421
2422 ###########################################################################
2423 # Setup PKGD (from D)
2424 ###########################################################################
2425
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002426 for f in (d.getVar('PACKAGEBUILDPKGD') or '').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002427 bb.build.exec_func(f, d)
2428
2429 ###########################################################################
2430 # Split up PKGD into PKGDEST
2431 ###########################################################################
2432
2433 cpath = oe.cachedpath.CachedPath()
2434
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002435 for f in (d.getVar('PACKAGESPLITFUNCS') or '').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002436 bb.build.exec_func(f, d)
2437
2438 ###########################################################################
2439 # Process PKGDEST
2440 ###########################################################################
2441
2442 # Build global list of files in each split package
2443 global pkgfiles
2444 pkgfiles = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002445 packages = d.getVar('PACKAGES').split()
2446 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002447 for pkg in packages:
2448 pkgfiles[pkg] = []
2449 for walkroot, dirs, files in cpath.walk(pkgdest + "/" + pkg):
2450 for file in files:
2451 pkgfiles[pkg].append(walkroot + os.sep + file)
2452
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002453 for f in (d.getVar('PACKAGEFUNCS') or '').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002454 bb.build.exec_func(f, d)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05002455
Andrew Geisslereff27472021-10-29 15:35:00 -05002456 oe.qa.exit_if_errors(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002457}
2458
2459do_package[dirs] = "${SHLIBSWORKDIR} ${PKGDESTWORK} ${D}"
2460do_package[vardeps] += "${PACKAGEBUILDPKGD} ${PACKAGESPLITFUNCS} ${PACKAGEFUNCS} ${@gen_packagevar(d)}"
2461addtask package after do_install
2462
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002463SSTATETASKS += "do_package"
2464do_package[cleandirs] = "${PKGDEST} ${PKGDESTWORK}"
2465do_package[sstate-plaindirs] = "${PKGD} ${PKGDEST} ${PKGDESTWORK}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002466do_package_setscene[dirs] = "${STAGING_DIR}"
2467
2468python do_package_setscene () {
2469 sstate_setscene(d)
2470}
2471addtask do_package_setscene
2472
Brad Bishopc68388fc2019-08-26 01:33:31 -04002473# Copy from PKGDESTWORK to tempdirectory as tempdirectory can be cleaned at both
2474# do_package_setscene and do_packagedata_setscene leading to races
2475python do_packagedata () {
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002476 bb.build.exec_func("package_get_auto_pr", d)
2477
Brad Bishopc68388fc2019-08-26 01:33:31 -04002478 src = d.expand("${PKGDESTWORK}")
2479 dest = d.expand("${WORKDIR}/pkgdata-pdata-input")
2480 oe.path.copyhardlinktree(src, dest)
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002481
2482 bb.build.exec_func("packagedata_translate_pr_autoinc", d)
2483}
Andrew Geisslerd1e89492021-02-12 15:35:20 -06002484do_packagedata[cleandirs] += "${WORKDIR}/pkgdata-pdata-input"
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002485
2486# Translate the EXTENDPRAUTO and AUTOINC to the final values
2487packagedata_translate_pr_autoinc() {
2488 find ${WORKDIR}/pkgdata-pdata-input -type f | xargs --no-run-if-empty \
2489 sed -e 's,@PRSERV_PV_AUTOINC@,${PRSERV_PV_AUTOINC},g' \
2490 -e 's,@EXTENDPRAUTO@,${EXTENDPRAUTO},g' -i
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002491}
2492
2493addtask packagedata before do_build after do_package
2494
2495SSTATETASKS += "do_packagedata"
Brad Bishopc68388fc2019-08-26 01:33:31 -04002496do_packagedata[sstate-inputdirs] = "${WORKDIR}/pkgdata-pdata-input"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002497do_packagedata[sstate-outputdirs] = "${PKGDATA_DIR}"
Brad Bishop316dfdd2018-06-25 12:45:53 -04002498do_packagedata[stamp-extra-info] = "${MACHINE_ARCH}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002499
2500python do_packagedata_setscene () {
2501 sstate_setscene(d)
2502}
2503addtask do_packagedata_setscene
2504
2505#
2506# Helper functions for the package writing classes
2507#
2508
2509def mapping_rename_hook(d):
2510 """
2511 Rewrite variables to account for package renaming in things
2512 like debian.bbclass or manual PKG variable name changes
2513 """
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002514 pkg = d.getVar("PKG")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002515 runtime_mapping_rename("RDEPENDS", pkg, d)
2516 runtime_mapping_rename("RRECOMMENDS", pkg, d)
2517 runtime_mapping_rename("RSUGGESTS", pkg, d)