blob: 460997ad5439440a431daf3b5d3038d1a1ed6143 [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 -050044
45# Need the package_qa_handle_error() in insane.bbclass
46inherit insane
47
48PKGD = "${WORKDIR}/package"
49PKGDEST = "${WORKDIR}/packages-split"
50
51LOCALE_SECTION ?= ''
52
53ALL_MULTILIB_PACKAGE_ARCHS = "${@all_multilib_tune_values(d, 'PACKAGE_ARCHS')}"
54
55# rpm is used for the per-file dependency identification
Brad Bishop316dfdd2018-06-25 12:45:53 -040056# dwarfsrcfiles is used to determine the list of debug source files
57PACKAGE_DEPENDS += "rpm-native dwarfsrcfiles-native"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050058
Brad Bishop6e60e8b2018-02-01 10:27:11 -050059
60# If your postinstall can execute at rootfs creation time rather than on
61# target but depends on a native/cross tool in order to execute, you need to
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080062# list that tool in PACKAGE_WRITE_DEPS. Target package dependencies belong
Brad Bishop6e60e8b2018-02-01 10:27:11 -050063# in the package dependencies as normal, this is just for native/cross support
64# tools at rootfs build time.
65PACKAGE_WRITE_DEPS ??= ""
66
Patrick Williamsc124f4f2015-09-15 14:41:29 -050067def legitimize_package_name(s):
68 """
69 Make sure package names are legitimate strings
70 """
71 import re
72
73 def fixutf(m):
74 cp = m.group(1)
75 if cp:
Patrick Williamsc0f7c042017-02-23 20:41:17 -060076 return ('\\u%s' % cp).encode('latin-1').decode('unicode_escape')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050077
78 # Handle unicode codepoints encoded as <U0123>, as in glibc locale files.
Brad Bishop19323692019-04-05 15:28:33 -040079 s = re.sub(r'<U([0-9A-Fa-f]{1,4})>', fixutf, s)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050080
81 # Remaining package name validity fixes
82 return s.lower().replace('_', '-').replace('@', '+').replace(',', '+').replace('/', '-')
83
84def 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):
85 """
86 Used in .bb files to split up dynamically generated subpackages of a
87 given package, usually plugins or modules.
88
89 Arguments:
90 root -- the path in which to search
91 file_regex -- regular expression to match searched files. Use
92 parentheses () to mark the part of this expression
93 that should be used to derive the module name (to be
94 substituted where %s is used in other function
95 arguments as noted below)
96 output_pattern -- pattern to use for the package names. Must include %s.
97 description -- description to set for each package. Must include %s.
98 postinst -- postinstall script to use for all packages (as a
99 string)
100 recursive -- True to perform a recursive search - default False
101 hook -- a hook function to be called for every match. The
102 function will be called with the following arguments
103 (in the order listed):
104 f: full path to the file/directory match
105 pkg: the package name
106 file_regex: as above
107 output_pattern: as above
108 modulename: the module name derived using file_regex
109 extra_depends -- extra runtime dependencies (RDEPENDS) to be set for
110 all packages. The default value of None causes a
111 dependency on the main package (${PN}) - if you do
112 not want this, pass '' for this parameter.
113 aux_files_pattern -- extra item(s) to be added to FILES for each
114 package. Can be a single string item or a list of
115 strings for multiple items. Must include %s.
116 postrm -- postrm script to use for all packages (as a string)
117 allow_dirs -- True allow directories to be matched - default False
118 prepend -- if True, prepend created packages to PACKAGES instead
119 of the default False which appends them
120 match_path -- match file_regex on the whole relative path to the
121 root rather than just the file name
122 aux_files_pattern_verbatim -- extra item(s) to be added to FILES for
123 each package, using the actual derived module name
124 rather than converting it to something legal for a
125 package name. Can be a single string item or a list
126 of strings for multiple items. Must include %s.
127 allow_links -- True to allow symlinks to be matched - default False
128 summary -- Summary to set for each package. Must include %s;
129 defaults to description if not set.
130
131 """
132
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500133 dvar = d.getVar('PKGD')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500134 root = d.expand(root)
135 output_pattern = d.expand(output_pattern)
136 extra_depends = d.expand(extra_depends)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500137
138 # If the root directory doesn't exist, don't error out later but silently do
139 # no splitting.
140 if not os.path.exists(dvar + root):
141 return []
142
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500143 ml = d.getVar("MLPREFIX")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500144 if ml:
145 if not output_pattern.startswith(ml):
146 output_pattern = ml + output_pattern
147
148 newdeps = []
149 for dep in (extra_depends or "").split():
150 if dep.startswith(ml):
151 newdeps.append(dep)
152 else:
153 newdeps.append(ml + dep)
154 if newdeps:
155 extra_depends = " ".join(newdeps)
156
157
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500158 packages = d.getVar('PACKAGES').split()
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600159 split_packages = set()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500160
161 if postinst:
162 postinst = '#!/bin/sh\n' + postinst + '\n'
163 if postrm:
164 postrm = '#!/bin/sh\n' + postrm + '\n'
165 if not recursive:
166 objs = os.listdir(dvar + root)
167 else:
168 objs = []
169 for walkroot, dirs, files in os.walk(dvar + root):
170 for file in files:
171 relpath = os.path.join(walkroot, file).replace(dvar + root + '/', '', 1)
172 if relpath:
173 objs.append(relpath)
174
175 if extra_depends == None:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500176 extra_depends = d.getVar("PN")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500177
178 if not summary:
179 summary = description
180
181 for o in sorted(objs):
182 import re, stat
183 if match_path:
184 m = re.match(file_regex, o)
185 else:
186 m = re.match(file_regex, os.path.basename(o))
187
188 if not m:
189 continue
190 f = os.path.join(dvar + root, o)
191 mode = os.lstat(f).st_mode
192 if not (stat.S_ISREG(mode) or (allow_links and stat.S_ISLNK(mode)) or (allow_dirs and stat.S_ISDIR(mode))):
193 continue
194 on = legitimize_package_name(m.group(1))
195 pkg = output_pattern % on
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600196 split_packages.add(pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500197 if not pkg in packages:
198 if prepend:
199 packages = [pkg] + packages
200 else:
201 packages.append(pkg)
Patrick Williams213cb262021-08-07 19:21:33 -0500202 oldfiles = d.getVar('FILES:' + pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500203 newfile = os.path.join(root, o)
204 # These names will be passed through glob() so if the filename actually
205 # contains * or ? (rare, but possible) we need to handle that specially
206 newfile = newfile.replace('*', '[*]')
207 newfile = newfile.replace('?', '[?]')
208 if not oldfiles:
209 the_files = [newfile]
210 if aux_files_pattern:
211 if type(aux_files_pattern) is list:
212 for fp in aux_files_pattern:
213 the_files.append(fp % on)
214 else:
215 the_files.append(aux_files_pattern % on)
216 if aux_files_pattern_verbatim:
217 if type(aux_files_pattern_verbatim) is list:
218 for fp in aux_files_pattern_verbatim:
219 the_files.append(fp % m.group(1))
220 else:
221 the_files.append(aux_files_pattern_verbatim % m.group(1))
Patrick Williams213cb262021-08-07 19:21:33 -0500222 d.setVar('FILES:' + pkg, " ".join(the_files))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500223 else:
Patrick Williams213cb262021-08-07 19:21:33 -0500224 d.setVar('FILES:' + pkg, oldfiles + " " + newfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500225 if extra_depends != '':
Patrick Williams213cb262021-08-07 19:21:33 -0500226 d.appendVar('RDEPENDS:' + pkg, ' ' + extra_depends)
227 if not d.getVar('DESCRIPTION:' + pkg):
228 d.setVar('DESCRIPTION:' + pkg, description % on)
229 if not d.getVar('SUMMARY:' + pkg):
230 d.setVar('SUMMARY:' + pkg, summary % on)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500231 if postinst:
Patrick Williams213cb262021-08-07 19:21:33 -0500232 d.setVar('pkg_postinst:' + pkg, postinst)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500233 if postrm:
Patrick Williams213cb262021-08-07 19:21:33 -0500234 d.setVar('pkg_postrm:' + pkg, postrm)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500235 if callable(hook):
236 hook(f, pkg, file_regex, output_pattern, m.group(1))
237
238 d.setVar('PACKAGES', ' '.join(packages))
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600239 return list(split_packages)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500240
241PACKAGE_DEPENDS += "file-native"
242
243python () {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500244 if d.getVar('PACKAGES') != '':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500245 deps = ""
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500246 for dep in (d.getVar('PACKAGE_DEPENDS') or "").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500247 deps += " %s:do_populate_sysroot" % dep
Andrew Geissler82c905d2020-04-13 13:39:40 -0500248 if d.getVar('PACKAGE_MINIDEBUGINFO') == '1':
249 deps += ' xz-native:do_populate_sysroot'
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500250 d.appendVarFlag('do_package', 'depends', deps)
251
252 # shlibs requires any DEPENDS to have already packaged for the *.list files
253 d.appendVarFlag('do_package', 'deptask', " do_packagedata")
254}
255
256# Get a list of files from file vars by searching files under current working directory
257# The list contains symlinks, directories and normal files.
258def files_from_filevars(filevars):
259 import os,glob
260 cpath = oe.cachedpath.CachedPath()
261 files = []
262 for f in filevars:
263 if os.path.isabs(f):
264 f = '.' + f
265 if not f.startswith("./"):
266 f = './' + f
267 globbed = glob.glob(f)
268 if globbed:
269 if [ f ] != globbed:
270 files += globbed
271 continue
272 files.append(f)
273
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600274 symlink_paths = []
275 for ind, f in enumerate(files):
276 # Handle directory symlinks. Truncate path to the lowest level symlink
277 parent = ''
278 for dirname in f.split('/')[:-1]:
279 parent = os.path.join(parent, dirname)
280 if dirname == '.':
281 continue
282 if cpath.islink(parent):
283 bb.warn("FILES contains file '%s' which resides under a "
284 "directory symlink. Please fix the recipe and use the "
285 "real path for the file." % f[1:])
286 symlink_paths.append(f)
287 files[ind] = parent
288 f = parent
289 break
290
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500291 if not cpath.islink(f):
292 if cpath.isdir(f):
293 newfiles = [ os.path.join(f,x) for x in os.listdir(f) ]
294 if newfiles:
295 files += newfiles
296
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600297 return files, symlink_paths
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500298
299# Called in package_<rpm,ipk,deb>.bbclass to get the correct list of configuration files
300def get_conffiles(pkg, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500301 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500302 root = os.path.join(pkgdest, pkg)
303 cwd = os.getcwd()
304 os.chdir(root)
305
Patrick Williams213cb262021-08-07 19:21:33 -0500306 conffiles = d.getVar('CONFFILES:%s' % pkg);
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500307 if conffiles == None:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500308 conffiles = d.getVar('CONFFILES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500309 if conffiles == None:
310 conffiles = ""
311 conffiles = conffiles.split()
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600312 conf_orig_list = files_from_filevars(conffiles)[0]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500313
314 # Remove links and directories from conf_orig_list to get conf_list which only contains normal files
315 conf_list = []
316 for f in conf_orig_list:
317 if os.path.isdir(f):
318 continue
319 if os.path.islink(f):
320 continue
321 if not os.path.exists(f):
322 continue
323 conf_list.append(f)
324
325 # Remove the leading './'
326 for i in range(0, len(conf_list)):
327 conf_list[i] = conf_list[i][1:]
328
329 os.chdir(cwd)
330 return conf_list
331
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500332def checkbuildpath(file, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500333 tmpdir = d.getVar('TMPDIR')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500334 with open(file) as f:
335 file_content = f.read()
336 if tmpdir in file_content:
337 return True
338
339 return False
340
Brad Bishop316dfdd2018-06-25 12:45:53 -0400341def parse_debugsources_from_dwarfsrcfiles_output(dwarfsrcfiles_output):
342 debugfiles = {}
343
344 for line in dwarfsrcfiles_output.splitlines():
345 if line.startswith("\t"):
346 debugfiles[os.path.normpath(line.split()[0])] = ""
347
348 return debugfiles.keys()
349
Brad Bishop19323692019-04-05 15:28:33 -0400350def source_info(file, d, fatal=True):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800351 import subprocess
352
353 cmd = ["dwarfsrcfiles", file]
354 try:
355 output = subprocess.check_output(cmd, universal_newlines=True, stderr=subprocess.STDOUT)
356 retval = 0
357 except subprocess.CalledProcessError as exc:
358 output = exc.output
359 retval = exc.returncode
360
Brad Bishop316dfdd2018-06-25 12:45:53 -0400361 # 255 means a specific file wasn't fully parsed to get the debug file list, which is not a fatal failure
362 if retval != 0 and retval != 255:
363 msg = "dwarfsrcfiles failed with exit code %s (cmd was %s)%s" % (retval, cmd, ":\n%s" % output if output else "")
364 if fatal:
365 bb.fatal(msg)
366 bb.note(msg)
367
368 debugsources = parse_debugsources_from_dwarfsrcfiles_output(output)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400369
Brad Bishop19323692019-04-05 15:28:33 -0400370 return list(debugsources)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400371
Brad Bishop19323692019-04-05 15:28:33 -0400372def splitdebuginfo(file, dvar, debugdir, debuglibdir, debugappend, debugsrcdir, d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500373 # Function to split a single file into two components, one is the stripped
374 # target system binary, the other contains any debugging information. The
375 # two files are linked to reference each other.
376 #
Brad Bishop19323692019-04-05 15:28:33 -0400377 # return a mapping of files:debugsources
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500378
379 import stat
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800380 import subprocess
381
382 src = file[len(dvar):]
383 dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(src) + debugappend
384 debugfile = dvar + dest
Brad Bishop19323692019-04-05 15:28:33 -0400385 sources = []
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800386
387 # Split the file...
388 bb.utils.mkdirhier(os.path.dirname(debugfile))
389 #bb.note("Split %s -> %s" % (file, debugfile))
390 # Only store off the hard link reference if we successfully split!
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500391
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500392 dvar = d.getVar('PKGD')
393 objcopy = d.getVar("OBJCOPY")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500394
395 # We ignore kernel modules, we don't generate debug info files.
396 if file.find("/lib/modules/") != -1 and file.endswith(".ko"):
Brad Bishop19323692019-04-05 15:28:33 -0400397 return (file, sources)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500398
399 newmode = None
400 if not os.access(file, os.W_OK) or os.access(file, os.R_OK):
401 origmode = os.stat(file)[stat.ST_MODE]
402 newmode = origmode | stat.S_IWRITE | stat.S_IREAD
403 os.chmod(file, newmode)
404
405 # We need to extract the debug src information here...
406 if debugsrcdir:
Brad Bishop19323692019-04-05 15:28:33 -0400407 sources = source_info(file, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500408
409 bb.utils.mkdirhier(os.path.dirname(debugfile))
410
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800411 subprocess.check_output([objcopy, '--only-keep-debug', file, debugfile], stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500412
413 # Set the debuglink to have the view of the file path on the target
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800414 subprocess.check_output([objcopy, '--add-gnu-debuglink', debugfile, file], stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500415
416 if newmode:
417 os.chmod(file, origmode)
418
Brad Bishop19323692019-04-05 15:28:33 -0400419 return (file, sources)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500420
Andrew Geissler82c905d2020-04-13 13:39:40 -0500421def splitstaticdebuginfo(file, dvar, debugstaticdir, debugstaticlibdir, debugstaticappend, debugsrcdir, d):
422 # Unlike the function above, there is no way to split a static library
423 # two components. So to get similar results we will copy the unmodified
424 # static library (containing the debug symbols) into a new directory.
425 # We will then strip (preserving symbols) the static library in the
426 # typical location.
427 #
428 # return a mapping of files:debugsources
429
430 import stat
431 import shutil
432
433 src = file[len(dvar):]
434 dest = debugstaticlibdir + os.path.dirname(src) + debugstaticdir + "/" + os.path.basename(src) + debugstaticappend
435 debugfile = dvar + dest
436 sources = []
437
438 # Copy the file...
439 bb.utils.mkdirhier(os.path.dirname(debugfile))
440 #bb.note("Copy %s -> %s" % (file, debugfile))
441
442 dvar = d.getVar('PKGD')
443
444 newmode = None
445 if not os.access(file, os.W_OK) or os.access(file, os.R_OK):
446 origmode = os.stat(file)[stat.ST_MODE]
447 newmode = origmode | stat.S_IWRITE | stat.S_IREAD
448 os.chmod(file, newmode)
449
450 # We need to extract the debug src information here...
451 if debugsrcdir:
452 sources = source_info(file, d)
453
454 bb.utils.mkdirhier(os.path.dirname(debugfile))
455
456 # Copy the unmodified item to the debug directory
457 shutil.copy2(file, debugfile)
458
459 if newmode:
460 os.chmod(file, origmode)
461
462 return (file, sources)
463
464def inject_minidebuginfo(file, dvar, debugdir, debuglibdir, debugappend, debugsrcdir, d):
465 # Extract just the symbols from debuginfo into minidebuginfo,
466 # compress it with xz and inject it back into the binary in a .gnu_debugdata section.
467 # https://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html
468
469 import subprocess
470
471 readelf = d.getVar('READELF')
472 nm = d.getVar('NM')
473 objcopy = d.getVar('OBJCOPY')
474
475 minidebuginfodir = d.expand('${WORKDIR}/minidebuginfo')
476
477 src = file[len(dvar):]
478 dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(src) + debugappend
479 debugfile = dvar + dest
480 minidebugfile = minidebuginfodir + src + '.minidebug'
481 bb.utils.mkdirhier(os.path.dirname(minidebugfile))
482
483 # If we didn't produce debuginfo for any reason, we can't produce minidebuginfo either
484 # so skip it.
485 if not os.path.exists(debugfile):
486 bb.debug(1, 'ELF file {} has no debuginfo, skipping minidebuginfo injection'.format(file))
487 return
488
489 # Find non-allocated PROGBITS, NOTE, and NOBITS sections in the debuginfo.
490 # We will exclude all of these from minidebuginfo to save space.
491 remove_section_names = []
492 for line in subprocess.check_output([readelf, '-W', '-S', debugfile], universal_newlines=True).splitlines():
493 fields = line.split()
494 if len(fields) < 8:
495 continue
496 name = fields[0]
497 type = fields[1]
498 flags = fields[7]
499 # .debug_ sections will be removed by objcopy -S so no need to explicitly remove them
500 if name.startswith('.debug_'):
501 continue
502 if 'A' not in flags and type in ['PROGBITS', 'NOTE', 'NOBITS']:
503 remove_section_names.append(name)
504
505 # List dynamic symbols in the binary. We can exclude these from minidebuginfo
506 # because they are always present in the binary.
507 dynsyms = set()
508 for line in subprocess.check_output([nm, '-D', file, '--format=posix', '--defined-only'], universal_newlines=True).splitlines():
509 dynsyms.add(line.split()[0])
510
511 # Find all function symbols from debuginfo which aren't in the dynamic symbols table.
512 # These are the ones we want to keep in minidebuginfo.
513 keep_symbols_file = minidebugfile + '.symlist'
514 found_any_symbols = False
515 with open(keep_symbols_file, 'w') as f:
516 for line in subprocess.check_output([nm, debugfile, '--format=sysv', '--defined-only'], universal_newlines=True).splitlines():
517 fields = line.split('|')
518 if len(fields) < 7:
519 continue
520 name = fields[0].strip()
521 type = fields[3].strip()
522 if type == 'FUNC' and name not in dynsyms:
523 f.write('{}\n'.format(name))
524 found_any_symbols = True
525
526 if not found_any_symbols:
527 bb.debug(1, 'ELF file {} contains no symbols, skipping minidebuginfo injection'.format(file))
528 return
529
530 bb.utils.remove(minidebugfile)
531 bb.utils.remove(minidebugfile + '.xz')
532
533 subprocess.check_call([objcopy, '-S'] +
534 ['--remove-section={}'.format(s) for s in remove_section_names] +
535 ['--keep-symbols={}'.format(keep_symbols_file), debugfile, minidebugfile])
536
537 subprocess.check_call(['xz', '--keep', minidebugfile])
538
539 subprocess.check_call([objcopy, '--add-section', '.gnu_debugdata={}.xz'.format(minidebugfile), file])
540
Brad Bishop19323692019-04-05 15:28:33 -0400541def copydebugsources(debugsrcdir, sources, d):
Brad Bishop316dfdd2018-06-25 12:45:53 -0400542 # The debug src information written out to sourcefile is further processed
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500543 # and copied to the destination here.
544
545 import stat
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800546 import subprocess
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500547
Brad Bishop19323692019-04-05 15:28:33 -0400548 if debugsrcdir and sources:
549 sourcefile = d.expand("${WORKDIR}/debugsources.list")
550 bb.utils.remove(sourcefile)
551
552 # filenames are null-separated - this is an artefact of the previous use
553 # of rpm's debugedit, which was writing them out that way, and the code elsewhere
554 # is still assuming that.
555 debuglistoutput = '\0'.join(sources) + '\0'
556 with open(sourcefile, 'a') as sf:
557 sf.write(debuglistoutput)
558
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500559 dvar = d.getVar('PKGD')
560 strip = d.getVar("STRIP")
561 objcopy = d.getVar("OBJCOPY")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500562 workdir = d.getVar("WORKDIR")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500563 workparentdir = os.path.dirname(os.path.dirname(workdir))
564 workbasedir = os.path.basename(os.path.dirname(workdir)) + "/" + os.path.basename(workdir)
565
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500566 # If build path exists in sourcefile, it means toolchain did not use
567 # -fdebug-prefix-map to compile
568 if checkbuildpath(sourcefile, d):
569 localsrc_prefix = workparentdir + "/"
570 else:
571 localsrc_prefix = "/usr/src/debug/"
572
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500573 nosuchdir = []
574 basepath = dvar
575 for p in debugsrcdir.split("/"):
576 basepath = basepath + "/" + p
577 if not cpath.exists(basepath):
578 nosuchdir.append(basepath)
579 bb.utils.mkdirhier(basepath)
580 cpath.updatecache(basepath)
581
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500582 # Ignore files from the recipe sysroots (target and native)
583 processdebugsrc = "LC_ALL=C ; sort -z -u '%s' | egrep -v -z '((<internal>|<built-in>)$|/.*recipe-sysroot.*/)' | "
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500584 # We need to ignore files that are not actually ours
585 # we do this by only paying attention to items from this package
586 processdebugsrc += "fgrep -zw '%s' | "
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500587 # Remove prefix in the source paths
588 processdebugsrc += "sed 's#%s##g' | "
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500589 processdebugsrc += "(cd '%s' ; cpio -pd0mlL --no-preserve-owner '%s%s' 2>/dev/null)"
590
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500591 cmd = processdebugsrc % (sourcefile, workbasedir, localsrc_prefix, workparentdir, dvar, debugsrcdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800592 try:
593 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
594 except subprocess.CalledProcessError:
595 # Can "fail" if internal headers/transient sources are attempted
596 pass
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500597
598 # cpio seems to have a bug with -lL together and symbolic links are just copied, not dereferenced.
599 # Work around this by manually finding and copying any symbolic links that made it through.
Brad Bishop19323692019-04-05 15:28:33 -0400600 cmd = "find %s%s -type l -print0 -delete | sed s#%s%s/##g | (cd '%s' ; cpio -pd0mL --no-preserve-owner '%s%s')" % \
601 (dvar, debugsrcdir, dvar, debugsrcdir, workparentdir, dvar, debugsrcdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800602 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500603
604 # The copy by cpio may have resulted in some empty directories! Remove these
605 cmd = "find %s%s -empty -type d -delete" % (dvar, debugsrcdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800606 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500607
608 # Also remove debugsrcdir if its empty
609 for p in nosuchdir[::-1]:
610 if os.path.exists(p) and not os.listdir(p):
611 os.rmdir(p)
612
613#
614# Package data handling routines
615#
616
Andrew Geissler82c905d2020-04-13 13:39:40 -0500617def get_package_mapping (pkg, basepkg, d, depversions=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500618 import oe.packagedata
619
620 data = oe.packagedata.read_subpkgdata(pkg, d)
Patrick Williams213cb262021-08-07 19:21:33 -0500621 key = "PKG:%s" % pkg
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500622
623 if key in data:
624 # Have to avoid undoing the write_extra_pkgs(global_variants...)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800625 if bb.data.inherits_class('allarch', d) and not d.getVar('MULTILIB_VARIANTS') \
626 and data[key] == basepkg:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500627 return pkg
Andrew Geissler82c905d2020-04-13 13:39:40 -0500628 if depversions == []:
629 # Avoid returning a mapping if the renamed package rprovides its original name
Patrick Williams213cb262021-08-07 19:21:33 -0500630 rprovkey = "RPROVIDES:%s" % pkg
Andrew Geissler82c905d2020-04-13 13:39:40 -0500631 if rprovkey in data:
632 if pkg in bb.utils.explode_dep_versions2(data[rprovkey]):
633 bb.note("%s rprovides %s, not replacing the latter" % (data[key], pkg))
634 return pkg
635 # Do map to rewritten package name
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500636 return data[key]
637
638 return pkg
639
640def get_package_additional_metadata (pkg_type, d):
641 base_key = "PACKAGE_ADD_METADATA"
642 for key in ("%s_%s" % (base_key, pkg_type.upper()), base_key):
643 if d.getVar(key, False) is None:
644 continue
645 d.setVarFlag(key, "type", "list")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500646 if d.getVarFlag(key, "separator") is None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500647 d.setVarFlag(key, "separator", "\\n")
648 metadata_fields = [field.strip() for field in oe.data.typed_value(key, d)]
649 return "\n".join(metadata_fields).strip()
650
651def runtime_mapping_rename (varname, pkg, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500652 #bb.note("%s before: %s" % (varname, d.getVar(varname)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500653
654 new_depends = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500655 deps = bb.utils.explode_dep_versions2(d.getVar(varname) or "")
Andrew Geissler82c905d2020-04-13 13:39:40 -0500656 for depend, depversions in deps.items():
657 new_depend = get_package_mapping(depend, pkg, d, depversions)
658 if depend != new_depend:
659 bb.note("package name mapping done: %s -> %s" % (depend, new_depend))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500660 new_depends[new_depend] = deps[depend]
661
662 d.setVar(varname, bb.utils.join_deps(new_depends, commasep=False))
663
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500664 #bb.note("%s after: %s" % (varname, d.getVar(varname)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500665
666#
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500667# Used by do_packagedata (and possibly other routines post do_package)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500668#
669
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500670package_get_auto_pr[vardepsexclude] = "BB_TASKDEPDATA"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500671python package_get_auto_pr() {
672 import oe.prservice
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500673
674 def get_do_package_hash(pn):
675 if d.getVar("BB_RUNTASK") != "do_package":
676 taskdepdata = d.getVar("BB_TASKDEPDATA", False)
677 for dep in taskdepdata:
678 if taskdepdata[dep][1] == "do_package" and taskdepdata[dep][0] == pn:
679 return taskdepdata[dep][6]
680 return None
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500681
682 # Support per recipe PRSERV_HOST
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500683 pn = d.getVar('PN')
684 host = d.getVar("PRSERV_HOST_" + pn)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500685 if not (host is None):
686 d.setVar("PRSERV_HOST", host)
687
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500688 pkgv = d.getVar("PKGV")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500689
690 # PR Server not active, handle AUTOINC
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500691 if not d.getVar('PRSERV_HOST'):
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500692 d.setVar("PRSERV_PV_AUTOINC", "0")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500693 return
694
695 auto_pr = None
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500696 pv = d.getVar("PV")
697 version = d.getVar("PRAUTOINX")
698 pkgarch = d.getVar("PACKAGE_ARCH")
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500699 checksum = get_do_package_hash(pn)
700
701 # If do_package isn't in the dependencies, we can't get the checksum...
702 if not checksum:
703 bb.warn('Task %s requested do_package unihash, but it was not available.' % d.getVar('BB_RUNTASK'))
704 #taskdepdata = d.getVar("BB_TASKDEPDATA", False)
705 #for dep in taskdepdata:
706 # bb.warn('%s:%s = %s' % (taskdepdata[dep][0], taskdepdata[dep][1], taskdepdata[dep][6]))
707 return
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500708
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500709 if d.getVar('PRSERV_LOCKDOWN'):
710 auto_pr = d.getVar('PRAUTO_' + version + '_' + pkgarch) or d.getVar('PRAUTO_' + version) or None
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500711 if auto_pr is None:
712 bb.fatal("Can NOT get PRAUTO from lockdown exported file")
713 d.setVar('PRAUTO',str(auto_pr))
714 return
715
716 try:
Andrew Geisslerd159c7f2021-09-02 21:05:58 -0500717 conn = oe.prservice.prserv_make_conn(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500718 if conn is not None:
719 if "AUTOINC" in pkgv:
720 srcpv = bb.fetch2.get_srcrev(d)
721 base_ver = "AUTOINC-%s" % version[:version.find(srcpv)]
722 value = conn.getPR(base_ver, pkgarch, srcpv)
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500723 d.setVar("PRSERV_PV_AUTOINC", str(value))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500724
725 auto_pr = conn.getPR(version, pkgarch, checksum)
Andrew Geisslerd159c7f2021-09-02 21:05:58 -0500726 conn.close()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500727 except Exception as e:
728 bb.fatal("Can NOT get PRAUTO, exception %s" % str(e))
729 if auto_pr is None:
730 bb.fatal("Can NOT get PRAUTO from remote PR service")
731 d.setVar('PRAUTO',str(auto_pr))
732}
733
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500734#
735# Package functions suitable for inclusion in PACKAGEFUNCS
736#
737
738python package_convert_pr_autoinc() {
739 pkgv = d.getVar("PKGV")
740
741 # Adjust pkgv as necessary...
742 if 'AUTOINC' in pkgv:
743 d.setVar("PKGV", pkgv.replace("AUTOINC", "${PRSERV_PV_AUTOINC}"))
744
745 # Change PRSERV_PV_AUTOINC and EXTENDPRAUTO usage to special values
746 d.setVar('PRSERV_PV_AUTOINC', '@PRSERV_PV_AUTOINC@')
747 d.setVar('EXTENDPRAUTO', '@EXTENDPRAUTO@')
748}
749
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500750LOCALEBASEPN ??= "${PN}"
751
752python package_do_split_locales() {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500753 if (d.getVar('PACKAGE_NO_LOCALE') == '1'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500754 bb.debug(1, "package requested not splitting locales")
755 return
756
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500757 packages = (d.getVar('PACKAGES') or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500758
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500759 datadir = d.getVar('datadir')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500760 if not datadir:
761 bb.note("datadir not defined")
762 return
763
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500764 dvar = d.getVar('PKGD')
765 pn = d.getVar('LOCALEBASEPN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500766
767 if pn + '-locale' in packages:
768 packages.remove(pn + '-locale')
769
770 localedir = os.path.join(dvar + datadir, 'locale')
771
772 if not cpath.isdir(localedir):
773 bb.debug(1, "No locale files in this package")
774 return
775
776 locales = os.listdir(localedir)
777
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500778 summary = d.getVar('SUMMARY') or pn
779 description = d.getVar('DESCRIPTION') or ""
780 locale_section = d.getVar('LOCALE_SECTION')
781 mlprefix = d.getVar('MLPREFIX') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500782 for l in sorted(locales):
783 ln = legitimize_package_name(l)
784 pkg = pn + '-locale-' + ln
785 packages.append(pkg)
Patrick Williams213cb262021-08-07 19:21:33 -0500786 d.setVar('FILES:' + pkg, os.path.join(datadir, 'locale', l))
787 d.setVar('RRECOMMENDS:' + pkg, '%svirtual-locale-%s' % (mlprefix, ln))
788 d.setVar('RPROVIDES:' + pkg, '%s-locale %s%s-translation' % (pn, mlprefix, ln))
789 d.setVar('SUMMARY:' + pkg, '%s - %s translations' % (summary, l))
790 d.setVar('DESCRIPTION:' + pkg, '%s This package contains language translation files for the %s locale.' % (description, l))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500791 if locale_section:
Patrick Williams213cb262021-08-07 19:21:33 -0500792 d.setVar('SECTION:' + pkg, locale_section)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500793
794 d.setVar('PACKAGES', ' '.join(packages))
795
796 # Disabled by RP 18/06/07
797 # Wildcards aren't supported in debian
798 # They break with ipkg since glibc-locale* will mean that
799 # glibc-localedata-translit* won't install as a dependency
800 # for some other package which breaks meta-toolchain
801 # Probably breaks since virtual-locale- isn't provided anywhere
Patrick Williams213cb262021-08-07 19:21:33 -0500802 #rdep = (d.getVar('RDEPENDS:%s' % pn) or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500803 #rdep.append('%s-locale*' % pn)
Patrick Williams213cb262021-08-07 19:21:33 -0500804 #d.setVar('RDEPENDS:%s' % pn, ' '.join(rdep))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500805}
806
807python perform_packagecopy () {
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800808 import subprocess
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600809 import shutil
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800810
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500811 dest = d.getVar('D')
812 dvar = d.getVar('PKGD')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500813
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600814 # Remove ${D}/sysroot-only if present
815 sysroot_only = os.path.join(dest, 'sysroot-only')
816 if cpath.exists(sysroot_only) and cpath.isdir(sysroot_only):
817 shutil.rmtree(sysroot_only)
818
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500819 # Start by package population by taking a copy of the installed
820 # files to operate on
821 # Preserve sparse files and hard links
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800822 cmd = 'tar -cf - -C %s -p -S . | tar -xf - -C %s' % (dest, dvar)
823 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500824
825 # replace RPATHs for the nativesdk binaries, to make them relocatable
826 if bb.data.inherits_class('nativesdk', d) or bb.data.inherits_class('cross-canadian', d):
827 rpath_replace (dvar, d)
828}
829perform_packagecopy[cleandirs] = "${PKGD}"
830perform_packagecopy[dirs] = "${PKGD}"
831
832# We generate a master list of directories to process, we start by
833# seeding this list with reasonable defaults, then load from
834# the fs-perms.txt files
835python fixup_perms () {
836 import pwd, grp
837
838 # init using a string with the same format as a line as documented in
839 # the fs-perms.txt file
840 # <path> <mode> <uid> <gid> <walk> <fmode> <fuid> <fgid>
841 # <path> link <link target>
842 #
843 # __str__ can be used to print out an entry in the input format
844 #
845 # if fs_perms_entry.path is None:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400846 # an error occurred
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500847 # if fs_perms_entry.link, you can retrieve:
848 # fs_perms_entry.path = path
849 # fs_perms_entry.link = target of link
850 # if not fs_perms_entry.link, you can retrieve:
851 # fs_perms_entry.path = path
852 # fs_perms_entry.mode = expected dir mode or None
853 # fs_perms_entry.uid = expected uid or -1
854 # fs_perms_entry.gid = expected gid or -1
855 # fs_perms_entry.walk = 'true' or something else
856 # fs_perms_entry.fmode = expected file mode or None
857 # fs_perms_entry.fuid = expected file uid or -1
858 # fs_perms_entry_fgid = expected file gid or -1
859 class fs_perms_entry():
860 def __init__(self, line):
861 lsplit = line.split()
862 if len(lsplit) == 3 and lsplit[1].lower() == "link":
863 self._setlink(lsplit[0], lsplit[2])
864 elif len(lsplit) == 8:
865 self._setdir(lsplit[0], lsplit[1], lsplit[2], lsplit[3], lsplit[4], lsplit[5], lsplit[6], lsplit[7])
866 else:
867 msg = "Fixup Perms: invalid config line %s" % line
868 package_qa_handle_error("perm-config", msg, d)
869 self.path = None
870 self.link = None
871
872 def _setdir(self, path, mode, uid, gid, walk, fmode, fuid, fgid):
873 self.path = os.path.normpath(path)
874 self.link = None
875 self.mode = self._procmode(mode)
876 self.uid = self._procuid(uid)
877 self.gid = self._procgid(gid)
878 self.walk = walk.lower()
879 self.fmode = self._procmode(fmode)
880 self.fuid = self._procuid(fuid)
881 self.fgid = self._procgid(fgid)
882
883 def _setlink(self, path, link):
884 self.path = os.path.normpath(path)
885 self.link = link
886
887 def _procmode(self, mode):
888 if not mode or (mode and mode == "-"):
889 return None
890 else:
891 return int(mode,8)
892
893 # Note uid/gid -1 has special significance in os.lchown
894 def _procuid(self, uid):
895 if uid is None or uid == "-":
896 return -1
897 elif uid.isdigit():
898 return int(uid)
899 else:
900 return pwd.getpwnam(uid).pw_uid
901
902 def _procgid(self, gid):
903 if gid is None or gid == "-":
904 return -1
905 elif gid.isdigit():
906 return int(gid)
907 else:
908 return grp.getgrnam(gid).gr_gid
909
910 # Use for debugging the entries
911 def __str__(self):
912 if self.link:
913 return "%s link %s" % (self.path, self.link)
914 else:
915 mode = "-"
916 if self.mode:
917 mode = "0%o" % self.mode
918 fmode = "-"
919 if self.fmode:
920 fmode = "0%o" % self.fmode
921 uid = self._mapugid(self.uid)
922 gid = self._mapugid(self.gid)
923 fuid = self._mapugid(self.fuid)
924 fgid = self._mapugid(self.fgid)
925 return "%s %s %s %s %s %s %s %s" % (self.path, mode, uid, gid, self.walk, fmode, fuid, fgid)
926
927 def _mapugid(self, id):
928 if id is None or id == -1:
929 return "-"
930 else:
931 return "%d" % id
932
933 # Fix the permission, owner and group of path
934 def fix_perms(path, mode, uid, gid, dir):
935 if mode and not os.path.islink(path):
936 #bb.note("Fixup Perms: chmod 0%o %s" % (mode, dir))
937 os.chmod(path, mode)
938 # -1 is a special value that means don't change the uid/gid
939 # if they are BOTH -1, don't bother to lchown
940 if not (uid == -1 and gid == -1):
941 #bb.note("Fixup Perms: lchown %d:%d %s" % (uid, gid, dir))
942 os.lchown(path, uid, gid)
943
944 # Return a list of configuration files based on either the default
945 # files/fs-perms.txt or the contents of FILESYSTEM_PERMS_TABLES
946 # paths are resolved via BBPATH
947 def get_fs_perms_list(d):
948 str = ""
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500949 bbpath = d.getVar('BBPATH')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500950 fs_perms_tables = d.getVar('FILESYSTEM_PERMS_TABLES') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500951 for conf_file in fs_perms_tables.split():
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800952 confpath = bb.utils.which(bbpath, conf_file)
953 if confpath:
954 str += " %s" % bb.utils.which(bbpath, conf_file)
955 else:
956 bb.warn("cannot find %s specified in FILESYSTEM_PERMS_TABLES" % conf_file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500957 return str
958
959
960
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500961 dvar = d.getVar('PKGD')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500962
963 fs_perms_table = {}
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500964 fs_link_table = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500965
966 # By default all of the standard directories specified in
967 # bitbake.conf will get 0755 root:root.
968 target_path_vars = [ 'base_prefix',
969 'prefix',
970 'exec_prefix',
971 'base_bindir',
972 'base_sbindir',
973 'base_libdir',
974 'datadir',
975 'sysconfdir',
976 'servicedir',
977 'sharedstatedir',
978 'localstatedir',
979 'infodir',
980 'mandir',
981 'docdir',
982 'bindir',
983 'sbindir',
984 'libexecdir',
985 'libdir',
986 'includedir',
987 'oldincludedir' ]
988
989 for path in target_path_vars:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500990 dir = d.getVar(path) or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500991 if dir == "":
992 continue
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500993 fs_perms_table[dir] = fs_perms_entry(d.expand("%s 0755 root root false - - -" % (dir)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500994
995 # Now we actually load from the configuration files
996 for conf in get_fs_perms_list(d).split():
Brad Bishop64c979e2019-11-04 13:55:29 -0500997 if not os.path.exists(conf):
998 continue
999 with open(conf) as f:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001000 for line in f:
1001 if line.startswith('#'):
1002 continue
1003 lsplit = line.split()
1004 if len(lsplit) == 0:
1005 continue
1006 if len(lsplit) != 8 and not (len(lsplit) == 3 and lsplit[1].lower() == "link"):
1007 msg = "Fixup perms: %s invalid line: %s" % (conf, line)
1008 package_qa_handle_error("perm-line", msg, d)
1009 continue
1010 entry = fs_perms_entry(d.expand(line))
1011 if entry and entry.path:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001012 if entry.link:
1013 fs_link_table[entry.path] = entry
1014 if entry.path in fs_perms_table:
1015 fs_perms_table.pop(entry.path)
1016 else:
1017 fs_perms_table[entry.path] = entry
1018 if entry.path in fs_link_table:
1019 fs_link_table.pop(entry.path)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001020
1021 # Debug -- list out in-memory table
1022 #for dir in fs_perms_table:
1023 # bb.note("Fixup Perms: %s: %s" % (dir, str(fs_perms_table[dir])))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001024 #for link in fs_link_table:
1025 # bb.note("Fixup Perms: %s: %s" % (link, str(fs_link_table[link])))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001026
1027 # We process links first, so we can go back and fixup directory ownership
1028 # for any newly created directories
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001029 # Process in sorted order so /run gets created before /run/lock, etc.
1030 for entry in sorted(fs_link_table.values(), key=lambda x: x.link):
1031 link = entry.link
1032 dir = entry.path
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001033 origin = dvar + dir
1034 if not (cpath.exists(origin) and cpath.isdir(origin) and not cpath.islink(origin)):
1035 continue
1036
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001037 if link[0] == "/":
1038 target = dvar + link
1039 ptarget = link
1040 else:
1041 target = os.path.join(os.path.dirname(origin), link)
1042 ptarget = os.path.join(os.path.dirname(dir), link)
1043 if os.path.exists(target):
1044 msg = "Fixup Perms: Unable to correct directory link, target already exists: %s -> %s" % (dir, ptarget)
1045 package_qa_handle_error("perm-link", msg, d)
1046 continue
1047
1048 # Create path to move directory to, move it, and then setup the symlink
1049 bb.utils.mkdirhier(os.path.dirname(target))
1050 #bb.note("Fixup Perms: Rename %s -> %s" % (dir, ptarget))
Andrew Geisslerc926e172021-05-07 16:11:35 -05001051 bb.utils.rename(origin, target)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001052 #bb.note("Fixup Perms: Link %s -> %s" % (dir, link))
1053 os.symlink(link, origin)
1054
1055 for dir in fs_perms_table:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001056 origin = dvar + dir
1057 if not (cpath.exists(origin) and cpath.isdir(origin)):
1058 continue
1059
1060 fix_perms(origin, fs_perms_table[dir].mode, fs_perms_table[dir].uid, fs_perms_table[dir].gid, dir)
1061
1062 if fs_perms_table[dir].walk == 'true':
1063 for root, dirs, files in os.walk(origin):
1064 for dr in dirs:
1065 each_dir = os.path.join(root, dr)
1066 fix_perms(each_dir, fs_perms_table[dir].mode, fs_perms_table[dir].uid, fs_perms_table[dir].gid, dir)
1067 for f in files:
1068 each_file = os.path.join(root, f)
1069 fix_perms(each_file, fs_perms_table[dir].fmode, fs_perms_table[dir].fuid, fs_perms_table[dir].fgid, dir)
1070}
1071
1072python split_and_strip_files () {
1073 import stat, errno
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001074 import subprocess
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001075
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001076 dvar = d.getVar('PKGD')
1077 pn = d.getVar('PN')
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001078 hostos = d.getVar('HOST_OS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001079
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001080 oldcwd = os.getcwd()
1081 os.chdir(dvar)
1082
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001083 # We default to '.debug' style
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001084 if d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-file-directory':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001085 # Single debug-file-directory style debug info
1086 debugappend = ".debug"
Andrew Geissler82c905d2020-04-13 13:39:40 -05001087 debugstaticappend = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001088 debugdir = ""
Andrew Geissler82c905d2020-04-13 13:39:40 -05001089 debugstaticdir = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001090 debuglibdir = "/usr/lib/debug"
Andrew Geissler82c905d2020-04-13 13:39:40 -05001091 debugstaticlibdir = "/usr/lib/debug-static"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001092 debugsrcdir = "/usr/src/debug"
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001093 elif d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-without-src':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001094 # Original OE-core, a.k.a. ".debug", style debug info, but without sources in /usr/src/debug
1095 debugappend = ""
Andrew Geissler82c905d2020-04-13 13:39:40 -05001096 debugstaticappend = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001097 debugdir = "/.debug"
Andrew Geissler82c905d2020-04-13 13:39:40 -05001098 debugstaticdir = "/.debug-static"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001099 debuglibdir = ""
Andrew Geissler82c905d2020-04-13 13:39:40 -05001100 debugstaticlibdir = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001101 debugsrcdir = ""
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001102 elif d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-with-srcpkg':
1103 debugappend = ""
Andrew Geissler82c905d2020-04-13 13:39:40 -05001104 debugstaticappend = ""
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001105 debugdir = "/.debug"
Andrew Geissler82c905d2020-04-13 13:39:40 -05001106 debugstaticdir = "/.debug-static"
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001107 debuglibdir = ""
Andrew Geissler82c905d2020-04-13 13:39:40 -05001108 debugstaticlibdir = ""
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001109 debugsrcdir = "/usr/src/debug"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001110 else:
1111 # Original OE-core, a.k.a. ".debug", style debug info
1112 debugappend = ""
Andrew Geissler82c905d2020-04-13 13:39:40 -05001113 debugstaticappend = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001114 debugdir = "/.debug"
Andrew Geissler82c905d2020-04-13 13:39:40 -05001115 debugstaticdir = "/.debug-static"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001116 debuglibdir = ""
Andrew Geissler82c905d2020-04-13 13:39:40 -05001117 debugstaticlibdir = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001118 debugsrcdir = "/usr/src/debug"
1119
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001120 #
1121 # First lets figure out all of the files we may have to process ... do this only once!
1122 #
1123 elffiles = {}
1124 symlinks = {}
1125 kernmods = []
Brad Bishop316dfdd2018-06-25 12:45:53 -04001126 staticlibs = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001127 inodes = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001128 libdir = os.path.abspath(dvar + os.sep + d.getVar("libdir"))
1129 baselibdir = os.path.abspath(dvar + os.sep + d.getVar("base_libdir"))
Brad Bishop316dfdd2018-06-25 12:45:53 -04001130 skipfiles = (d.getVar("INHIBIT_PACKAGE_STRIP_FILES") or "").split()
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001131 if (d.getVar('INHIBIT_PACKAGE_STRIP') != '1' or \
1132 d.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT') != '1'):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001133 checkelf = {}
1134 checkelflinks = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001135 for root, dirs, files in cpath.walk(dvar):
1136 for f in files:
1137 file = os.path.join(root, f)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001138
1139 # Skip debug files
1140 if debugappend and file.endswith(debugappend):
1141 continue
1142 if debugdir and debugdir in os.path.dirname(file[len(dvar):]):
1143 continue
1144
Brad Bishop316dfdd2018-06-25 12:45:53 -04001145 if file in skipfiles:
1146 continue
1147
Andrew Geissler82c905d2020-04-13 13:39:40 -05001148 if file.endswith(".ko") and file.find("/lib/modules/") != -1:
1149 kernmods.append(file)
1150 continue
1151 if oe.package.is_static_lib(file):
1152 staticlibs.append(file)
1153 continue
1154
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001155 try:
1156 ltarget = cpath.realpath(file, dvar, False)
1157 s = cpath.lstat(ltarget)
1158 except OSError as e:
1159 (err, strerror) = e.args
1160 if err != errno.ENOENT:
1161 raise
1162 # Skip broken symlinks
1163 continue
1164 if not s:
1165 continue
Brad Bishop316dfdd2018-06-25 12:45:53 -04001166 # Check its an executable
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001167 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 -05001168 or ((file.startswith(libdir) or file.startswith(baselibdir)) and (".so" in f or ".node" in f)):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001169
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001170 if cpath.islink(file):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001171 checkelflinks[file] = ltarget
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001172 continue
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001173 # Use a reference of device ID and inode number to identify files
1174 file_reference = "%d_%d" % (s.st_dev, s.st_ino)
1175 checkelf[file] = (file, file_reference)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001176
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001177 results = oe.utils.multiprocess_launch(oe.package.is_elf, checkelflinks.values(), d)
1178 results_map = {}
1179 for (ltarget, elf_file) in results:
1180 results_map[ltarget] = elf_file
1181 for file in checkelflinks:
1182 ltarget = checkelflinks[file]
1183 # If it's a symlink, and points to an ELF file, we capture the readlink target
1184 if results_map[ltarget]:
1185 target = os.readlink(file)
1186 #bb.note("Sym: %s (%d)" % (ltarget, results_map[ltarget]))
1187 symlinks[file] = target
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001188
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001189 results = oe.utils.multiprocess_launch(oe.package.is_elf, checkelf.keys(), d)
Brad Bishop15ae2502019-06-18 21:44:24 -04001190
1191 # Sort results by file path. This ensures that the files are always
1192 # processed in the same order, which is important to make sure builds
1193 # are reproducible when dealing with hardlinks
1194 results.sort(key=lambda x: x[0])
1195
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001196 for (file, elf_file) in results:
1197 # It's a file (or hardlink), not a link
1198 # ...but is it ELF, and is it already stripped?
1199 if elf_file & 1:
1200 if elf_file & 2:
Patrick Williams213cb262021-08-07 19:21:33 -05001201 if 'already-stripped' in (d.getVar('INSANE_SKIP:' + pn) or "").split():
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001202 bb.note("Skipping file %s from %s for already-stripped QA test" % (file[len(dvar):], pn))
1203 else:
1204 msg = "File '%s' from %s was already stripped, this will prevent future debugging!" % (file[len(dvar):], pn)
1205 package_qa_handle_error("already-stripped", msg, d)
1206 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001207
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001208 # At this point we have an unstripped elf file. We need to:
1209 # a) Make sure any file we strip is not hardlinked to anything else outside this tree
1210 # b) Only strip any hardlinked file once (no races)
1211 # c) Track any hardlinks between files so that we can reconstruct matching debug file hardlinks
1212
1213 # Use a reference of device ID and inode number to identify files
1214 file_reference = checkelf[file][1]
1215 if file_reference in inodes:
1216 os.unlink(file)
1217 os.link(inodes[file_reference][0], file)
1218 inodes[file_reference].append(file)
1219 else:
1220 inodes[file_reference] = [file]
1221 # break hardlink
1222 bb.utils.break_hardlinks(file)
1223 elffiles[file] = elf_file
1224 # Modified the file so clear the cache
1225 cpath.updatecache(file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001226
Andrew Geissler5199d832021-09-24 16:47:35 -05001227 def strip_pkgd_prefix(f):
1228 nonlocal dvar
1229
1230 if f.startswith(dvar):
1231 return f[len(dvar):]
1232
1233 return f
1234
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001235 #
1236 # First lets process debug splitting
1237 #
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001238 if (d.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT') != '1'):
Brad Bishop19323692019-04-05 15:28:33 -04001239 results = oe.utils.multiprocess_launch(splitdebuginfo, list(elffiles), d, extraargs=(dvar, debugdir, debuglibdir, debugappend, debugsrcdir, d))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001240
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001241 if debugsrcdir and not hostos.startswith("mingw"):
Andrew Geissler82c905d2020-04-13 13:39:40 -05001242 if (d.getVar('PACKAGE_DEBUG_STATIC_SPLIT') == '1'):
1243 results = oe.utils.multiprocess_launch(splitstaticdebuginfo, staticlibs, d, extraargs=(dvar, debugstaticdir, debugstaticlibdir, debugstaticappend, debugsrcdir, d))
1244 else:
1245 for file in staticlibs:
1246 results.append( (file,source_info(file, d)) )
Brad Bishop19323692019-04-05 15:28:33 -04001247
Andrew Geissler5199d832021-09-24 16:47:35 -05001248 d.setVar("PKGDEBUGSOURCES", {strip_pkgd_prefix(f): sorted(s) for f, s in results})
1249
Brad Bishop19323692019-04-05 15:28:33 -04001250 sources = set()
1251 for r in results:
1252 sources.update(r[1])
Brad Bishop316dfdd2018-06-25 12:45:53 -04001253
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001254 # Hardlink our debug symbols to the other hardlink copies
1255 for ref in inodes:
1256 if len(inodes[ref]) == 1:
1257 continue
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001258
1259 target = inodes[ref][0][len(dvar):]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001260 for file in inodes[ref][1:]:
1261 src = file[len(dvar):]
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001262 dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(target) + debugappend
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001263 fpath = dvar + dest
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001264 ftarget = dvar + debuglibdir + os.path.dirname(target) + debugdir + "/" + os.path.basename(target) + debugappend
1265 bb.utils.mkdirhier(os.path.dirname(fpath))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001266 # Only one hardlink of separated debug info file in each directory
1267 if not os.access(fpath, os.R_OK):
1268 #bb.note("Link %s -> %s" % (fpath, ftarget))
1269 os.link(ftarget, fpath)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001270
1271 # Create symlinks for all cases we were able to split symbols
1272 for file in symlinks:
1273 src = file[len(dvar):]
1274 dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(src) + debugappend
1275 fpath = dvar + dest
1276 # Skip it if the target doesn't exist
1277 try:
1278 s = os.stat(fpath)
1279 except OSError as e:
1280 (err, strerror) = e.args
1281 if err != errno.ENOENT:
1282 raise
1283 continue
1284
1285 ltarget = symlinks[file]
1286 lpath = os.path.dirname(ltarget)
1287 lbase = os.path.basename(ltarget)
1288 ftarget = ""
1289 if lpath and lpath != ".":
1290 ftarget += lpath + debugdir + "/"
1291 ftarget += lbase + debugappend
1292 if lpath.startswith(".."):
1293 ftarget = os.path.join("..", ftarget)
1294 bb.utils.mkdirhier(os.path.dirname(fpath))
1295 #bb.note("Symlink %s -> %s" % (fpath, ftarget))
1296 os.symlink(ftarget, fpath)
1297
1298 # Process the debugsrcdir if requested...
1299 # This copies and places the referenced sources for later debugging...
Brad Bishop19323692019-04-05 15:28:33 -04001300 copydebugsources(debugsrcdir, sources, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001301 #
1302 # End of debug splitting
1303 #
1304
1305 #
1306 # Now lets go back over things and strip them
1307 #
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001308 if (d.getVar('INHIBIT_PACKAGE_STRIP') != '1'):
1309 strip = d.getVar("STRIP")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001310 sfiles = []
1311 for file in elffiles:
1312 elf_file = int(elffiles[file])
1313 #bb.note("Strip %s" % file)
1314 sfiles.append((file, elf_file, strip))
1315 for f in kernmods:
1316 sfiles.append((f, 16, strip))
Andrew Geissler82c905d2020-04-13 13:39:40 -05001317 if (d.getVar('PACKAGE_STRIP_STATIC') == '1' or d.getVar('PACKAGE_DEBUG_STATIC_SPLIT') == '1'):
1318 for f in staticlibs:
1319 sfiles.append((f, 16, strip))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001320
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001321 oe.utils.multiprocess_launch(oe.package.runstrip, sfiles, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001322
Andrew Geissler82c905d2020-04-13 13:39:40 -05001323 # Build "minidebuginfo" and reinject it back into the stripped binaries
1324 if d.getVar('PACKAGE_MINIDEBUGINFO') == '1':
1325 oe.utils.multiprocess_launch(inject_minidebuginfo, list(elffiles), d,
1326 extraargs=(dvar, debugdir, debuglibdir, debugappend, debugsrcdir, d))
1327
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001328 #
1329 # End of strip
1330 #
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001331 os.chdir(oldcwd)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001332}
1333
1334python populate_packages () {
1335 import glob, re
1336
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001337 workdir = d.getVar('WORKDIR')
1338 outdir = d.getVar('DEPLOY_DIR')
1339 dvar = d.getVar('PKGD')
Brad Bishop19323692019-04-05 15:28:33 -04001340 packages = d.getVar('PACKAGES').split()
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001341 pn = d.getVar('PN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001342
1343 bb.utils.mkdirhier(outdir)
1344 os.chdir(dvar)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001345
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001346 autodebug = not (d.getVar("NOAUTOPACKAGEDEBUG") or False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001347
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001348 split_source_package = (d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-with-srcpkg')
1349
Brad Bishop19323692019-04-05 15:28:33 -04001350 # If debug-with-srcpkg mode is enabled then add the source package if it
1351 # doesn't exist and add the source file contents to the source package.
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001352 if split_source_package:
1353 src_package_name = ('%s-src' % d.getVar('PN'))
Brad Bishop19323692019-04-05 15:28:33 -04001354 if not src_package_name in packages:
1355 packages.append(src_package_name)
Patrick Williams213cb262021-08-07 19:21:33 -05001356 d.setVar('FILES:%s' % src_package_name, '/usr/src/debug')
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001357
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001358 # Sanity check PACKAGES for duplicates
Brad Bishop316dfdd2018-06-25 12:45:53 -04001359 # Sanity should be moved to sanity.bbclass once we have the infrastructure
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001360 package_dict = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001361
Brad Bishop19323692019-04-05 15:28:33 -04001362 for i, pkg in enumerate(packages):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001363 if pkg in package_dict:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001364 msg = "%s is listed in PACKAGES multiple times, this leads to packaging errors." % pkg
1365 package_qa_handle_error("packages-list", msg, d)
Brad Bishop19323692019-04-05 15:28:33 -04001366 # Ensure the source package gets the chance to pick up the source files
1367 # before the debug package by ordering it first in PACKAGES. Whether it
1368 # actually picks up any source files is controlled by
1369 # PACKAGE_DEBUG_SPLIT_STYLE.
1370 elif pkg.endswith("-src"):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001371 package_dict[pkg] = (10, i)
1372 elif autodebug and pkg.endswith("-dbg"):
1373 package_dict[pkg] = (30, i)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001374 else:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001375 package_dict[pkg] = (50, i)
Brad Bishop19323692019-04-05 15:28:33 -04001376 packages = sorted(package_dict.keys(), key=package_dict.get)
1377 d.setVar('PACKAGES', ' '.join(packages))
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001378 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001379
1380 seen = []
1381
1382 # os.mkdir masks the permissions with umask so we have to unset it first
1383 oldumask = os.umask(0)
1384
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001385 debug = []
1386 for root, dirs, files in cpath.walk(dvar):
1387 dir = root[len(dvar):]
1388 if not dir:
1389 dir = os.sep
1390 for f in (files + dirs):
1391 path = "." + os.path.join(dir, f)
Andrew Geissler82c905d2020-04-13 13:39:40 -05001392 if "/.debug/" in path or "/.debug-static/" in path or path.endswith("/.debug"):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001393 debug.append(path)
1394
Brad Bishop19323692019-04-05 15:28:33 -04001395 for pkg in packages:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001396 root = os.path.join(pkgdest, pkg)
1397 bb.utils.mkdirhier(root)
1398
Patrick Williams213cb262021-08-07 19:21:33 -05001399 filesvar = d.getVar('FILES:%s' % pkg) or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001400 if "//" in filesvar:
1401 msg = "FILES variable for package %s contains '//' which is invalid. Attempting to fix this but you should correct the metadata.\n" % pkg
1402 package_qa_handle_error("files-invalid", msg, d)
1403 filesvar.replace("//", "/")
1404
1405 origfiles = filesvar.split()
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001406 files, symlink_paths = files_from_filevars(origfiles)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001407
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001408 if autodebug and pkg.endswith("-dbg"):
1409 files.extend(debug)
1410
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001411 for file in files:
1412 if (not cpath.islink(file)) and (not cpath.exists(file)):
1413 continue
1414 if file in seen:
1415 continue
1416 seen.append(file)
1417
1418 def mkdir(src, dest, p):
1419 src = os.path.join(src, p)
1420 dest = os.path.join(dest, p)
1421 fstat = cpath.stat(src)
Brad Bishop96ff1982019-08-19 13:50:42 -04001422 os.mkdir(dest)
1423 os.chmod(dest, fstat.st_mode)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001424 os.chown(dest, fstat.st_uid, fstat.st_gid)
1425 if p not in seen:
1426 seen.append(p)
1427 cpath.updatecache(dest)
1428
1429 def mkdir_recurse(src, dest, paths):
1430 if cpath.exists(dest + '/' + paths):
1431 return
1432 while paths.startswith("./"):
1433 paths = paths[2:]
1434 p = "."
1435 for c in paths.split("/"):
1436 p = os.path.join(p, c)
1437 if not cpath.exists(os.path.join(dest, p)):
1438 mkdir(src, dest, p)
1439
1440 if cpath.isdir(file) and not cpath.islink(file):
1441 mkdir_recurse(dvar, root, file)
1442 continue
1443
1444 mkdir_recurse(dvar, root, os.path.dirname(file))
1445 fpath = os.path.join(root,file)
1446 if not cpath.islink(file):
1447 os.link(file, fpath)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001448 continue
1449 ret = bb.utils.copyfile(file, fpath)
1450 if ret is False or ret == 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001451 bb.fatal("File population failed")
1452
1453 # Check if symlink paths exist
1454 for file in symlink_paths:
1455 if not os.path.exists(os.path.join(root,file)):
1456 bb.fatal("File '%s' cannot be packaged into '%s' because its "
1457 "parent directory structure does not exist. One of "
1458 "its parent directories is a symlink whose target "
1459 "directory is not included in the package." %
1460 (file, pkg))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001461
1462 os.umask(oldumask)
1463 os.chdir(workdir)
1464
1465 # Handle LICENSE_EXCLUSION
1466 package_list = []
Brad Bishop19323692019-04-05 15:28:33 -04001467 for pkg in packages:
Andrew Geissler82c905d2020-04-13 13:39:40 -05001468 licenses = d.getVar('LICENSE_EXCLUSION-' + pkg)
1469 if licenses:
1470 msg = "Excluding %s from packaging as it has incompatible license(s): %s" % (pkg, licenses)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001471 package_qa_handle_error("incompatible-license", msg, d)
1472 else:
1473 package_list.append(pkg)
1474 d.setVar('PACKAGES', ' '.join(package_list))
1475
1476 unshipped = []
1477 for root, dirs, files in cpath.walk(dvar):
1478 dir = root[len(dvar):]
1479 if not dir:
1480 dir = os.sep
1481 for f in (files + dirs):
1482 path = os.path.join(dir, f)
1483 if ('.' + path) not in seen:
1484 unshipped.append(path)
1485
1486 if unshipped != []:
1487 msg = pn + ": Files/directories were installed but not shipped in any package:"
Patrick Williams213cb262021-08-07 19:21:33 -05001488 if "installed-vs-shipped" in (d.getVar('INSANE_SKIP:' + pn) or "").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001489 bb.note("Package %s skipping QA tests: installed-vs-shipped" % pn)
1490 else:
1491 for f in unshipped:
1492 msg = msg + "\n " + f
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001493 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"
1494 msg = msg + "%s: %d installed and not shipped files." % (pn, len(unshipped))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001495 package_qa_handle_error("installed-vs-shipped", msg, d)
1496}
1497populate_packages[dirs] = "${D}"
1498
1499python package_fixsymlinks () {
1500 import errno
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001501 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001502 packages = d.getVar("PACKAGES", False).split()
1503
1504 dangling_links = {}
1505 pkg_files = {}
1506 for pkg in packages:
1507 dangling_links[pkg] = []
1508 pkg_files[pkg] = []
1509 inst_root = os.path.join(pkgdest, pkg)
1510 for path in pkgfiles[pkg]:
1511 rpath = path[len(inst_root):]
1512 pkg_files[pkg].append(rpath)
1513 rtarget = cpath.realpath(path, inst_root, True, assume_dir = True)
1514 if not cpath.lexists(rtarget):
1515 dangling_links[pkg].append(os.path.normpath(rtarget[len(inst_root):]))
1516
1517 newrdepends = {}
1518 for pkg in dangling_links:
1519 for l in dangling_links[pkg]:
1520 found = False
1521 bb.debug(1, "%s contains dangling link %s" % (pkg, l))
1522 for p in packages:
1523 if l in pkg_files[p]:
1524 found = True
1525 bb.debug(1, "target found in %s" % p)
1526 if p == pkg:
1527 break
1528 if pkg not in newrdepends:
1529 newrdepends[pkg] = []
1530 newrdepends[pkg].append(p)
1531 break
1532 if found == False:
1533 bb.note("%s contains dangling symlink to %s" % (pkg, l))
1534
1535 for pkg in newrdepends:
Patrick Williams213cb262021-08-07 19:21:33 -05001536 rdepends = bb.utils.explode_dep_versions2(d.getVar('RDEPENDS:' + pkg) or "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001537 for p in newrdepends[pkg]:
1538 if p not in rdepends:
1539 rdepends[p] = []
Patrick Williams213cb262021-08-07 19:21:33 -05001540 d.setVar('RDEPENDS:' + pkg, bb.utils.join_deps(rdepends, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001541}
1542
1543
1544python package_package_name_hook() {
1545 """
1546 A package_name_hook function can be used to rewrite the package names by
1547 changing PKG. For an example, see debian.bbclass.
1548 """
1549 pass
1550}
1551
1552EXPORT_FUNCTIONS package_name_hook
1553
1554
1555PKGDESTWORK = "${WORKDIR}/pkgdata"
1556
Andrew Geissler1e34c2d2020-05-29 16:02:59 -05001557PKGDATA_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 -04001558
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001559python emit_pkgdata() {
1560 from glob import glob
1561 import json
Andrew Geissler5199d832021-09-24 16:47:35 -05001562 import bb.compress.zstd
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001563
Brad Bishop316dfdd2018-06-25 12:45:53 -04001564 def process_postinst_on_target(pkg, mlprefix):
Patrick Williams213cb262021-08-07 19:21:33 -05001565 pkgval = d.getVar('PKG:%s' % pkg)
Brad Bishop96ff1982019-08-19 13:50:42 -04001566 if pkgval is None:
1567 pkgval = pkg
1568
Brad Bishop316dfdd2018-06-25 12:45:53 -04001569 defer_fragment = """
1570if [ -n "$D" ]; then
1571 $INTERCEPT_DIR/postinst_intercept delay_to_first_boot %s mlprefix=%s
1572 exit 0
1573fi
Brad Bishop96ff1982019-08-19 13:50:42 -04001574""" % (pkgval, mlprefix)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001575
Patrick Williams213cb262021-08-07 19:21:33 -05001576 postinst = d.getVar('pkg_postinst:%s' % pkg)
1577 postinst_ontarget = d.getVar('pkg_postinst_ontarget:%s' % pkg)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001578
1579 if postinst_ontarget:
1580 bb.debug(1, 'adding deferred pkg_postinst_ontarget() to pkg_postinst() for %s' % pkg)
1581 if not postinst:
1582 postinst = '#!/bin/sh\n'
1583 postinst += defer_fragment
1584 postinst += postinst_ontarget
Patrick Williams213cb262021-08-07 19:21:33 -05001585 d.setVar('pkg_postinst:%s' % pkg, postinst)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001586
1587 def add_set_e_to_scriptlets(pkg):
1588 for scriptlet_name in ('pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm'):
Patrick Williams213cb262021-08-07 19:21:33 -05001589 scriptlet = d.getVar('%s:%s' % (scriptlet_name, pkg))
Brad Bishop316dfdd2018-06-25 12:45:53 -04001590 if scriptlet:
1591 scriptlet_split = scriptlet.split('\n')
1592 if scriptlet_split[0].startswith("#!"):
1593 scriptlet = scriptlet_split[0] + "\nset -e\n" + "\n".join(scriptlet_split[1:])
1594 else:
1595 scriptlet = "set -e\n" + "\n".join(scriptlet_split[0:])
Patrick Williams213cb262021-08-07 19:21:33 -05001596 d.setVar('%s:%s' % (scriptlet_name, pkg), scriptlet)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001597
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001598 def write_if_exists(f, pkg, var):
1599 def encode(str):
1600 import codecs
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001601 c = codecs.getencoder("unicode_escape")
1602 return c(str)[0].decode("latin1")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001603
Patrick Williams213cb262021-08-07 19:21:33 -05001604 val = d.getVar('%s:%s' % (var, pkg))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001605 if val:
Patrick Williams213cb262021-08-07 19:21:33 -05001606 f.write('%s:%s: %s\n' % (var, pkg, encode(val)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001607 return val
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001608 val = d.getVar('%s' % (var))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001609 if val:
1610 f.write('%s: %s\n' % (var, encode(val)))
1611 return val
1612
1613 def write_extra_pkgs(variants, pn, packages, pkgdatadir):
1614 for variant in variants:
1615 with open("%s/%s-%s" % (pkgdatadir, variant, pn), 'w') as fd:
1616 fd.write("PACKAGES: %s\n" % ' '.join(
1617 map(lambda pkg: '%s-%s' % (variant, pkg), packages.split())))
1618
1619 def write_extra_runtime_pkgs(variants, packages, pkgdatadir):
1620 for variant in variants:
1621 for pkg in packages.split():
1622 ml_pkg = "%s-%s" % (variant, pkg)
1623 subdata_file = "%s/runtime/%s" % (pkgdatadir, ml_pkg)
1624 with open(subdata_file, 'w') as fd:
Patrick Williams213cb262021-08-07 19:21:33 -05001625 fd.write("PKG:%s: %s" % (ml_pkg, pkg))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001626
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001627 packages = d.getVar('PACKAGES')
1628 pkgdest = d.getVar('PKGDEST')
1629 pkgdatadir = d.getVar('PKGDESTWORK')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001630
Brad Bishop64c979e2019-11-04 13:55:29 -05001631 data_file = pkgdatadir + d.expand("/${PN}")
1632 with open(data_file, 'w') as fd:
1633 fd.write("PACKAGES: %s\n" % packages)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001634
Andrew Geissler5199d832021-09-24 16:47:35 -05001635 pkgdebugsource = d.getVar("PKGDEBUGSOURCES") or []
1636
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001637 pn = d.getVar('PN')
1638 global_variants = (d.getVar('MULTILIB_GLOBAL_VARIANTS') or "").split()
1639 variants = (d.getVar('MULTILIB_VARIANTS') or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001640
1641 if bb.data.inherits_class('kernel', d) or bb.data.inherits_class('module-base', d):
1642 write_extra_pkgs(variants, pn, packages, pkgdatadir)
1643
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001644 if bb.data.inherits_class('allarch', d) and not variants \
1645 and not bb.data.inherits_class('packagegroup', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001646 write_extra_pkgs(global_variants, pn, packages, pkgdatadir)
1647
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001648 workdir = d.getVar('WORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001649
1650 for pkg in packages.split():
Patrick Williams213cb262021-08-07 19:21:33 -05001651 pkgval = d.getVar('PKG:%s' % pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001652 if pkgval is None:
1653 pkgval = pkg
Patrick Williams213cb262021-08-07 19:21:33 -05001654 d.setVar('PKG:%s' % pkg, pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001655
Andrew Geissler5199d832021-09-24 16:47:35 -05001656 extended_data = {
1657 "files_info": {}
1658 }
1659
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001660 pkgdestpkg = os.path.join(pkgdest, pkg)
1661 files = {}
Andrew Geissler5199d832021-09-24 16:47:35 -05001662 files_extra = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001663 total_size = 0
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001664 seen = set()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001665 for f in pkgfiles[pkg]:
Andrew Geissler5199d832021-09-24 16:47:35 -05001666 fpath = os.sep + os.path.relpath(f, pkgdestpkg)
1667
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001668 fstat = os.lstat(f)
Andrew Geissler5199d832021-09-24 16:47:35 -05001669 files[fpath] = fstat.st_size
1670
1671 extended_data["files_info"].setdefault(fpath, {})
1672 extended_data["files_info"][fpath]['size'] = fstat.st_size
1673
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001674 if fstat.st_ino not in seen:
1675 seen.add(fstat.st_ino)
1676 total_size += fstat.st_size
Andrew Geissler5199d832021-09-24 16:47:35 -05001677
1678 if fpath in pkgdebugsource:
1679 extended_data["files_info"][fpath]['debugsrc'] = pkgdebugsource[fpath]
1680 del pkgdebugsource[fpath]
1681
Andrew Geisslerd159c7f2021-09-02 21:05:58 -05001682 d.setVar('FILES_INFO:' + pkg , json.dumps(files, sort_keys=True))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001683
Brad Bishop316dfdd2018-06-25 12:45:53 -04001684 process_postinst_on_target(pkg, d.getVar("MLPREFIX"))
1685 add_set_e_to_scriptlets(pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001686
Brad Bishop15ae2502019-06-18 21:44:24 -04001687 subdata_file = pkgdatadir + "/runtime/%s" % pkg
1688 with open(subdata_file, 'w') as sf:
1689 for var in (d.getVar('PKGDATA_VARS') or "").split():
1690 val = write_if_exists(sf, pkg, var)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001691
Brad Bishop15ae2502019-06-18 21:44:24 -04001692 write_if_exists(sf, pkg, 'FILERPROVIDESFLIST')
Andrew Geissler5199d832021-09-24 16:47:35 -05001693 for dfile in sorted((d.getVar('FILERPROVIDESFLIST:' + pkg) or "").split()):
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001694 write_if_exists(sf, pkg, 'FILERPROVIDES:' + dfile)
Brad Bishop15ae2502019-06-18 21:44:24 -04001695
1696 write_if_exists(sf, pkg, 'FILERDEPENDSFLIST')
Andrew Geissler5199d832021-09-24 16:47:35 -05001697 for dfile in sorted((d.getVar('FILERDEPENDSFLIST:' + pkg) or "").split()):
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001698 write_if_exists(sf, pkg, 'FILERDEPENDS:' + dfile)
Brad Bishop15ae2502019-06-18 21:44:24 -04001699
Andrew Geisslerd159c7f2021-09-02 21:05:58 -05001700 sf.write('%s:%s: %d\n' % ('PKGSIZE', pkg, total_size))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001701
Andrew Geissler5199d832021-09-24 16:47:35 -05001702 subdata_extended_file = pkgdatadir + "/extended/%s.json.zstd" % pkg
1703 num_threads = int(d.getVar("BB_NUMBER_THREADS"))
1704 with bb.compress.zstd.open(subdata_extended_file, "wt", encoding="utf-8", num_threads=num_threads) as f:
1705 json.dump(extended_data, f, sort_keys=True, separators=(",", ":"))
1706
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001707 # Symlinks needed for rprovides lookup
Patrick Williams213cb262021-08-07 19:21:33 -05001708 rprov = d.getVar('RPROVIDES:%s' % pkg) or d.getVar('RPROVIDES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001709 if rprov:
Andrew Geisslerc9f78652020-09-18 14:11:35 -05001710 for p in bb.utils.explode_deps(rprov):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001711 subdata_sym = pkgdatadir + "/runtime-rprovides/%s/%s" % (p, pkg)
1712 bb.utils.mkdirhier(os.path.dirname(subdata_sym))
1713 oe.path.symlink("../../runtime/%s" % pkg, subdata_sym, True)
1714
Patrick Williams213cb262021-08-07 19:21:33 -05001715 allow_empty = d.getVar('ALLOW_EMPTY:%s' % pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001716 if not allow_empty:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001717 allow_empty = d.getVar('ALLOW_EMPTY')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001718 root = "%s/%s" % (pkgdest, pkg)
1719 os.chdir(root)
1720 g = glob('*')
1721 if g or allow_empty == "1":
1722 # Symlinks needed for reverse lookups (from the final package name)
1723 subdata_sym = pkgdatadir + "/runtime-reverse/%s" % pkgval
1724 oe.path.symlink("../runtime/%s" % pkg, subdata_sym, True)
1725
1726 packagedfile = pkgdatadir + '/runtime/%s.packaged' % pkg
1727 open(packagedfile, 'w').close()
1728
1729 if bb.data.inherits_class('kernel', d) or bb.data.inherits_class('module-base', d):
1730 write_extra_runtime_pkgs(variants, packages, pkgdatadir)
1731
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001732 if bb.data.inherits_class('allarch', d) and not variants \
1733 and not bb.data.inherits_class('packagegroup', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001734 write_extra_runtime_pkgs(global_variants, packages, pkgdatadir)
1735
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001736}
Andrew Geissler5199d832021-09-24 16:47:35 -05001737emit_pkgdata[dirs] = "${PKGDESTWORK}/runtime ${PKGDESTWORK}/runtime-reverse ${PKGDESTWORK}/runtime-rprovides ${PKGDESTWORK}/extended"
1738emit_pkgdata[vardepsexclude] = "BB_NUMBER_THREADS"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001739
1740ldconfig_postinst_fragment() {
1741if [ x"$D" = "x" ]; then
1742 if [ -x /sbin/ldconfig ]; then /sbin/ldconfig ; fi
1743fi
1744}
1745
Andrew Geissler90fd73c2021-03-05 15:25:55 -06001746RPMDEPS = "${STAGING_LIBDIR_NATIVE}/rpm/rpmdeps --alldeps --define '__font_provides %{nil}'"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001747
1748# Collect perfile run-time dependency metadata
1749# Output:
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001750# FILERPROVIDESFLIST:pkg - list of all files w/ deps
1751# FILERPROVIDES:filepath:pkg - per file dep
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001752#
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001753# FILERDEPENDSFLIST:pkg - list of all files w/ deps
1754# FILERDEPENDS:filepath:pkg - per file dep
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001755
1756python package_do_filedeps() {
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001757 if d.getVar('SKIP_FILEDEPS') == '1':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001758 return
1759
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001760 pkgdest = d.getVar('PKGDEST')
1761 packages = d.getVar('PACKAGES')
1762 rpmdeps = d.getVar('RPMDEPS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001763
1764 def chunks(files, n):
1765 return [files[i:i+n] for i in range(0, len(files), n)]
1766
1767 pkglist = []
1768 for pkg in packages.split():
Patrick Williams213cb262021-08-07 19:21:33 -05001769 if d.getVar('SKIP_FILEDEPS:' + pkg) == '1':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001770 continue
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001771 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 -05001772 continue
1773 for files in chunks(pkgfiles[pkg], 100):
1774 pkglist.append((pkg, files, rpmdeps, pkgdest))
1775
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001776 processed = oe.utils.multiprocess_launch(oe.package.filedeprunner, pkglist, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001777
1778 provides_files = {}
1779 requires_files = {}
1780
1781 for result in processed:
1782 (pkg, provides, requires) = result
1783
1784 if pkg not in provides_files:
1785 provides_files[pkg] = []
1786 if pkg not in requires_files:
1787 requires_files[pkg] = []
1788
Brad Bishop19323692019-04-05 15:28:33 -04001789 for file in sorted(provides):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001790 provides_files[pkg].append(file)
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001791 key = "FILERPROVIDES:" + file + ":" + pkg
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001792 d.appendVar(key, " " + " ".join(provides[file]))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001793
Brad Bishop19323692019-04-05 15:28:33 -04001794 for file in sorted(requires):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001795 requires_files[pkg].append(file)
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001796 key = "FILERDEPENDS:" + file + ":" + pkg
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001797 d.appendVar(key, " " + " ".join(requires[file]))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001798
1799 for pkg in requires_files:
Andrew Geissler5199d832021-09-24 16:47:35 -05001800 d.setVar("FILERDEPENDSFLIST:" + pkg, " ".join(sorted(requires_files[pkg])))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001801 for pkg in provides_files:
Andrew Geissler5199d832021-09-24 16:47:35 -05001802 d.setVar("FILERPROVIDESFLIST:" + pkg, " ".join(sorted(provides_files[pkg])))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001803}
1804
Brad Bishop96ff1982019-08-19 13:50:42 -04001805SHLIBSDIRS = "${WORKDIR_PKGDATA}/${MLPREFIX}shlibs2"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001806SHLIBSWORKDIR = "${PKGDESTWORK}/${MLPREFIX}shlibs2"
1807
1808python package_do_shlibs() {
Brad Bishop00e122a2019-10-05 11:10:57 -04001809 import itertools
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001810 import re, pipes
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001811 import subprocess
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001812
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001813 exclude_shlibs = d.getVar('EXCLUDE_FROM_SHLIBS', False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001814 if exclude_shlibs:
1815 bb.note("not generating shlibs")
1816 return
1817
Brad Bishop19323692019-04-05 15:28:33 -04001818 lib_re = re.compile(r"^.*\.so")
1819 libdir_re = re.compile(r".*/%s$" % d.getVar('baselib'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001820
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001821 packages = d.getVar('PACKAGES')
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001822
1823 shlib_pkgs = []
1824 exclusion_list = d.getVar("EXCLUDE_PACKAGES_FROM_SHLIBS")
1825 if exclusion_list:
1826 for pkg in packages.split():
1827 if pkg not in exclusion_list.split():
1828 shlib_pkgs.append(pkg)
1829 else:
1830 bb.note("not generating shlibs for %s" % pkg)
1831 else:
1832 shlib_pkgs = packages.split()
1833
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001834 hostos = d.getVar('HOST_OS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001835
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001836 workdir = d.getVar('WORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001837
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001838 ver = d.getVar('PKGV')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001839 if not ver:
1840 msg = "PKGV not defined"
1841 package_qa_handle_error("pkgv-undefined", msg, d)
1842 return
1843
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001844 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001845
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001846 shlibswork_dir = d.getVar('SHLIBSWORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001847
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001848 def linux_so(file, pkg, pkgver, d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001849 needs_ldconfig = False
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001850 needed = set()
1851 sonames = set()
1852 renames = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001853 ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '')
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001854 cmd = d.getVar('OBJDUMP') + " -p " + pipes.quote(file) + " 2>/dev/null"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001855 fd = os.popen(cmd)
1856 lines = fd.readlines()
1857 fd.close()
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001858 rpath = tuple()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001859 for l in lines:
Brad Bishop19323692019-04-05 15:28:33 -04001860 m = re.match(r"\s+RPATH\s+([^\s]*)", l)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001861 if m:
1862 rpaths = m.group(1).replace("$ORIGIN", ldir).split(":")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001863 rpath = tuple(map(os.path.normpath, rpaths))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001864 for l in lines:
Brad Bishop19323692019-04-05 15:28:33 -04001865 m = re.match(r"\s+NEEDED\s+([^\s]*)", l)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001866 if m:
1867 dep = m.group(1)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001868 if dep not in needed:
1869 needed.add((dep, file, rpath))
Brad Bishop19323692019-04-05 15:28:33 -04001870 m = re.match(r"\s+SONAME\s+([^\s]*)", l)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001871 if m:
1872 this_soname = m.group(1)
1873 prov = (this_soname, ldir, pkgver)
1874 if not prov in sonames:
1875 # if library is private (only used by package) then do not build shlib for it
Brad Bishop79641f22019-09-10 07:20:22 -04001876 import fnmatch
1877 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 -08001878 sonames.add(prov)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001879 if libdir_re.match(os.path.dirname(file)):
1880 needs_ldconfig = True
1881 if snap_symlinks and (os.path.basename(file) != this_soname):
1882 renames.append((file, os.path.join(os.path.dirname(file), this_soname)))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001883 return (needs_ldconfig, needed, sonames, renames)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001884
1885 def darwin_so(file, needed, sonames, renames, pkgver):
1886 if not os.path.exists(file):
1887 return
1888 ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '')
1889
1890 def get_combinations(base):
1891 #
1892 # Given a base library name, find all combinations of this split by "." and "-"
1893 #
1894 combos = []
1895 options = base.split(".")
1896 for i in range(1, len(options) + 1):
1897 combos.append(".".join(options[0:i]))
1898 options = base.split("-")
1899 for i in range(1, len(options) + 1):
1900 combos.append("-".join(options[0:i]))
1901 return combos
1902
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001903 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 -05001904 # Drop suffix
1905 name = os.path.basename(file).rsplit(".",1)[0]
1906 # Find all combinations
1907 combos = get_combinations(name)
1908 for combo in combos:
1909 if not combo in sonames:
1910 prov = (combo, ldir, pkgver)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001911 sonames.add(prov)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001912 if file.endswith('.dylib') or file.endswith('.so'):
1913 rpath = []
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001914 p = subprocess.Popen([d.expand("${HOST_PREFIX}otool"), '-l', file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001915 out, err = p.communicate()
1916 # If returned successfully, process stdout for results
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001917 if p.returncode == 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001918 for l in out.split("\n"):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001919 l = l.strip()
1920 if l.startswith('path '):
1921 rpath.append(l.split()[1])
1922
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001923 p = subprocess.Popen([d.expand("${HOST_PREFIX}otool"), '-L', file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001924 out, err = p.communicate()
1925 # If returned successfully, process stdout for results
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001926 if p.returncode == 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001927 for l in out.split("\n"):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001928 l = l.strip()
1929 if not l or l.endswith(":"):
1930 continue
1931 if "is not an object file" in l:
1932 continue
1933 name = os.path.basename(l.split()[0]).rsplit(".", 1)[0]
1934 if name and name not in needed[pkg]:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001935 needed[pkg].add((name, file, tuple()))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001936
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001937 def mingw_dll(file, needed, sonames, renames, pkgver):
1938 if not os.path.exists(file):
1939 return
1940
1941 if file.endswith(".dll"):
1942 # assume all dlls are shared objects provided by the package
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001943 sonames.add((os.path.basename(file), os.path.dirname(file).replace(pkgdest + "/" + pkg, ''), pkgver))
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001944
1945 if (file.endswith(".dll") or file.endswith(".exe")):
1946 # use objdump to search for "DLL Name: .*\.dll"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001947 p = subprocess.Popen([d.expand("${HOST_PREFIX}objdump"), "-p", file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001948 out, err = p.communicate()
1949 # process the output, grabbing all .dll names
1950 if p.returncode == 0:
Brad Bishop19323692019-04-05 15:28:33 -04001951 for m in re.finditer(r"DLL Name: (.*?\.dll)$", out.decode(), re.MULTILINE | re.IGNORECASE):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001952 dllname = m.group(1)
1953 if dllname:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001954 needed[pkg].add((dllname, file, tuple()))
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001955
1956 if d.getVar('PACKAGE_SNAP_LIB_SYMLINKS') == "1":
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001957 snap_symlinks = True
1958 else:
1959 snap_symlinks = False
1960
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001961 needed = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001962
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001963 shlib_provider = oe.package.read_shlib_providers(d)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001964
1965 for pkg in shlib_pkgs:
Patrick Williams213cb262021-08-07 19:21:33 -05001966 private_libs = d.getVar('PRIVATE_LIBS:' + pkg) or d.getVar('PRIVATE_LIBS') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001967 private_libs = private_libs.split()
1968 needs_ldconfig = False
1969 bb.debug(2, "calculating shlib provides for %s" % pkg)
1970
Patrick Williams213cb262021-08-07 19:21:33 -05001971 pkgver = d.getVar('PKGV:' + pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001972 if not pkgver:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001973 pkgver = d.getVar('PV_' + pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001974 if not pkgver:
1975 pkgver = ver
1976
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001977 needed[pkg] = set()
1978 sonames = set()
1979 renames = []
1980 linuxlist = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001981 for file in pkgfiles[pkg]:
1982 soname = None
1983 if cpath.islink(file):
1984 continue
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001985 if hostos == "darwin" or hostos == "darwin8":
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001986 darwin_so(file, needed, sonames, renames, pkgver)
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001987 elif hostos.startswith("mingw"):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001988 mingw_dll(file, needed, sonames, renames, pkgver)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001989 elif os.access(file, os.X_OK) or lib_re.match(file):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001990 linuxlist.append(file)
1991
1992 if linuxlist:
1993 results = oe.utils.multiprocess_launch(linux_so, linuxlist, d, extraargs=(pkg, pkgver, d))
1994 for r in results:
1995 ldconfig = r[0]
1996 needed[pkg] |= r[1]
1997 sonames |= r[2]
1998 renames.extend(r[3])
1999 needs_ldconfig = needs_ldconfig or ldconfig
2000
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002001 for (old, new) in renames:
2002 bb.note("Renaming %s to %s" % (old, new))
Andrew Geisslerc926e172021-05-07 16:11:35 -05002003 bb.utils.rename(old, new)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002004 pkgfiles[pkg].remove(old)
Brad Bishop64c979e2019-11-04 13:55:29 -05002005
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002006 shlibs_file = os.path.join(shlibswork_dir, pkg + ".list")
2007 if len(sonames):
Brad Bishop64c979e2019-11-04 13:55:29 -05002008 with open(shlibs_file, 'w') as fd:
Andrew Geissler635e0e42020-08-21 15:58:33 -05002009 for s in sorted(sonames):
Brad Bishop64c979e2019-11-04 13:55:29 -05002010 if s[0] in shlib_provider and s[1] in shlib_provider[s[0]]:
2011 (old_pkg, old_pkgver) = shlib_provider[s[0]][s[1]]
2012 if old_pkg != pkg:
2013 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))
2014 bb.debug(1, 'registering %s-%s as shlib provider for %s' % (pkg, pkgver, s[0]))
2015 fd.write(s[0] + ':' + s[1] + ':' + s[2] + '\n')
2016 if s[0] not in shlib_provider:
2017 shlib_provider[s[0]] = {}
2018 shlib_provider[s[0]][s[1]] = (pkg, pkgver)
Brad Bishop1d80a2e2019-11-15 16:35:03 -05002019 if needs_ldconfig:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002020 bb.debug(1, 'adding ldconfig call to postinst for %s' % pkg)
Patrick Williams213cb262021-08-07 19:21:33 -05002021 postinst = d.getVar('pkg_postinst:%s' % pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002022 if not postinst:
2023 postinst = '#!/bin/sh\n'
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002024 postinst += d.getVar('ldconfig_postinst_fragment')
Patrick Williams213cb262021-08-07 19:21:33 -05002025 d.setVar('pkg_postinst:%s' % pkg, postinst)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002026 bb.debug(1, 'LIBNAMES: pkg %s sonames %s' % (pkg, sonames))
2027
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002028 assumed_libs = d.getVar('ASSUME_SHLIBS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002029 if assumed_libs:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002030 libdir = d.getVar("libdir")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002031 for e in assumed_libs.split():
2032 l, dep_pkg = e.split(":")
2033 lib_ver = None
2034 dep_pkg = dep_pkg.rsplit("_", 1)
2035 if len(dep_pkg) == 2:
2036 lib_ver = dep_pkg[1]
2037 dep_pkg = dep_pkg[0]
2038 if l not in shlib_provider:
2039 shlib_provider[l] = {}
2040 shlib_provider[l][libdir] = (dep_pkg, lib_ver)
2041
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002042 libsearchpath = [d.getVar('libdir'), d.getVar('base_libdir')]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002043
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08002044 for pkg in shlib_pkgs:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002045 bb.debug(2, "calculating shlib requirements for %s" % pkg)
2046
Patrick Williams213cb262021-08-07 19:21:33 -05002047 private_libs = d.getVar('PRIVATE_LIBS:' + pkg) or d.getVar('PRIVATE_LIBS') or ""
Brad Bishop316dfdd2018-06-25 12:45:53 -04002048 private_libs = private_libs.split()
2049
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002050 deps = list()
2051 for n in needed[pkg]:
2052 # if n is in private libraries, don't try to search provider for it
2053 # this could cause problem in case some abc.bb provides private
2054 # /opt/abc/lib/libfoo.so.1 and contains /usr/bin/abc depending on system library libfoo.so.1
2055 # but skipping it is still better alternative than providing own
2056 # version and then adding runtime dependency for the same system library
Brad Bishop79641f22019-09-10 07:20:22 -04002057 import fnmatch
2058 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 -05002059 bb.debug(2, '%s: Dependency %s covered by PRIVATE_LIBS' % (pkg, n[0]))
2060 continue
2061 if n[0] in shlib_provider.keys():
Brad Bishop00e122a2019-10-05 11:10:57 -04002062 shlib_provider_map = shlib_provider[n[0]]
2063 matches = set()
2064 for p in itertools.chain(list(n[2]), sorted(shlib_provider_map.keys()), libsearchpath):
2065 if p in shlib_provider_map:
2066 matches.add(p)
2067 if len(matches) > 1:
2068 matchpkgs = ', '.join([shlib_provider_map[match][0] for match in matches])
2069 bb.error("%s: Multiple shlib providers for %s: %s (used by files: %s)" % (pkg, n[0], matchpkgs, n[1]))
2070 elif len(matches) == 1:
2071 (dep_pkg, ver_needed) = shlib_provider_map[matches.pop()]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002072
2073 bb.debug(2, '%s: Dependency %s requires package %s (used by files: %s)' % (pkg, n[0], dep_pkg, n[1]))
2074
2075 if dep_pkg == pkg:
2076 continue
2077
2078 if ver_needed:
2079 dep = "%s (>= %s)" % (dep_pkg, ver_needed)
2080 else:
2081 dep = dep_pkg
2082 if not dep in deps:
2083 deps.append(dep)
2084 continue
2085 bb.note("Couldn't find shared library provider for %s, used by files: %s" % (n[0], n[1]))
2086
2087 deps_file = os.path.join(pkgdest, pkg + ".shlibdeps")
2088 if os.path.exists(deps_file):
2089 os.remove(deps_file)
Brad Bishop64c979e2019-11-04 13:55:29 -05002090 if deps:
2091 with open(deps_file, 'w') as fd:
2092 for dep in sorted(deps):
2093 fd.write(dep + '\n')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002094}
2095
2096python package_do_pkgconfig () {
2097 import re
2098
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002099 packages = d.getVar('PACKAGES')
2100 workdir = d.getVar('WORKDIR')
2101 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002102
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002103 shlibs_dirs = d.getVar('SHLIBSDIRS').split()
2104 shlibswork_dir = d.getVar('SHLIBSWORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002105
Brad Bishop19323692019-04-05 15:28:33 -04002106 pc_re = re.compile(r'(.*)\.pc$')
2107 var_re = re.compile(r'(.*)=(.*)')
2108 field_re = re.compile(r'(.*): (.*)')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002109
2110 pkgconfig_provided = {}
2111 pkgconfig_needed = {}
2112 for pkg in packages.split():
2113 pkgconfig_provided[pkg] = []
2114 pkgconfig_needed[pkg] = []
2115 for file in pkgfiles[pkg]:
2116 m = pc_re.match(file)
2117 if m:
2118 pd = bb.data.init()
2119 name = m.group(1)
2120 pkgconfig_provided[pkg].append(name)
2121 if not os.access(file, os.R_OK):
2122 continue
Brad Bishop64c979e2019-11-04 13:55:29 -05002123 with open(file, 'r') as f:
2124 lines = f.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002125 for l in lines:
2126 m = var_re.match(l)
2127 if m:
2128 name = m.group(1)
2129 val = m.group(2)
2130 pd.setVar(name, pd.expand(val))
2131 continue
2132 m = field_re.match(l)
2133 if m:
2134 hdr = m.group(1)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002135 exp = pd.expand(m.group(2))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002136 if hdr == 'Requires':
2137 pkgconfig_needed[pkg] += exp.replace(',', ' ').split()
2138
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002139 for pkg in packages.split():
2140 pkgs_file = os.path.join(shlibswork_dir, pkg + ".pclist")
2141 if pkgconfig_provided[pkg] != []:
Brad Bishop64c979e2019-11-04 13:55:29 -05002142 with open(pkgs_file, 'w') as f:
2143 for p in pkgconfig_provided[pkg]:
2144 f.write('%s\n' % p)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002145
2146 # Go from least to most specific since the last one found wins
2147 for dir in reversed(shlibs_dirs):
2148 if not os.path.exists(dir):
2149 continue
Brad Bishop08902b02019-08-20 09:16:51 -04002150 for file in sorted(os.listdir(dir)):
Brad Bishop19323692019-04-05 15:28:33 -04002151 m = re.match(r'^(.*)\.pclist$', file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002152 if m:
2153 pkg = m.group(1)
Brad Bishop64c979e2019-11-04 13:55:29 -05002154 with open(os.path.join(dir, file)) as fd:
2155 lines = fd.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002156 pkgconfig_provided[pkg] = []
2157 for l in lines:
2158 pkgconfig_provided[pkg].append(l.rstrip())
2159
2160 for pkg in packages.split():
2161 deps = []
2162 for n in pkgconfig_needed[pkg]:
2163 found = False
2164 for k in pkgconfig_provided.keys():
2165 if n in pkgconfig_provided[k]:
2166 if k != pkg and not (k in deps):
2167 deps.append(k)
2168 found = True
2169 if found == False:
2170 bb.note("couldn't find pkgconfig module '%s' in any package" % n)
2171 deps_file = os.path.join(pkgdest, pkg + ".pcdeps")
2172 if len(deps):
Brad Bishop64c979e2019-11-04 13:55:29 -05002173 with open(deps_file, 'w') as fd:
2174 for dep in deps:
2175 fd.write(dep + '\n')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002176}
2177
2178def read_libdep_files(d):
2179 pkglibdeps = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002180 packages = d.getVar('PACKAGES').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002181 for pkg in packages:
2182 pkglibdeps[pkg] = {}
2183 for extension in ".shlibdeps", ".pcdeps", ".clilibdeps":
2184 depsfile = d.expand("${PKGDEST}/" + pkg + extension)
2185 if os.access(depsfile, os.R_OK):
Brad Bishop64c979e2019-11-04 13:55:29 -05002186 with open(depsfile) as fd:
2187 lines = fd.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002188 for l in lines:
2189 l.rstrip()
2190 deps = bb.utils.explode_dep_versions2(l)
2191 for dep in deps:
2192 if not dep in pkglibdeps[pkg]:
2193 pkglibdeps[pkg][dep] = deps[dep]
2194 return pkglibdeps
2195
2196python read_shlibdeps () {
2197 pkglibdeps = read_libdep_files(d)
2198
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002199 packages = d.getVar('PACKAGES').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002200 for pkg in packages:
Patrick Williams213cb262021-08-07 19:21:33 -05002201 rdepends = bb.utils.explode_dep_versions2(d.getVar('RDEPENDS:' + pkg) or "")
Brad Bishop19323692019-04-05 15:28:33 -04002202 for dep in sorted(pkglibdeps[pkg]):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002203 # Add the dep if it's not already there, or if no comparison is set
2204 if dep not in rdepends:
2205 rdepends[dep] = []
2206 for v in pkglibdeps[pkg][dep]:
2207 if v not in rdepends[dep]:
2208 rdepends[dep].append(v)
Patrick Williams213cb262021-08-07 19:21:33 -05002209 d.setVar('RDEPENDS:' + pkg, bb.utils.join_deps(rdepends, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002210}
2211
2212python package_depchains() {
2213 """
2214 For a given set of prefix and postfix modifiers, make those packages
2215 RRECOMMENDS on the corresponding packages for its RDEPENDS.
2216
2217 Example: If package A depends upon package B, and A's .bb emits an
2218 A-dev package, this would make A-dev Recommends: B-dev.
2219
2220 If only one of a given suffix is specified, it will take the RRECOMMENDS
2221 based on the RDEPENDS of *all* other packages. If more than one of a given
2222 suffix is specified, its will only use the RDEPENDS of the single parent
2223 package.
2224 """
2225
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002226 packages = d.getVar('PACKAGES')
2227 postfixes = (d.getVar('DEPCHAIN_POST') or '').split()
2228 prefixes = (d.getVar('DEPCHAIN_PRE') or '').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002229
2230 def pkg_adddeprrecs(pkg, base, suffix, getname, depends, d):
2231
2232 #bb.note('depends for %s is %s' % (base, depends))
Patrick Williams213cb262021-08-07 19:21:33 -05002233 rreclist = bb.utils.explode_dep_versions2(d.getVar('RRECOMMENDS:' + pkg) or "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002234
Brad Bishop19323692019-04-05 15:28:33 -04002235 for depend in sorted(depends):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002236 if depend.find('-native') != -1 or depend.find('-cross') != -1 or depend.startswith('virtual/'):
2237 #bb.note("Skipping %s" % depend)
2238 continue
2239 if depend.endswith('-dev'):
2240 depend = depend[:-4]
2241 if depend.endswith('-dbg'):
2242 depend = depend[:-4]
2243 pkgname = getname(depend, suffix)
2244 #bb.note("Adding %s for %s" % (pkgname, depend))
2245 if pkgname not in rreclist and pkgname != pkg:
2246 rreclist[pkgname] = []
2247
Patrick Williams213cb262021-08-07 19:21:33 -05002248 #bb.note('setting: RRECOMMENDS:%s=%s' % (pkg, ' '.join(rreclist)))
2249 d.setVar('RRECOMMENDS:%s' % pkg, bb.utils.join_deps(rreclist, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002250
2251 def pkg_addrrecs(pkg, base, suffix, getname, rdepends, d):
2252
2253 #bb.note('rdepends for %s is %s' % (base, rdepends))
Patrick Williams213cb262021-08-07 19:21:33 -05002254 rreclist = bb.utils.explode_dep_versions2(d.getVar('RRECOMMENDS:' + pkg) or "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002255
Brad Bishop19323692019-04-05 15:28:33 -04002256 for depend in sorted(rdepends):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002257 if depend.find('virtual-locale-') != -1:
2258 #bb.note("Skipping %s" % depend)
2259 continue
2260 if depend.endswith('-dev'):
2261 depend = depend[:-4]
2262 if depend.endswith('-dbg'):
2263 depend = depend[:-4]
2264 pkgname = getname(depend, suffix)
2265 #bb.note("Adding %s for %s" % (pkgname, depend))
2266 if pkgname not in rreclist and pkgname != pkg:
2267 rreclist[pkgname] = []
2268
Patrick Williams213cb262021-08-07 19:21:33 -05002269 #bb.note('setting: RRECOMMENDS:%s=%s' % (pkg, ' '.join(rreclist)))
2270 d.setVar('RRECOMMENDS:%s' % pkg, bb.utils.join_deps(rreclist, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002271
2272 def add_dep(list, dep):
2273 if dep not in list:
2274 list.append(dep)
2275
2276 depends = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002277 for dep in bb.utils.explode_deps(d.getVar('DEPENDS') or ""):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002278 add_dep(depends, dep)
2279
2280 rdepends = []
2281 for pkg in packages.split():
Patrick Williams213cb262021-08-07 19:21:33 -05002282 for dep in bb.utils.explode_deps(d.getVar('RDEPENDS:' + pkg) or ""):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002283 add_dep(rdepends, dep)
2284
2285 #bb.note('rdepends is %s' % rdepends)
2286
2287 def post_getname(name, suffix):
2288 return '%s%s' % (name, suffix)
2289 def pre_getname(name, suffix):
2290 return '%s%s' % (suffix, name)
2291
2292 pkgs = {}
2293 for pkg in packages.split():
2294 for postfix in postfixes:
2295 if pkg.endswith(postfix):
2296 if not postfix in pkgs:
2297 pkgs[postfix] = {}
2298 pkgs[postfix][pkg] = (pkg[:-len(postfix)], post_getname)
2299
2300 for prefix in prefixes:
2301 if pkg.startswith(prefix):
2302 if not prefix in pkgs:
2303 pkgs[prefix] = {}
2304 pkgs[prefix][pkg] = (pkg[:-len(prefix)], pre_getname)
2305
2306 if "-dbg" in pkgs:
2307 pkglibdeps = read_libdep_files(d)
2308 pkglibdeplist = []
2309 for pkg in pkglibdeps:
2310 for k in pkglibdeps[pkg]:
2311 add_dep(pkglibdeplist, k)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002312 dbgdefaultdeps = ((d.getVar('DEPCHAIN_DBGDEFAULTDEPS') == '1') or (bb.data.inherits_class('packagegroup', d)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002313
2314 for suffix in pkgs:
2315 for pkg in pkgs[suffix]:
Patrick Williams213cb262021-08-07 19:21:33 -05002316 if d.getVarFlag('RRECOMMENDS:' + pkg, 'nodeprrecs'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002317 continue
2318 (base, func) = pkgs[suffix][pkg]
2319 if suffix == "-dev":
2320 pkg_adddeprrecs(pkg, base, suffix, func, depends, d)
2321 elif suffix == "-dbg":
2322 if not dbgdefaultdeps:
2323 pkg_addrrecs(pkg, base, suffix, func, pkglibdeplist, d)
2324 continue
2325 if len(pkgs[suffix]) == 1:
2326 pkg_addrrecs(pkg, base, suffix, func, rdepends, d)
2327 else:
2328 rdeps = []
Patrick Williams213cb262021-08-07 19:21:33 -05002329 for dep in bb.utils.explode_deps(d.getVar('RDEPENDS:' + base) or ""):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002330 add_dep(rdeps, dep)
2331 pkg_addrrecs(pkg, base, suffix, func, rdeps, d)
2332}
2333
2334# Since bitbake can't determine which variables are accessed during package
2335# iteration, we need to list them here:
Andrew Geissler1e34c2d2020-05-29 16:02:59 -05002336PACKAGEVARS = "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 -05002337
Andrew Geissler82c905d2020-04-13 13:39:40 -05002338def gen_packagevar(d, pkgvars="PACKAGEVARS"):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002339 ret = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002340 pkgs = (d.getVar("PACKAGES") or "").split()
Andrew Geissler82c905d2020-04-13 13:39:40 -05002341 vars = (d.getVar(pkgvars) or "").split()
2342 for v in vars:
2343 ret.append(v)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002344 for p in pkgs:
2345 for v in vars:
Patrick Williams213cb262021-08-07 19:21:33 -05002346 ret.append(v + ":" + p)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002347
2348 # Ensure that changes to INCOMPATIBLE_LICENSE re-run do_package for
2349 # affected recipes.
2350 ret.append('LICENSE_EXCLUSION-%s' % p)
2351 return " ".join(ret)
2352
2353PACKAGE_PREPROCESS_FUNCS ?= ""
2354# Functions for setting up PKGD
2355PACKAGEBUILDPKGD ?= " \
Brad Bishop96ff1982019-08-19 13:50:42 -04002356 package_prepare_pkgdata \
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002357 perform_packagecopy \
2358 ${PACKAGE_PREPROCESS_FUNCS} \
2359 split_and_strip_files \
2360 fixup_perms \
2361 "
2362# Functions which split PKGD up into separate packages
2363PACKAGESPLITFUNCS ?= " \
2364 package_do_split_locales \
2365 populate_packages"
2366# Functions which process metadata based on split packages
2367PACKAGEFUNCS += " \
2368 package_fixsymlinks \
2369 package_name_hook \
2370 package_do_filedeps \
2371 package_do_shlibs \
2372 package_do_pkgconfig \
2373 read_shlibdeps \
2374 package_depchains \
2375 emit_pkgdata"
2376
2377python do_package () {
2378 # Change the following version to cause sstate to invalidate the package
2379 # cache. This is useful if an item this class depends on changes in a
2380 # way that the output of this class changes. rpmdeps is a good example
2381 # as any change to rpmdeps requires this to be rerun.
Andrew Geissler6ce62a22020-11-30 19:58:47 -06002382 # PACKAGE_BBCLASS_VERSION = "4"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002383
2384 # Init cachedpath
2385 global cpath
2386 cpath = oe.cachedpath.CachedPath()
2387
2388 ###########################################################################
2389 # Sanity test the setup
2390 ###########################################################################
2391
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002392 packages = (d.getVar('PACKAGES') or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002393 if len(packages) < 1:
2394 bb.debug(1, "No packages to build, skipping do_package")
2395 return
2396
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002397 workdir = d.getVar('WORKDIR')
2398 outdir = d.getVar('DEPLOY_DIR')
2399 dest = d.getVar('D')
2400 dvar = d.getVar('PKGD')
2401 pn = d.getVar('PN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002402
2403 if not workdir or not outdir or not dest or not dvar or not pn:
2404 msg = "WORKDIR, DEPLOY_DIR, D, PN and PKGD all must be defined, unable to package"
2405 package_qa_handle_error("var-undefined", msg, d)
2406 return
2407
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002408 bb.build.exec_func("package_convert_pr_autoinc", d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002409
2410 ###########################################################################
2411 # Optimisations
2412 ###########################################################################
2413
2414 # Continually expanding complex expressions is inefficient, particularly
2415 # when we write to the datastore and invalidate the expansion cache. This
2416 # code pre-expands some frequently used variables
2417
2418 def expandVar(x, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002419 d.setVar(x, d.getVar(x))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002420
2421 for x in 'PN', 'PV', 'BPN', 'TARGET_SYS', 'EXTENDPRAUTO':
2422 expandVar(x, d)
2423
2424 ###########################################################################
2425 # Setup PKGD (from D)
2426 ###########################################################################
2427
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002428 for f in (d.getVar('PACKAGEBUILDPKGD') or '').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002429 bb.build.exec_func(f, d)
2430
2431 ###########################################################################
2432 # Split up PKGD into PKGDEST
2433 ###########################################################################
2434
2435 cpath = oe.cachedpath.CachedPath()
2436
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002437 for f in (d.getVar('PACKAGESPLITFUNCS') or '').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002438 bb.build.exec_func(f, d)
2439
2440 ###########################################################################
2441 # Process PKGDEST
2442 ###########################################################################
2443
2444 # Build global list of files in each split package
2445 global pkgfiles
2446 pkgfiles = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002447 packages = d.getVar('PACKAGES').split()
2448 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002449 for pkg in packages:
2450 pkgfiles[pkg] = []
2451 for walkroot, dirs, files in cpath.walk(pkgdest + "/" + pkg):
2452 for file in files:
2453 pkgfiles[pkg].append(walkroot + os.sep + file)
2454
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002455 for f in (d.getVar('PACKAGEFUNCS') or '').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002456 bb.build.exec_func(f, d)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05002457
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002458 qa_sane = d.getVar("QA_SANE")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05002459 if not qa_sane:
2460 bb.fatal("Fatal QA errors found, failing task.")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002461}
2462
2463do_package[dirs] = "${SHLIBSWORKDIR} ${PKGDESTWORK} ${D}"
2464do_package[vardeps] += "${PACKAGEBUILDPKGD} ${PACKAGESPLITFUNCS} ${PACKAGEFUNCS} ${@gen_packagevar(d)}"
2465addtask package after do_install
2466
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002467SSTATETASKS += "do_package"
2468do_package[cleandirs] = "${PKGDEST} ${PKGDESTWORK}"
2469do_package[sstate-plaindirs] = "${PKGD} ${PKGDEST} ${PKGDESTWORK}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002470do_package_setscene[dirs] = "${STAGING_DIR}"
2471
2472python do_package_setscene () {
2473 sstate_setscene(d)
2474}
2475addtask do_package_setscene
2476
Brad Bishopc68388fc2019-08-26 01:33:31 -04002477# Copy from PKGDESTWORK to tempdirectory as tempdirectory can be cleaned at both
2478# do_package_setscene and do_packagedata_setscene leading to races
2479python do_packagedata () {
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002480 bb.build.exec_func("package_get_auto_pr", d)
2481
Brad Bishopc68388fc2019-08-26 01:33:31 -04002482 src = d.expand("${PKGDESTWORK}")
2483 dest = d.expand("${WORKDIR}/pkgdata-pdata-input")
2484 oe.path.copyhardlinktree(src, dest)
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002485
2486 bb.build.exec_func("packagedata_translate_pr_autoinc", d)
2487}
Andrew Geisslerd1e89492021-02-12 15:35:20 -06002488do_packagedata[cleandirs] += "${WORKDIR}/pkgdata-pdata-input"
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002489
2490# Translate the EXTENDPRAUTO and AUTOINC to the final values
2491packagedata_translate_pr_autoinc() {
2492 find ${WORKDIR}/pkgdata-pdata-input -type f | xargs --no-run-if-empty \
2493 sed -e 's,@PRSERV_PV_AUTOINC@,${PRSERV_PV_AUTOINC},g' \
2494 -e 's,@EXTENDPRAUTO@,${EXTENDPRAUTO},g' -i
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002495}
2496
2497addtask packagedata before do_build after do_package
2498
2499SSTATETASKS += "do_packagedata"
Brad Bishopc68388fc2019-08-26 01:33:31 -04002500do_packagedata[sstate-inputdirs] = "${WORKDIR}/pkgdata-pdata-input"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002501do_packagedata[sstate-outputdirs] = "${PKGDATA_DIR}"
Brad Bishop316dfdd2018-06-25 12:45:53 -04002502do_packagedata[stamp-extra-info] = "${MACHINE_ARCH}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002503
2504python do_packagedata_setscene () {
2505 sstate_setscene(d)
2506}
2507addtask do_packagedata_setscene
2508
2509#
2510# Helper functions for the package writing classes
2511#
2512
2513def mapping_rename_hook(d):
2514 """
2515 Rewrite variables to account for package renaming in things
2516 like debian.bbclass or manual PKG variable name changes
2517 """
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002518 pkg = d.getVar("PKG")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002519 runtime_mapping_rename("RDEPENDS", pkg, d)
2520 runtime_mapping_rename("RRECOMMENDS", pkg, d)
2521 runtime_mapping_rename("RSUGGESTS", pkg, d)