diff options
Diffstat (limited to 'meta/lib/oe/package.py')
-rw-r--r-- | meta/lib/oe/package.py | 182 |
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 | |||
14 | import stat | 14 | import stat |
15 | import mmap | 15 | import mmap |
16 | import subprocess | 16 | import subprocess |
17 | import shutil | ||
17 | 18 | ||
19 | import bb.parse | ||
18 | import oe.cachedpath | 20 | import oe.cachedpath |
19 | 21 | ||
20 | def runstrip(arg): | 22 | def 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 | ||
194 | TRANSLATE = ( | ||
195 | ("@", "@at@"), | ||
196 | (" ", "@space@"), | ||
197 | ("\t", "@tab@"), | ||
198 | ("[", "@openbrace@"), | ||
199 | ("]", "@closebrace@"), | ||
200 | ("_", "@underscore@"), | ||
201 | (":", "@colon@"), | ||
202 | ) | ||
198 | 203 | ||
199 | def file_translate(file): | 204 | def 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 | |
211 | def 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 | ||
208 | def filedeprunner(arg): | 218 | def 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") | ||
1054 | def 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") | ||
1087 | def 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 | ||
1041 | def process_split_and_strip_files(d): | 1099 | def 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) |