Gentoo Archives: gentoo-commits

From: Zac Medico <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: lib/portage/util/_dyn_libs/
Date: Sat, 08 Feb 2020 23:16:37
Message-Id: 1581202164.0edb0cd52e25a3ce168f712258ded9ccc6a5bee4.zmedico@gentoo
1 commit: 0edb0cd52e25a3ce168f712258ded9ccc6a5bee4
2 Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
3 AuthorDate: Sat Feb 8 19:43:27 2020 +0000
4 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
5 CommitDate: Sat Feb 8 22:49:24 2020 +0000
6 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=0edb0cd5
7
8 preserve-libs: generate implicit rpath for bundled libs (bug 705736)
9
10 In order to account for internal library resolution which a package
11 may implement (useful at least for handling of bundled libraries),
12 generate implicit runpath entries for any needed sonames which are
13 provided by the same owner package.
14
15 For packages that have bundled versions of system libraries, this will
16 prevent preserve-libs from unecessarily preserving system libraries as
17 reported in bug 705736. For the www-client/firefox-bin-72.0.2 package,
18 this adds an implicit /opt/firefox runpath entry to 15 files.
19
20 Bug: https://bugs.gentoo.org/705736
21 Signed-off-by: Zac Medico <zmedico <AT> gentoo.org>
22
23 lib/portage/util/_dyn_libs/LinkageMapELF.py | 63 ++++++++++++++++++++++++-----
24 1 file changed, 54 insertions(+), 9 deletions(-)
25
26 diff --git a/lib/portage/util/_dyn_libs/LinkageMapELF.py b/lib/portage/util/_dyn_libs/LinkageMapELF.py
27 index 92a50b444..70bec116a 100644
28 --- a/lib/portage/util/_dyn_libs/LinkageMapELF.py
29 +++ b/lib/portage/util/_dyn_libs/LinkageMapELF.py
30 @@ -1,7 +1,9 @@
31 -# Copyright 1998-2019 Gentoo Authors
32 +# Copyright 1998-2020 Gentoo Authors
33 # Distributed under the terms of the GNU General Public License v2
34
35 +import collections
36 import errno
37 +import itertools
38 import logging
39 import subprocess
40 import sys
41 @@ -14,6 +16,7 @@ from portage import _unicode_encode
42 from portage.cache.mappings import slot_dict_class
43 from portage.const import EPREFIX
44 from portage.dep.soname.multilib_category import compute_multilib_category
45 +from portage.dep.soname.SonameAtom import SonameAtom
46 from portage.exception import CommandNotFound, InvalidData
47 from portage.localization import _
48 from portage.util import getlibpaths
49 @@ -328,8 +331,13 @@ class LinkageMapELF(object):
50 # Share identical frozenset instances when available,
51 # in order to conserve memory.
52 frozensets = {}
53 + owner_entries = collections.defaultdict(list)
54
55 - for owner, location, l in lines:
56 + while True:
57 + try:
58 + owner, location, l = lines.pop()
59 + except IndexError:
60 + break
61 l = l.rstrip("\n")
62 if not l:
63 continue
64 @@ -352,18 +360,55 @@ class LinkageMapELF(object):
65 # exists, map e_machine (entry.arch) to an approximate
66 # multilib category. If all else fails, use e_machine, just
67 # as older versions of portage did.
68 - arch = entry.multilib_category
69 - if arch is None:
70 - arch = _approx_multilib_categories.get(
71 + if entry.multilib_category is None:
72 + entry.multilib_category = _approx_multilib_categories.get(
73 entry.arch, entry.arch)
74
75 - obj = entry.filename
76 - soname = entry.soname
77 + entry.filename = normalize_path(entry.filename)
78 expand = {"ORIGIN": os.path.dirname(entry.filename)}
79 - path = frozenset(normalize_path(
80 + entry.runpaths = frozenset(normalize_path(
81 varexpand(x, expand, error_leader=lambda: "%s: " % location))
82 for x in entry.runpaths)
83 - path = frozensets.setdefault(path, path)
84 + entry.runpaths = frozensets.setdefault(entry.runpaths, entry.runpaths)
85 + owner_entries[owner].append(entry)
86 +
87 + # In order to account for internal library resolution which a package
88 + # may implement (useful at least for handling of bundled libraries),
89 + # generate implicit runpath entries for any needed sonames which are
90 + # provided by the same owner package.
91 + for owner, entries in owner_entries.items():
92 + if owner is None:
93 + continue
94 +
95 + providers = {}
96 + for entry in entries:
97 + if entry.soname:
98 + providers[SonameAtom(entry.multilib_category, entry.soname)] = entry
99 +
100 + for entry in entries:
101 + implicit_runpaths = []
102 + for soname in entry.needed:
103 + soname_atom = SonameAtom(entry.multilib_category, soname)
104 + provider = providers.get(soname_atom)
105 + if provider is None:
106 + continue
107 + provider_dir = os.path.dirname(provider.filename)
108 + if provider_dir not in entry.runpaths:
109 + implicit_runpaths.append(provider_dir)
110 +
111 + if implicit_runpaths:
112 + entry.runpaths = frozenset(
113 + itertools.chain(entry.runpaths, implicit_runpaths))
114 + entry.runpaths = frozensets.setdefault(
115 + entry.runpaths, entry.runpaths)
116 +
117 + for owner, entry in ((owner, entry)
118 + for (owner, entries) in owner_entries.items()
119 + for entry in entries):
120 + arch = entry.multilib_category
121 + obj = entry.filename
122 + soname = entry.soname
123 + path = entry.runpaths
124 needed = frozenset(entry.needed)
125
126 needed = frozensets.setdefault(needed, needed)