blob: 44fbc32df6aaa8ac1a7b1b9ed2c100a4cb7554e7 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001#
2# Packaging process
3#
4# Executive summary: This class iterates over the functions listed in PACKAGEFUNCS
5# Taking D and splitting it up into the packages listed in PACKAGES, placing the
6# resulting output in PKGDEST.
7#
8# There are the following default steps but PACKAGEFUNCS can be extended:
9#
Andrew Geisslerc9f78652020-09-18 14:11:35 -050010# a) package_convert_pr_autoinc - convert AUTOINC in PKGV to ${PRSERV_PV_AUTOINC}
Patrick Williamsc124f4f2015-09-15 14:41:29 -050011#
12# b) perform_packagecopy - Copy D into PKGD
13#
14# c) package_do_split_locales - Split out the locale files, updates FILES and PACKAGES
15#
16# d) split_and_strip_files - split the files into runtime and debug and strip them.
17# Debug files include debug info split, and associated sources that end up in -dbg packages
18#
19# e) fixup_perms - Fix up permissions in the package before we split it.
20#
21# f) populate_packages - Split the files in PKGD into separate packages in PKGDEST/<pkgname>
22# Also triggers the binary stripping code to put files in -dbg packages.
23#
24# g) package_do_filedeps - Collect perfile run-time dependency metadata
25# The data is stores in FILER{PROVIDES,DEPENDS}_file_pkg variables with
26# a list of affected files in FILER{PROVIDES,DEPENDS}FLIST_pkg
27#
28# h) package_do_shlibs - Look at the shared libraries generated and autotmatically add any
Brad Bishop316dfdd2018-06-25 12:45:53 -040029# dependencies found. Also stores the package name so anyone else using this library
Patrick Williamsc124f4f2015-09-15 14:41:29 -050030# knows which package to depend on.
31#
32# i) package_do_pkgconfig - Keep track of which packages need and provide which .pc files
33#
34# j) read_shlibdeps - Reads the stored shlibs information into the metadata
35#
36# k) package_depchains - Adds automatic dependencies to -dbg and -dev packages
37#
38# l) emit_pkgdata - saves the packaging data into PKGDATA_DIR for use in later
39# packaging steps
40
41inherit packagedata
Patrick Williamsc124f4f2015-09-15 14:41:29 -050042inherit chrpath
Brad Bishop96ff1982019-08-19 13:50:42 -040043inherit package_pkgdata
Patrick Williamsc124f4f2015-09-15 14:41:29 -050044inherit insane
45
46PKGD = "${WORKDIR}/package"
47PKGDEST = "${WORKDIR}/packages-split"
48
49LOCALE_SECTION ?= ''
50
51ALL_MULTILIB_PACKAGE_ARCHS = "${@all_multilib_tune_values(d, 'PACKAGE_ARCHS')}"
52
53# rpm is used for the per-file dependency identification
Brad Bishop316dfdd2018-06-25 12:45:53 -040054# dwarfsrcfiles is used to determine the list of debug source files
55PACKAGE_DEPENDS += "rpm-native dwarfsrcfiles-native"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050056
Brad Bishop6e60e8b2018-02-01 10:27:11 -050057
58# If your postinstall can execute at rootfs creation time rather than on
59# target but depends on a native/cross tool in order to execute, you need to
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080060# list that tool in PACKAGE_WRITE_DEPS. Target package dependencies belong
Brad Bishop6e60e8b2018-02-01 10:27:11 -050061# in the package dependencies as normal, this is just for native/cross support
62# tools at rootfs build time.
63PACKAGE_WRITE_DEPS ??= ""
64
Patrick Williamsc124f4f2015-09-15 14:41:29 -050065def legitimize_package_name(s):
66 """
67 Make sure package names are legitimate strings
68 """
69 import re
70
71 def fixutf(m):
72 cp = m.group(1)
73 if cp:
Patrick Williamsc0f7c042017-02-23 20:41:17 -060074 return ('\\u%s' % cp).encode('latin-1').decode('unicode_escape')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050075
76 # Handle unicode codepoints encoded as <U0123>, as in glibc locale files.
Brad Bishop19323692019-04-05 15:28:33 -040077 s = re.sub(r'<U([0-9A-Fa-f]{1,4})>', fixutf, s)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050078
79 # Remaining package name validity fixes
80 return s.lower().replace('_', '-').replace('@', '+').replace(',', '+').replace('/', '-')
81
82def do_split_packages(d, root, file_regex, output_pattern, description, postinst=None, recursive=False, hook=None, extra_depends=None, aux_files_pattern=None, postrm=None, allow_dirs=False, prepend=False, match_path=False, aux_files_pattern_verbatim=None, allow_links=False, summary=None):
83 """
84 Used in .bb files to split up dynamically generated subpackages of a
85 given package, usually plugins or modules.
86
87 Arguments:
88 root -- the path in which to search
89 file_regex -- regular expression to match searched files. Use
90 parentheses () to mark the part of this expression
91 that should be used to derive the module name (to be
92 substituted where %s is used in other function
93 arguments as noted below)
94 output_pattern -- pattern to use for the package names. Must include %s.
95 description -- description to set for each package. Must include %s.
96 postinst -- postinstall script to use for all packages (as a
97 string)
98 recursive -- True to perform a recursive search - default False
99 hook -- a hook function to be called for every match. The
100 function will be called with the following arguments
101 (in the order listed):
102 f: full path to the file/directory match
103 pkg: the package name
104 file_regex: as above
105 output_pattern: as above
106 modulename: the module name derived using file_regex
107 extra_depends -- extra runtime dependencies (RDEPENDS) to be set for
108 all packages. The default value of None causes a
109 dependency on the main package (${PN}) - if you do
110 not want this, pass '' for this parameter.
111 aux_files_pattern -- extra item(s) to be added to FILES for each
112 package. Can be a single string item or a list of
113 strings for multiple items. Must include %s.
114 postrm -- postrm script to use for all packages (as a string)
115 allow_dirs -- True allow directories to be matched - default False
116 prepend -- if True, prepend created packages to PACKAGES instead
117 of the default False which appends them
118 match_path -- match file_regex on the whole relative path to the
119 root rather than just the file name
120 aux_files_pattern_verbatim -- extra item(s) to be added to FILES for
121 each package, using the actual derived module name
122 rather than converting it to something legal for a
123 package name. Can be a single string item or a list
124 of strings for multiple items. Must include %s.
125 allow_links -- True to allow symlinks to be matched - default False
126 summary -- Summary to set for each package. Must include %s;
127 defaults to description if not set.
128
129 """
130
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500131 dvar = d.getVar('PKGD')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500132 root = d.expand(root)
133 output_pattern = d.expand(output_pattern)
134 extra_depends = d.expand(extra_depends)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500135
136 # If the root directory doesn't exist, don't error out later but silently do
137 # no splitting.
138 if not os.path.exists(dvar + root):
139 return []
140
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500141 ml = d.getVar("MLPREFIX")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500142 if ml:
143 if not output_pattern.startswith(ml):
144 output_pattern = ml + output_pattern
145
146 newdeps = []
147 for dep in (extra_depends or "").split():
148 if dep.startswith(ml):
149 newdeps.append(dep)
150 else:
151 newdeps.append(ml + dep)
152 if newdeps:
153 extra_depends = " ".join(newdeps)
154
155
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500156 packages = d.getVar('PACKAGES').split()
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600157 split_packages = set()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500158
159 if postinst:
160 postinst = '#!/bin/sh\n' + postinst + '\n'
161 if postrm:
162 postrm = '#!/bin/sh\n' + postrm + '\n'
163 if not recursive:
164 objs = os.listdir(dvar + root)
165 else:
166 objs = []
167 for walkroot, dirs, files in os.walk(dvar + root):
168 for file in files:
169 relpath = os.path.join(walkroot, file).replace(dvar + root + '/', '', 1)
170 if relpath:
171 objs.append(relpath)
172
173 if extra_depends == None:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500174 extra_depends = d.getVar("PN")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500175
176 if not summary:
177 summary = description
178
179 for o in sorted(objs):
180 import re, stat
181 if match_path:
182 m = re.match(file_regex, o)
183 else:
184 m = re.match(file_regex, os.path.basename(o))
185
186 if not m:
187 continue
188 f = os.path.join(dvar + root, o)
189 mode = os.lstat(f).st_mode
190 if not (stat.S_ISREG(mode) or (allow_links and stat.S_ISLNK(mode)) or (allow_dirs and stat.S_ISDIR(mode))):
191 continue
192 on = legitimize_package_name(m.group(1))
193 pkg = output_pattern % on
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600194 split_packages.add(pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500195 if not pkg in packages:
196 if prepend:
197 packages = [pkg] + packages
198 else:
199 packages.append(pkg)
Patrick Williams213cb262021-08-07 19:21:33 -0500200 oldfiles = d.getVar('FILES:' + pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500201 newfile = os.path.join(root, o)
202 # These names will be passed through glob() so if the filename actually
203 # contains * or ? (rare, but possible) we need to handle that specially
204 newfile = newfile.replace('*', '[*]')
205 newfile = newfile.replace('?', '[?]')
206 if not oldfiles:
207 the_files = [newfile]
208 if aux_files_pattern:
209 if type(aux_files_pattern) is list:
210 for fp in aux_files_pattern:
211 the_files.append(fp % on)
212 else:
213 the_files.append(aux_files_pattern % on)
214 if aux_files_pattern_verbatim:
215 if type(aux_files_pattern_verbatim) is list:
216 for fp in aux_files_pattern_verbatim:
217 the_files.append(fp % m.group(1))
218 else:
219 the_files.append(aux_files_pattern_verbatim % m.group(1))
Patrick Williams213cb262021-08-07 19:21:33 -0500220 d.setVar('FILES:' + pkg, " ".join(the_files))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500221 else:
Patrick Williams213cb262021-08-07 19:21:33 -0500222 d.setVar('FILES:' + pkg, oldfiles + " " + newfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500223 if extra_depends != '':
Patrick Williams213cb262021-08-07 19:21:33 -0500224 d.appendVar('RDEPENDS:' + pkg, ' ' + extra_depends)
225 if not d.getVar('DESCRIPTION:' + pkg):
226 d.setVar('DESCRIPTION:' + pkg, description % on)
227 if not d.getVar('SUMMARY:' + pkg):
228 d.setVar('SUMMARY:' + pkg, summary % on)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500229 if postinst:
Patrick Williams213cb262021-08-07 19:21:33 -0500230 d.setVar('pkg_postinst:' + pkg, postinst)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500231 if postrm:
Patrick Williams213cb262021-08-07 19:21:33 -0500232 d.setVar('pkg_postrm:' + pkg, postrm)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500233 if callable(hook):
234 hook(f, pkg, file_regex, output_pattern, m.group(1))
235
236 d.setVar('PACKAGES', ' '.join(packages))
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600237 return list(split_packages)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500238
239PACKAGE_DEPENDS += "file-native"
240
241python () {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500242 if d.getVar('PACKAGES') != '':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500243 deps = ""
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500244 for dep in (d.getVar('PACKAGE_DEPENDS') or "").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500245 deps += " %s:do_populate_sysroot" % dep
Andrew Geissler82c905d2020-04-13 13:39:40 -0500246 if d.getVar('PACKAGE_MINIDEBUGINFO') == '1':
247 deps += ' xz-native:do_populate_sysroot'
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500248 d.appendVarFlag('do_package', 'depends', deps)
249
250 # shlibs requires any DEPENDS to have already packaged for the *.list files
251 d.appendVarFlag('do_package', 'deptask', " do_packagedata")
252}
253
254# Get a list of files from file vars by searching files under current working directory
255# The list contains symlinks, directories and normal files.
256def files_from_filevars(filevars):
257 import os,glob
258 cpath = oe.cachedpath.CachedPath()
259 files = []
260 for f in filevars:
261 if os.path.isabs(f):
262 f = '.' + f
263 if not f.startswith("./"):
264 f = './' + f
265 globbed = glob.glob(f)
266 if globbed:
267 if [ f ] != globbed:
268 files += globbed
269 continue
270 files.append(f)
271
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600272 symlink_paths = []
273 for ind, f in enumerate(files):
274 # Handle directory symlinks. Truncate path to the lowest level symlink
275 parent = ''
276 for dirname in f.split('/')[:-1]:
277 parent = os.path.join(parent, dirname)
278 if dirname == '.':
279 continue
280 if cpath.islink(parent):
281 bb.warn("FILES contains file '%s' which resides under a "
282 "directory symlink. Please fix the recipe and use the "
283 "real path for the file." % f[1:])
284 symlink_paths.append(f)
285 files[ind] = parent
286 f = parent
287 break
288
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500289 if not cpath.islink(f):
290 if cpath.isdir(f):
291 newfiles = [ os.path.join(f,x) for x in os.listdir(f) ]
292 if newfiles:
293 files += newfiles
294
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600295 return files, symlink_paths
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500296
297# Called in package_<rpm,ipk,deb>.bbclass to get the correct list of configuration files
298def get_conffiles(pkg, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500299 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500300 root = os.path.join(pkgdest, pkg)
301 cwd = os.getcwd()
302 os.chdir(root)
303
Patrick Williams213cb262021-08-07 19:21:33 -0500304 conffiles = d.getVar('CONFFILES:%s' % pkg);
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500305 if conffiles == None:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500306 conffiles = d.getVar('CONFFILES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500307 if conffiles == None:
308 conffiles = ""
309 conffiles = conffiles.split()
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600310 conf_orig_list = files_from_filevars(conffiles)[0]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500311
312 # Remove links and directories from conf_orig_list to get conf_list which only contains normal files
313 conf_list = []
314 for f in conf_orig_list:
315 if os.path.isdir(f):
316 continue
317 if os.path.islink(f):
318 continue
319 if not os.path.exists(f):
320 continue
321 conf_list.append(f)
322
323 # Remove the leading './'
324 for i in range(0, len(conf_list)):
325 conf_list[i] = conf_list[i][1:]
326
327 os.chdir(cwd)
328 return conf_list
329
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500330def checkbuildpath(file, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500331 tmpdir = d.getVar('TMPDIR')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500332 with open(file) as f:
333 file_content = f.read()
334 if tmpdir in file_content:
335 return True
336
337 return False
338
Brad Bishop316dfdd2018-06-25 12:45:53 -0400339def parse_debugsources_from_dwarfsrcfiles_output(dwarfsrcfiles_output):
340 debugfiles = {}
341
342 for line in dwarfsrcfiles_output.splitlines():
343 if line.startswith("\t"):
344 debugfiles[os.path.normpath(line.split()[0])] = ""
345
346 return debugfiles.keys()
347
Brad Bishop19323692019-04-05 15:28:33 -0400348def source_info(file, d, fatal=True):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800349 import subprocess
350
351 cmd = ["dwarfsrcfiles", file]
352 try:
353 output = subprocess.check_output(cmd, universal_newlines=True, stderr=subprocess.STDOUT)
354 retval = 0
355 except subprocess.CalledProcessError as exc:
356 output = exc.output
357 retval = exc.returncode
358
Brad Bishop316dfdd2018-06-25 12:45:53 -0400359 # 255 means a specific file wasn't fully parsed to get the debug file list, which is not a fatal failure
360 if retval != 0 and retval != 255:
361 msg = "dwarfsrcfiles failed with exit code %s (cmd was %s)%s" % (retval, cmd, ":\n%s" % output if output else "")
362 if fatal:
363 bb.fatal(msg)
364 bb.note(msg)
365
366 debugsources = parse_debugsources_from_dwarfsrcfiles_output(output)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400367
Brad Bishop19323692019-04-05 15:28:33 -0400368 return list(debugsources)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400369
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000370def splitdebuginfo(file, dvar, dv, d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500371 # Function to split a single file into two components, one is the stripped
372 # target system binary, the other contains any debugging information. The
373 # two files are linked to reference each other.
374 #
Brad Bishop19323692019-04-05 15:28:33 -0400375 # return a mapping of files:debugsources
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500376
377 import stat
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800378 import subprocess
379
380 src = file[len(dvar):]
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000381 dest = dv["libdir"] + os.path.dirname(src) + dv["dir"] + "/" + os.path.basename(src) + dv["append"]
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800382 debugfile = dvar + dest
Brad Bishop19323692019-04-05 15:28:33 -0400383 sources = []
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800384
385 # Split the file...
386 bb.utils.mkdirhier(os.path.dirname(debugfile))
387 #bb.note("Split %s -> %s" % (file, debugfile))
388 # Only store off the hard link reference if we successfully split!
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500389
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500390 dvar = d.getVar('PKGD')
391 objcopy = d.getVar("OBJCOPY")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500392
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500393 newmode = None
394 if not os.access(file, os.W_OK) or os.access(file, os.R_OK):
395 origmode = os.stat(file)[stat.ST_MODE]
396 newmode = origmode | stat.S_IWRITE | stat.S_IREAD
397 os.chmod(file, newmode)
398
399 # We need to extract the debug src information here...
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000400 if dv["srcdir"]:
Brad Bishop19323692019-04-05 15:28:33 -0400401 sources = source_info(file, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500402
403 bb.utils.mkdirhier(os.path.dirname(debugfile))
404
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800405 subprocess.check_output([objcopy, '--only-keep-debug', file, debugfile], stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500406
407 # Set the debuglink to have the view of the file path on the target
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800408 subprocess.check_output([objcopy, '--add-gnu-debuglink', debugfile, file], stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500409
410 if newmode:
411 os.chmod(file, origmode)
412
Brad Bishop19323692019-04-05 15:28:33 -0400413 return (file, sources)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500414
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000415def splitstaticdebuginfo(file, dvar, dv, d):
Andrew Geissler82c905d2020-04-13 13:39:40 -0500416 # Unlike the function above, there is no way to split a static library
417 # two components. So to get similar results we will copy the unmodified
418 # static library (containing the debug symbols) into a new directory.
419 # We will then strip (preserving symbols) the static library in the
420 # typical location.
421 #
422 # return a mapping of files:debugsources
423
424 import stat
Andrew Geissler82c905d2020-04-13 13:39:40 -0500425
426 src = file[len(dvar):]
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000427 dest = dv["staticlibdir"] + os.path.dirname(src) + dv["staticdir"] + "/" + os.path.basename(src) + dv["staticappend"]
Andrew Geissler82c905d2020-04-13 13:39:40 -0500428 debugfile = dvar + dest
429 sources = []
430
431 # Copy the file...
432 bb.utils.mkdirhier(os.path.dirname(debugfile))
433 #bb.note("Copy %s -> %s" % (file, debugfile))
434
435 dvar = d.getVar('PKGD')
436
437 newmode = None
438 if not os.access(file, os.W_OK) or os.access(file, os.R_OK):
439 origmode = os.stat(file)[stat.ST_MODE]
440 newmode = origmode | stat.S_IWRITE | stat.S_IREAD
441 os.chmod(file, newmode)
442
443 # We need to extract the debug src information here...
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000444 if dv["srcdir"]:
Andrew Geissler82c905d2020-04-13 13:39:40 -0500445 sources = source_info(file, d)
446
447 bb.utils.mkdirhier(os.path.dirname(debugfile))
448
449 # Copy the unmodified item to the debug directory
450 shutil.copy2(file, debugfile)
451
452 if newmode:
453 os.chmod(file, origmode)
454
455 return (file, sources)
456
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000457def inject_minidebuginfo(file, dvar, dv, d):
Andrew Geissler82c905d2020-04-13 13:39:40 -0500458 # Extract just the symbols from debuginfo into minidebuginfo,
459 # compress it with xz and inject it back into the binary in a .gnu_debugdata section.
460 # https://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html
461
462 import subprocess
463
464 readelf = d.getVar('READELF')
465 nm = d.getVar('NM')
466 objcopy = d.getVar('OBJCOPY')
467
468 minidebuginfodir = d.expand('${WORKDIR}/minidebuginfo')
469
470 src = file[len(dvar):]
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000471 dest = dv["libdir"] + os.path.dirname(src) + dv["dir"] + "/" + os.path.basename(src) + dv["append"]
Andrew Geissler82c905d2020-04-13 13:39:40 -0500472 debugfile = dvar + dest
473 minidebugfile = minidebuginfodir + src + '.minidebug'
474 bb.utils.mkdirhier(os.path.dirname(minidebugfile))
475
476 # If we didn't produce debuginfo for any reason, we can't produce minidebuginfo either
477 # so skip it.
478 if not os.path.exists(debugfile):
479 bb.debug(1, 'ELF file {} has no debuginfo, skipping minidebuginfo injection'.format(file))
480 return
481
482 # Find non-allocated PROGBITS, NOTE, and NOBITS sections in the debuginfo.
483 # We will exclude all of these from minidebuginfo to save space.
484 remove_section_names = []
485 for line in subprocess.check_output([readelf, '-W', '-S', debugfile], universal_newlines=True).splitlines():
486 fields = line.split()
487 if len(fields) < 8:
488 continue
489 name = fields[0]
490 type = fields[1]
491 flags = fields[7]
492 # .debug_ sections will be removed by objcopy -S so no need to explicitly remove them
493 if name.startswith('.debug_'):
494 continue
495 if 'A' not in flags and type in ['PROGBITS', 'NOTE', 'NOBITS']:
496 remove_section_names.append(name)
497
498 # List dynamic symbols in the binary. We can exclude these from minidebuginfo
499 # because they are always present in the binary.
500 dynsyms = set()
501 for line in subprocess.check_output([nm, '-D', file, '--format=posix', '--defined-only'], universal_newlines=True).splitlines():
502 dynsyms.add(line.split()[0])
503
504 # Find all function symbols from debuginfo which aren't in the dynamic symbols table.
505 # These are the ones we want to keep in minidebuginfo.
506 keep_symbols_file = minidebugfile + '.symlist'
507 found_any_symbols = False
508 with open(keep_symbols_file, 'w') as f:
509 for line in subprocess.check_output([nm, debugfile, '--format=sysv', '--defined-only'], universal_newlines=True).splitlines():
510 fields = line.split('|')
511 if len(fields) < 7:
512 continue
513 name = fields[0].strip()
514 type = fields[3].strip()
515 if type == 'FUNC' and name not in dynsyms:
516 f.write('{}\n'.format(name))
517 found_any_symbols = True
518
519 if not found_any_symbols:
520 bb.debug(1, 'ELF file {} contains no symbols, skipping minidebuginfo injection'.format(file))
521 return
522
523 bb.utils.remove(minidebugfile)
524 bb.utils.remove(minidebugfile + '.xz')
525
526 subprocess.check_call([objcopy, '-S'] +
527 ['--remove-section={}'.format(s) for s in remove_section_names] +
528 ['--keep-symbols={}'.format(keep_symbols_file), debugfile, minidebugfile])
529
530 subprocess.check_call(['xz', '--keep', minidebugfile])
531
532 subprocess.check_call([objcopy, '--add-section', '.gnu_debugdata={}.xz'.format(minidebugfile), file])
533
Brad Bishop19323692019-04-05 15:28:33 -0400534def copydebugsources(debugsrcdir, sources, d):
Brad Bishop316dfdd2018-06-25 12:45:53 -0400535 # The debug src information written out to sourcefile is further processed
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500536 # and copied to the destination here.
537
538 import stat
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800539 import subprocess
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500540
Brad Bishop19323692019-04-05 15:28:33 -0400541 if debugsrcdir and sources:
542 sourcefile = d.expand("${WORKDIR}/debugsources.list")
543 bb.utils.remove(sourcefile)
544
545 # filenames are null-separated - this is an artefact of the previous use
546 # of rpm's debugedit, which was writing them out that way, and the code elsewhere
547 # is still assuming that.
548 debuglistoutput = '\0'.join(sources) + '\0'
549 with open(sourcefile, 'a') as sf:
550 sf.write(debuglistoutput)
551
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500552 dvar = d.getVar('PKGD')
553 strip = d.getVar("STRIP")
554 objcopy = d.getVar("OBJCOPY")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500555 workdir = d.getVar("WORKDIR")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500556 workparentdir = os.path.dirname(os.path.dirname(workdir))
557 workbasedir = os.path.basename(os.path.dirname(workdir)) + "/" + os.path.basename(workdir)
558
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500559 # If build path exists in sourcefile, it means toolchain did not use
560 # -fdebug-prefix-map to compile
561 if checkbuildpath(sourcefile, d):
562 localsrc_prefix = workparentdir + "/"
563 else:
564 localsrc_prefix = "/usr/src/debug/"
565
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500566 nosuchdir = []
567 basepath = dvar
568 for p in debugsrcdir.split("/"):
569 basepath = basepath + "/" + p
570 if not cpath.exists(basepath):
571 nosuchdir.append(basepath)
572 bb.utils.mkdirhier(basepath)
573 cpath.updatecache(basepath)
574
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500575 # Ignore files from the recipe sysroots (target and native)
576 processdebugsrc = "LC_ALL=C ; sort -z -u '%s' | egrep -v -z '((<internal>|<built-in>)$|/.*recipe-sysroot.*/)' | "
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500577 # We need to ignore files that are not actually ours
578 # we do this by only paying attention to items from this package
579 processdebugsrc += "fgrep -zw '%s' | "
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500580 # Remove prefix in the source paths
581 processdebugsrc += "sed 's#%s##g' | "
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500582 processdebugsrc += "(cd '%s' ; cpio -pd0mlL --no-preserve-owner '%s%s' 2>/dev/null)"
583
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500584 cmd = processdebugsrc % (sourcefile, workbasedir, localsrc_prefix, workparentdir, dvar, debugsrcdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800585 try:
586 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
587 except subprocess.CalledProcessError:
588 # Can "fail" if internal headers/transient sources are attempted
589 pass
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500590
591 # cpio seems to have a bug with -lL together and symbolic links are just copied, not dereferenced.
592 # Work around this by manually finding and copying any symbolic links that made it through.
Brad Bishop19323692019-04-05 15:28:33 -0400593 cmd = "find %s%s -type l -print0 -delete | sed s#%s%s/##g | (cd '%s' ; cpio -pd0mL --no-preserve-owner '%s%s')" % \
594 (dvar, debugsrcdir, dvar, debugsrcdir, workparentdir, dvar, debugsrcdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800595 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500596
597 # The copy by cpio may have resulted in some empty directories! Remove these
598 cmd = "find %s%s -empty -type d -delete" % (dvar, debugsrcdir)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800599 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500600
601 # Also remove debugsrcdir if its empty
602 for p in nosuchdir[::-1]:
603 if os.path.exists(p) and not os.listdir(p):
604 os.rmdir(p)
605
606#
607# Package data handling routines
608#
609
Andrew Geissler82c905d2020-04-13 13:39:40 -0500610def get_package_mapping (pkg, basepkg, d, depversions=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500611 import oe.packagedata
612
613 data = oe.packagedata.read_subpkgdata(pkg, d)
Patrick Williams213cb262021-08-07 19:21:33 -0500614 key = "PKG:%s" % pkg
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500615
616 if key in data:
Andrew Geissler595f6302022-01-24 19:11:47 +0000617 if bb.data.inherits_class('allarch', d) and bb.data.inherits_class('packagegroup', d) and pkg != data[key]:
618 bb.error("An allarch packagegroup shouldn't depend on packages which are dynamically renamed (%s to %s)" % (pkg, data[key]))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500619 # Have to avoid undoing the write_extra_pkgs(global_variants...)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800620 if bb.data.inherits_class('allarch', d) and not d.getVar('MULTILIB_VARIANTS') \
621 and data[key] == basepkg:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500622 return pkg
Andrew Geissler82c905d2020-04-13 13:39:40 -0500623 if depversions == []:
624 # Avoid returning a mapping if the renamed package rprovides its original name
Patrick Williams213cb262021-08-07 19:21:33 -0500625 rprovkey = "RPROVIDES:%s" % pkg
Andrew Geissler82c905d2020-04-13 13:39:40 -0500626 if rprovkey in data:
627 if pkg in bb.utils.explode_dep_versions2(data[rprovkey]):
628 bb.note("%s rprovides %s, not replacing the latter" % (data[key], pkg))
629 return pkg
630 # Do map to rewritten package name
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500631 return data[key]
632
633 return pkg
634
635def get_package_additional_metadata (pkg_type, d):
636 base_key = "PACKAGE_ADD_METADATA"
637 for key in ("%s_%s" % (base_key, pkg_type.upper()), base_key):
638 if d.getVar(key, False) is None:
639 continue
640 d.setVarFlag(key, "type", "list")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500641 if d.getVarFlag(key, "separator") is None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500642 d.setVarFlag(key, "separator", "\\n")
643 metadata_fields = [field.strip() for field in oe.data.typed_value(key, d)]
644 return "\n".join(metadata_fields).strip()
645
646def runtime_mapping_rename (varname, pkg, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500647 #bb.note("%s before: %s" % (varname, d.getVar(varname)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500648
649 new_depends = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500650 deps = bb.utils.explode_dep_versions2(d.getVar(varname) or "")
Andrew Geissler82c905d2020-04-13 13:39:40 -0500651 for depend, depversions in deps.items():
652 new_depend = get_package_mapping(depend, pkg, d, depversions)
653 if depend != new_depend:
654 bb.note("package name mapping done: %s -> %s" % (depend, new_depend))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500655 new_depends[new_depend] = deps[depend]
656
657 d.setVar(varname, bb.utils.join_deps(new_depends, commasep=False))
658
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500659 #bb.note("%s after: %s" % (varname, d.getVar(varname)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500660
661#
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500662# Used by do_packagedata (and possibly other routines post do_package)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500663#
664
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500665package_get_auto_pr[vardepsexclude] = "BB_TASKDEPDATA"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500666python package_get_auto_pr() {
667 import oe.prservice
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500668
669 def get_do_package_hash(pn):
670 if d.getVar("BB_RUNTASK") != "do_package":
671 taskdepdata = d.getVar("BB_TASKDEPDATA", False)
672 for dep in taskdepdata:
673 if taskdepdata[dep][1] == "do_package" and taskdepdata[dep][0] == pn:
674 return taskdepdata[dep][6]
675 return None
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500676
677 # Support per recipe PRSERV_HOST
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500678 pn = d.getVar('PN')
679 host = d.getVar("PRSERV_HOST_" + pn)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500680 if not (host is None):
681 d.setVar("PRSERV_HOST", host)
682
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500683 pkgv = d.getVar("PKGV")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500684
685 # PR Server not active, handle AUTOINC
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500686 if not d.getVar('PRSERV_HOST'):
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500687 d.setVar("PRSERV_PV_AUTOINC", "0")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500688 return
689
690 auto_pr = None
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500691 pv = d.getVar("PV")
692 version = d.getVar("PRAUTOINX")
693 pkgarch = d.getVar("PACKAGE_ARCH")
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500694 checksum = get_do_package_hash(pn)
695
696 # If do_package isn't in the dependencies, we can't get the checksum...
697 if not checksum:
698 bb.warn('Task %s requested do_package unihash, but it was not available.' % d.getVar('BB_RUNTASK'))
699 #taskdepdata = d.getVar("BB_TASKDEPDATA", False)
700 #for dep in taskdepdata:
701 # bb.warn('%s:%s = %s' % (taskdepdata[dep][0], taskdepdata[dep][1], taskdepdata[dep][6]))
702 return
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500703
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500704 if d.getVar('PRSERV_LOCKDOWN'):
705 auto_pr = d.getVar('PRAUTO_' + version + '_' + pkgarch) or d.getVar('PRAUTO_' + version) or None
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500706 if auto_pr is None:
707 bb.fatal("Can NOT get PRAUTO from lockdown exported file")
708 d.setVar('PRAUTO',str(auto_pr))
709 return
710
711 try:
Andrew Geisslerd159c7f2021-09-02 21:05:58 -0500712 conn = oe.prservice.prserv_make_conn(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500713 if conn is not None:
714 if "AUTOINC" in pkgv:
715 srcpv = bb.fetch2.get_srcrev(d)
716 base_ver = "AUTOINC-%s" % version[:version.find(srcpv)]
717 value = conn.getPR(base_ver, pkgarch, srcpv)
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500718 d.setVar("PRSERV_PV_AUTOINC", str(value))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500719
720 auto_pr = conn.getPR(version, pkgarch, checksum)
Andrew Geisslerd159c7f2021-09-02 21:05:58 -0500721 conn.close()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500722 except Exception as e:
723 bb.fatal("Can NOT get PRAUTO, exception %s" % str(e))
724 if auto_pr is None:
725 bb.fatal("Can NOT get PRAUTO from remote PR service")
726 d.setVar('PRAUTO',str(auto_pr))
727}
728
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500729#
730# Package functions suitable for inclusion in PACKAGEFUNCS
731#
732
733python package_convert_pr_autoinc() {
734 pkgv = d.getVar("PKGV")
735
736 # Adjust pkgv as necessary...
737 if 'AUTOINC' in pkgv:
738 d.setVar("PKGV", pkgv.replace("AUTOINC", "${PRSERV_PV_AUTOINC}"))
739
740 # Change PRSERV_PV_AUTOINC and EXTENDPRAUTO usage to special values
741 d.setVar('PRSERV_PV_AUTOINC', '@PRSERV_PV_AUTOINC@')
742 d.setVar('EXTENDPRAUTO', '@EXTENDPRAUTO@')
743}
744
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500745LOCALEBASEPN ??= "${PN}"
746
747python package_do_split_locales() {
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500748 if (d.getVar('PACKAGE_NO_LOCALE') == '1'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500749 bb.debug(1, "package requested not splitting locales")
750 return
751
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500752 packages = (d.getVar('PACKAGES') or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500753
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500754 datadir = d.getVar('datadir')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500755 if not datadir:
756 bb.note("datadir not defined")
757 return
758
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500759 dvar = d.getVar('PKGD')
760 pn = d.getVar('LOCALEBASEPN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500761
762 if pn + '-locale' in packages:
763 packages.remove(pn + '-locale')
764
765 localedir = os.path.join(dvar + datadir, 'locale')
766
767 if not cpath.isdir(localedir):
768 bb.debug(1, "No locale files in this package")
769 return
770
771 locales = os.listdir(localedir)
772
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500773 summary = d.getVar('SUMMARY') or pn
774 description = d.getVar('DESCRIPTION') or ""
775 locale_section = d.getVar('LOCALE_SECTION')
776 mlprefix = d.getVar('MLPREFIX') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500777 for l in sorted(locales):
778 ln = legitimize_package_name(l)
779 pkg = pn + '-locale-' + ln
780 packages.append(pkg)
Patrick Williams213cb262021-08-07 19:21:33 -0500781 d.setVar('FILES:' + pkg, os.path.join(datadir, 'locale', l))
782 d.setVar('RRECOMMENDS:' + pkg, '%svirtual-locale-%s' % (mlprefix, ln))
783 d.setVar('RPROVIDES:' + pkg, '%s-locale %s%s-translation' % (pn, mlprefix, ln))
784 d.setVar('SUMMARY:' + pkg, '%s - %s translations' % (summary, l))
785 d.setVar('DESCRIPTION:' + pkg, '%s This package contains language translation files for the %s locale.' % (description, l))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500786 if locale_section:
Patrick Williams213cb262021-08-07 19:21:33 -0500787 d.setVar('SECTION:' + pkg, locale_section)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500788
789 d.setVar('PACKAGES', ' '.join(packages))
790
791 # Disabled by RP 18/06/07
792 # Wildcards aren't supported in debian
793 # They break with ipkg since glibc-locale* will mean that
794 # glibc-localedata-translit* won't install as a dependency
795 # for some other package which breaks meta-toolchain
796 # Probably breaks since virtual-locale- isn't provided anywhere
Patrick Williams213cb262021-08-07 19:21:33 -0500797 #rdep = (d.getVar('RDEPENDS:%s' % pn) or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500798 #rdep.append('%s-locale*' % pn)
Patrick Williams213cb262021-08-07 19:21:33 -0500799 #d.setVar('RDEPENDS:%s' % pn, ' '.join(rdep))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500800}
801
802python perform_packagecopy () {
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800803 import subprocess
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600804 import shutil
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800805
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500806 dest = d.getVar('D')
807 dvar = d.getVar('PKGD')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500808
809 # Start by package population by taking a copy of the installed
810 # files to operate on
811 # Preserve sparse files and hard links
Patrick Williams03907ee2022-05-01 06:28:52 -0500812 cmd = 'tar --exclude=./sysroot-only -cf - -C %s -p -S . | tar -xf - -C %s' % (dest, dvar)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800813 subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500814
815 # replace RPATHs for the nativesdk binaries, to make them relocatable
816 if bb.data.inherits_class('nativesdk', d) or bb.data.inherits_class('cross-canadian', d):
817 rpath_replace (dvar, d)
818}
819perform_packagecopy[cleandirs] = "${PKGD}"
820perform_packagecopy[dirs] = "${PKGD}"
821
822# We generate a master list of directories to process, we start by
823# seeding this list with reasonable defaults, then load from
824# the fs-perms.txt files
825python fixup_perms () {
826 import pwd, grp
827
828 # init using a string with the same format as a line as documented in
829 # the fs-perms.txt file
830 # <path> <mode> <uid> <gid> <walk> <fmode> <fuid> <fgid>
831 # <path> link <link target>
832 #
833 # __str__ can be used to print out an entry in the input format
834 #
835 # if fs_perms_entry.path is None:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400836 # an error occurred
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500837 # if fs_perms_entry.link, you can retrieve:
838 # fs_perms_entry.path = path
839 # fs_perms_entry.link = target of link
840 # if not fs_perms_entry.link, you can retrieve:
841 # fs_perms_entry.path = path
842 # fs_perms_entry.mode = expected dir mode or None
843 # fs_perms_entry.uid = expected uid or -1
844 # fs_perms_entry.gid = expected gid or -1
845 # fs_perms_entry.walk = 'true' or something else
846 # fs_perms_entry.fmode = expected file mode or None
847 # fs_perms_entry.fuid = expected file uid or -1
848 # fs_perms_entry_fgid = expected file gid or -1
849 class fs_perms_entry():
850 def __init__(self, line):
851 lsplit = line.split()
852 if len(lsplit) == 3 and lsplit[1].lower() == "link":
853 self._setlink(lsplit[0], lsplit[2])
854 elif len(lsplit) == 8:
855 self._setdir(lsplit[0], lsplit[1], lsplit[2], lsplit[3], lsplit[4], lsplit[5], lsplit[6], lsplit[7])
856 else:
857 msg = "Fixup Perms: invalid config line %s" % line
Andrew Geisslereff27472021-10-29 15:35:00 -0500858 oe.qa.handle_error("perm-config", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500859 self.path = None
860 self.link = None
861
862 def _setdir(self, path, mode, uid, gid, walk, fmode, fuid, fgid):
863 self.path = os.path.normpath(path)
864 self.link = None
865 self.mode = self._procmode(mode)
866 self.uid = self._procuid(uid)
867 self.gid = self._procgid(gid)
868 self.walk = walk.lower()
869 self.fmode = self._procmode(fmode)
870 self.fuid = self._procuid(fuid)
871 self.fgid = self._procgid(fgid)
872
873 def _setlink(self, path, link):
874 self.path = os.path.normpath(path)
875 self.link = link
876
877 def _procmode(self, mode):
878 if not mode or (mode and mode == "-"):
879 return None
880 else:
881 return int(mode,8)
882
883 # Note uid/gid -1 has special significance in os.lchown
884 def _procuid(self, uid):
885 if uid is None or uid == "-":
886 return -1
887 elif uid.isdigit():
888 return int(uid)
889 else:
890 return pwd.getpwnam(uid).pw_uid
891
892 def _procgid(self, gid):
893 if gid is None or gid == "-":
894 return -1
895 elif gid.isdigit():
896 return int(gid)
897 else:
898 return grp.getgrnam(gid).gr_gid
899
900 # Use for debugging the entries
901 def __str__(self):
902 if self.link:
903 return "%s link %s" % (self.path, self.link)
904 else:
905 mode = "-"
906 if self.mode:
907 mode = "0%o" % self.mode
908 fmode = "-"
909 if self.fmode:
910 fmode = "0%o" % self.fmode
911 uid = self._mapugid(self.uid)
912 gid = self._mapugid(self.gid)
913 fuid = self._mapugid(self.fuid)
914 fgid = self._mapugid(self.fgid)
915 return "%s %s %s %s %s %s %s %s" % (self.path, mode, uid, gid, self.walk, fmode, fuid, fgid)
916
917 def _mapugid(self, id):
918 if id is None or id == -1:
919 return "-"
920 else:
921 return "%d" % id
922
923 # Fix the permission, owner and group of path
924 def fix_perms(path, mode, uid, gid, dir):
925 if mode and not os.path.islink(path):
926 #bb.note("Fixup Perms: chmod 0%o %s" % (mode, dir))
927 os.chmod(path, mode)
928 # -1 is a special value that means don't change the uid/gid
929 # if they are BOTH -1, don't bother to lchown
930 if not (uid == -1 and gid == -1):
931 #bb.note("Fixup Perms: lchown %d:%d %s" % (uid, gid, dir))
932 os.lchown(path, uid, gid)
933
934 # Return a list of configuration files based on either the default
935 # files/fs-perms.txt or the contents of FILESYSTEM_PERMS_TABLES
936 # paths are resolved via BBPATH
937 def get_fs_perms_list(d):
938 str = ""
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500939 bbpath = d.getVar('BBPATH')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500940 fs_perms_tables = d.getVar('FILESYSTEM_PERMS_TABLES') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500941 for conf_file in fs_perms_tables.split():
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800942 confpath = bb.utils.which(bbpath, conf_file)
943 if confpath:
944 str += " %s" % bb.utils.which(bbpath, conf_file)
945 else:
946 bb.warn("cannot find %s specified in FILESYSTEM_PERMS_TABLES" % conf_file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500947 return str
948
949
950
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500951 dvar = d.getVar('PKGD')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500952
953 fs_perms_table = {}
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500954 fs_link_table = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500955
956 # By default all of the standard directories specified in
957 # bitbake.conf will get 0755 root:root.
958 target_path_vars = [ 'base_prefix',
959 'prefix',
960 'exec_prefix',
961 'base_bindir',
962 'base_sbindir',
963 'base_libdir',
964 'datadir',
965 'sysconfdir',
966 'servicedir',
967 'sharedstatedir',
968 'localstatedir',
969 'infodir',
970 'mandir',
971 'docdir',
972 'bindir',
973 'sbindir',
974 'libexecdir',
975 'libdir',
976 'includedir',
977 'oldincludedir' ]
978
979 for path in target_path_vars:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500980 dir = d.getVar(path) or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500981 if dir == "":
982 continue
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500983 fs_perms_table[dir] = fs_perms_entry(d.expand("%s 0755 root root false - - -" % (dir)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500984
985 # Now we actually load from the configuration files
986 for conf in get_fs_perms_list(d).split():
Brad Bishop64c979e2019-11-04 13:55:29 -0500987 if not os.path.exists(conf):
988 continue
989 with open(conf) as f:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500990 for line in f:
991 if line.startswith('#'):
992 continue
993 lsplit = line.split()
994 if len(lsplit) == 0:
995 continue
996 if len(lsplit) != 8 and not (len(lsplit) == 3 and lsplit[1].lower() == "link"):
997 msg = "Fixup perms: %s invalid line: %s" % (conf, line)
Andrew Geisslereff27472021-10-29 15:35:00 -0500998 oe.qa.handle_error("perm-line", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500999 continue
1000 entry = fs_perms_entry(d.expand(line))
1001 if entry and entry.path:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001002 if entry.link:
1003 fs_link_table[entry.path] = entry
1004 if entry.path in fs_perms_table:
1005 fs_perms_table.pop(entry.path)
1006 else:
1007 fs_perms_table[entry.path] = entry
1008 if entry.path in fs_link_table:
1009 fs_link_table.pop(entry.path)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001010
1011 # Debug -- list out in-memory table
1012 #for dir in fs_perms_table:
1013 # bb.note("Fixup Perms: %s: %s" % (dir, str(fs_perms_table[dir])))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001014 #for link in fs_link_table:
1015 # bb.note("Fixup Perms: %s: %s" % (link, str(fs_link_table[link])))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001016
1017 # We process links first, so we can go back and fixup directory ownership
1018 # for any newly created directories
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001019 # Process in sorted order so /run gets created before /run/lock, etc.
1020 for entry in sorted(fs_link_table.values(), key=lambda x: x.link):
1021 link = entry.link
1022 dir = entry.path
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001023 origin = dvar + dir
1024 if not (cpath.exists(origin) and cpath.isdir(origin) and not cpath.islink(origin)):
1025 continue
1026
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001027 if link[0] == "/":
1028 target = dvar + link
1029 ptarget = link
1030 else:
1031 target = os.path.join(os.path.dirname(origin), link)
1032 ptarget = os.path.join(os.path.dirname(dir), link)
1033 if os.path.exists(target):
1034 msg = "Fixup Perms: Unable to correct directory link, target already exists: %s -> %s" % (dir, ptarget)
Andrew Geisslereff27472021-10-29 15:35:00 -05001035 oe.qa.handle_error("perm-link", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001036 continue
1037
1038 # Create path to move directory to, move it, and then setup the symlink
1039 bb.utils.mkdirhier(os.path.dirname(target))
1040 #bb.note("Fixup Perms: Rename %s -> %s" % (dir, ptarget))
Andrew Geisslerc926e172021-05-07 16:11:35 -05001041 bb.utils.rename(origin, target)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001042 #bb.note("Fixup Perms: Link %s -> %s" % (dir, link))
1043 os.symlink(link, origin)
1044
1045 for dir in fs_perms_table:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001046 origin = dvar + dir
1047 if not (cpath.exists(origin) and cpath.isdir(origin)):
1048 continue
1049
1050 fix_perms(origin, fs_perms_table[dir].mode, fs_perms_table[dir].uid, fs_perms_table[dir].gid, dir)
1051
1052 if fs_perms_table[dir].walk == 'true':
1053 for root, dirs, files in os.walk(origin):
1054 for dr in dirs:
1055 each_dir = os.path.join(root, dr)
1056 fix_perms(each_dir, fs_perms_table[dir].mode, fs_perms_table[dir].uid, fs_perms_table[dir].gid, dir)
1057 for f in files:
1058 each_file = os.path.join(root, f)
1059 fix_perms(each_file, fs_perms_table[dir].fmode, fs_perms_table[dir].fuid, fs_perms_table[dir].fgid, dir)
1060}
1061
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001062def package_debug_vars(d):
1063 # We default to '.debug' style
1064 if d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-file-directory':
1065 # Single debug-file-directory style debug info
1066 debug_vars = {
1067 "append": ".debug",
1068 "staticappend": "",
1069 "dir": "",
1070 "staticdir": "",
1071 "libdir": "/usr/lib/debug",
1072 "staticlibdir": "/usr/lib/debug-static",
1073 "srcdir": "/usr/src/debug",
1074 }
1075 elif d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-without-src':
1076 # Original OE-core, a.k.a. ".debug", style debug info, but without sources in /usr/src/debug
1077 debug_vars = {
1078 "append": "",
1079 "staticappend": "",
1080 "dir": "/.debug",
1081 "staticdir": "/.debug-static",
1082 "libdir": "",
1083 "staticlibdir": "",
1084 "srcdir": "",
1085 }
1086 elif d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-with-srcpkg':
1087 debug_vars = {
1088 "append": "",
1089 "staticappend": "",
1090 "dir": "/.debug",
1091 "staticdir": "/.debug-static",
1092 "libdir": "",
1093 "staticlibdir": "",
1094 "srcdir": "/usr/src/debug",
1095 }
1096 else:
1097 # Original OE-core, a.k.a. ".debug", style debug info
1098 debug_vars = {
1099 "append": "",
1100 "staticappend": "",
1101 "dir": "/.debug",
1102 "staticdir": "/.debug-static",
1103 "libdir": "",
1104 "staticlibdir": "",
1105 "srcdir": "/usr/src/debug",
1106 }
1107
1108 return debug_vars
1109
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001110python split_and_strip_files () {
1111 import stat, errno
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001112 import subprocess
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001113
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001114 dvar = d.getVar('PKGD')
1115 pn = d.getVar('PN')
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001116 hostos = d.getVar('HOST_OS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001117
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001118 oldcwd = os.getcwd()
1119 os.chdir(dvar)
1120
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001121 dv = package_debug_vars(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001122
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001123 #
1124 # First lets figure out all of the files we may have to process ... do this only once!
1125 #
1126 elffiles = {}
1127 symlinks = {}
Brad Bishop316dfdd2018-06-25 12:45:53 -04001128 staticlibs = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001129 inodes = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001130 libdir = os.path.abspath(dvar + os.sep + d.getVar("libdir"))
1131 baselibdir = os.path.abspath(dvar + os.sep + d.getVar("base_libdir"))
Brad Bishop316dfdd2018-06-25 12:45:53 -04001132 skipfiles = (d.getVar("INHIBIT_PACKAGE_STRIP_FILES") or "").split()
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001133 if (d.getVar('INHIBIT_PACKAGE_STRIP') != '1' or \
1134 d.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT') != '1'):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001135 checkelf = {}
1136 checkelflinks = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001137 for root, dirs, files in cpath.walk(dvar):
1138 for f in files:
1139 file = os.path.join(root, f)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001140
1141 # Skip debug files
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001142 if dv["append"] and file.endswith(dv["append"]):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001143 continue
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001144 if dv["dir"] and dv["dir"] in os.path.dirname(file[len(dvar):]):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001145 continue
1146
Brad Bishop316dfdd2018-06-25 12:45:53 -04001147 if file in skipfiles:
1148 continue
1149
Andrew Geissler82c905d2020-04-13 13:39:40 -05001150 if oe.package.is_static_lib(file):
1151 staticlibs.append(file)
1152 continue
1153
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001154 try:
1155 ltarget = cpath.realpath(file, dvar, False)
1156 s = cpath.lstat(ltarget)
1157 except OSError as e:
1158 (err, strerror) = e.args
1159 if err != errno.ENOENT:
1160 raise
1161 # Skip broken symlinks
1162 continue
1163 if not s:
1164 continue
Brad Bishop316dfdd2018-06-25 12:45:53 -04001165 # Check its an executable
Andrew Geissler595f6302022-01-24 19:11:47 +00001166 if (s[stat.ST_MODE] & stat.S_IXUSR) or (s[stat.ST_MODE] & stat.S_IXGRP) \
1167 or (s[stat.ST_MODE] & stat.S_IXOTH) \
1168 or ((file.startswith(libdir) or file.startswith(baselibdir)) \
1169 and (".so" in f or ".node" in f)) \
1170 or (f.startswith('vmlinux') or ".ko" in f):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001171
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001172 if cpath.islink(file):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001173 checkelflinks[file] = ltarget
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001174 continue
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001175 # Use a reference of device ID and inode number to identify files
1176 file_reference = "%d_%d" % (s.st_dev, s.st_ino)
1177 checkelf[file] = (file, file_reference)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001178
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001179 results = oe.utils.multiprocess_launch(oe.package.is_elf, checkelflinks.values(), d)
1180 results_map = {}
1181 for (ltarget, elf_file) in results:
1182 results_map[ltarget] = elf_file
1183 for file in checkelflinks:
1184 ltarget = checkelflinks[file]
1185 # If it's a symlink, and points to an ELF file, we capture the readlink target
1186 if results_map[ltarget]:
1187 target = os.readlink(file)
1188 #bb.note("Sym: %s (%d)" % (ltarget, results_map[ltarget]))
1189 symlinks[file] = target
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001190
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001191 results = oe.utils.multiprocess_launch(oe.package.is_elf, checkelf.keys(), d)
Brad Bishop15ae2502019-06-18 21:44:24 -04001192
1193 # Sort results by file path. This ensures that the files are always
1194 # processed in the same order, which is important to make sure builds
1195 # are reproducible when dealing with hardlinks
1196 results.sort(key=lambda x: x[0])
1197
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001198 for (file, elf_file) in results:
1199 # It's a file (or hardlink), not a link
1200 # ...but is it ELF, and is it already stripped?
1201 if elf_file & 1:
1202 if elf_file & 2:
Patrick Williams213cb262021-08-07 19:21:33 -05001203 if 'already-stripped' in (d.getVar('INSANE_SKIP:' + pn) or "").split():
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001204 bb.note("Skipping file %s from %s for already-stripped QA test" % (file[len(dvar):], pn))
1205 else:
1206 msg = "File '%s' from %s was already stripped, this will prevent future debugging!" % (file[len(dvar):], pn)
Andrew Geisslereff27472021-10-29 15:35:00 -05001207 oe.qa.handle_error("already-stripped", msg, d)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001208 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001209
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001210 # At this point we have an unstripped elf file. We need to:
1211 # a) Make sure any file we strip is not hardlinked to anything else outside this tree
1212 # b) Only strip any hardlinked file once (no races)
1213 # c) Track any hardlinks between files so that we can reconstruct matching debug file hardlinks
1214
1215 # Use a reference of device ID and inode number to identify files
1216 file_reference = checkelf[file][1]
1217 if file_reference in inodes:
1218 os.unlink(file)
1219 os.link(inodes[file_reference][0], file)
1220 inodes[file_reference].append(file)
1221 else:
1222 inodes[file_reference] = [file]
1223 # break hardlink
1224 bb.utils.break_hardlinks(file)
1225 elffiles[file] = elf_file
1226 # Modified the file so clear the cache
1227 cpath.updatecache(file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001228
Andrew Geissler5199d832021-09-24 16:47:35 -05001229 def strip_pkgd_prefix(f):
1230 nonlocal dvar
1231
1232 if f.startswith(dvar):
1233 return f[len(dvar):]
1234
1235 return f
1236
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001237 #
1238 # First lets process debug splitting
1239 #
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001240 if (d.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT') != '1'):
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001241 results = oe.utils.multiprocess_launch(splitdebuginfo, list(elffiles), d, extraargs=(dvar, dv, d))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001242
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001243 if dv["srcdir"] and not hostos.startswith("mingw"):
Andrew Geissler82c905d2020-04-13 13:39:40 -05001244 if (d.getVar('PACKAGE_DEBUG_STATIC_SPLIT') == '1'):
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001245 results = oe.utils.multiprocess_launch(splitstaticdebuginfo, staticlibs, d, extraargs=(dvar, dv, d))
Andrew Geissler82c905d2020-04-13 13:39:40 -05001246 else:
1247 for file in staticlibs:
1248 results.append( (file,source_info(file, d)) )
Brad Bishop19323692019-04-05 15:28:33 -04001249
Andrew Geissler5199d832021-09-24 16:47:35 -05001250 d.setVar("PKGDEBUGSOURCES", {strip_pkgd_prefix(f): sorted(s) for f, s in results})
1251
Brad Bishop19323692019-04-05 15:28:33 -04001252 sources = set()
1253 for r in results:
1254 sources.update(r[1])
Brad Bishop316dfdd2018-06-25 12:45:53 -04001255
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001256 # Hardlink our debug symbols to the other hardlink copies
1257 for ref in inodes:
1258 if len(inodes[ref]) == 1:
1259 continue
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001260
1261 target = inodes[ref][0][len(dvar):]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001262 for file in inodes[ref][1:]:
1263 src = file[len(dvar):]
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001264 dest = dv["libdir"] + os.path.dirname(src) + dv["dir"] + "/" + os.path.basename(target) + dv["append"]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001265 fpath = dvar + dest
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001266 ftarget = dvar + dv["libdir"] + os.path.dirname(target) + dv["dir"] + "/" + os.path.basename(target) + dv["append"]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001267 bb.utils.mkdirhier(os.path.dirname(fpath))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001268 # Only one hardlink of separated debug info file in each directory
1269 if not os.access(fpath, os.R_OK):
1270 #bb.note("Link %s -> %s" % (fpath, ftarget))
1271 os.link(ftarget, fpath)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001272
1273 # Create symlinks for all cases we were able to split symbols
1274 for file in symlinks:
1275 src = file[len(dvar):]
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001276 dest = dv["libdir"] + os.path.dirname(src) + dv["dir"] + "/" + os.path.basename(src) + dv["append"]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001277 fpath = dvar + dest
1278 # Skip it if the target doesn't exist
1279 try:
1280 s = os.stat(fpath)
1281 except OSError as e:
1282 (err, strerror) = e.args
1283 if err != errno.ENOENT:
1284 raise
1285 continue
1286
1287 ltarget = symlinks[file]
1288 lpath = os.path.dirname(ltarget)
1289 lbase = os.path.basename(ltarget)
1290 ftarget = ""
1291 if lpath and lpath != ".":
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001292 ftarget += lpath + dv["dir"] + "/"
1293 ftarget += lbase + dv["append"]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001294 if lpath.startswith(".."):
1295 ftarget = os.path.join("..", ftarget)
1296 bb.utils.mkdirhier(os.path.dirname(fpath))
1297 #bb.note("Symlink %s -> %s" % (fpath, ftarget))
1298 os.symlink(ftarget, fpath)
1299
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001300 # Process the dv["srcdir"] if requested...
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001301 # This copies and places the referenced sources for later debugging...
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001302 copydebugsources(dv["srcdir"], sources, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001303 #
1304 # End of debug splitting
1305 #
1306
1307 #
1308 # Now lets go back over things and strip them
1309 #
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001310 if (d.getVar('INHIBIT_PACKAGE_STRIP') != '1'):
1311 strip = d.getVar("STRIP")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001312 sfiles = []
1313 for file in elffiles:
1314 elf_file = int(elffiles[file])
1315 #bb.note("Strip %s" % file)
1316 sfiles.append((file, elf_file, strip))
Andrew Geissler82c905d2020-04-13 13:39:40 -05001317 if (d.getVar('PACKAGE_STRIP_STATIC') == '1' or d.getVar('PACKAGE_DEBUG_STATIC_SPLIT') == '1'):
1318 for f in staticlibs:
1319 sfiles.append((f, 16, strip))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001320
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001321 oe.utils.multiprocess_launch(oe.package.runstrip, sfiles, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001322
Andrew Geissler82c905d2020-04-13 13:39:40 -05001323 # Build "minidebuginfo" and reinject it back into the stripped binaries
1324 if d.getVar('PACKAGE_MINIDEBUGINFO') == '1':
1325 oe.utils.multiprocess_launch(inject_minidebuginfo, list(elffiles), d,
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001326 extraargs=(dvar, dv, d))
Andrew Geissler82c905d2020-04-13 13:39:40 -05001327
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001328 #
1329 # End of strip
1330 #
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001331 os.chdir(oldcwd)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001332}
1333
1334python populate_packages () {
1335 import glob, re
1336
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001337 workdir = d.getVar('WORKDIR')
1338 outdir = d.getVar('DEPLOY_DIR')
1339 dvar = d.getVar('PKGD')
Brad Bishop19323692019-04-05 15:28:33 -04001340 packages = d.getVar('PACKAGES').split()
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001341 pn = d.getVar('PN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001342
1343 bb.utils.mkdirhier(outdir)
1344 os.chdir(dvar)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001345
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001346 autodebug = not (d.getVar("NOAUTOPACKAGEDEBUG") or False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001347
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001348 split_source_package = (d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-with-srcpkg')
1349
Brad Bishop19323692019-04-05 15:28:33 -04001350 # If debug-with-srcpkg mode is enabled then add the source package if it
1351 # doesn't exist and add the source file contents to the source package.
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001352 if split_source_package:
1353 src_package_name = ('%s-src' % d.getVar('PN'))
Brad Bishop19323692019-04-05 15:28:33 -04001354 if not src_package_name in packages:
1355 packages.append(src_package_name)
Patrick Williams213cb262021-08-07 19:21:33 -05001356 d.setVar('FILES:%s' % src_package_name, '/usr/src/debug')
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001357
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001358 # Sanity check PACKAGES for duplicates
Brad Bishop316dfdd2018-06-25 12:45:53 -04001359 # Sanity should be moved to sanity.bbclass once we have the infrastructure
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001360 package_dict = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001361
Brad Bishop19323692019-04-05 15:28:33 -04001362 for i, pkg in enumerate(packages):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001363 if pkg in package_dict:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001364 msg = "%s is listed in PACKAGES multiple times, this leads to packaging errors." % pkg
Andrew Geisslereff27472021-10-29 15:35:00 -05001365 oe.qa.handle_error("packages-list", msg, d)
Brad Bishop19323692019-04-05 15:28:33 -04001366 # Ensure the source package gets the chance to pick up the source files
1367 # before the debug package by ordering it first in PACKAGES. Whether it
1368 # actually picks up any source files is controlled by
1369 # PACKAGE_DEBUG_SPLIT_STYLE.
1370 elif pkg.endswith("-src"):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001371 package_dict[pkg] = (10, i)
1372 elif autodebug and pkg.endswith("-dbg"):
1373 package_dict[pkg] = (30, i)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001374 else:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001375 package_dict[pkg] = (50, i)
Brad Bishop19323692019-04-05 15:28:33 -04001376 packages = sorted(package_dict.keys(), key=package_dict.get)
1377 d.setVar('PACKAGES', ' '.join(packages))
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001378 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001379
1380 seen = []
1381
1382 # os.mkdir masks the permissions with umask so we have to unset it first
1383 oldumask = os.umask(0)
1384
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001385 debug = []
1386 for root, dirs, files in cpath.walk(dvar):
1387 dir = root[len(dvar):]
1388 if not dir:
1389 dir = os.sep
1390 for f in (files + dirs):
1391 path = "." + os.path.join(dir, f)
Andrew Geissler82c905d2020-04-13 13:39:40 -05001392 if "/.debug/" in path or "/.debug-static/" in path or path.endswith("/.debug"):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001393 debug.append(path)
1394
Brad Bishop19323692019-04-05 15:28:33 -04001395 for pkg in packages:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001396 root = os.path.join(pkgdest, pkg)
1397 bb.utils.mkdirhier(root)
1398
Patrick Williams213cb262021-08-07 19:21:33 -05001399 filesvar = d.getVar('FILES:%s' % pkg) or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001400 if "//" in filesvar:
1401 msg = "FILES variable for package %s contains '//' which is invalid. Attempting to fix this but you should correct the metadata.\n" % pkg
Andrew Geisslereff27472021-10-29 15:35:00 -05001402 oe.qa.handle_error("files-invalid", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001403 filesvar.replace("//", "/")
1404
1405 origfiles = filesvar.split()
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001406 files, symlink_paths = files_from_filevars(origfiles)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001407
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001408 if autodebug and pkg.endswith("-dbg"):
1409 files.extend(debug)
1410
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001411 for file in files:
1412 if (not cpath.islink(file)) and (not cpath.exists(file)):
1413 continue
1414 if file in seen:
1415 continue
1416 seen.append(file)
1417
1418 def mkdir(src, dest, p):
1419 src = os.path.join(src, p)
1420 dest = os.path.join(dest, p)
1421 fstat = cpath.stat(src)
Brad Bishop96ff1982019-08-19 13:50:42 -04001422 os.mkdir(dest)
1423 os.chmod(dest, fstat.st_mode)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001424 os.chown(dest, fstat.st_uid, fstat.st_gid)
1425 if p not in seen:
1426 seen.append(p)
1427 cpath.updatecache(dest)
1428
1429 def mkdir_recurse(src, dest, paths):
1430 if cpath.exists(dest + '/' + paths):
1431 return
1432 while paths.startswith("./"):
1433 paths = paths[2:]
1434 p = "."
1435 for c in paths.split("/"):
1436 p = os.path.join(p, c)
1437 if not cpath.exists(os.path.join(dest, p)):
1438 mkdir(src, dest, p)
1439
1440 if cpath.isdir(file) and not cpath.islink(file):
1441 mkdir_recurse(dvar, root, file)
1442 continue
1443
1444 mkdir_recurse(dvar, root, os.path.dirname(file))
1445 fpath = os.path.join(root,file)
1446 if not cpath.islink(file):
1447 os.link(file, fpath)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001448 continue
1449 ret = bb.utils.copyfile(file, fpath)
1450 if ret is False or ret == 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001451 bb.fatal("File population failed")
1452
1453 # Check if symlink paths exist
1454 for file in symlink_paths:
1455 if not os.path.exists(os.path.join(root,file)):
1456 bb.fatal("File '%s' cannot be packaged into '%s' because its "
1457 "parent directory structure does not exist. One of "
1458 "its parent directories is a symlink whose target "
1459 "directory is not included in the package." %
1460 (file, pkg))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001461
1462 os.umask(oldumask)
1463 os.chdir(workdir)
1464
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001465 # Handle excluding packages with incompatible licenses
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001466 package_list = []
Brad Bishop19323692019-04-05 15:28:33 -04001467 for pkg in packages:
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00001468 licenses = d.getVar('_exclude_incompatible-' + pkg)
Andrew Geissler82c905d2020-04-13 13:39:40 -05001469 if licenses:
1470 msg = "Excluding %s from packaging as it has incompatible license(s): %s" % (pkg, licenses)
Andrew Geisslereff27472021-10-29 15:35:00 -05001471 oe.qa.handle_error("incompatible-license", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001472 else:
1473 package_list.append(pkg)
1474 d.setVar('PACKAGES', ' '.join(package_list))
1475
1476 unshipped = []
1477 for root, dirs, files in cpath.walk(dvar):
1478 dir = root[len(dvar):]
1479 if not dir:
1480 dir = os.sep
1481 for f in (files + dirs):
1482 path = os.path.join(dir, f)
1483 if ('.' + path) not in seen:
1484 unshipped.append(path)
1485
1486 if unshipped != []:
1487 msg = pn + ": Files/directories were installed but not shipped in any package:"
Patrick Williams213cb262021-08-07 19:21:33 -05001488 if "installed-vs-shipped" in (d.getVar('INSANE_SKIP:' + pn) or "").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001489 bb.note("Package %s skipping QA tests: installed-vs-shipped" % pn)
1490 else:
1491 for f in unshipped:
1492 msg = msg + "\n " + f
Patrick Williamsf1e5d692016-03-30 15:21:19 -05001493 msg = msg + "\nPlease set FILES such that these items are packaged. Alternatively if they are unneeded, avoid installing them or delete them within do_install.\n"
1494 msg = msg + "%s: %d installed and not shipped files." % (pn, len(unshipped))
Andrew Geisslereff27472021-10-29 15:35:00 -05001495 oe.qa.handle_error("installed-vs-shipped", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001496}
1497populate_packages[dirs] = "${D}"
1498
1499python package_fixsymlinks () {
1500 import errno
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001501 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001502 packages = d.getVar("PACKAGES", False).split()
1503
1504 dangling_links = {}
1505 pkg_files = {}
1506 for pkg in packages:
1507 dangling_links[pkg] = []
1508 pkg_files[pkg] = []
1509 inst_root = os.path.join(pkgdest, pkg)
1510 for path in pkgfiles[pkg]:
1511 rpath = path[len(inst_root):]
1512 pkg_files[pkg].append(rpath)
1513 rtarget = cpath.realpath(path, inst_root, True, assume_dir = True)
1514 if not cpath.lexists(rtarget):
1515 dangling_links[pkg].append(os.path.normpath(rtarget[len(inst_root):]))
1516
1517 newrdepends = {}
1518 for pkg in dangling_links:
1519 for l in dangling_links[pkg]:
1520 found = False
1521 bb.debug(1, "%s contains dangling link %s" % (pkg, l))
1522 for p in packages:
1523 if l in pkg_files[p]:
1524 found = True
1525 bb.debug(1, "target found in %s" % p)
1526 if p == pkg:
1527 break
1528 if pkg not in newrdepends:
1529 newrdepends[pkg] = []
1530 newrdepends[pkg].append(p)
1531 break
1532 if found == False:
1533 bb.note("%s contains dangling symlink to %s" % (pkg, l))
1534
1535 for pkg in newrdepends:
Patrick Williams213cb262021-08-07 19:21:33 -05001536 rdepends = bb.utils.explode_dep_versions2(d.getVar('RDEPENDS:' + pkg) or "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001537 for p in newrdepends[pkg]:
1538 if p not in rdepends:
1539 rdepends[p] = []
Patrick Williams213cb262021-08-07 19:21:33 -05001540 d.setVar('RDEPENDS:' + pkg, bb.utils.join_deps(rdepends, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001541}
1542
1543
1544python package_package_name_hook() {
1545 """
1546 A package_name_hook function can be used to rewrite the package names by
1547 changing PKG. For an example, see debian.bbclass.
1548 """
1549 pass
1550}
1551
1552EXPORT_FUNCTIONS package_name_hook
1553
1554
1555PKGDESTWORK = "${WORKDIR}/pkgdata"
1556
Andrew Geissler1e34c2d2020-05-29 16:02:59 -05001557PKGDATA_VARS = "PN PE PV PR PKGE PKGV PKGR LICENSE DESCRIPTION SUMMARY RDEPENDS RPROVIDES RRECOMMENDS RSUGGESTS RREPLACES RCONFLICTS SECTION PKG ALLOW_EMPTY FILES CONFFILES FILES_INFO PACKAGE_ADD_METADATA pkg_postinst pkg_postrm pkg_preinst pkg_prerm"
Brad Bishop15ae2502019-06-18 21:44:24 -04001558
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001559python emit_pkgdata() {
1560 from glob import glob
1561 import json
Andrew Geissler5199d832021-09-24 16:47:35 -05001562 import bb.compress.zstd
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001563
Brad Bishop316dfdd2018-06-25 12:45:53 -04001564 def process_postinst_on_target(pkg, mlprefix):
Patrick Williams213cb262021-08-07 19:21:33 -05001565 pkgval = d.getVar('PKG:%s' % pkg)
Brad Bishop96ff1982019-08-19 13:50:42 -04001566 if pkgval is None:
1567 pkgval = pkg
1568
Brad Bishop316dfdd2018-06-25 12:45:53 -04001569 defer_fragment = """
1570if [ -n "$D" ]; then
1571 $INTERCEPT_DIR/postinst_intercept delay_to_first_boot %s mlprefix=%s
1572 exit 0
1573fi
Brad Bishop96ff1982019-08-19 13:50:42 -04001574""" % (pkgval, mlprefix)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001575
Patrick Williams213cb262021-08-07 19:21:33 -05001576 postinst = d.getVar('pkg_postinst:%s' % pkg)
1577 postinst_ontarget = d.getVar('pkg_postinst_ontarget:%s' % pkg)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001578
1579 if postinst_ontarget:
1580 bb.debug(1, 'adding deferred pkg_postinst_ontarget() to pkg_postinst() for %s' % pkg)
1581 if not postinst:
1582 postinst = '#!/bin/sh\n'
1583 postinst += defer_fragment
1584 postinst += postinst_ontarget
Patrick Williams213cb262021-08-07 19:21:33 -05001585 d.setVar('pkg_postinst:%s' % pkg, postinst)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001586
1587 def add_set_e_to_scriptlets(pkg):
1588 for scriptlet_name in ('pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm'):
Patrick Williams213cb262021-08-07 19:21:33 -05001589 scriptlet = d.getVar('%s:%s' % (scriptlet_name, pkg))
Brad Bishop316dfdd2018-06-25 12:45:53 -04001590 if scriptlet:
1591 scriptlet_split = scriptlet.split('\n')
1592 if scriptlet_split[0].startswith("#!"):
1593 scriptlet = scriptlet_split[0] + "\nset -e\n" + "\n".join(scriptlet_split[1:])
1594 else:
1595 scriptlet = "set -e\n" + "\n".join(scriptlet_split[0:])
Patrick Williams213cb262021-08-07 19:21:33 -05001596 d.setVar('%s:%s' % (scriptlet_name, pkg), scriptlet)
Brad Bishop316dfdd2018-06-25 12:45:53 -04001597
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001598 def write_if_exists(f, pkg, var):
1599 def encode(str):
1600 import codecs
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001601 c = codecs.getencoder("unicode_escape")
1602 return c(str)[0].decode("latin1")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001603
Patrick Williams213cb262021-08-07 19:21:33 -05001604 val = d.getVar('%s:%s' % (var, pkg))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001605 if val:
Patrick Williams213cb262021-08-07 19:21:33 -05001606 f.write('%s:%s: %s\n' % (var, pkg, encode(val)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001607 return val
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001608 val = d.getVar('%s' % (var))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001609 if val:
1610 f.write('%s: %s\n' % (var, encode(val)))
1611 return val
1612
1613 def write_extra_pkgs(variants, pn, packages, pkgdatadir):
1614 for variant in variants:
1615 with open("%s/%s-%s" % (pkgdatadir, variant, pn), 'w') as fd:
1616 fd.write("PACKAGES: %s\n" % ' '.join(
1617 map(lambda pkg: '%s-%s' % (variant, pkg), packages.split())))
1618
1619 def write_extra_runtime_pkgs(variants, packages, pkgdatadir):
1620 for variant in variants:
1621 for pkg in packages.split():
1622 ml_pkg = "%s-%s" % (variant, pkg)
1623 subdata_file = "%s/runtime/%s" % (pkgdatadir, ml_pkg)
1624 with open(subdata_file, 'w') as fd:
Patrick Williams213cb262021-08-07 19:21:33 -05001625 fd.write("PKG:%s: %s" % (ml_pkg, pkg))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001626
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001627 packages = d.getVar('PACKAGES')
1628 pkgdest = d.getVar('PKGDEST')
1629 pkgdatadir = d.getVar('PKGDESTWORK')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001630
Brad Bishop64c979e2019-11-04 13:55:29 -05001631 data_file = pkgdatadir + d.expand("/${PN}")
1632 with open(data_file, 'w') as fd:
1633 fd.write("PACKAGES: %s\n" % packages)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001634
Andrew Geissler5199d832021-09-24 16:47:35 -05001635 pkgdebugsource = d.getVar("PKGDEBUGSOURCES") or []
1636
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001637 pn = d.getVar('PN')
1638 global_variants = (d.getVar('MULTILIB_GLOBAL_VARIANTS') or "").split()
1639 variants = (d.getVar('MULTILIB_VARIANTS') or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001640
1641 if bb.data.inherits_class('kernel', d) or bb.data.inherits_class('module-base', d):
1642 write_extra_pkgs(variants, pn, packages, pkgdatadir)
1643
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001644 if bb.data.inherits_class('allarch', d) and not variants \
1645 and not bb.data.inherits_class('packagegroup', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001646 write_extra_pkgs(global_variants, pn, packages, pkgdatadir)
1647
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001648 workdir = d.getVar('WORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001649
1650 for pkg in packages.split():
Patrick Williams213cb262021-08-07 19:21:33 -05001651 pkgval = d.getVar('PKG:%s' % pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001652 if pkgval is None:
1653 pkgval = pkg
Patrick Williams213cb262021-08-07 19:21:33 -05001654 d.setVar('PKG:%s' % pkg, pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001655
Andrew Geissler5199d832021-09-24 16:47:35 -05001656 extended_data = {
1657 "files_info": {}
1658 }
1659
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001660 pkgdestpkg = os.path.join(pkgdest, pkg)
1661 files = {}
Andrew Geissler5199d832021-09-24 16:47:35 -05001662 files_extra = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001663 total_size = 0
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001664 seen = set()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001665 for f in pkgfiles[pkg]:
Andrew Geissler5199d832021-09-24 16:47:35 -05001666 fpath = os.sep + os.path.relpath(f, pkgdestpkg)
1667
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001668 fstat = os.lstat(f)
Andrew Geissler5199d832021-09-24 16:47:35 -05001669 files[fpath] = fstat.st_size
1670
1671 extended_data["files_info"].setdefault(fpath, {})
1672 extended_data["files_info"][fpath]['size'] = fstat.st_size
1673
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001674 if fstat.st_ino not in seen:
1675 seen.add(fstat.st_ino)
1676 total_size += fstat.st_size
Andrew Geissler5199d832021-09-24 16:47:35 -05001677
1678 if fpath in pkgdebugsource:
1679 extended_data["files_info"][fpath]['debugsrc'] = pkgdebugsource[fpath]
1680 del pkgdebugsource[fpath]
1681
Andrew Geisslerd159c7f2021-09-02 21:05:58 -05001682 d.setVar('FILES_INFO:' + pkg , json.dumps(files, sort_keys=True))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001683
Brad Bishop316dfdd2018-06-25 12:45:53 -04001684 process_postinst_on_target(pkg, d.getVar("MLPREFIX"))
1685 add_set_e_to_scriptlets(pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001686
Brad Bishop15ae2502019-06-18 21:44:24 -04001687 subdata_file = pkgdatadir + "/runtime/%s" % pkg
1688 with open(subdata_file, 'w') as sf:
1689 for var in (d.getVar('PKGDATA_VARS') or "").split():
1690 val = write_if_exists(sf, pkg, var)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001691
Brad Bishop15ae2502019-06-18 21:44:24 -04001692 write_if_exists(sf, pkg, 'FILERPROVIDESFLIST')
Andrew Geissler5199d832021-09-24 16:47:35 -05001693 for dfile in sorted((d.getVar('FILERPROVIDESFLIST:' + pkg) or "").split()):
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001694 write_if_exists(sf, pkg, 'FILERPROVIDES:' + dfile)
Brad Bishop15ae2502019-06-18 21:44:24 -04001695
1696 write_if_exists(sf, pkg, 'FILERDEPENDSFLIST')
Andrew Geissler5199d832021-09-24 16:47:35 -05001697 for dfile in sorted((d.getVar('FILERDEPENDSFLIST:' + pkg) or "").split()):
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001698 write_if_exists(sf, pkg, 'FILERDEPENDS:' + dfile)
Brad Bishop15ae2502019-06-18 21:44:24 -04001699
Andrew Geisslerd159c7f2021-09-02 21:05:58 -05001700 sf.write('%s:%s: %d\n' % ('PKGSIZE', pkg, total_size))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001701
Andrew Geissler5199d832021-09-24 16:47:35 -05001702 subdata_extended_file = pkgdatadir + "/extended/%s.json.zstd" % pkg
1703 num_threads = int(d.getVar("BB_NUMBER_THREADS"))
1704 with bb.compress.zstd.open(subdata_extended_file, "wt", encoding="utf-8", num_threads=num_threads) as f:
1705 json.dump(extended_data, f, sort_keys=True, separators=(",", ":"))
1706
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001707 # Symlinks needed for rprovides lookup
Patrick Williams213cb262021-08-07 19:21:33 -05001708 rprov = d.getVar('RPROVIDES:%s' % pkg) or d.getVar('RPROVIDES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001709 if rprov:
Andrew Geisslerc9f78652020-09-18 14:11:35 -05001710 for p in bb.utils.explode_deps(rprov):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001711 subdata_sym = pkgdatadir + "/runtime-rprovides/%s/%s" % (p, pkg)
1712 bb.utils.mkdirhier(os.path.dirname(subdata_sym))
1713 oe.path.symlink("../../runtime/%s" % pkg, subdata_sym, True)
1714
Patrick Williams213cb262021-08-07 19:21:33 -05001715 allow_empty = d.getVar('ALLOW_EMPTY:%s' % pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001716 if not allow_empty:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001717 allow_empty = d.getVar('ALLOW_EMPTY')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001718 root = "%s/%s" % (pkgdest, pkg)
1719 os.chdir(root)
1720 g = glob('*')
1721 if g or allow_empty == "1":
1722 # Symlinks needed for reverse lookups (from the final package name)
1723 subdata_sym = pkgdatadir + "/runtime-reverse/%s" % pkgval
1724 oe.path.symlink("../runtime/%s" % pkg, subdata_sym, True)
1725
1726 packagedfile = pkgdatadir + '/runtime/%s.packaged' % pkg
1727 open(packagedfile, 'w').close()
1728
1729 if bb.data.inherits_class('kernel', d) or bb.data.inherits_class('module-base', d):
1730 write_extra_runtime_pkgs(variants, packages, pkgdatadir)
1731
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001732 if bb.data.inherits_class('allarch', d) and not variants \
1733 and not bb.data.inherits_class('packagegroup', d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001734 write_extra_runtime_pkgs(global_variants, packages, pkgdatadir)
1735
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001736}
Andrew Geissler5199d832021-09-24 16:47:35 -05001737emit_pkgdata[dirs] = "${PKGDESTWORK}/runtime ${PKGDESTWORK}/runtime-reverse ${PKGDESTWORK}/runtime-rprovides ${PKGDESTWORK}/extended"
1738emit_pkgdata[vardepsexclude] = "BB_NUMBER_THREADS"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001739
1740ldconfig_postinst_fragment() {
1741if [ x"$D" = "x" ]; then
1742 if [ -x /sbin/ldconfig ]; then /sbin/ldconfig ; fi
1743fi
1744}
1745
Andrew Geissler90fd73c2021-03-05 15:25:55 -06001746RPMDEPS = "${STAGING_LIBDIR_NATIVE}/rpm/rpmdeps --alldeps --define '__font_provides %{nil}'"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001747
1748# Collect perfile run-time dependency metadata
1749# Output:
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001750# FILERPROVIDESFLIST:pkg - list of all files w/ deps
1751# FILERPROVIDES:filepath:pkg - per file dep
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001752#
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001753# FILERDEPENDSFLIST:pkg - list of all files w/ deps
1754# FILERDEPENDS:filepath:pkg - per file dep
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001755
1756python package_do_filedeps() {
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001757 if d.getVar('SKIP_FILEDEPS') == '1':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001758 return
1759
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001760 pkgdest = d.getVar('PKGDEST')
1761 packages = d.getVar('PACKAGES')
1762 rpmdeps = d.getVar('RPMDEPS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001763
1764 def chunks(files, n):
1765 return [files[i:i+n] for i in range(0, len(files), n)]
1766
1767 pkglist = []
1768 for pkg in packages.split():
Patrick Williams213cb262021-08-07 19:21:33 -05001769 if d.getVar('SKIP_FILEDEPS:' + pkg) == '1':
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001770 continue
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001771 if pkg.endswith('-dbg') or pkg.endswith('-doc') or pkg.find('-locale-') != -1 or pkg.find('-localedata-') != -1 or pkg.find('-gconv-') != -1 or pkg.find('-charmap-') != -1 or pkg.startswith('kernel-module-') or pkg.endswith('-src'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001772 continue
1773 for files in chunks(pkgfiles[pkg], 100):
1774 pkglist.append((pkg, files, rpmdeps, pkgdest))
1775
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001776 processed = oe.utils.multiprocess_launch(oe.package.filedeprunner, pkglist, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001777
1778 provides_files = {}
1779 requires_files = {}
1780
1781 for result in processed:
1782 (pkg, provides, requires) = result
1783
1784 if pkg not in provides_files:
1785 provides_files[pkg] = []
1786 if pkg not in requires_files:
1787 requires_files[pkg] = []
1788
Brad Bishop19323692019-04-05 15:28:33 -04001789 for file in sorted(provides):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001790 provides_files[pkg].append(file)
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001791 key = "FILERPROVIDES:" + file + ":" + pkg
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001792 d.appendVar(key, " " + " ".join(provides[file]))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001793
Brad Bishop19323692019-04-05 15:28:33 -04001794 for file in sorted(requires):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001795 requires_files[pkg].append(file)
Patrick Williams0ca19cc2021-08-16 14:03:13 -05001796 key = "FILERDEPENDS:" + file + ":" + pkg
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001797 d.appendVar(key, " " + " ".join(requires[file]))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001798
1799 for pkg in requires_files:
Andrew Geissler5199d832021-09-24 16:47:35 -05001800 d.setVar("FILERDEPENDSFLIST:" + pkg, " ".join(sorted(requires_files[pkg])))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001801 for pkg in provides_files:
Andrew Geissler5199d832021-09-24 16:47:35 -05001802 d.setVar("FILERPROVIDESFLIST:" + pkg, " ".join(sorted(provides_files[pkg])))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001803}
1804
Brad Bishop96ff1982019-08-19 13:50:42 -04001805SHLIBSDIRS = "${WORKDIR_PKGDATA}/${MLPREFIX}shlibs2"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001806SHLIBSWORKDIR = "${PKGDESTWORK}/${MLPREFIX}shlibs2"
1807
1808python package_do_shlibs() {
Brad Bishop00e122a2019-10-05 11:10:57 -04001809 import itertools
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001810 import re, pipes
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001811 import subprocess
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001812
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001813 exclude_shlibs = d.getVar('EXCLUDE_FROM_SHLIBS', False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001814 if exclude_shlibs:
1815 bb.note("not generating shlibs")
1816 return
1817
Brad Bishop19323692019-04-05 15:28:33 -04001818 lib_re = re.compile(r"^.*\.so")
1819 libdir_re = re.compile(r".*/%s$" % d.getVar('baselib'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001820
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001821 packages = d.getVar('PACKAGES')
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001822
1823 shlib_pkgs = []
1824 exclusion_list = d.getVar("EXCLUDE_PACKAGES_FROM_SHLIBS")
1825 if exclusion_list:
1826 for pkg in packages.split():
1827 if pkg not in exclusion_list.split():
1828 shlib_pkgs.append(pkg)
1829 else:
1830 bb.note("not generating shlibs for %s" % pkg)
1831 else:
1832 shlib_pkgs = packages.split()
1833
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001834 hostos = d.getVar('HOST_OS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001835
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001836 workdir = d.getVar('WORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001837
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001838 ver = d.getVar('PKGV')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001839 if not ver:
1840 msg = "PKGV not defined"
Andrew Geisslereff27472021-10-29 15:35:00 -05001841 oe.qa.handle_error("pkgv-undefined", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001842 return
1843
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001844 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001845
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001846 shlibswork_dir = d.getVar('SHLIBSWORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001847
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001848 def linux_so(file, pkg, pkgver, d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001849 needs_ldconfig = False
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001850 needed = set()
1851 sonames = set()
1852 renames = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001853 ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '')
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001854 cmd = d.getVar('OBJDUMP') + " -p " + pipes.quote(file) + " 2>/dev/null"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001855 fd = os.popen(cmd)
1856 lines = fd.readlines()
1857 fd.close()
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001858 rpath = tuple()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001859 for l in lines:
Brad Bishop19323692019-04-05 15:28:33 -04001860 m = re.match(r"\s+RPATH\s+([^\s]*)", l)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001861 if m:
1862 rpaths = m.group(1).replace("$ORIGIN", ldir).split(":")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001863 rpath = tuple(map(os.path.normpath, rpaths))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001864 for l in lines:
Brad Bishop19323692019-04-05 15:28:33 -04001865 m = re.match(r"\s+NEEDED\s+([^\s]*)", l)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001866 if m:
1867 dep = m.group(1)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001868 if dep not in needed:
1869 needed.add((dep, file, rpath))
Brad Bishop19323692019-04-05 15:28:33 -04001870 m = re.match(r"\s+SONAME\s+([^\s]*)", l)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001871 if m:
1872 this_soname = m.group(1)
1873 prov = (this_soname, ldir, pkgver)
1874 if not prov in sonames:
1875 # if library is private (only used by package) then do not build shlib for it
Brad Bishop79641f22019-09-10 07:20:22 -04001876 import fnmatch
1877 if not private_libs or len([i for i in private_libs if fnmatch.fnmatch(this_soname, i)]) == 0:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001878 sonames.add(prov)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001879 if libdir_re.match(os.path.dirname(file)):
1880 needs_ldconfig = True
Andrew Geissler595f6302022-01-24 19:11:47 +00001881 if needs_ldconfig and snap_symlinks and (os.path.basename(file) != this_soname):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001882 renames.append((file, os.path.join(os.path.dirname(file), this_soname)))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001883 return (needs_ldconfig, needed, sonames, renames)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001884
1885 def darwin_so(file, needed, sonames, renames, pkgver):
1886 if not os.path.exists(file):
1887 return
1888 ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '')
1889
1890 def get_combinations(base):
1891 #
1892 # Given a base library name, find all combinations of this split by "." and "-"
1893 #
1894 combos = []
1895 options = base.split(".")
1896 for i in range(1, len(options) + 1):
1897 combos.append(".".join(options[0:i]))
1898 options = base.split("-")
1899 for i in range(1, len(options) + 1):
1900 combos.append("-".join(options[0:i]))
1901 return combos
1902
Brad Bishopd7bf8c12018-02-25 22:55:05 -05001903 if (file.endswith('.dylib') or file.endswith('.so')) and not pkg.endswith('-dev') and not pkg.endswith('-dbg') and not pkg.endswith('-src'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001904 # Drop suffix
1905 name = os.path.basename(file).rsplit(".",1)[0]
1906 # Find all combinations
1907 combos = get_combinations(name)
1908 for combo in combos:
1909 if not combo in sonames:
1910 prov = (combo, ldir, pkgver)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001911 sonames.add(prov)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001912 if file.endswith('.dylib') or file.endswith('.so'):
1913 rpath = []
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001914 p = subprocess.Popen([d.expand("${HOST_PREFIX}otool"), '-l', file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001915 out, err = p.communicate()
1916 # If returned successfully, process stdout for results
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001917 if p.returncode == 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001918 for l in out.split("\n"):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001919 l = l.strip()
1920 if l.startswith('path '):
1921 rpath.append(l.split()[1])
1922
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001923 p = subprocess.Popen([d.expand("${HOST_PREFIX}otool"), '-L', file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001924 out, err = p.communicate()
1925 # If returned successfully, process stdout for results
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001926 if p.returncode == 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001927 for l in out.split("\n"):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001928 l = l.strip()
1929 if not l or l.endswith(":"):
1930 continue
1931 if "is not an object file" in l:
1932 continue
1933 name = os.path.basename(l.split()[0]).rsplit(".", 1)[0]
1934 if name and name not in needed[pkg]:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001935 needed[pkg].add((name, file, tuple()))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001936
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001937 def mingw_dll(file, needed, sonames, renames, pkgver):
1938 if not os.path.exists(file):
1939 return
1940
1941 if file.endswith(".dll"):
1942 # assume all dlls are shared objects provided by the package
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001943 sonames.add((os.path.basename(file), os.path.dirname(file).replace(pkgdest + "/" + pkg, ''), pkgver))
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001944
1945 if (file.endswith(".dll") or file.endswith(".exe")):
1946 # use objdump to search for "DLL Name: .*\.dll"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001947 p = subprocess.Popen([d.expand("${HOST_PREFIX}objdump"), "-p", file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001948 out, err = p.communicate()
1949 # process the output, grabbing all .dll names
1950 if p.returncode == 0:
Brad Bishop19323692019-04-05 15:28:33 -04001951 for m in re.finditer(r"DLL Name: (.*?\.dll)$", out.decode(), re.MULTILINE | re.IGNORECASE):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001952 dllname = m.group(1)
1953 if dllname:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001954 needed[pkg].add((dllname, file, tuple()))
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001955
1956 if d.getVar('PACKAGE_SNAP_LIB_SYMLINKS') == "1":
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001957 snap_symlinks = True
1958 else:
1959 snap_symlinks = False
1960
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001961 needed = {}
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001962
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001963 shlib_provider = oe.package.read_shlib_providers(d)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001964
1965 for pkg in shlib_pkgs:
Patrick Williams213cb262021-08-07 19:21:33 -05001966 private_libs = d.getVar('PRIVATE_LIBS:' + pkg) or d.getVar('PRIVATE_LIBS') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001967 private_libs = private_libs.split()
1968 needs_ldconfig = False
1969 bb.debug(2, "calculating shlib provides for %s" % pkg)
1970
Patrick Williams213cb262021-08-07 19:21:33 -05001971 pkgver = d.getVar('PKGV:' + pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001972 if not pkgver:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001973 pkgver = d.getVar('PV_' + pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001974 if not pkgver:
1975 pkgver = ver
1976
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001977 needed[pkg] = set()
1978 sonames = set()
1979 renames = []
1980 linuxlist = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001981 for file in pkgfiles[pkg]:
1982 soname = None
1983 if cpath.islink(file):
1984 continue
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001985 if hostos == "darwin" or hostos == "darwin8":
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001986 darwin_so(file, needed, sonames, renames, pkgver)
Andrew Geisslerb7d28612020-07-24 16:15:54 -05001987 elif hostos.startswith("mingw"):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001988 mingw_dll(file, needed, sonames, renames, pkgver)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001989 elif os.access(file, os.X_OK) or lib_re.match(file):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001990 linuxlist.append(file)
1991
1992 if linuxlist:
1993 results = oe.utils.multiprocess_launch(linux_so, linuxlist, d, extraargs=(pkg, pkgver, d))
1994 for r in results:
1995 ldconfig = r[0]
1996 needed[pkg] |= r[1]
1997 sonames |= r[2]
1998 renames.extend(r[3])
1999 needs_ldconfig = needs_ldconfig or ldconfig
2000
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002001 for (old, new) in renames:
2002 bb.note("Renaming %s to %s" % (old, new))
Andrew Geisslerc926e172021-05-07 16:11:35 -05002003 bb.utils.rename(old, new)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002004 pkgfiles[pkg].remove(old)
Brad Bishop64c979e2019-11-04 13:55:29 -05002005
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002006 shlibs_file = os.path.join(shlibswork_dir, pkg + ".list")
2007 if len(sonames):
Brad Bishop64c979e2019-11-04 13:55:29 -05002008 with open(shlibs_file, 'w') as fd:
Andrew Geissler635e0e42020-08-21 15:58:33 -05002009 for s in sorted(sonames):
Brad Bishop64c979e2019-11-04 13:55:29 -05002010 if s[0] in shlib_provider and s[1] in shlib_provider[s[0]]:
2011 (old_pkg, old_pkgver) = shlib_provider[s[0]][s[1]]
2012 if old_pkg != pkg:
2013 bb.warn('%s-%s was registered as shlib provider for %s, changing it to %s-%s because it was built later' % (old_pkg, old_pkgver, s[0], pkg, pkgver))
2014 bb.debug(1, 'registering %s-%s as shlib provider for %s' % (pkg, pkgver, s[0]))
2015 fd.write(s[0] + ':' + s[1] + ':' + s[2] + '\n')
2016 if s[0] not in shlib_provider:
2017 shlib_provider[s[0]] = {}
2018 shlib_provider[s[0]][s[1]] = (pkg, pkgver)
Brad Bishop1d80a2e2019-11-15 16:35:03 -05002019 if needs_ldconfig:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002020 bb.debug(1, 'adding ldconfig call to postinst for %s' % pkg)
Patrick Williams213cb262021-08-07 19:21:33 -05002021 postinst = d.getVar('pkg_postinst:%s' % pkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002022 if not postinst:
2023 postinst = '#!/bin/sh\n'
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002024 postinst += d.getVar('ldconfig_postinst_fragment')
Patrick Williams213cb262021-08-07 19:21:33 -05002025 d.setVar('pkg_postinst:%s' % pkg, postinst)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002026 bb.debug(1, 'LIBNAMES: pkg %s sonames %s' % (pkg, sonames))
2027
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002028 assumed_libs = d.getVar('ASSUME_SHLIBS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002029 if assumed_libs:
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002030 libdir = d.getVar("libdir")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002031 for e in assumed_libs.split():
2032 l, dep_pkg = e.split(":")
2033 lib_ver = None
2034 dep_pkg = dep_pkg.rsplit("_", 1)
2035 if len(dep_pkg) == 2:
2036 lib_ver = dep_pkg[1]
2037 dep_pkg = dep_pkg[0]
2038 if l not in shlib_provider:
2039 shlib_provider[l] = {}
2040 shlib_provider[l][libdir] = (dep_pkg, lib_ver)
2041
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002042 libsearchpath = [d.getVar('libdir'), d.getVar('base_libdir')]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002043
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08002044 for pkg in shlib_pkgs:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002045 bb.debug(2, "calculating shlib requirements for %s" % pkg)
2046
Patrick Williams213cb262021-08-07 19:21:33 -05002047 private_libs = d.getVar('PRIVATE_LIBS:' + pkg) or d.getVar('PRIVATE_LIBS') or ""
Brad Bishop316dfdd2018-06-25 12:45:53 -04002048 private_libs = private_libs.split()
2049
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002050 deps = list()
2051 for n in needed[pkg]:
2052 # if n is in private libraries, don't try to search provider for it
2053 # this could cause problem in case some abc.bb provides private
2054 # /opt/abc/lib/libfoo.so.1 and contains /usr/bin/abc depending on system library libfoo.so.1
2055 # but skipping it is still better alternative than providing own
2056 # version and then adding runtime dependency for the same system library
Brad Bishop79641f22019-09-10 07:20:22 -04002057 import fnmatch
2058 if private_libs and len([i for i in private_libs if fnmatch.fnmatch(n[0], i)]) > 0:
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002059 bb.debug(2, '%s: Dependency %s covered by PRIVATE_LIBS' % (pkg, n[0]))
2060 continue
2061 if n[0] in shlib_provider.keys():
Brad Bishop00e122a2019-10-05 11:10:57 -04002062 shlib_provider_map = shlib_provider[n[0]]
2063 matches = set()
2064 for p in itertools.chain(list(n[2]), sorted(shlib_provider_map.keys()), libsearchpath):
2065 if p in shlib_provider_map:
2066 matches.add(p)
2067 if len(matches) > 1:
2068 matchpkgs = ', '.join([shlib_provider_map[match][0] for match in matches])
2069 bb.error("%s: Multiple shlib providers for %s: %s (used by files: %s)" % (pkg, n[0], matchpkgs, n[1]))
2070 elif len(matches) == 1:
2071 (dep_pkg, ver_needed) = shlib_provider_map[matches.pop()]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002072
2073 bb.debug(2, '%s: Dependency %s requires package %s (used by files: %s)' % (pkg, n[0], dep_pkg, n[1]))
2074
2075 if dep_pkg == pkg:
2076 continue
2077
2078 if ver_needed:
2079 dep = "%s (>= %s)" % (dep_pkg, ver_needed)
2080 else:
2081 dep = dep_pkg
2082 if not dep in deps:
2083 deps.append(dep)
2084 continue
2085 bb.note("Couldn't find shared library provider for %s, used by files: %s" % (n[0], n[1]))
2086
2087 deps_file = os.path.join(pkgdest, pkg + ".shlibdeps")
2088 if os.path.exists(deps_file):
2089 os.remove(deps_file)
Brad Bishop64c979e2019-11-04 13:55:29 -05002090 if deps:
2091 with open(deps_file, 'w') as fd:
2092 for dep in sorted(deps):
2093 fd.write(dep + '\n')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002094}
2095
2096python package_do_pkgconfig () {
2097 import re
2098
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002099 packages = d.getVar('PACKAGES')
2100 workdir = d.getVar('WORKDIR')
2101 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002102
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002103 shlibs_dirs = d.getVar('SHLIBSDIRS').split()
2104 shlibswork_dir = d.getVar('SHLIBSWORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002105
Brad Bishop19323692019-04-05 15:28:33 -04002106 pc_re = re.compile(r'(.*)\.pc$')
2107 var_re = re.compile(r'(.*)=(.*)')
2108 field_re = re.compile(r'(.*): (.*)')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002109
2110 pkgconfig_provided = {}
2111 pkgconfig_needed = {}
2112 for pkg in packages.split():
2113 pkgconfig_provided[pkg] = []
2114 pkgconfig_needed[pkg] = []
Patrick Williams93c203f2021-10-06 16:15:23 -05002115 for file in sorted(pkgfiles[pkg]):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002116 m = pc_re.match(file)
2117 if m:
2118 pd = bb.data.init()
2119 name = m.group(1)
Patrick Williams93c203f2021-10-06 16:15:23 -05002120 pkgconfig_provided[pkg].append(os.path.basename(name))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002121 if not os.access(file, os.R_OK):
2122 continue
Brad Bishop64c979e2019-11-04 13:55:29 -05002123 with open(file, 'r') as f:
2124 lines = f.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002125 for l in lines:
2126 m = var_re.match(l)
2127 if m:
2128 name = m.group(1)
2129 val = m.group(2)
2130 pd.setVar(name, pd.expand(val))
2131 continue
2132 m = field_re.match(l)
2133 if m:
2134 hdr = m.group(1)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002135 exp = pd.expand(m.group(2))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002136 if hdr == 'Requires':
2137 pkgconfig_needed[pkg] += exp.replace(',', ' ').split()
2138
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002139 for pkg in packages.split():
2140 pkgs_file = os.path.join(shlibswork_dir, pkg + ".pclist")
2141 if pkgconfig_provided[pkg] != []:
Brad Bishop64c979e2019-11-04 13:55:29 -05002142 with open(pkgs_file, 'w') as f:
Patrick Williams93c203f2021-10-06 16:15:23 -05002143 for p in sorted(pkgconfig_provided[pkg]):
Brad Bishop64c979e2019-11-04 13:55:29 -05002144 f.write('%s\n' % p)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002145
2146 # Go from least to most specific since the last one found wins
2147 for dir in reversed(shlibs_dirs):
2148 if not os.path.exists(dir):
2149 continue
Brad Bishop08902b02019-08-20 09:16:51 -04002150 for file in sorted(os.listdir(dir)):
Brad Bishop19323692019-04-05 15:28:33 -04002151 m = re.match(r'^(.*)\.pclist$', file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002152 if m:
2153 pkg = m.group(1)
Brad Bishop64c979e2019-11-04 13:55:29 -05002154 with open(os.path.join(dir, file)) as fd:
2155 lines = fd.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002156 pkgconfig_provided[pkg] = []
2157 for l in lines:
2158 pkgconfig_provided[pkg].append(l.rstrip())
2159
2160 for pkg in packages.split():
2161 deps = []
2162 for n in pkgconfig_needed[pkg]:
2163 found = False
2164 for k in pkgconfig_provided.keys():
2165 if n in pkgconfig_provided[k]:
2166 if k != pkg and not (k in deps):
2167 deps.append(k)
2168 found = True
2169 if found == False:
2170 bb.note("couldn't find pkgconfig module '%s' in any package" % n)
2171 deps_file = os.path.join(pkgdest, pkg + ".pcdeps")
2172 if len(deps):
Brad Bishop64c979e2019-11-04 13:55:29 -05002173 with open(deps_file, 'w') as fd:
2174 for dep in deps:
2175 fd.write(dep + '\n')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002176}
2177
2178def read_libdep_files(d):
2179 pkglibdeps = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002180 packages = d.getVar('PACKAGES').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002181 for pkg in packages:
2182 pkglibdeps[pkg] = {}
2183 for extension in ".shlibdeps", ".pcdeps", ".clilibdeps":
2184 depsfile = d.expand("${PKGDEST}/" + pkg + extension)
2185 if os.access(depsfile, os.R_OK):
Brad Bishop64c979e2019-11-04 13:55:29 -05002186 with open(depsfile) as fd:
2187 lines = fd.readlines()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002188 for l in lines:
2189 l.rstrip()
2190 deps = bb.utils.explode_dep_versions2(l)
2191 for dep in deps:
2192 if not dep in pkglibdeps[pkg]:
2193 pkglibdeps[pkg][dep] = deps[dep]
2194 return pkglibdeps
2195
2196python read_shlibdeps () {
2197 pkglibdeps = read_libdep_files(d)
2198
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002199 packages = d.getVar('PACKAGES').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002200 for pkg in packages:
Patrick Williams213cb262021-08-07 19:21:33 -05002201 rdepends = bb.utils.explode_dep_versions2(d.getVar('RDEPENDS:' + pkg) or "")
Brad Bishop19323692019-04-05 15:28:33 -04002202 for dep in sorted(pkglibdeps[pkg]):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002203 # Add the dep if it's not already there, or if no comparison is set
2204 if dep not in rdepends:
2205 rdepends[dep] = []
2206 for v in pkglibdeps[pkg][dep]:
2207 if v not in rdepends[dep]:
2208 rdepends[dep].append(v)
Patrick Williams213cb262021-08-07 19:21:33 -05002209 d.setVar('RDEPENDS:' + pkg, bb.utils.join_deps(rdepends, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002210}
2211
2212python package_depchains() {
2213 """
2214 For a given set of prefix and postfix modifiers, make those packages
2215 RRECOMMENDS on the corresponding packages for its RDEPENDS.
2216
2217 Example: If package A depends upon package B, and A's .bb emits an
2218 A-dev package, this would make A-dev Recommends: B-dev.
2219
2220 If only one of a given suffix is specified, it will take the RRECOMMENDS
2221 based on the RDEPENDS of *all* other packages. If more than one of a given
2222 suffix is specified, its will only use the RDEPENDS of the single parent
2223 package.
2224 """
2225
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002226 packages = d.getVar('PACKAGES')
2227 postfixes = (d.getVar('DEPCHAIN_POST') or '').split()
2228 prefixes = (d.getVar('DEPCHAIN_PRE') or '').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002229
2230 def pkg_adddeprrecs(pkg, base, suffix, getname, depends, d):
2231
2232 #bb.note('depends for %s is %s' % (base, depends))
Patrick Williams213cb262021-08-07 19:21:33 -05002233 rreclist = bb.utils.explode_dep_versions2(d.getVar('RRECOMMENDS:' + pkg) or "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002234
Brad Bishop19323692019-04-05 15:28:33 -04002235 for depend in sorted(depends):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002236 if depend.find('-native') != -1 or depend.find('-cross') != -1 or depend.startswith('virtual/'):
2237 #bb.note("Skipping %s" % depend)
2238 continue
2239 if depend.endswith('-dev'):
2240 depend = depend[:-4]
2241 if depend.endswith('-dbg'):
2242 depend = depend[:-4]
2243 pkgname = getname(depend, suffix)
2244 #bb.note("Adding %s for %s" % (pkgname, depend))
2245 if pkgname not in rreclist and pkgname != pkg:
2246 rreclist[pkgname] = []
2247
Patrick Williams213cb262021-08-07 19:21:33 -05002248 #bb.note('setting: RRECOMMENDS:%s=%s' % (pkg, ' '.join(rreclist)))
2249 d.setVar('RRECOMMENDS:%s' % pkg, bb.utils.join_deps(rreclist, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002250
2251 def pkg_addrrecs(pkg, base, suffix, getname, rdepends, d):
2252
2253 #bb.note('rdepends for %s is %s' % (base, rdepends))
Patrick Williams213cb262021-08-07 19:21:33 -05002254 rreclist = bb.utils.explode_dep_versions2(d.getVar('RRECOMMENDS:' + pkg) or "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002255
Brad Bishop19323692019-04-05 15:28:33 -04002256 for depend in sorted(rdepends):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002257 if depend.find('virtual-locale-') != -1:
2258 #bb.note("Skipping %s" % depend)
2259 continue
2260 if depend.endswith('-dev'):
2261 depend = depend[:-4]
2262 if depend.endswith('-dbg'):
2263 depend = depend[:-4]
2264 pkgname = getname(depend, suffix)
2265 #bb.note("Adding %s for %s" % (pkgname, depend))
2266 if pkgname not in rreclist and pkgname != pkg:
2267 rreclist[pkgname] = []
2268
Patrick Williams213cb262021-08-07 19:21:33 -05002269 #bb.note('setting: RRECOMMENDS:%s=%s' % (pkg, ' '.join(rreclist)))
2270 d.setVar('RRECOMMENDS:%s' % pkg, bb.utils.join_deps(rreclist, commasep=False))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002271
2272 def add_dep(list, dep):
2273 if dep not in list:
2274 list.append(dep)
2275
2276 depends = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002277 for dep in bb.utils.explode_deps(d.getVar('DEPENDS') or ""):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002278 add_dep(depends, dep)
2279
2280 rdepends = []
2281 for pkg in packages.split():
Patrick Williams213cb262021-08-07 19:21:33 -05002282 for dep in bb.utils.explode_deps(d.getVar('RDEPENDS:' + pkg) or ""):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002283 add_dep(rdepends, dep)
2284
2285 #bb.note('rdepends is %s' % rdepends)
2286
2287 def post_getname(name, suffix):
2288 return '%s%s' % (name, suffix)
2289 def pre_getname(name, suffix):
2290 return '%s%s' % (suffix, name)
2291
2292 pkgs = {}
2293 for pkg in packages.split():
2294 for postfix in postfixes:
2295 if pkg.endswith(postfix):
2296 if not postfix in pkgs:
2297 pkgs[postfix] = {}
2298 pkgs[postfix][pkg] = (pkg[:-len(postfix)], post_getname)
2299
2300 for prefix in prefixes:
2301 if pkg.startswith(prefix):
2302 if not prefix in pkgs:
2303 pkgs[prefix] = {}
2304 pkgs[prefix][pkg] = (pkg[:-len(prefix)], pre_getname)
2305
2306 if "-dbg" in pkgs:
2307 pkglibdeps = read_libdep_files(d)
2308 pkglibdeplist = []
2309 for pkg in pkglibdeps:
2310 for k in pkglibdeps[pkg]:
2311 add_dep(pkglibdeplist, k)
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002312 dbgdefaultdeps = ((d.getVar('DEPCHAIN_DBGDEFAULTDEPS') == '1') or (bb.data.inherits_class('packagegroup', d)))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002313
2314 for suffix in pkgs:
2315 for pkg in pkgs[suffix]:
Patrick Williams213cb262021-08-07 19:21:33 -05002316 if d.getVarFlag('RRECOMMENDS:' + pkg, 'nodeprrecs'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002317 continue
2318 (base, func) = pkgs[suffix][pkg]
2319 if suffix == "-dev":
2320 pkg_adddeprrecs(pkg, base, suffix, func, depends, d)
2321 elif suffix == "-dbg":
2322 if not dbgdefaultdeps:
2323 pkg_addrrecs(pkg, base, suffix, func, pkglibdeplist, d)
2324 continue
2325 if len(pkgs[suffix]) == 1:
2326 pkg_addrrecs(pkg, base, suffix, func, rdepends, d)
2327 else:
2328 rdeps = []
Patrick Williams213cb262021-08-07 19:21:33 -05002329 for dep in bb.utils.explode_deps(d.getVar('RDEPENDS:' + base) or ""):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002330 add_dep(rdeps, dep)
2331 pkg_addrrecs(pkg, base, suffix, func, rdeps, d)
2332}
2333
2334# Since bitbake can't determine which variables are accessed during package
2335# iteration, we need to list them here:
Andrew Geissler1e34c2d2020-05-29 16:02:59 -05002336PACKAGEVARS = "FILES RDEPENDS RRECOMMENDS SUMMARY DESCRIPTION RSUGGESTS RPROVIDES RCONFLICTS PKG ALLOW_EMPTY pkg_postinst pkg_postrm pkg_postinst_ontarget INITSCRIPT_NAME INITSCRIPT_PARAMS DEBIAN_NOAUTONAME ALTERNATIVE PKGE PKGV PKGR USERADD_PARAM GROUPADD_PARAM CONFFILES SYSTEMD_SERVICE LICENSE SECTION pkg_preinst pkg_prerm RREPLACES GROUPMEMS_PARAM SYSTEMD_AUTO_ENABLE SKIP_FILEDEPS PRIVATE_LIBS PACKAGE_ADD_METADATA"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002337
Andrew Geissler82c905d2020-04-13 13:39:40 -05002338def gen_packagevar(d, pkgvars="PACKAGEVARS"):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002339 ret = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002340 pkgs = (d.getVar("PACKAGES") or "").split()
Andrew Geissler82c905d2020-04-13 13:39:40 -05002341 vars = (d.getVar(pkgvars) or "").split()
2342 for v in vars:
2343 ret.append(v)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002344 for p in pkgs:
2345 for v in vars:
Patrick Williams213cb262021-08-07 19:21:33 -05002346 ret.append(v + ":" + p)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002347
2348 # Ensure that changes to INCOMPATIBLE_LICENSE re-run do_package for
2349 # affected recipes.
Andrew Geissler7e0e3c02022-02-25 20:34:39 +00002350 ret.append('_exclude_incompatible-%s' % p)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002351 return " ".join(ret)
2352
2353PACKAGE_PREPROCESS_FUNCS ?= ""
2354# Functions for setting up PKGD
2355PACKAGEBUILDPKGD ?= " \
Brad Bishop96ff1982019-08-19 13:50:42 -04002356 package_prepare_pkgdata \
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002357 perform_packagecopy \
2358 ${PACKAGE_PREPROCESS_FUNCS} \
2359 split_and_strip_files \
2360 fixup_perms \
2361 "
2362# Functions which split PKGD up into separate packages
2363PACKAGESPLITFUNCS ?= " \
2364 package_do_split_locales \
2365 populate_packages"
2366# Functions which process metadata based on split packages
2367PACKAGEFUNCS += " \
2368 package_fixsymlinks \
2369 package_name_hook \
2370 package_do_filedeps \
2371 package_do_shlibs \
2372 package_do_pkgconfig \
2373 read_shlibdeps \
2374 package_depchains \
2375 emit_pkgdata"
2376
2377python do_package () {
2378 # Change the following version to cause sstate to invalidate the package
2379 # cache. This is useful if an item this class depends on changes in a
2380 # way that the output of this class changes. rpmdeps is a good example
2381 # as any change to rpmdeps requires this to be rerun.
Andrew Geissler6ce62a22020-11-30 19:58:47 -06002382 # PACKAGE_BBCLASS_VERSION = "4"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002383
2384 # Init cachedpath
2385 global cpath
2386 cpath = oe.cachedpath.CachedPath()
2387
2388 ###########################################################################
2389 # Sanity test the setup
2390 ###########################################################################
2391
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002392 packages = (d.getVar('PACKAGES') or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002393 if len(packages) < 1:
2394 bb.debug(1, "No packages to build, skipping do_package")
2395 return
2396
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002397 workdir = d.getVar('WORKDIR')
2398 outdir = d.getVar('DEPLOY_DIR')
2399 dest = d.getVar('D')
2400 dvar = d.getVar('PKGD')
2401 pn = d.getVar('PN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002402
2403 if not workdir or not outdir or not dest or not dvar or not pn:
2404 msg = "WORKDIR, DEPLOY_DIR, D, PN and PKGD all must be defined, unable to package"
Andrew Geisslereff27472021-10-29 15:35:00 -05002405 oe.qa.handle_error("var-undefined", msg, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002406 return
2407
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002408 bb.build.exec_func("package_convert_pr_autoinc", d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002409
2410 ###########################################################################
2411 # Optimisations
2412 ###########################################################################
2413
2414 # Continually expanding complex expressions is inefficient, particularly
2415 # when we write to the datastore and invalidate the expansion cache. This
2416 # code pre-expands some frequently used variables
2417
2418 def expandVar(x, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002419 d.setVar(x, d.getVar(x))
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002420
2421 for x in 'PN', 'PV', 'BPN', 'TARGET_SYS', 'EXTENDPRAUTO':
2422 expandVar(x, d)
2423
2424 ###########################################################################
2425 # Setup PKGD (from D)
2426 ###########################################################################
2427
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002428 for f in (d.getVar('PACKAGEBUILDPKGD') or '').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002429 bb.build.exec_func(f, d)
2430
2431 ###########################################################################
2432 # Split up PKGD into PKGDEST
2433 ###########################################################################
2434
2435 cpath = oe.cachedpath.CachedPath()
2436
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002437 for f in (d.getVar('PACKAGESPLITFUNCS') or '').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002438 bb.build.exec_func(f, d)
2439
2440 ###########################################################################
2441 # Process PKGDEST
2442 ###########################################################################
2443
2444 # Build global list of files in each split package
2445 global pkgfiles
2446 pkgfiles = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002447 packages = d.getVar('PACKAGES').split()
2448 pkgdest = d.getVar('PKGDEST')
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002449 for pkg in packages:
2450 pkgfiles[pkg] = []
2451 for walkroot, dirs, files in cpath.walk(pkgdest + "/" + pkg):
2452 for file in files:
2453 pkgfiles[pkg].append(walkroot + os.sep + file)
2454
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002455 for f in (d.getVar('PACKAGEFUNCS') or '').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002456 bb.build.exec_func(f, d)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05002457
Andrew Geisslereff27472021-10-29 15:35:00 -05002458 oe.qa.exit_if_errors(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002459}
2460
Andrew Geissler9aee5002022-03-30 16:27:02 +00002461do_package[dirs] = "${SHLIBSWORKDIR} ${D}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002462do_package[vardeps] += "${PACKAGEBUILDPKGD} ${PACKAGESPLITFUNCS} ${PACKAGEFUNCS} ${@gen_packagevar(d)}"
2463addtask package after do_install
2464
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002465SSTATETASKS += "do_package"
2466do_package[cleandirs] = "${PKGDEST} ${PKGDESTWORK}"
2467do_package[sstate-plaindirs] = "${PKGD} ${PKGDEST} ${PKGDESTWORK}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002468do_package_setscene[dirs] = "${STAGING_DIR}"
2469
2470python do_package_setscene () {
2471 sstate_setscene(d)
2472}
2473addtask do_package_setscene
2474
Brad Bishopc68388fc2019-08-26 01:33:31 -04002475# Copy from PKGDESTWORK to tempdirectory as tempdirectory can be cleaned at both
2476# do_package_setscene and do_packagedata_setscene leading to races
2477python do_packagedata () {
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002478 bb.build.exec_func("package_get_auto_pr", d)
2479
Brad Bishopc68388fc2019-08-26 01:33:31 -04002480 src = d.expand("${PKGDESTWORK}")
2481 dest = d.expand("${WORKDIR}/pkgdata-pdata-input")
2482 oe.path.copyhardlinktree(src, dest)
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002483
2484 bb.build.exec_func("packagedata_translate_pr_autoinc", d)
2485}
Andrew Geisslerd1e89492021-02-12 15:35:20 -06002486do_packagedata[cleandirs] += "${WORKDIR}/pkgdata-pdata-input"
Andrew Geisslerc9f78652020-09-18 14:11:35 -05002487
2488# Translate the EXTENDPRAUTO and AUTOINC to the final values
2489packagedata_translate_pr_autoinc() {
2490 find ${WORKDIR}/pkgdata-pdata-input -type f | xargs --no-run-if-empty \
2491 sed -e 's,@PRSERV_PV_AUTOINC@,${PRSERV_PV_AUTOINC},g' \
2492 -e 's,@EXTENDPRAUTO@,${EXTENDPRAUTO},g' -i
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002493}
2494
2495addtask packagedata before do_build after do_package
2496
2497SSTATETASKS += "do_packagedata"
Brad Bishopc68388fc2019-08-26 01:33:31 -04002498do_packagedata[sstate-inputdirs] = "${WORKDIR}/pkgdata-pdata-input"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002499do_packagedata[sstate-outputdirs] = "${PKGDATA_DIR}"
Brad Bishop316dfdd2018-06-25 12:45:53 -04002500do_packagedata[stamp-extra-info] = "${MACHINE_ARCH}"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002501
2502python do_packagedata_setscene () {
2503 sstate_setscene(d)
2504}
2505addtask do_packagedata_setscene
2506
2507#
2508# Helper functions for the package writing classes
2509#
2510
2511def mapping_rename_hook(d):
2512 """
2513 Rewrite variables to account for package renaming in things
2514 like debian.bbclass or manual PKG variable name changes
2515 """
Brad Bishop6e60e8b2018-02-01 10:27:11 -05002516 pkg = d.getVar("PKG")
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002517 runtime_mapping_rename("RDEPENDS", pkg, d)
2518 runtime_mapping_rename("RRECOMMENDS", pkg, d)
2519 runtime_mapping_rename("RSUGGESTS", pkg, d)