55import  re 
66import  shutil 
77import  stat 
8- from  collections  import  OrderedDict 
8+ from  collections  import  OrderedDict ,  defaultdict 
99from  os .path  import  abspath , basename , dirname , exists , isabs 
1010from  os .path  import  join  as  pjoin 
1111from  subprocess  import  check_call 
12- from  typing  import  Dict , Iterable , List , Optional , Tuple 
12+ from  typing  import  Dict , Iterable , List , Optional , Set ,  Tuple 
1313
1414from  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
165191def  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