summaryrefslogtreecommitdiffstats
path: root/meta/lib/oe/package.py
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib/oe/package.py')
-rw-r--r--meta/lib/oe/package.py182
1 files changed, 133 insertions, 49 deletions
diff --git a/meta/lib/oe/package.py b/meta/lib/oe/package.py
index 1511ba47c4..ce69151e5d 100644
--- a/meta/lib/oe/package.py
+++ b/meta/lib/oe/package.py
@@ -14,10 +14,12 @@ import glob
14import stat 14import stat
15import mmap 15import mmap
16import subprocess 16import subprocess
17import shutil
17 18
19import bb.parse
18import oe.cachedpath 20import oe.cachedpath
19 21
20def runstrip(arg): 22def runstrip(file, elftype, strip, extra_strip_sections=''):
21 # Function to strip a single file, called from split_and_strip_files below 23 # Function to strip a single file, called from split_and_strip_files below
22 # A working 'file' (one which works on the target architecture) 24 # A working 'file' (one which works on the target architecture)
23 # 25 #
@@ -27,12 +29,6 @@ def runstrip(arg):
27 # 8 - shared library 29 # 8 - shared library
28 # 16 - kernel module 30 # 16 - kernel module
29 31
30 if len(arg) == 3:
31 (file, elftype, strip) = arg
32 extra_strip_sections = ''
33 else:
34 (file, elftype, strip, extra_strip_sections) = arg
35
36 newmode = None 32 newmode = None
37 if not os.access(file, os.W_OK) or os.access(file, os.R_OK): 33 if not os.access(file, os.W_OK) or os.access(file, os.R_OK):
38 origmode = os.stat(file)[stat.ST_MODE] 34 origmode = os.stat(file)[stat.ST_MODE]
@@ -195,20 +191,33 @@ def strip_execs(pn, dstdir, strip_cmd, libdir, base_libdir, max_process, qa_alre
195 191
196 oe.utils.multiprocess_launch_mp(runstrip, sfiles, max_process) 192 oe.utils.multiprocess_launch_mp(runstrip, sfiles, max_process)
197 193
194TRANSLATE = (
195 ("@", "@at@"),
196 (" ", "@space@"),
197 ("\t", "@tab@"),
198 ("[", "@openbrace@"),
199 ("]", "@closebrace@"),
200 ("_", "@underscore@"),
201 (":", "@colon@"),
202)
198 203
199def file_translate(file): 204def file_translate(file):
200 ft = file.replace("@", "@at@") 205 ft = file
201 ft = ft.replace(" ", "@space@") 206 for s, replace in TRANSLATE:
202 ft = ft.replace("\t", "@tab@") 207 ft = ft.replace(s, replace)
203 ft = ft.replace("[", "@openbrace@") 208
204 ft = ft.replace("]", "@closebrace@") 209 return ft
205 ft = ft.replace("_", "@underscore@") 210
211def file_reverse_translate(file):
212 ft = file
213 for s, replace in reversed(TRANSLATE):
214 ft = ft.replace(replace, s)
215
206 return ft 216 return ft
207 217
208def filedeprunner(arg): 218def filedeprunner(pkg, pkgfiles, rpmdeps, pkgdest):
209 import re, subprocess, shlex 219 import re, subprocess, shlex
210 220
211 (pkg, pkgfiles, rpmdeps, pkgdest) = arg
212 provides = {} 221 provides = {}
213 requires = {} 222 requires = {}
214 223
@@ -648,6 +657,8 @@ def split_locales(d):
648 except ValueError: 657 except ValueError:
649 locale_index = len(packages) 658 locale_index = len(packages)
650 659
660 lic = d.getVar("LICENSE:" + pn + "-locale")
661
651 localepaths = [] 662 localepaths = []
652 locales = set() 663 locales = set()
653 for localepath in (d.getVar('LOCALE_PATHS') or "").split(): 664 for localepath in (d.getVar('LOCALE_PATHS') or "").split():
@@ -683,6 +694,8 @@ def split_locales(d):
683 d.setVar('RPROVIDES:' + pkg, '%s-locale %s%s-translation' % (pn, mlprefix, ln)) 694 d.setVar('RPROVIDES:' + pkg, '%s-locale %s%s-translation' % (pn, mlprefix, ln))
684 d.setVar('SUMMARY:' + pkg, '%s - %s translations' % (summary, l)) 695 d.setVar('SUMMARY:' + pkg, '%s - %s translations' % (summary, l))
685 d.setVar('DESCRIPTION:' + pkg, '%s This package contains language translation files for the %s locale.' % (description, l)) 696 d.setVar('DESCRIPTION:' + pkg, '%s This package contains language translation files for the %s locale.' % (description, l))
697 if lic:
698 d.setVar('LICENSE:' + pkg, lic)
686 if locale_section: 699 if locale_section:
687 d.setVar('SECTION:' + pkg, locale_section) 700 d.setVar('SECTION:' + pkg, locale_section)
688 701
@@ -979,7 +992,7 @@ def copydebugsources(debugsrcdir, sources, d):
979 992
980 prefixmap = {} 993 prefixmap = {}
981 for flag in cflags.split(): 994 for flag in cflags.split():
982 if not flag.startswith("-fdebug-prefix-map"): 995 if not flag.startswith("-ffile-prefix-map"):
983 continue 996 continue
984 if "recipe-sysroot" in flag: 997 if "recipe-sysroot" in flag:
985 continue 998 continue
@@ -1037,6 +1050,51 @@ def copydebugsources(debugsrcdir, sources, d):
1037 if os.path.exists(p) and not os.listdir(p): 1050 if os.path.exists(p) and not os.listdir(p):
1038 os.rmdir(p) 1051 os.rmdir(p)
1039 1052
1053@bb.parse.vardepsexclude("BB_NUMBER_THREADS")
1054def save_debugsources_info(debugsrcdir, sources_raw, d):
1055 import json
1056 import bb.compress.zstd
1057 if debugsrcdir and sources_raw:
1058 debugsources_file = d.expand("${PKGDESTWORK}/debugsources/${PN}-debugsources.json.zstd")
1059 debugsources_dir = os.path.dirname(debugsources_file)
1060 if not os.path.isdir(debugsources_dir):
1061 bb.utils.mkdirhier(debugsources_dir)
1062 bb.utils.remove(debugsources_file)
1063
1064 workdir = d.getVar("WORKDIR")
1065 pn = d.getVar('PN')
1066
1067 # Kernel sources are in a different directory and are special case
1068 # we format the sources as expected by spdx by replacing /usr/src/kernel/
1069 # into BP/
1070 kernel_src = d.getVar('KERNEL_SRC_PATH')
1071 bp = d.getVar('BP')
1072 sources_dict = {}
1073 for file, src_files in sources_raw:
1074 file_clean = file.replace(f"{workdir}/package/","")
1075 sources_clean = [
1076 src.replace(f"{debugsrcdir}/{pn}/", "")
1077 if not kernel_src else src.replace(f"{kernel_src}/", f"{bp}/")
1078 for src in src_files
1079 if not any(keyword in src for keyword in ("<internal>", "<built-in>")) and not src.endswith("/")
1080 ]
1081 sources_dict[file_clean] = sorted(sources_clean)
1082 num_threads = int(d.getVar("BB_NUMBER_THREADS"))
1083 with bb.compress.zstd.open(debugsources_file, "wt", encoding="utf-8", num_threads=num_threads) as f:
1084 json.dump(sources_dict, f, sort_keys=True)
1085
1086@bb.parse.vardepsexclude("BB_NUMBER_THREADS")
1087def read_debugsources_info(d):
1088 import json
1089 import bb.compress.zstd
1090 try:
1091 fn = d.expand("${PKGDESTWORK}/debugsources/${PN}-debugsources.json.zstd")
1092 num_threads = int(d.getVar("BB_NUMBER_THREADS"))
1093 with bb.compress.zstd.open(fn, "rt", encoding="utf-8", num_threads=num_threads) as f:
1094 return json.load(f)
1095 except FileNotFoundError:
1096 bb.debug(1, f"File not found: {fn}")
1097 return None
1040 1098
1041def process_split_and_strip_files(d): 1099def process_split_and_strip_files(d):
1042 cpath = oe.cachedpath.CachedPath() 1100 cpath = oe.cachedpath.CachedPath()
@@ -1064,6 +1122,7 @@ def process_split_and_strip_files(d):
1064 d.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT') != '1'): 1122 d.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT') != '1'):
1065 checkelf = {} 1123 checkelf = {}
1066 checkelflinks = {} 1124 checkelflinks = {}
1125 checkstatic = {}
1067 for root, dirs, files in cpath.walk(dvar): 1126 for root, dirs, files in cpath.walk(dvar):
1068 for f in files: 1127 for f in files:
1069 file = os.path.join(root, f) 1128 file = os.path.join(root, f)
@@ -1077,10 +1136,6 @@ def process_split_and_strip_files(d):
1077 if file in skipfiles: 1136 if file in skipfiles:
1078 continue 1137 continue
1079 1138
1080 if oe.package.is_static_lib(file):
1081 staticlibs.append(file)
1082 continue
1083
1084 try: 1139 try:
1085 ltarget = cpath.realpath(file, dvar, False) 1140 ltarget = cpath.realpath(file, dvar, False)
1086 s = cpath.lstat(ltarget) 1141 s = cpath.lstat(ltarget)
@@ -1092,6 +1147,13 @@ def process_split_and_strip_files(d):
1092 continue 1147 continue
1093 if not s: 1148 if not s:
1094 continue 1149 continue
1150
1151 if oe.package.is_static_lib(file):
1152 # Use a reference of device ID and inode number to identify files
1153 file_reference = "%d_%d" % (s.st_dev, s.st_ino)
1154 checkstatic[file] = (file, file_reference)
1155 continue
1156
1095 # Check its an executable 1157 # Check its an executable
1096 if (s[stat.ST_MODE] & stat.S_IXUSR) or (s[stat.ST_MODE] & stat.S_IXGRP) \ 1158 if (s[stat.ST_MODE] & stat.S_IXUSR) or (s[stat.ST_MODE] & stat.S_IXGRP) \
1097 or (s[stat.ST_MODE] & stat.S_IXOTH) \ 1159 or (s[stat.ST_MODE] & stat.S_IXOTH) \
@@ -1156,6 +1218,27 @@ def process_split_and_strip_files(d):
1156 # Modified the file so clear the cache 1218 # Modified the file so clear the cache
1157 cpath.updatecache(file) 1219 cpath.updatecache(file)
1158 1220
1221 # Do the same hardlink processing as above, but for static libraries
1222 results = list(checkstatic.keys())
1223
1224 # As above, sort the results.
1225 results.sort(key=lambda x: x[0])
1226
1227 for file in results:
1228 # Use a reference of device ID and inode number to identify files
1229 file_reference = checkstatic[file][1]
1230 if file_reference in inodes:
1231 os.unlink(file)
1232 os.link(inodes[file_reference][0], file)
1233 inodes[file_reference].append(file)
1234 else:
1235 inodes[file_reference] = [file]
1236 # break hardlink
1237 bb.utils.break_hardlinks(file)
1238 staticlibs.append(file)
1239 # Modified the file so clear the cache
1240 cpath.updatecache(file)
1241
1159 def strip_pkgd_prefix(f): 1242 def strip_pkgd_prefix(f):
1160 nonlocal dvar 1243 nonlocal dvar
1161 1244
@@ -1194,11 +1277,24 @@ def process_split_and_strip_files(d):
1194 dest = dv["libdir"] + os.path.dirname(src) + dv["dir"] + "/" + os.path.basename(target) + dv["append"] 1277 dest = dv["libdir"] + os.path.dirname(src) + dv["dir"] + "/" + os.path.basename(target) + dv["append"]
1195 fpath = dvar + dest 1278 fpath = dvar + dest
1196 ftarget = dvar + dv["libdir"] + os.path.dirname(target) + dv["dir"] + "/" + os.path.basename(target) + dv["append"] 1279 ftarget = dvar + dv["libdir"] + os.path.dirname(target) + dv["dir"] + "/" + os.path.basename(target) + dv["append"]
1197 bb.utils.mkdirhier(os.path.dirname(fpath)) 1280 if os.access(ftarget, os.R_OK):
1198 # Only one hardlink of separated debug info file in each directory 1281 bb.utils.mkdirhier(os.path.dirname(fpath))
1199 if not os.access(fpath, os.R_OK): 1282 # Only one hardlink of separated debug info file in each directory
1200 #bb.note("Link %s -> %s" % (fpath, ftarget)) 1283 if not os.access(fpath, os.R_OK):
1201 os.link(ftarget, fpath) 1284 #bb.note("Link %s -> %s" % (fpath, ftarget))
1285 os.link(ftarget, fpath)
1286 elif (d.getVar('PACKAGE_DEBUG_STATIC_SPLIT') == '1'):
1287 deststatic = dv["staticlibdir"] + os.path.dirname(src) + dv["staticdir"] + "/" + os.path.basename(file) + dv["staticappend"]
1288 fpath = dvar + deststatic
1289 ftarget = dvar + dv["staticlibdir"] + os.path.dirname(target) + dv["staticdir"] + "/" + os.path.basename(target) + dv["staticappend"]
1290 if os.access(ftarget, os.R_OK):
1291 bb.utils.mkdirhier(os.path.dirname(fpath))
1292 # Only one hardlink of separated debug info file in each directory
1293 if not os.access(fpath, os.R_OK):
1294 #bb.note("Link %s -> %s" % (fpath, ftarget))
1295 os.link(ftarget, fpath)
1296 else:
1297 bb.note("Unable to find inode link target %s" % (target))
1202 1298
1203 # Create symlinks for all cases we were able to split symbols 1299 # Create symlinks for all cases we were able to split symbols
1204 for file in symlinks: 1300 for file in symlinks:
@@ -1230,6 +1326,9 @@ def process_split_and_strip_files(d):
1230 # Process the dv["srcdir"] if requested... 1326 # Process the dv["srcdir"] if requested...
1231 # This copies and places the referenced sources for later debugging... 1327 # This copies and places the referenced sources for later debugging...
1232 copydebugsources(dv["srcdir"], sources, d) 1328 copydebugsources(dv["srcdir"], sources, d)
1329
1330 # Save source info to be accessible to other tasks
1331 save_debugsources_info(dv["srcdir"], results, d)
1233 # 1332 #
1234 # End of debug splitting 1333 # End of debug splitting
1235 # 1334 #
@@ -1394,10 +1493,10 @@ def populate_packages(d):
1394 1493
1395 # Handle excluding packages with incompatible licenses 1494 # Handle excluding packages with incompatible licenses
1396 package_list = [] 1495 package_list = []
1496 skipped_pkgs = oe.license.skip_incompatible_package_licenses(d, packages)
1397 for pkg in packages: 1497 for pkg in packages:
1398 licenses = d.getVar('_exclude_incompatible-' + pkg) 1498 if pkg in skipped_pkgs:
1399 if licenses: 1499 msg = "Excluding %s from packaging as it has incompatible license(s): %s" % (pkg, skipped_pkgs[pkg])
1400 msg = "Excluding %s from packaging as it has incompatible license(s): %s" % (pkg, licenses)
1401 oe.qa.handle_error("incompatible-license", msg, d) 1500 oe.qa.handle_error("incompatible-license", msg, d)
1402 else: 1501 else:
1403 package_list.append(pkg) 1502 package_list.append(pkg)
@@ -1566,7 +1665,6 @@ def process_shlibs(pkgfiles, d):
1566 needs_ldconfig = False 1665 needs_ldconfig = False
1567 needed = set() 1666 needed = set()
1568 sonames = set() 1667 sonames = set()
1569 renames = []
1570 ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '') 1668 ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '')
1571 cmd = d.getVar('OBJDUMP') + " -p " + shlex.quote(file) + " 2>/dev/null" 1669 cmd = d.getVar('OBJDUMP') + " -p " + shlex.quote(file) + " 2>/dev/null"
1572 fd = os.popen(cmd) 1670 fd = os.popen(cmd)
@@ -1594,11 +1692,9 @@ def process_shlibs(pkgfiles, d):
1594 sonames.add(prov) 1692 sonames.add(prov)
1595 if libdir_re.match(os.path.dirname(file)): 1693 if libdir_re.match(os.path.dirname(file)):
1596 needs_ldconfig = True 1694 needs_ldconfig = True
1597 if needs_ldconfig and snap_symlinks and (os.path.basename(file) != this_soname): 1695 return (needs_ldconfig, needed, sonames)
1598 renames.append((file, os.path.join(os.path.dirname(file), this_soname)))
1599 return (needs_ldconfig, needed, sonames, renames)
1600 1696
1601 def darwin_so(file, needed, sonames, renames, pkgver): 1697 def darwin_so(file, needed, sonames, pkgver):
1602 if not os.path.exists(file): 1698 if not os.path.exists(file):
1603 return 1699 return
1604 ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '') 1700 ldir = os.path.dirname(file).replace(pkgdest + "/" + pkg, '')
@@ -1650,7 +1746,7 @@ def process_shlibs(pkgfiles, d):
1650 if name and name not in needed[pkg]: 1746 if name and name not in needed[pkg]:
1651 needed[pkg].add((name, file, tuple())) 1747 needed[pkg].add((name, file, tuple()))
1652 1748
1653 def mingw_dll(file, needed, sonames, renames, pkgver): 1749 def mingw_dll(file, needed, sonames, pkgver):
1654 if not os.path.exists(file): 1750 if not os.path.exists(file):
1655 return 1751 return
1656 1752
@@ -1669,11 +1765,6 @@ def process_shlibs(pkgfiles, d):
1669 if dllname: 1765 if dllname:
1670 needed[pkg].add((dllname, file, tuple())) 1766 needed[pkg].add((dllname, file, tuple()))
1671 1767
1672 if d.getVar('PACKAGE_SNAP_LIB_SYMLINKS') == "1":
1673 snap_symlinks = True
1674 else:
1675 snap_symlinks = False
1676
1677 needed = {} 1768 needed = {}
1678 1769
1679 shlib_provider = oe.package.read_shlib_providers(d) 1770 shlib_provider = oe.package.read_shlib_providers(d)
@@ -1692,16 +1783,15 @@ def process_shlibs(pkgfiles, d):
1692 1783
1693 needed[pkg] = set() 1784 needed[pkg] = set()
1694 sonames = set() 1785 sonames = set()
1695 renames = []
1696 linuxlist = [] 1786 linuxlist = []
1697 for file in pkgfiles[pkg]: 1787 for file in pkgfiles[pkg]:
1698 soname = None 1788 soname = None
1699 if cpath.islink(file): 1789 if cpath.islink(file):
1700 continue 1790 continue
1701 if hostos.startswith("darwin"): 1791 if hostos.startswith("darwin"):
1702 darwin_so(file, needed, sonames, renames, pkgver) 1792 darwin_so(file, needed, sonames, pkgver)
1703 elif hostos.startswith("mingw"): 1793 elif hostos.startswith("mingw"):
1704 mingw_dll(file, needed, sonames, renames, pkgver) 1794 mingw_dll(file, needed, sonames, pkgver)
1705 elif os.access(file, os.X_OK) or lib_re.match(file): 1795 elif os.access(file, os.X_OK) or lib_re.match(file):
1706 linuxlist.append(file) 1796 linuxlist.append(file)
1707 1797
@@ -1711,14 +1801,8 @@ def process_shlibs(pkgfiles, d):
1711 ldconfig = r[0] 1801 ldconfig = r[0]
1712 needed[pkg] |= r[1] 1802 needed[pkg] |= r[1]
1713 sonames |= r[2] 1803 sonames |= r[2]
1714 renames.extend(r[3])
1715 needs_ldconfig = needs_ldconfig or ldconfig 1804 needs_ldconfig = needs_ldconfig or ldconfig
1716 1805
1717 for (old, new) in renames:
1718 bb.note("Renaming %s to %s" % (old, new))
1719 bb.utils.rename(old, new)
1720 pkgfiles[pkg].remove(old)
1721
1722 shlibs_file = os.path.join(shlibswork_dir, pkg + ".list") 1806 shlibs_file = os.path.join(shlibswork_dir, pkg + ".list")
1723 if len(sonames): 1807 if len(sonames):
1724 with open(shlibs_file, 'w') as fd: 1808 with open(shlibs_file, 'w') as fd:
@@ -1839,7 +1923,7 @@ def process_pkgconfig(pkgfiles, d):
1839 if m: 1923 if m:
1840 hdr = m.group(1) 1924 hdr = m.group(1)
1841 exp = pd.expand(m.group(2)) 1925 exp = pd.expand(m.group(2))
1842 if hdr == 'Requires': 1926 if hdr == 'Requires' or hdr == 'Requires.private':
1843 pkgconfig_needed[pkg] += exp.replace(',', ' ').split() 1927 pkgconfig_needed[pkg] += exp.replace(',', ' ').split()
1844 continue 1928 continue
1845 m = var_re.match(l) 1929 m = var_re.match(l)