1
+ import itertools
2
+ import logging
1
3
import os
2
4
import re
3
5
import stat
4
6
import shutil
5
- import itertools
6
- import functools
7
- from os .path import exists , relpath , dirname , basename , abspath , isabs
7
+ from os .path import exists , basename , abspath , isabs
8
8
from os .path import join as pjoin
9
- from subprocess import check_call , check_output , CalledProcessError
10
- from distutils .spawn import find_executable
11
9
from typing import Dict , Optional
12
- import logging
13
10
14
- from .policy import get_replace_platforms
15
- from .wheeltools import InWheelCtx , add_platforms
16
- from .wheel_abi import get_wheel_elfdata
11
+ from auditwheel .patcher import ElfPatcher
17
12
from .elfutils import elf_read_rpaths , elf_read_dt_needed
18
13
from .hashfile import hashfile
19
-
14
+ from .policy import get_replace_platforms
15
+ from .wheel_abi import get_wheel_elfdata
16
+ from .wheeltools import InWheelCtx , add_platforms
20
17
21
18
logger = logging .getLogger (__name__ )
22
19
28
25
re .VERBOSE ).match
29
26
30
27
31
- @functools .lru_cache ()
32
- def verify_patchelf ():
33
- """This function looks for the ``patchelf`` external binary in the PATH,
34
- checks for the required version, and throws an exception if a proper
35
- version can't be found. Otherwise, silcence is golden
36
- """
37
- if not find_executable ('patchelf' ):
38
- raise ValueError ('Cannot find required utility `patchelf` in PATH' )
39
- try :
40
- version = check_output (['patchelf' , '--version' ]).decode ('utf-8' )
41
- except CalledProcessError :
42
- raise ValueError ('Could not call `patchelf` binary' )
43
-
44
- m = re .match (r'patchelf\s+(\d+(.\d+)?)' , version )
45
- if m and tuple (int (x ) for x in m .group (1 ).split ('.' )) >= (0 , 9 ):
46
- return
47
- raise ValueError (('patchelf %s found. auditwheel repair requires '
48
- 'patchelf >= 0.9.' ) %
49
- version )
50
-
51
-
52
28
def repair_wheel (wheel_path : str , abi : str , lib_sdir : str , out_dir : str ,
53
- update_tags : bool ) -> Optional [str ]:
29
+ update_tags : bool , patcher : ElfPatcher ) -> Optional [str ]:
54
30
55
31
external_refs_by_fn = get_wheel_elfdata (wheel_path )[1 ]
56
32
@@ -83,13 +59,14 @@ def repair_wheel(wheel_path: str, abi: str, lib_sdir: str, out_dir: str,
83
59
'library "%s" could not be located' ) %
84
60
soname )
85
61
86
- new_soname , new_path = copylib (src_path , dest_dir )
62
+ new_soname , new_path = copylib (src_path , dest_dir , patcher )
87
63
soname_map [soname ] = (new_soname , new_path )
88
- check_call (['patchelf' , '--replace-needed' , soname ,
89
- new_soname , fn ])
64
+ patcher .replace_needed (fn , soname , new_soname )
90
65
91
66
if len (ext_libs ) > 0 :
92
- patchelf_set_rpath (fn , dest_dir )
67
+ new_rpath = os .path .relpath (dest_dir , os .path .dirname (fn ))
68
+ new_rpath = os .path .join ('$ORIGIN' , new_rpath )
69
+ patcher .set_rpath (fn , new_rpath )
93
70
94
71
# we grafted in a bunch of libraries and modified their sonames, but
95
72
# they may have internal dependencies (DT_NEEDED) on one another, so
@@ -99,16 +76,15 @@ def repair_wheel(wheel_path: str, abi: str, lib_sdir: str, out_dir: str,
99
76
needed = elf_read_dt_needed (path )
100
77
for n in needed :
101
78
if n in soname_map :
102
- check_call (['patchelf' , '--replace-needed' , n ,
103
- soname_map [n ][0 ], path ])
79
+ patcher .replace_needed (path , n , soname_map [n ][0 ])
104
80
105
81
if update_tags :
106
82
ctx .out_wheel = add_platforms (ctx , [abi ],
107
83
get_replace_platforms (abi ))
108
84
return ctx .out_wheel
109
85
110
86
111
- def copylib (src_path , dest_dir ):
87
+ def copylib (src_path , dest_dir , patcher ):
112
88
"""Graft a shared library from the system into the wheel and update the
113
89
relevant links.
114
90
@@ -142,17 +118,9 @@ def copylib(src_path, dest_dir):
142
118
if not statinfo .st_mode & stat .S_IWRITE :
143
119
os .chmod (dest_path , statinfo .st_mode | stat .S_IWRITE )
144
120
145
- verify_patchelf ()
146
- check_call (['patchelf' , '--set-soname' , new_soname , dest_path ])
121
+ patcher .set_soname (dest_path , new_soname )
147
122
148
123
if any (itertools .chain (rpaths ['rpaths' ], rpaths ['runpaths' ])):
149
- patchelf_set_rpath (dest_path , dest_dir )
124
+ patcher . set_rpath (dest_path , dest_dir )
150
125
151
126
return new_soname , dest_path
152
-
153
-
154
- def patchelf_set_rpath (fn , libdir ):
155
- rpath = pjoin ('$ORIGIN' , relpath (libdir , dirname (fn )))
156
- logger .debug ('Setting RPATH: %s to "%s"' , fn , rpath )
157
- check_call (['patchelf' , '--remove-rpath' , fn ])
158
- check_call (['patchelf' , '--force-rpath' , '--set-rpath' , rpath , fn ])
0 commit comments