blob: c4c5515d5df47a105404af79f9c5200dc8b7746c [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
1227 #
1228 # First lets process debug splitting
1229 #
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001230 if (d.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT') != '1'):
Brad Bishop19323692019-04-05 15:28:33 -04001231 results = oe.utils.multiprocess_launch(splitdebuginfo, list(elffiles), d, extraargs=(dvar, debugdir, debuglibdir, debugappend, debugsrcdir, d))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001232
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001233 if debugsrcdir and not hostos.startswith("mingw"):
Andrew Geissler82c905d2020-04-13 13:39:40 -05001234 if (d.getVar('PACKAGE_DEBUG_STATIC_SPLIT') == '1'):
1235 results = oe.utils.multiprocess_launch(splitstaticdebuginfo, staticlibs, d, extraargs=(dvar, debugstaticdir, debugstaticlibdir, debugstaticappend, debugsrcdir, d))
1236 else:
1237 for file in staticlibs:
1238 results.append( (file,source_info(file, d)) )
Brad Bishop19323692019-04-05 15:28:33 -04001239
1240 sources = set()
1241 for r in results:
1242 sources.update(r[1])
Brad Bishop316dfdd2018-06-25 12:45:53 -04001243
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001244 # Hardlink our debug symbols to the other hardlink copies
1245 for ref in inodes:
1246 if len(inodes[ref]) == 1:
1247 continue
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001248
1249 target = inodes[ref][0][len(dvar):]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001250 for file in inodes[ref][1:]:
1251 src = file[len(dvar):]
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001252 dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(target) + debugappend
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001253 fpath = dvar + dest
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001254 ftarget = dvar + debuglibdir + os.path.dirname(target) + debugdir + "/" + os.path.basename(target) + debugappend
1255 bb.utils.mkdirhier(os.path.dirname(fpath))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001256 # Only one hardlink of separated debug info file in each directory
1257 if not os.access(fpath, os.R_OK):
1258 #bb.note("Link %s -> %s" % (fpath, ftarget))
1259 os.link(ftarget, fpath)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001260
1261 # Create symlinks for all cases we were able to split symbols
1262 for file in symlinks:
1263 src = file[len(dvar):]
1264 dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(src) + debugappend
1265 fpath = dvar + dest
1266 # Skip it if the target doesn't exist
1267 try:
1268 s = os.stat(fpath)
1269 except OSError as e:
1270 (err, strerror) = e.args
1271 if err != errno.ENOENT:
1272 raise
1273 continue
1274
1275 ltarget = symlinks[file]
1276 lpath = os.path.dirname(ltarget)
1277 lbase = os.path.basename(ltarget)
1278 ftarget = ""
1279 if lpath and lpath != ".":
1280 ftarget += lpath + debugdir + "/"
1281 ftarget += lbase + debugappend
1282 if lpath.startswith(".."):
1283 ftarget = os.path.join("..", ftarget)
1284 bb.utils.mkdirhier(os.path.dirname(fpath))
1285 #bb.note("Symlink %s -> %s" % (fpath, ftarget))
1286 os.symlink(ftarget, fpath)
1287
1288 # Process the debugsrcdir if requested...
1289 # This copies and places the referenced sources for later debugging...
Brad Bishop19323692019-04-05 15:28:33 -04001290 copydebugsources(debugsrcdir, sources, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001291 #
1292 # End of debug splitting
1293 #
1294
1295 #
1296 # Now lets go back over things and strip them
1297 #
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001298 if (d.getVar('INHIBIT_PACKAGE_STRIP') != '1'):
1299 strip = d.getVar("STRIP")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001300 sfiles = []
1301 for file in elffiles:
1302 elf_file = int(elffiles[file])
1303 #bb.note("Strip %s" % file)
1304 sfiles.append((file, elf_file, strip))
1305 for f in kernmods:
1306 sfiles.append((f, 16, strip))
Andrew Geissler82c905d2020-04-13 13:39:40 -05001307 if (d.getVar('PACKAGE_STRIP_STATIC') == '1' or d.getVar('PACKAGE_DEBUG_STATIC_SPLIT') == '1'):
1308 for f in staticlibs:
1309 sfiles.append((f, 16, strip))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001310
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001311 oe.utils.multiprocess_launch(oe.package.runstrip, sfiles, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001312
Andrew Geissler82c905d2020-04-13 13:39:40 -05001313 # Build "minidebuginfo" and reinject it back into the stripped binaries
1314 if d.getVar('PACKAGE_MINIDEBUGINFO') == '1':
1315 oe.utils.multiprocess_launch(inject_minidebuginfo, list(elffiles), d,
1316 extraargs=(dvar, debugdir, debuglibdir, debugappend, debugsrcdir, d))
1317
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001318 #
1319 # End of strip
1320 #
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001321 os.chdir(oldcwd)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001322}
1323
1324python populate_packages () {
1325 import glob, re
1326
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001327 workdir = d.getVar('WORKDIR')
1328 outdir = d.getVar('DEPLOY_DIR')
1329 dvar = d.getVar('PKGD')
Brad Bishop19323692019-04-05 15:28:33 -04001330 packages = d.getVar('PACKAGES').split()
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001331 pn = d.getVar('PN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001332
1333 bb.utils.mkdirhier(outdir)
1334 os.chdir(dvar)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001335
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001336 autodebug = not (d.getVar("NOAUTOPACKAGEDEBUG") or False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001337
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001338 split_source_package = (d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-with-srcpkg')
1339
Brad Bishop19323692019-04-05 15:28:33 -04001340 # If debug-with-srcpkg mode is enabled then add the source package if it
1341 # doesn't exist and add the source file contents to the source package.
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001342 if split_source_package:
1343 src_package_name = ('%s-src' % d.getVar('PN'))
Brad Bishop19323692019-04-05 15:28:33 -04001344 if not src_package_name in packages:
1345 packages.append(src_package_name)
Patrick Williams213cb262021-08-07 19:21:33 -05001346 d.setVar('FILES:%s' % src_package_name, '/usr/src/debug')
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001347
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001348 # Sanity check PACKAGES for duplicates
Brad Bishop316dfdd2018-06-25 12:45:53 -04001349 # Sanity should be moved to sanity.bbclass once we have the infrastructure
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001350 package_dict = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001351
Brad Bishop19323692019-04-05 15:28:33 -04001352 for i, pkg in enumerate(packages):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001353 if pkg in package_dict:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001354 msg = "%s is listed in PACKAGES multiple times, this leads to packaging errors." % pkg
1355 package_qa_handle_error("packages-list", msg, d)
Brad Bishop19323692019-04-05 15:28:33 -04001356 # Ensure the source package gets the chance to pick up the source files
1357 # before the debug package by ordering it first in PACKAGES. Whether it
1358 # actually picks up any source files is controlled by
1359 # PACKAGE_DEBUG_SPLIT_STYLE.
1360 elif pkg.endswith("-src"):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001361 package_dict[pkg] = (10, i)
1362 elif autodebug and pkg.endswith("-dbg"):
1363 package_dict[pkg] = (30, i)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001364 else:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001365 package_dict[pkg] = (50, i)
Brad Bishop19323692019-04-05 15:28:33 -04001366 packages = sorted(package_dict.keys(), key=package_dict.get)
1367 d.setVar('PACKAGES', ' '.join(packages))
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001368 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001369
1370 seen = []
1371
1372 # os.mkdir masks the permissions with umask so we have to unset it first
1373 oldumask = os.umask(0)
1374
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001375 debug = []
1376 for root, dirs, files in cpath.walk(dvar):
1377 dir = root[len(dvar):]
1378 if not dir:
1379 dir = os.sep
1380 for f in (files + dirs):
1381 path = "." + os.path.join(dir, f)
Andrew Geissler82c905d2020-04-13 13:39:40 -05001382 if "/.debug/" in path or "/.debug-static/" in path or path.endswith("/.debug"):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001383 debug.append(path)
1384
Brad Bishop19323692019-04-05 15:28:33 -04001385 for pkg in packages:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001386 root = os.path.join(pkgdest, pkg)
1387 bb.utils.mkdirhier(root)
1388
Patrick Williams213cb262021-08-07 19:21:33 -05001389 filesvar = d.getVar('FILES:%s' % pkg) or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001390 if "//" in filesvar:
1391 msg = "FILES variable for package %s contains '//' which is invalid. Attempting to fix this but you should correct the metadata.\n" % pkg
1392 package_qa_handle_error("files-invalid", msg, d)
1393 filesvar.replace("//", "/")
1394
1395 origfiles = filesvar.split()
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001396 files, symlink_paths = files_from_filevars(origfiles)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001397
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001398 if autodebug and pkg.endswith("-dbg"):
1399 files.extend(debug)
1400
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001401 for file in files:
1402 if (not cpath.islink(file)) and (not cpath.exists(file)):
1403 continue
1404 if file in seen:
1405 continue
1406 seen.append(file)
1407
1408 def mkdir(src, dest, p):
1409 src = os.path.join(src, p)
1410 dest = os.path.join(dest, p)
1411 fstat = cpath.stat(src)
Brad Bishop96ff1982019-08-19 13:50:42 -04001412 os.mkdir(dest)
1413 os.chmod(dest, fstat.st_mode)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001414 os.chown(dest, fstat.st_uid, fstat.st_gid)
1415 if p not in seen:
1416 seen.append(p)
1417 cpath.updatecache(dest)
1418
1419 def mkdir_recurse(src, dest, paths):
1420 if cpath.exists(dest + '/' + paths):
1421 return
1422 while paths.startswith("./"):
1423 paths = paths[2:]
1424 p = "."
1425 for c in paths.split("/"):
1426 p = os.path.join(p, c)
1427 if not cpath.exists(os.path.join(dest, p)):
1428 mkdir(src, dest, p)
1429
1430 if cpath.isdir(file) and not cpath.islink(file):
1431 mkdir_recurse(dvar, root, file)
1432 continue
1433
1434 mkdir_recurse(dvar, root, os.path.dirname(file))
1435 fpath = os.path.join(root,file)
1436 if not cpath.islink(file):
1437 os.link(file, fpath)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001438 continue
1439 ret = bb.utils.copyfile(file, fpath)
1440 if ret is False or ret == 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001441 bb.fatal("File population failed")
1442
1443 # Check if symlink paths exist
1444 for file in symlink_paths:
1445 if not os.path.exists(os.path.join(root,file)):
1446 bb.fatal("File '%s' cannot be packaged into '%s' because its "
1447 "parent directory structure does not exist. One of "
1448 "its parent directories is a symlink whose target "
1449 "directory is not included in the package." %
1450 (file, pkg))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001451
1452 os.umask(oldumask)
1453 os.chdir(workdir)
1454
1455 # Handle LICENSE_EXCLUSION
1456 package_list = []
Brad Bishop19323692019-04-05 15:28:33 -04001457 for pkg in packages:
Andrew Geissler82c905d2020-04-13 13:39:40 -05001458 licenses = d.getVar('LICENSE_EXCLUSION-' + pkg)
1459 if licenses:
1460 msg = "Excluding %s from packaging as it has incompatible license(s): %s" % (pkg, licenses)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001461 package_qa_handle_error("incompatible-license", msg, d)
1462 else:
1463 package_list.append(pkg)
1464 d.setVar('PACKAGES', ' '.join(package_list))
1465
1466 unshipped = []
1467 for root, dirs, files in cpath.walk(dvar):
1468 dir = root[len(dvar):]
1469 if not dir:
1470 dir = os.sep
1471 for f in (files + dirs):
1472 path = os.path.join(dir, f)
1473 if ('.' + path) not in seen:
1474 unshipped.append(path)
1475
1476 if unshipped != []:
1477 msg = pn + ": Files/directories were installed but not shipped in any package:"
Patrick Williams213cb262021-08-07 19:21:33 -05001478 if "installed-vs-shipped" in (d.getVar('INSANE_SKIP:' + pn) or "").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001479 bb.note("Package %s skipping QA tests: installed-vs-shipped" % pn)
1480 else:
1481 for f in unshipped:
1482 msg = msg + "\n " + f
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001483 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"
1484 msg = msg + "%s: %d installed and not shipped files." % (pn, len(unshipped))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001485 package_qa_handle_error("installed-vs-shipped", msg, d)
1486}
1487populate_packages[dirs] = "${D}"
1488
1489python package_fixsymlinks () {
1490 import errno
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001491 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001492 packages = d.getVar("PACKAGES", False).split()
1493
1494 dangling_links = {}
1495 pkg_files = {}
1496 for pkg in packages:
1497 dangling_links[pkg] = []
1498 pkg_files[pkg] = []
1499 inst_root = os.path.join(pkgdest, pkg)
1500 for path in pkgfiles[pkg]:
1501 rpath = path[len(inst_root):]
1502 pkg_files[pkg].append(rpath)
1503 rtarget = cpath.realpath(path, inst_root, True, assume_dir = True)
1504 if not cpath.lexists(rtarget):
1505 dangling_links[pkg].append(os.path.normpath(rtarget[len(inst_root):]))
1506
1507 newrdepends = {}
1508 for pkg in dangling_links:
1509 for l in dangling_links[pkg]:
1510 found = False
1511 bb.debug(1, "%s contains dangling link %s" % (pkg, l))
1512 for p in packages:
1513 if l in pkg_files[p]:
1514 found = True
1515 bb.debug(1, "target found in %s" % p)
1516 if p == pkg:
1517 break
1518 if pkg not in newrdepends:
1519 newrdepends[pkg] = []
1520 newrdepends[pkg].append(p)
1521 break
1522 if found == False:
1523 bb.note("%s contains dangling symlink to %s" % (pkg, l))
1524
1525 for pkg in newrdepends:
Patrick Williams213cb262021-08-07 19:21:33 -05001526 rdepends = bb.utils.explode_dep_versions2(d.getVar('RDEPENDS:' + pkg) or "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001527 for p in newrdepends[pkg]:
1528 if p not in rdepends:
1529 rdepends[p] = []
Patrick Williams213cb262021-08-07 19:21:33 -05001530 d.setVar('RDEPENDS:' + pkg, bb.utils.join_deps(rdepends, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001531}
1532
1533
1534python package_package_name_hook() {
1535 """
1536 A package_name_hook function can be used to rewrite the package names by
1537 changing PKG. For an example, see debian.bbclass.
1538 """
1539 pass
1540}
1541
1542EXPORT_FUNCTIONS package_name_hook
1543
1544
1545PKGDESTWORK = "${WORKDIR}/pkgdata"
1546
Andrew Geissler1e34c2d2020-05-29 16:02:59 -05001547PKGDATA_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 -04001548
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001549python emit_pkgdata() {
1550 from glob import glob
1551 import json
1552
Brad Bishop316dfdd2018-06-25 12:45:53 -04001553 def process_postinst_on_target(pkg, mlprefix):
Patrick Williams213cb262021-08-07 19:21:33 -05001554 pkgval = d.getVar('PKG:%s' % pkg)
Brad Bishop96ff1982019-08-19 13:50:42 -04001555 if pkgval is None:
1556 pkgval = pkg
1557
Brad Bishop316dfdd2018-06-25 12:45:53 -04001558 defer_fragment = """
1559if [ -n "$D" ]; then
1560 $INTERCEPT_DIR/postinst_intercept delay_to_first_boot %s mlprefix=%s
1561 exit 0
1562fi
Brad Bishop96ff1982019-08-19 13:50:42 -04001563""" % (pkgval, mlprefix)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001564
Patrick Williams213cb262021-08-07 19:21:33 -05001565 postinst = d.getVar('pkg_postinst:%s' % pkg)
1566 postinst_ontarget = d.getVar('pkg_postinst_ontarget:%s' % pkg)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001567
1568 if postinst_ontarget:
1569 bb.debug(1, 'adding deferred pkg_postinst_ontarget() to pkg_postinst() for %s' % pkg)
1570 if not postinst:
1571 postinst = '#!/bin/sh\n'
1572 postinst += defer_fragment
1573 postinst += postinst_ontarget
Patrick Williams213cb262021-08-07 19:21:33 -05001574 d.setVar('pkg_postinst:%s' % pkg, postinst)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001575
1576 def add_set_e_to_scriptlets(pkg):
1577 for scriptlet_name in ('pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm'):
Patrick Williams213cb262021-08-07 19:21:33 -05001578 scriptlet = d.getVar('%s:%s' % (scriptlet_name, pkg))
Brad Bishop316dfdd2018-06-25 12:45:53 -04001579 if scriptlet:
1580 scriptlet_split = scriptlet.split('\n')
1581 if scriptlet_split[0].startswith("#!"):
1582 scriptlet = scriptlet_split[0] + "\nset -e\n" + "\n".join(scriptlet_split[1:])
1583 else:
1584 scriptlet = "set -e\n" + "\n".join(scriptlet_split[0:])
Patrick Williams213cb262021-08-07 19:21:33 -05001585 d.setVar('%s:%s' % (scriptlet_name, pkg), scriptlet)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001586
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001587 def write_if_exists(f, pkg, var):
1588 def encode(str):
1589 import codecs
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001590 c = codecs.getencoder("unicode_escape")
1591 return c(str)[0].decode("latin1")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001592
Patrick Williams213cb262021-08-07 19:21:33 -05001593 val = d.getVar('%s:%s' % (var, pkg))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001594 if val:
Patrick Williams213cb262021-08-07 19:21:33 -05001595 f.write('%s:%s: %s\n' % (var, pkg, encode(val)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001596 return val
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001597 val = d.getVar('%s' % (var))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001598 if val:
1599 f.write('%s: %s\n' % (var, encode(val)))
1600 return val
1601
1602 def write_extra_pkgs(variants, pn, packages, pkgdatadir):
1603 for variant in variants:
1604 with open("%s/%s-%s" % (pkgdatadir, variant, pn), 'w') as fd:
1605 fd.write("PACKAGES: %s\n" % ' '.join(
1606 map(lambda pkg: '%s-%s' % (variant, pkg), packages.split())))
1607
1608 def write_extra_runtime_pkgs(variants, packages, pkgdatadir):
1609 for variant in variants:
1610 for pkg in packages.split():
1611 ml_pkg = "%s-%s" % (variant, pkg)
1612 subdata_file = "%s/runtime/%s" % (pkgdatadir, ml_pkg)
1613 with open(subdata_file, 'w') as fd:
Patrick Williams213cb262021-08-07 19:21:33 -05001614 fd.write("PKG:%s: %s" % (ml_pkg, pkg))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001615
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001616 packages = d.getVar('PACKAGES')
1617 pkgdest = d.getVar('PKGDEST')
1618 pkgdatadir = d.getVar('PKGDESTWORK')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001619
Brad Bishop64c979e2019-11-04 13:55:29 -05001620 data_file = pkgdatadir + d.expand("/${PN}")
1621 with open(data_file, 'w') as fd:
1622 fd.write("PACKAGES: %s\n" % packages)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001623
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001624 pn = d.getVar('PN')
1625 global_variants = (d.getVar('MULTILIB_GLOBAL_VARIANTS') or "").split()
1626 variants = (d.getVar('MULTILIB_VARIANTS') or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001627
1628 if bb.data.inherits_class('kernel', d) or bb.data.inherits_class('module-base', d):
1629 write_extra_pkgs(variants, pn, packages, pkgdatadir)
1630
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001631 if bb.data.inherits_class('allarch', d) and not variants \
1632 and not bb.data.inherits_class('packagegroup', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001633 write_extra_pkgs(global_variants, pn, packages, pkgdatadir)
1634
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001635 workdir = d.getVar('WORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001636
1637 for pkg in packages.split():
Patrick Williams213cb262021-08-07 19:21:33 -05001638 pkgval = d.getVar('PKG:%s' % pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001639 if pkgval is None:
1640 pkgval = pkg
Patrick Williams213cb262021-08-07 19:21:33 -05001641 d.setVar('PKG:%s' % pkg, pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001642
1643 pkgdestpkg = os.path.join(pkgdest, pkg)
1644 files = {}
1645 total_size = 0
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001646 seen = set()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001647 for f in pkgfiles[pkg]:
1648 relpth = os.path.relpath(f, pkgdestpkg)
1649 fstat = os.lstat(f)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001650 files[os.sep + relpth] = fstat.st_size
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001651 if fstat.st_ino not in seen:
1652 seen.add(fstat.st_ino)
1653 total_size += fstat.st_size
Andrew Geisslerd159c7f2021-09-02 21:05:58 -05001654 d.setVar('FILES_INFO:' + pkg , json.dumps(files, sort_keys=True))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001655
Brad Bishop316dfdd2018-06-25 12:45:53 -04001656 process_postinst_on_target(pkg, d.getVar("MLPREFIX"))
1657 add_set_e_to_scriptlets(pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001658
Brad Bishop15ae2502019-06-18 21:44:24 -04001659 subdata_file = pkgdatadir + "/runtime/%s" % pkg
1660 with open(subdata_file, 'w') as sf:
1661 for var in (d.getVar('PKGDATA_VARS') or "").split():
1662 val = write_if_exists(sf, pkg, var)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001663
Brad Bishop15ae2502019-06-18 21:44:24 -04001664 write_if_exists(sf, pkg, 'FILERPROVIDESFLIST')
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001665 for dfile in (d.getVar('FILERPROVIDESFLIST:' + pkg) or "").split():
1666 write_if_exists(sf, pkg, 'FILERPROVIDES:' + dfile)
Brad Bishop15ae2502019-06-18 21:44:24 -04001667
1668 write_if_exists(sf, pkg, 'FILERDEPENDSFLIST')
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001669 for dfile in (d.getVar('FILERDEPENDSFLIST:' + pkg) or "").split():
1670 write_if_exists(sf, pkg, 'FILERDEPENDS:' + dfile)
Brad Bishop15ae2502019-06-18 21:44:24 -04001671
Andrew Geisslerd159c7f2021-09-02 21:05:58 -05001672 sf.write('%s:%s: %d\n' % ('PKGSIZE', pkg, total_size))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001673
1674 # Symlinks needed for rprovides lookup
Patrick Williams213cb262021-08-07 19:21:33 -05001675 rprov = d.getVar('RPROVIDES:%s' % pkg) or d.getVar('RPROVIDES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001676 if rprov:
Andrew Geisslerc9f78652020-09-18 14:11:35 -05001677 for p in bb.utils.explode_deps(rprov):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001678 subdata_sym = pkgdatadir + "/runtime-rprovides/%s/%s" % (p, pkg)
1679 bb.utils.mkdirhier(os.path.dirname(subdata_sym))
1680 oe.path.symlink("../../runtime/%s" % pkg, subdata_sym, True)
1681
Patrick Williams213cb262021-08-07 19:21:33 -05001682 allow_empty = d.getVar('ALLOW_EMPTY:%s' % pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001683 if not allow_empty:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001684 allow_empty = d.getVar('ALLOW_EMPTY')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001685 root = "%s/%s" % (pkgdest, pkg)
1686 os.chdir(root)
1687 g = glob('*')
1688 if g or allow_empty == "1":
1689 # Symlinks needed for reverse lookups (from the final package name)
1690 subdata_sym = pkgdatadir + "/runtime-reverse/%s" % pkgval
1691 oe.path.symlink("../runtime/%s" % pkg, subdata_sym, True)
1692
1693 packagedfile = pkgdatadir + '/runtime/%s.packaged' % pkg
1694 open(packagedfile, 'w').close()
1695
1696 if bb.data.inherits_class('kernel', d) or bb.data.inherits_class('module-base', d):
1697 write_extra_runtime_pkgs(variants, packages, pkgdatadir)
1698
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001699 if bb.data.inherits_class('allarch', d) and not variants \
1700 and not bb.data.inherits_class('packagegroup', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001701 write_extra_runtime_pkgs(global_variants, packages, pkgdatadir)
1702
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001703}
1704emit_pkgdata[dirs] = "${PKGDESTWORK}/runtime ${PKGDESTWORK}/runtime-reverse ${PKGDESTWORK}/runtime-rprovides"
1705
1706ldconfig_postinst_fragment() {
1707if [ x"$D" = "x" ]; then
1708 if [ -x /sbin/ldconfig ]; then /sbin/ldconfig ; fi
1709fi
1710}
1711
Andrew Geissler90fd73c2021-03-05 15:25:55 -06001712RPMDEPS = "${STAGING_LIBDIR_NATIVE}/rpm/rpmdeps --alldeps --define '__font_provides %{nil}'"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001713
1714# Collect perfile run-time dependency metadata
1715# Output:
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001716# FILERPROVIDESFLIST:pkg - list of all files w/ deps
1717# FILERPROVIDES:filepath:pkg - per file dep
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001718#
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001719# FILERDEPENDSFLIST:pkg - list of all files w/ deps
1720# FILERDEPENDS:filepath:pkg - per file dep
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001721
1722python package_do_filedeps() {
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001723 if d.getVar('SKIP_FILEDEPS') == '1':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001724 return
1725
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001726 pkgdest = d.getVar('PKGDEST')
1727 packages = d.getVar('PACKAGES')
1728 rpmdeps = d.getVar('RPMDEPS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001729
1730 def chunks(files, n):
1731 return [files[i:i+n] for i in range(0, len(files), n)]
1732
1733 pkglist = []
1734 for pkg in packages.split():
Patrick Williams213cb262021-08-07 19:21:33 -05001735 if d.getVar('SKIP_FILEDEPS:' + pkg) == '1':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001736 continue
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001737 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 -05001738 continue
1739 for files in chunks(pkgfiles[pkg], 100):
1740 pkglist.append((pkg, files, rpmdeps, pkgdest))
1741
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001742 processed = oe.utils.multiprocess_launch(oe.package.filedeprunner, pkglist, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001743
1744 provides_files = {}
1745 requires_files = {}
1746
1747 for result in processed:
1748 (pkg, provides, requires) = result
1749
1750 if pkg not in provides_files:
1751 provides_files[pkg] = []
1752 if pkg not in requires_files:
1753 requires_files[pkg] = []
1754
Brad Bishop19323692019-04-05 15:28:33 -04001755 for file in sorted(provides):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001756 provides_files[pkg].append(file)
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001757 key = "FILERPROVIDES:" + file + ":" + pkg
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001758 d.appendVar(key, " " + " ".join(provides[file]))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001759
Brad Bishop19323692019-04-05 15:28:33 -04001760 for file in sorted(requires):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001761 requires_files[pkg].append(file)
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001762 key = "FILERDEPENDS:" + file + ":" + pkg
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001763 d.appendVar(key, " " + " ".join(requires[file]))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001764
1765 for pkg in requires_files:
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001766 d.setVar("FILERDEPENDSFLIST:" + pkg, " ".join(requires_files[pkg]))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001767 for pkg in provides_files:
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001768 d.setVar("FILERPROVIDESFLIST:" + pkg, " ".join(provides_files[pkg]))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001769}
1770
Brad Bishop96ff1982019-08-19 13:50:42 -04001771SHLIBSDIRS = "${WORKDIR_PKGDATA}/${MLPREFIX}shlibs2"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001772SHLIBSWORKDIR = "${PKGDESTWORK}/${MLPREFIX}shlibs2"
1773
1774python package_do_shlibs() {
Brad Bishop00e122a2019-10-05 11:10:57 -04001775 import itertools
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001776 import re, pipes
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001777 import subprocess
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001778
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001779 exclude_shlibs = d.getVar('EXCLUDE_FROM_SHLIBS', False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001780 if exclude_shlibs:
1781 bb.note("not generating shlibs")
1782 return
1783
Brad Bishop19323692019-04-05 15:28:33 -04001784 lib_re = re.compile(r"^.*\.so")
1785 libdir_re = re.compile(r".*/%s$" % d.getVar('baselib'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001786
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001787 packages = d.getVar('PACKAGES')
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001788
1789 shlib_pkgs = []
1790 exclusion_list = d.getVar("EXCLUDE_PACKAGES_FROM_SHLIBS")
1791 if exclusion_list:
1792 for pkg in packages.split():
1793 if pkg not in exclusion_list.split():
1794 shlib_pkgs.append(pkg)
1795 else:
1796 bb.note("not generating shlibs for %s" % pkg)
1797 else:
1798 shlib_pkgs = packages.split()
1799
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001800 hostos = d.getVar('HOST_OS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001801
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001802 workdir = d.getVar('WORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001803
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001804 ver = d.getVar('PKGV')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001805 if not ver:
1806 msg = "PKGV not defined"
1807 package_qa_handle_error("pkgv-undefined", msg, d)
1808 return
1809
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001810 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001811
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001812 shlibswork_dir = d.getVar('SHLIBSWORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001813
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001814 def linux_so(file, pkg, pkgver, d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001815 needs_ldconfig = False
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001816 needed = set()
1817 sonames = set()
1818 renames = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001819 ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '')
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001820 cmd = d.getVar('OBJDUMP') + " -p " + pipes.quote(file) + " 2>/dev/null"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001821 fd = os.popen(cmd)
1822 lines = fd.readlines()
1823 fd.close()
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001824 rpath = tuple()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001825 for l in lines:
Brad Bishop19323692019-04-05 15:28:33 -04001826 m = re.match(r"\s+RPATH\s+([^\s]*)", l)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001827 if m:
1828 rpaths = m.group(1).replace("$ORIGIN", ldir).split(":")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001829 rpath = tuple(map(os.path.normpath, rpaths))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001830 for l in lines:
Brad Bishop19323692019-04-05 15:28:33 -04001831 m = re.match(r"\s+NEEDED\s+([^\s]*)", l)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001832 if m:
1833 dep = m.group(1)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001834 if dep not in needed:
1835 needed.add((dep, file, rpath))
Brad Bishop19323692019-04-05 15:28:33 -04001836 m = re.match(r"\s+SONAME\s+([^\s]*)", l)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001837 if m:
1838 this_soname = m.group(1)
1839 prov = (this_soname, ldir, pkgver)
1840 if not prov in sonames:
1841 # if library is private (only used by package) then do not build shlib for it
Brad Bishop79641f22019-09-10 07:20:22 -04001842 import fnmatch
1843 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 -08001844 sonames.add(prov)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001845 if libdir_re.match(os.path.dirname(file)):
1846 needs_ldconfig = True
1847 if snap_symlinks and (os.path.basename(file) != this_soname):
1848 renames.append((file, os.path.join(os.path.dirname(file), this_soname)))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001849 return (needs_ldconfig, needed, sonames, renames)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001850
1851 def darwin_so(file, needed, sonames, renames, pkgver):
1852 if not os.path.exists(file):
1853 return
1854 ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '')
1855
1856 def get_combinations(base):
1857 #
1858 # Given a base library name, find all combinations of this split by "." and "-"
1859 #
1860 combos = []
1861 options = base.split(".")
1862 for i in range(1, len(options) + 1):
1863 combos.append(".".join(options[0:i]))
1864 options = base.split("-")
1865 for i in range(1, len(options) + 1):
1866 combos.append("-".join(options[0:i]))
1867 return combos
1868
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001869 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 -05001870 # Drop suffix
1871 name = os.path.basename(file).rsplit(".",1)[0]
1872 # Find all combinations
1873 combos = get_combinations(name)
1874 for combo in combos:
1875 if not combo in sonames:
1876 prov = (combo, ldir, pkgver)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001877 sonames.add(prov)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001878 if file.endswith('.dylib') or file.endswith('.so'):
1879 rpath = []
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001880 p = subprocess.Popen([d.expand("${HOST_PREFIX}otool"), '-l', file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001881 out, err = p.communicate()
1882 # If returned successfully, process stdout for results
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001883 if p.returncode == 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001884 for l in out.split("\n"):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001885 l = l.strip()
1886 if l.startswith('path '):
1887 rpath.append(l.split()[1])
1888
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001889 p = subprocess.Popen([d.expand("${HOST_PREFIX}otool"), '-L', file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001890 out, err = p.communicate()
1891 # If returned successfully, process stdout for results
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001892 if p.returncode == 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001893 for l in out.split("\n"):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001894 l = l.strip()
1895 if not l or l.endswith(":"):
1896 continue
1897 if "is not an object file" in l:
1898 continue
1899 name = os.path.basename(l.split()[0]).rsplit(".", 1)[0]
1900 if name and name not in needed[pkg]:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001901 needed[pkg].add((name, file, tuple()))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001902
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001903 def mingw_dll(file, needed, sonames, renames, pkgver):
1904 if not os.path.exists(file):
1905 return
1906
1907 if file.endswith(".dll"):
1908 # assume all dlls are shared objects provided by the package
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001909 sonames.add((os.path.basename(file), os.path.dirname(file).replace(pkgdest + "/" + pkg, ''), pkgver))
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001910
1911 if (file.endswith(".dll") or file.endswith(".exe")):
1912 # use objdump to search for "DLL Name: .*\.dll"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001913 p = subprocess.Popen([d.expand("${HOST_PREFIX}objdump"), "-p", file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001914 out, err = p.communicate()
1915 # process the output, grabbing all .dll names
1916 if p.returncode == 0:
Brad Bishop19323692019-04-05 15:28:33 -04001917 for m in re.finditer(r"DLL Name: (.*?\.dll)$", out.decode(), re.MULTILINE | re.IGNORECASE):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001918 dllname = m.group(1)
1919 if dllname:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001920 needed[pkg].add((dllname, file, tuple()))
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001921
1922 if d.getVar('PACKAGE_SNAP_LIB_SYMLINKS') == "1":
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001923 snap_symlinks = True
1924 else:
1925 snap_symlinks = False
1926
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001927 needed = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001928
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001929 shlib_provider = oe.package.read_shlib_providers(d)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001930
1931 for pkg in shlib_pkgs:
Patrick Williams213cb262021-08-07 19:21:33 -05001932 private_libs = d.getVar('PRIVATE_LIBS:' + pkg) or d.getVar('PRIVATE_LIBS') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001933 private_libs = private_libs.split()
1934 needs_ldconfig = False
1935 bb.debug(2, "calculating shlib provides for %s" % pkg)
1936
Patrick Williams213cb262021-08-07 19:21:33 -05001937 pkgver = d.getVar('PKGV:' + pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001938 if not pkgver:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001939 pkgver = d.getVar('PV_' + pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001940 if not pkgver:
1941 pkgver = ver
1942
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001943 needed[pkg] = set()
1944 sonames = set()
1945 renames = []
1946 linuxlist = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001947 for file in pkgfiles[pkg]:
1948 soname = None
1949 if cpath.islink(file):
1950 continue
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001951 if hostos == "darwin" or hostos == "darwin8":
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001952 darwin_so(file, needed, sonames, renames, pkgver)
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001953 elif hostos.startswith("mingw"):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001954 mingw_dll(file, needed, sonames, renames, pkgver)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001955 elif os.access(file, os.X_OK) or lib_re.match(file):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001956 linuxlist.append(file)
1957
1958 if linuxlist:
1959 results = oe.utils.multiprocess_launch(linux_so, linuxlist, d, extraargs=(pkg, pkgver, d))
1960 for r in results:
1961 ldconfig = r[0]
1962 needed[pkg] |= r[1]
1963 sonames |= r[2]
1964 renames.extend(r[3])
1965 needs_ldconfig = needs_ldconfig or ldconfig
1966
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001967 for (old, new) in renames:
1968 bb.note("Renaming %s to %s" % (old, new))
Andrew Geisslerc926e172021-05-07 16:11:35 -05001969 bb.utils.rename(old, new)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001970 pkgfiles[pkg].remove(old)
Brad Bishop64c979e2019-11-04 13:55:29 -05001971
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001972 shlibs_file = os.path.join(shlibswork_dir, pkg + ".list")
1973 if len(sonames):
Brad Bishop64c979e2019-11-04 13:55:29 -05001974 with open(shlibs_file, 'w') as fd:
Andrew Geissler635e0e42020-08-21 15:58:33 -05001975 for s in sorted(sonames):
Brad Bishop64c979e2019-11-04 13:55:29 -05001976 if s[0] in shlib_provider and s[1] in shlib_provider[s[0]]:
1977 (old_pkg, old_pkgver) = shlib_provider[s[0]][s[1]]
1978 if old_pkg != pkg:
1979 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))
1980 bb.debug(1, 'registering %s-%s as shlib provider for %s' % (pkg, pkgver, s[0]))
1981 fd.write(s[0] + ':' + s[1] + ':' + s[2] + '\n')
1982 if s[0] not in shlib_provider:
1983 shlib_provider[s[0]] = {}
1984 shlib_provider[s[0]][s[1]] = (pkg, pkgver)
Brad Bishop1d80a2e2019-11-15 16:35:03 -05001985 if needs_ldconfig:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001986 bb.debug(1, 'adding ldconfig call to postinst for %s' % pkg)
Patrick Williams213cb262021-08-07 19:21:33 -05001987 postinst = d.getVar('pkg_postinst:%s' % pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001988 if not postinst:
1989 postinst = '#!/bin/sh\n'
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001990 postinst += d.getVar('ldconfig_postinst_fragment')
Patrick Williams213cb262021-08-07 19:21:33 -05001991 d.setVar('pkg_postinst:%s' % pkg, postinst)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001992 bb.debug(1, 'LIBNAMES: pkg %s sonames %s' % (pkg, sonames))
1993
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001994 assumed_libs = d.getVar('ASSUME_SHLIBS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001995 if assumed_libs:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001996 libdir = d.getVar("libdir")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001997 for e in assumed_libs.split():
1998 l, dep_pkg = e.split(":")
1999 lib_ver = None
2000 dep_pkg = dep_pkg.rsplit("_", 1)
2001 if len(dep_pkg) == 2:
2002 lib_ver = dep_pkg[1]
2003 dep_pkg = dep_pkg[0]
2004 if l not in shlib_provider:
2005 shlib_provider[l] = {}
2006 shlib_provider[l][libdir] = (dep_pkg, lib_ver)
2007
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002008 libsearchpath = [d.getVar('libdir'), d.getVar('base_libdir')]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002009
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08002010 for pkg in shlib_pkgs:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002011 bb.debug(2, "calculating shlib requirements for %s" % pkg)
2012
Patrick Williams213cb262021-08-07 19:21:33 -05002013 private_libs = d.getVar('PRIVATE_LIBS:' + pkg) or d.getVar('PRIVATE_LIBS') or ""
Brad Bishop316dfdd2018-06-25 12:45:53 -04002014 private_libs = private_libs.split()
2015
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002016 deps = list()
2017 for n in needed[pkg]:
2018 # if n is in private libraries, don't try to search provider for it
2019 # this could cause problem in case some abc.bb provides private
2020 # /opt/abc/lib/libfoo.so.1 and contains /usr/bin/abc depending on system library libfoo.so.1
2021 # but skipping it is still better alternative than providing own
2022 # version and then adding runtime dependency for the same system library
Brad Bishop79641f22019-09-10 07:20:22 -04002023 import fnmatch
2024 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 -05002025 bb.debug(2, '%s: Dependency %s covered by PRIVATE_LIBS' % (pkg, n[0]))
2026 continue
2027 if n[0] in shlib_provider.keys():
Brad Bishop00e122a2019-10-05 11:10:57 -04002028 shlib_provider_map = shlib_provider[n[0]]
2029 matches = set()
2030 for p in itertools.chain(list(n[2]), sorted(shlib_provider_map.keys()), libsearchpath):
2031 if p in shlib_provider_map:
2032 matches.add(p)
2033 if len(matches) > 1:
2034 matchpkgs = ', '.join([shlib_provider_map[match][0] for match in matches])
2035 bb.error("%s: Multiple shlib providers for %s: %s (used by files: %s)" % (pkg, n[0], matchpkgs, n[1]))
2036 elif len(matches) == 1:
2037 (dep_pkg, ver_needed) = shlib_provider_map[matches.pop()]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002038
2039 bb.debug(2, '%s: Dependency %s requires package %s (used by files: %s)' % (pkg, n[0], dep_pkg, n[1]))
2040
2041 if dep_pkg == pkg:
2042 continue
2043
2044 if ver_needed:
2045 dep = "%s (>= %s)" % (dep_pkg, ver_needed)
2046 else:
2047 dep = dep_pkg
2048 if not dep in deps:
2049 deps.append(dep)
2050 continue
2051 bb.note("Couldn't find shared library provider for %s, used by files: %s" % (n[0], n[1]))
2052
2053 deps_file = os.path.join(pkgdest, pkg + ".shlibdeps")
2054 if os.path.exists(deps_file):
2055 os.remove(deps_file)
Brad Bishop64c979e2019-11-04 13:55:29 -05002056 if deps:
2057 with open(deps_file, 'w') as fd:
2058 for dep in sorted(deps):
2059 fd.write(dep + '\n')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002060}
2061
2062python package_do_pkgconfig () {
2063 import re
2064
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002065 packages = d.getVar('PACKAGES')
2066 workdir = d.getVar('WORKDIR')
2067 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002068
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002069 shlibs_dirs = d.getVar('SHLIBSDIRS').split()
2070 shlibswork_dir = d.getVar('SHLIBSWORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002071
Brad Bishop19323692019-04-05 15:28:33 -04002072 pc_re = re.compile(r'(.*)\.pc$')
2073 var_re = re.compile(r'(.*)=(.*)')
2074 field_re = re.compile(r'(.*): (.*)')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002075
2076 pkgconfig_provided = {}
2077 pkgconfig_needed = {}
2078 for pkg in packages.split():
2079 pkgconfig_provided[pkg] = []
2080 pkgconfig_needed[pkg] = []
2081 for file in pkgfiles[pkg]:
2082 m = pc_re.match(file)
2083 if m:
2084 pd = bb.data.init()
2085 name = m.group(1)
2086 pkgconfig_provided[pkg].append(name)
2087 if not os.access(file, os.R_OK):
2088 continue
Brad Bishop64c979e2019-11-04 13:55:29 -05002089 with open(file, 'r') as f:
2090 lines = f.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002091 for l in lines:
2092 m = var_re.match(l)
2093 if m:
2094 name = m.group(1)
2095 val = m.group(2)
2096 pd.setVar(name, pd.expand(val))
2097 continue
2098 m = field_re.match(l)
2099 if m:
2100 hdr = m.group(1)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002101 exp = pd.expand(m.group(2))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002102 if hdr == 'Requires':
2103 pkgconfig_needed[pkg] += exp.replace(',', ' ').split()
2104
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002105 for pkg in packages.split():
2106 pkgs_file = os.path.join(shlibswork_dir, pkg + ".pclist")
2107 if pkgconfig_provided[pkg] != []:
Brad Bishop64c979e2019-11-04 13:55:29 -05002108 with open(pkgs_file, 'w') as f:
2109 for p in pkgconfig_provided[pkg]:
2110 f.write('%s\n' % p)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002111
2112 # Go from least to most specific since the last one found wins
2113 for dir in reversed(shlibs_dirs):
2114 if not os.path.exists(dir):
2115 continue
Brad Bishop08902b02019-08-20 09:16:51 -04002116 for file in sorted(os.listdir(dir)):
Brad Bishop19323692019-04-05 15:28:33 -04002117 m = re.match(r'^(.*)\.pclist$', file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002118 if m:
2119 pkg = m.group(1)
Brad Bishop64c979e2019-11-04 13:55:29 -05002120 with open(os.path.join(dir, file)) as fd:
2121 lines = fd.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002122 pkgconfig_provided[pkg] = []
2123 for l in lines:
2124 pkgconfig_provided[pkg].append(l.rstrip())
2125
2126 for pkg in packages.split():
2127 deps = []
2128 for n in pkgconfig_needed[pkg]:
2129 found = False
2130 for k in pkgconfig_provided.keys():
2131 if n in pkgconfig_provided[k]:
2132 if k != pkg and not (k in deps):
2133 deps.append(k)
2134 found = True
2135 if found == False:
2136 bb.note("couldn't find pkgconfig module '%s' in any package" % n)
2137 deps_file = os.path.join(pkgdest, pkg + ".pcdeps")
2138 if len(deps):
Brad Bishop64c979e2019-11-04 13:55:29 -05002139 with open(deps_file, 'w') as fd:
2140 for dep in deps:
2141 fd.write(dep + '\n')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002142}
2143
2144def read_libdep_files(d):
2145 pkglibdeps = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002146 packages = d.getVar('PACKAGES').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002147 for pkg in packages:
2148 pkglibdeps[pkg] = {}
2149 for extension in ".shlibdeps", ".pcdeps", ".clilibdeps":
2150 depsfile = d.expand("${PKGDEST}/" + pkg + extension)
2151 if os.access(depsfile, os.R_OK):
Brad Bishop64c979e2019-11-04 13:55:29 -05002152 with open(depsfile) as fd:
2153 lines = fd.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002154 for l in lines:
2155 l.rstrip()
2156 deps = bb.utils.explode_dep_versions2(l)
2157 for dep in deps:
2158 if not dep in pkglibdeps[pkg]:
2159 pkglibdeps[pkg][dep] = deps[dep]
2160 return pkglibdeps
2161
2162python read_shlibdeps () {
2163 pkglibdeps = read_libdep_files(d)
2164
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002165 packages = d.getVar('PACKAGES').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002166 for pkg in packages:
Patrick Williams213cb262021-08-07 19:21:33 -05002167 rdepends = bb.utils.explode_dep_versions2(d.getVar('RDEPENDS:' + pkg) or "")
Brad Bishop19323692019-04-05 15:28:33 -04002168 for dep in sorted(pkglibdeps[pkg]):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002169 # Add the dep if it's not already there, or if no comparison is set
2170 if dep not in rdepends:
2171 rdepends[dep] = []
2172 for v in pkglibdeps[pkg][dep]:
2173 if v not in rdepends[dep]:
2174 rdepends[dep].append(v)
Patrick Williams213cb262021-08-07 19:21:33 -05002175 d.setVar('RDEPENDS:' + pkg, bb.utils.join_deps(rdepends, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002176}
2177
2178python package_depchains() {
2179 """
2180 For a given set of prefix and postfix modifiers, make those packages
2181 RRECOMMENDS on the corresponding packages for its RDEPENDS.
2182
2183 Example: If package A depends upon package B, and A's .bb emits an
2184 A-dev package, this would make A-dev Recommends: B-dev.
2185
2186 If only one of a given suffix is specified, it will take the RRECOMMENDS
2187 based on the RDEPENDS of *all* other packages. If more than one of a given
2188 suffix is specified, its will only use the RDEPENDS of the single parent
2189 package.
2190 """
2191
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002192 packages = d.getVar('PACKAGES')
2193 postfixes = (d.getVar('DEPCHAIN_POST') or '').split()
2194 prefixes = (d.getVar('DEPCHAIN_PRE') or '').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002195
2196 def pkg_adddeprrecs(pkg, base, suffix, getname, depends, d):
2197
2198 #bb.note('depends for %s is %s' % (base, depends))
Patrick Williams213cb262021-08-07 19:21:33 -05002199 rreclist = bb.utils.explode_dep_versions2(d.getVar('RRECOMMENDS:' + pkg) or "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002200
Brad Bishop19323692019-04-05 15:28:33 -04002201 for depend in sorted(depends):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002202 if depend.find('-native') != -1 or depend.find('-cross') != -1 or depend.startswith('virtual/'):
2203 #bb.note("Skipping %s" % depend)
2204 continue
2205 if depend.endswith('-dev'):
2206 depend = depend[:-4]
2207 if depend.endswith('-dbg'):
2208 depend = depend[:-4]
2209 pkgname = getname(depend, suffix)
2210 #bb.note("Adding %s for %s" % (pkgname, depend))
2211 if pkgname not in rreclist and pkgname != pkg:
2212 rreclist[pkgname] = []
2213
Patrick Williams213cb262021-08-07 19:21:33 -05002214 #bb.note('setting: RRECOMMENDS:%s=%s' % (pkg, ' '.join(rreclist)))
2215 d.setVar('RRECOMMENDS:%s' % pkg, bb.utils.join_deps(rreclist, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002216
2217 def pkg_addrrecs(pkg, base, suffix, getname, rdepends, d):
2218
2219 #bb.note('rdepends for %s is %s' % (base, rdepends))
Patrick Williams213cb262021-08-07 19:21:33 -05002220 rreclist = bb.utils.explode_dep_versions2(d.getVar('RRECOMMENDS:' + pkg) or "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002221
Brad Bishop19323692019-04-05 15:28:33 -04002222 for depend in sorted(rdepends):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002223 if depend.find('virtual-locale-') != -1:
2224 #bb.note("Skipping %s" % depend)
2225 continue
2226 if depend.endswith('-dev'):
2227 depend = depend[:-4]
2228 if depend.endswith('-dbg'):
2229 depend = depend[:-4]
2230 pkgname = getname(depend, suffix)
2231 #bb.note("Adding %s for %s" % (pkgname, depend))
2232 if pkgname not in rreclist and pkgname != pkg:
2233 rreclist[pkgname] = []
2234
Patrick Williams213cb262021-08-07 19:21:33 -05002235 #bb.note('setting: RRECOMMENDS:%s=%s' % (pkg, ' '.join(rreclist)))
2236 d.setVar('RRECOMMENDS:%s' % pkg, bb.utils.join_deps(rreclist, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002237
2238 def add_dep(list, dep):
2239 if dep not in list:
2240 list.append(dep)
2241
2242 depends = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002243 for dep in bb.utils.explode_deps(d.getVar('DEPENDS') or ""):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002244 add_dep(depends, dep)
2245
2246 rdepends = []
2247 for pkg in packages.split():
Patrick Williams213cb262021-08-07 19:21:33 -05002248 for dep in bb.utils.explode_deps(d.getVar('RDEPENDS:' + pkg) or ""):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002249 add_dep(rdepends, dep)
2250
2251 #bb.note('rdepends is %s' % rdepends)
2252
2253 def post_getname(name, suffix):
2254 return '%s%s' % (name, suffix)
2255 def pre_getname(name, suffix):
2256 return '%s%s' % (suffix, name)
2257
2258 pkgs = {}
2259 for pkg in packages.split():
2260 for postfix in postfixes:
2261 if pkg.endswith(postfix):
2262 if not postfix in pkgs:
2263 pkgs[postfix] = {}
2264 pkgs[postfix][pkg] = (pkg[:-len(postfix)], post_getname)
2265
2266 for prefix in prefixes:
2267 if pkg.startswith(prefix):
2268 if not prefix in pkgs:
2269 pkgs[prefix] = {}
2270 pkgs[prefix][pkg] = (pkg[:-len(prefix)], pre_getname)
2271
2272 if "-dbg" in pkgs:
2273 pkglibdeps = read_libdep_files(d)
2274 pkglibdeplist = []
2275 for pkg in pkglibdeps:
2276 for k in pkglibdeps[pkg]:
2277 add_dep(pkglibdeplist, k)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002278 dbgdefaultdeps = ((d.getVar('DEPCHAIN_DBGDEFAULTDEPS') == '1') or (bb.data.inherits_class('packagegroup', d)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002279
2280 for suffix in pkgs:
2281 for pkg in pkgs[suffix]:
Patrick Williams213cb262021-08-07 19:21:33 -05002282 if d.getVarFlag('RRECOMMENDS:' + pkg, 'nodeprrecs'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002283 continue
2284 (base, func) = pkgs[suffix][pkg]
2285 if suffix == "-dev":
2286 pkg_adddeprrecs(pkg, base, suffix, func, depends, d)
2287 elif suffix == "-dbg":
2288 if not dbgdefaultdeps:
2289 pkg_addrrecs(pkg, base, suffix, func, pkglibdeplist, d)
2290 continue
2291 if len(pkgs[suffix]) == 1:
2292 pkg_addrrecs(pkg, base, suffix, func, rdepends, d)
2293 else:
2294 rdeps = []
Patrick Williams213cb262021-08-07 19:21:33 -05002295 for dep in bb.utils.explode_deps(d.getVar('RDEPENDS:' + base) or ""):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002296 add_dep(rdeps, dep)
2297 pkg_addrrecs(pkg, base, suffix, func, rdeps, d)
2298}
2299
2300# Since bitbake can't determine which variables are accessed during package
2301# iteration, we need to list them here:
Andrew Geissler1e34c2d2020-05-29 16:02:59 -05002302PACKAGEVARS = "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 -05002303
Andrew Geissler82c905d2020-04-13 13:39:40 -05002304def gen_packagevar(d, pkgvars="PACKAGEVARS"):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002305 ret = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002306 pkgs = (d.getVar("PACKAGES") or "").split()
Andrew Geissler82c905d2020-04-13 13:39:40 -05002307 vars = (d.getVar(pkgvars) or "").split()
2308 for v in vars:
2309 ret.append(v)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002310 for p in pkgs:
2311 for v in vars:
Patrick Williams213cb262021-08-07 19:21:33 -05002312 ret.append(v + ":" + p)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002313
2314 # Ensure that changes to INCOMPATIBLE_LICENSE re-run do_package for
2315 # affected recipes.
2316 ret.append('LICENSE_EXCLUSION-%s' % p)
2317 return " ".join(ret)
2318
2319PACKAGE_PREPROCESS_FUNCS ?= ""
2320# Functions for setting up PKGD
2321PACKAGEBUILDPKGD ?= " \
Brad Bishop96ff1982019-08-19 13:50:42 -04002322 package_prepare_pkgdata \
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002323 perform_packagecopy \
2324 ${PACKAGE_PREPROCESS_FUNCS} \
2325 split_and_strip_files \
2326 fixup_perms \
2327 "
2328# Functions which split PKGD up into separate packages
2329PACKAGESPLITFUNCS ?= " \
2330 package_do_split_locales \
2331 populate_packages"
2332# Functions which process metadata based on split packages
2333PACKAGEFUNCS += " \
2334 package_fixsymlinks \
2335 package_name_hook \
2336 package_do_filedeps \
2337 package_do_shlibs \
2338 package_do_pkgconfig \
2339 read_shlibdeps \
2340 package_depchains \
2341 emit_pkgdata"
2342
2343python do_package () {
2344 # Change the following version to cause sstate to invalidate the package
2345 # cache. This is useful if an item this class depends on changes in a
2346 # way that the output of this class changes. rpmdeps is a good example
2347 # as any change to rpmdeps requires this to be rerun.
Andrew Geissler6ce62a22020-11-30 19:58:47 -06002348 # PACKAGE_BBCLASS_VERSION = "4"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002349
2350 # Init cachedpath
2351 global cpath
2352 cpath = oe.cachedpath.CachedPath()
2353
2354 ###########################################################################
2355 # Sanity test the setup
2356 ###########################################################################
2357
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002358 packages = (d.getVar('PACKAGES') or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002359 if len(packages) < 1:
2360 bb.debug(1, "No packages to build, skipping do_package")
2361 return
2362
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002363 workdir = d.getVar('WORKDIR')
2364 outdir = d.getVar('DEPLOY_DIR')
2365 dest = d.getVar('D')
2366 dvar = d.getVar('PKGD')
2367 pn = d.getVar('PN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002368
2369 if not workdir or not outdir or not dest or not dvar or not pn:
2370 msg = "WORKDIR, DEPLOY_DIR, D, PN and PKGD all must be defined, unable to package"
2371 package_qa_handle_error("var-undefined", msg, d)
2372 return
2373
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002374 bb.build.exec_func("package_convert_pr_autoinc", d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002375
2376 ###########################################################################
2377 # Optimisations
2378 ###########################################################################
2379
2380 # Continually expanding complex expressions is inefficient, particularly
2381 # when we write to the datastore and invalidate the expansion cache. This
2382 # code pre-expands some frequently used variables
2383
2384 def expandVar(x, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002385 d.setVar(x, d.getVar(x))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002386
2387 for x in 'PN', 'PV', 'BPN', 'TARGET_SYS', 'EXTENDPRAUTO':
2388 expandVar(x, d)
2389
2390 ###########################################################################
2391 # Setup PKGD (from D)
2392 ###########################################################################
2393
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002394 for f in (d.getVar('PACKAGEBUILDPKGD') or '').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002395 bb.build.exec_func(f, d)
2396
2397 ###########################################################################
2398 # Split up PKGD into PKGDEST
2399 ###########################################################################
2400
2401 cpath = oe.cachedpath.CachedPath()
2402
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002403 for f in (d.getVar('PACKAGESPLITFUNCS') or '').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002404 bb.build.exec_func(f, d)
2405
2406 ###########################################################################
2407 # Process PKGDEST
2408 ###########################################################################
2409
2410 # Build global list of files in each split package
2411 global pkgfiles
2412 pkgfiles = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002413 packages = d.getVar('PACKAGES').split()
2414 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002415 for pkg in packages:
2416 pkgfiles[pkg] = []
2417 for walkroot, dirs, files in cpath.walk(pkgdest + "/" + pkg):
2418 for file in files:
2419 pkgfiles[pkg].append(walkroot + os.sep + file)
2420
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002421 for f in (d.getVar('PACKAGEFUNCS') or '').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002422 bb.build.exec_func(f, d)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05002423
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002424 qa_sane = d.getVar("QA_SANE")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05002425 if not qa_sane:
2426 bb.fatal("Fatal QA errors found, failing task.")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002427}
2428
2429do_package[dirs] = "${SHLIBSWORKDIR} ${PKGDESTWORK} ${D}"
2430do_package[vardeps] += "${PACKAGEBUILDPKGD} ${PACKAGESPLITFUNCS} ${PACKAGEFUNCS} ${@gen_packagevar(d)}"
2431addtask package after do_install
2432
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002433SSTATETASKS += "do_package"
2434do_package[cleandirs] = "${PKGDEST} ${PKGDESTWORK}"
2435do_package[sstate-plaindirs] = "${PKGD} ${PKGDEST} ${PKGDESTWORK}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002436do_package_setscene[dirs] = "${STAGING_DIR}"
2437
2438python do_package_setscene () {
2439 sstate_setscene(d)
2440}
2441addtask do_package_setscene
2442
Brad Bishopc68388fc2019-08-26 01:33:31 -04002443# Copy from PKGDESTWORK to tempdirectory as tempdirectory can be cleaned at both
2444# do_package_setscene and do_packagedata_setscene leading to races
2445python do_packagedata () {
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002446 bb.build.exec_func("package_get_auto_pr", d)
2447
Brad Bishopc68388fc2019-08-26 01:33:31 -04002448 src = d.expand("${PKGDESTWORK}")
2449 dest = d.expand("${WORKDIR}/pkgdata-pdata-input")
2450 oe.path.copyhardlinktree(src, dest)
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002451
2452 bb.build.exec_func("packagedata_translate_pr_autoinc", d)
2453}
Andrew Geisslerd1e89492021-02-12 15:35:20 -06002454do_packagedata[cleandirs] += "${WORKDIR}/pkgdata-pdata-input"
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002455
2456# Translate the EXTENDPRAUTO and AUTOINC to the final values
2457packagedata_translate_pr_autoinc() {
2458 find ${WORKDIR}/pkgdata-pdata-input -type f | xargs --no-run-if-empty \
2459 sed -e 's,@PRSERV_PV_AUTOINC@,${PRSERV_PV_AUTOINC},g' \
2460 -e 's,@EXTENDPRAUTO@,${EXTENDPRAUTO},g' -i
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002461}
2462
2463addtask packagedata before do_build after do_package
2464
2465SSTATETASKS += "do_packagedata"
Brad Bishopc68388fc2019-08-26 01:33:31 -04002466do_packagedata[sstate-inputdirs] = "${WORKDIR}/pkgdata-pdata-input"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002467do_packagedata[sstate-outputdirs] = "${PKGDATA_DIR}"
Brad Bishop316dfdd2018-06-25 12:45:53 -04002468do_packagedata[stamp-extra-info] = "${MACHINE_ARCH}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002469
2470python do_packagedata_setscene () {
2471 sstate_setscene(d)
2472}
2473addtask do_packagedata_setscene
2474
2475#
2476# Helper functions for the package writing classes
2477#
2478
2479def mapping_rename_hook(d):
2480 """
2481 Rewrite variables to account for package renaming in things
2482 like debian.bbclass or manual PKG variable name changes
2483 """
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002484 pkg = d.getVar("PKG")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002485 runtime_mapping_rename("RDEPENDS", pkg, d)
2486 runtime_mapping_rename("RRECOMMENDS", pkg, d)
2487 runtime_mapping_rename("RSUGGESTS", pkg, d)