Skip to content

Commit 48327fb

Browse files
committed
feat: do not copy libraries in site-packages
1 parent 5605098 commit 48327fb

File tree

2 files changed

+69
-12
lines changed

2 files changed

+69
-12
lines changed

src/auditwheel/patcher.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ class ElfPatcher:
99
def replace_needed(self, file_name: str, *old_new_pairs: Tuple[str, str]) -> None:
1010
raise NotImplementedError
1111

12+
def get_soname(self, file_name: str) -> str:
13+
raise NotImplementedError
14+
1215
def set_soname(self, file_name: str, new_so_name: str) -> None:
1316
raise NotImplementedError
1417

@@ -54,6 +57,13 @@ def replace_needed(self, file_name: str, *old_new_pairs: Tuple[str, str]) -> Non
5457
]
5558
)
5659

60+
def get_soname(self, file_name: str) -> str:
61+
return (
62+
check_output(["patchelf", "--print-soname", file_name])
63+
.decode("utf-8")
64+
.strip()
65+
)
66+
5767
def set_soname(self, file_name: str, new_so_name: str) -> None:
5868
check_call(["patchelf", "--set-soname", new_so_name, file_name])
5969

src/auditwheel/repair.py

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
import re
66
import shutil
77
import stat
8-
from collections import OrderedDict
8+
from collections import OrderedDict, defaultdict
99
from os.path import abspath, basename, dirname, exists, isabs
1010
from os.path import join as pjoin
1111
from subprocess import check_call
12-
from typing import Dict, Iterable, List, Optional, Tuple
12+
from typing import Dict, Iterable, List, Optional, Set, Tuple
1313

1414
from auditwheel.patcher import ElfPatcher
1515

@@ -69,7 +69,9 @@ def repair_wheel(
6969
for fn, v in external_refs_by_fn.items():
7070
ext_libs = v[abis[0]]["libs"] # type: Dict[str, str]
7171
replacements = [] # type: List[Tuple[str, str]]
72-
for soname, src_path in ext_libs.items():
72+
src_path_to_real_sonames = {} # type: Dict[str, str]
73+
same_soname_libs = defaultdict(set) # type: Dict[str, Set[str]]
74+
for soname, src_path in tuple(ext_libs.items()):
7375
if src_path is None:
7476
raise ValueError(
7577
(
@@ -78,16 +80,37 @@ def repair_wheel(
7880
)
7981
% soname
8082
)
83+
real_soname = patcher.get_soname(src_path)
84+
src_path_to_real_sonames[soname] = real_soname
85+
same_soname_libs[real_soname].add(soname)
86+
87+
for soname, src_path in tuple(ext_libs.items()):
88+
if "site-packages" in str(src_path).split(os.path.sep):
89+
try:
90+
del same_soname_libs[src_path_to_real_sonames[soname]]
91+
except KeyError:
92+
pass
93+
continue
94+
95+
for real_soname, sonames in same_soname_libs.items():
96+
if len(sonames) == 0:
97+
continue
98+
soname = sonames.pop() # only keep one .so file (remove duplicates)
99+
src_path = ext_libs[soname]
81100

82101
new_soname, new_path = copylib(src_path, dest_dir, patcher)
83102
soname_map[soname] = (new_soname, new_path)
84103
replacements.append((soname, new_soname))
104+
85105
if replacements:
86106
patcher.replace_needed(fn, *replacements)
87107

88108
if len(ext_libs) > 0:
89-
new_rpath = os.path.relpath(dest_dir, os.path.dirname(fn))
90-
new_rpath = os.path.join("$ORIGIN", new_rpath)
109+
if len(soname_map) > 0:
110+
new_rpath = os.path.relpath(dest_dir, os.path.dirname(fn))
111+
new_rpath = os.path.join("$ORIGIN", new_rpath)
112+
else:
113+
new_rpath = None # no new .so files are copied
91114
append_rpath_within_wheel(fn, new_rpath, ctx.name, patcher)
92115

93116
# we grafted in a bunch of libraries and modified their sonames, but
@@ -106,10 +129,13 @@ def repair_wheel(
106129
if update_tags:
107130
ctx.out_wheel = add_platforms(ctx, abis, get_replace_platforms(abis[0]))
108131

109-
if strip:
110-
libs_to_strip = [path for (_, path) in soname_map.values()]
111-
extensions = external_refs_by_fn.keys()
112-
strip_symbols(itertools.chain(libs_to_strip, extensions))
132+
if len(soname_map) > 0:
133+
if strip:
134+
libs_to_strip = [path for (_, path) in soname_map.values()]
135+
extensions = external_refs_by_fn.keys()
136+
strip_symbols(itertools.chain(libs_to_strip, extensions))
137+
else:
138+
shutil.rmtree(dest_dir, ignore_errors=True) # move unnecessary directory
113139

114140
return ctx.out_wheel
115141

@@ -163,7 +189,7 @@ def copylib(src_path: str, dest_dir: str, patcher: ElfPatcher) -> Tuple[str, str
163189

164190

165191
def append_rpath_within_wheel(
166-
lib_name: str, rpath: str, wheel_base_dir: str, patcher: ElfPatcher
192+
lib_name: str, rpath: Optional[str], wheel_base_dir: str, patcher: ElfPatcher
167193
) -> None:
168194
"""Add a new rpath entry to a file while preserving as many existing
169195
rpath entries as possible.
@@ -182,12 +208,23 @@ def append_rpath_within_wheel(
182208
def is_valid_rpath(rpath: str) -> bool:
183209
return _is_valid_rpath(rpath, lib_dir, wheel_base_dir)
184210

211+
site_packages = os.path.join("$ORIGIN", os.path.relpath(wheel_base_dir, lib_dir))
212+
185213
old_rpaths = patcher.get_rpath(lib_name)
186-
rpaths = filter(is_valid_rpath, old_rpaths.split(":"))
214+
rpaths = [rp for rp in old_rpaths.split(":") if is_valid_rpath(rp)]
215+
rpaths = [
216+
rp
217+
if "site-packages" not in rp.split(os.path.sep)
218+
else os.path.join(
219+
site_packages, rp.rpartition("site-packages" + os.path.sep)[-1]
220+
)
221+
for rp in rpaths
222+
]
187223
# Remove duplicates while preserving ordering
188224
# Fake an OrderedSet using OrderedDict
189225
rpath_set = OrderedDict([(old_rpath, "") for old_rpath in rpaths])
190-
rpath_set[rpath] = ""
226+
if rpath is not None:
227+
rpath_set[rpath] = ""
191228

192229
patcher.set_rpath(lib_name, ":".join(rpath_set))
193230

@@ -201,6 +238,16 @@ def _is_valid_rpath(rpath: str, lib_dir: str, wheel_base_dir: str) -> bool:
201238
)
202239
return False
203240
elif not is_subdir(full_rpath_entry, wheel_base_dir):
241+
if "site-packages" in full_rpath_entry.split(os.path.sep):
242+
site_packages = os.path.join(
243+
"$ORIGIN",
244+
os.path.relpath(wheel_base_dir, lib_dir),
245+
)
246+
new_rpath = os.path.join(
247+
site_packages, rpath.rpartition("site-packages" + os.path.sep)[-1]
248+
)
249+
logger.debug(f"Preserved rpath entry {rpath} as {new_rpath}")
250+
return True
204251
logger.debug(
205252
f"rpath entry {rpath} points outside the wheel -- " "discarding it."
206253
)

0 commit comments

Comments
 (0)