@@ -134,7 +134,7 @@ def build_wheels(pip):
134
134
env ["VIRTUAL_ENV" ] = abspath (dirname (dirname (pip )))
135
135
print ("Building" , name , version , "with" , script , flush = True )
136
136
if sys .platform == "win32" :
137
- cmd = [script , version ] # Python's subprocess.py does the quoting we need
137
+ cmd = [script , version ] # Python's subprocess.py does the quoting we need
138
138
else :
139
139
cmd = f"{ shlex .quote (script )} { version } "
140
140
subprocess .check_call (cmd , shell = True , env = env )
@@ -146,152 +146,26 @@ def build_wheels(pip):
146
146
subprocess .check_call ([pip , "wheel" , spec ])
147
147
148
148
149
- _warned_dlls = []
150
-
151
-
152
- def repair_wheels_windows (output_dir , wheels ):
153
- import pefile
154
- from machomachomangler .pe import redll
155
-
156
- def resolve_dll_src (dll ):
157
- # search for dependencies in system directories
158
- dll_search_paths = [
159
- os .environ ["WINDIR" ],
160
- join (os .environ ["WINDIR" ], "System32" ),
161
- * os .environ ["PATH" ].split (";" ),
162
- ]
163
- ignored_dlls = [
164
- # These DLLs are just provided by Windows.
165
- # This list is probably incomplete.
166
- r"advapi32\.dll" ,
167
- r"advapires32\.dll" ,
168
- r"atl.*\.dll" ,
169
- r"comctl32\.dll" ,
170
- r"comdlg32\.dll" ,
171
- r"crtdll\.dll" ,
172
- r"gdi32\.dll" ,
173
- r"hal.*\.dll" ,
174
- r"imm32\.dll" ,
175
- r"iphlpapi\.dll" ,
176
- r"kernel32\.dll" ,
177
- r"kernelbase\.dll" ,
178
- r"msvbvm60\.dll" ,
179
- r"msvcirt\.dll" ,
180
- r"msvcrt?.*\.dll" ,
181
- r"netapi32\.dll" ,
182
- r"ntdll\.dll" ,
183
- r"ole32\.dll" ,
184
- r"pdh\.dll" ,
185
- r"powrprof\.dll" ,
186
- r"psapi\.dll" ,
187
- r"rpcrt4\.dll" ,
188
- r"sechost\.dll" ,
189
- r"shell32\.dll" ,
190
- r"shlwapi\.dll" ,
191
- r"shscrap\.dll" ,
192
- r"ucrtbase\.dll" ,
193
- r"user32\.dll" ,
194
- r"version\.dll" ,
195
- r"winmm\.dll" ,
196
- r"ws2_32\.dll" ,
197
- # These match DLLs that provide API sets.
198
- # See https://learn.microsoft.com/en-us/windows/win32/apiindex/windows-apisets
199
- r"api-ms-win-.*\.dll" ,
200
- r"ext-ms-win-.*\.dll" ,
201
- # These match DLLs that we provide in GraalPy
202
- r"python.*\.dll" ,
203
- # These are the DLLs typically linked when building with MSVC. See
204
- # https://learn.microsoft.com/en-us/cpp/windows/determining-which-dlls-to-redistribute
205
- # When these are included, the user should install the latest
206
- # redist package from
207
- # https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist
208
- # However, https://aka.ms/vs/17/redist.txt lists the libraries
209
- # which can be included in application distributions.
210
- r"concrt.*\.dll" ,
211
- r"mfc.*\.dll" ,
212
- r"msvcp.*\.dll" ,
213
- r"vcamp.*\.dll" ,
214
- r"vccorlib.*\.dll" ,
215
- r"vcomp.*\.dll" ,
216
- r"vcruntime.*\.dll" ,
217
- ]
218
- if not dll :
219
- return
220
- if any (re .match (pat , basename (dll ), re .IGNORECASE ) for pat in ignored_dlls ):
221
- if dll not in _warned_dlls :
222
- print ("Not including" , dll , flush = True )
223
- _warned_dlls .append (dll )
224
- return
225
- if isabs (dll ):
226
- return dll
227
- for search_path in dll_search_paths :
228
- if exists (src := join (search_path , dll )):
229
- return src
230
-
231
- def resolve_dll_target (dll , dependent , checksum ):
232
- return join (dirname (dependent ), f"{ checksum } .{ basename (dll )} " )
233
-
234
- def filehash (files ):
235
- sha1 = hashlib .sha1 ()
236
- for file in files :
237
- with open (file , mode = "rb" ) as f :
238
- sha1 .update (f .read ())
239
- return sha1 .hexdigest ()[:8 ]
240
-
241
- for whl in wheels :
242
- with TemporaryDirectory () as name :
243
- with zipfile .ZipFile (whl ) as f :
244
- f .extractall (name )
245
-
246
- # find all pyd files and recursively copy dependencies
247
- dlls = glob (f"{ name } /**/*.pyd" , recursive = True )
248
- checksum = filehash (dlls )
249
- dependents_to_dependencies = {}
250
- while dlls :
251
- dll = dlls .pop ()
252
- with pefile .PE (dll ) as pe :
253
- pe_info = pe .dump_dict ()
254
- for syms in pe_info .get ("Imported symbols" , []):
255
- for sym in syms :
256
- if dep_src := resolve_dll_src (sym .get ("DLL" , b"" ).decode ("utf-8" )):
257
- if not exists (dep_tgt := resolve_dll_target (dep_src , dll , checksum )):
258
- print ("Including" , dep_src , "as" , dep_tgt , flush = True )
259
- shutil .copy (dep_src , dep_tgt )
260
- dlls .append (dep_tgt )
261
- dependents_to_dependencies .setdefault (dll , []).append (dep_src )
262
-
263
- for dll , dependencies in dependents_to_dependencies .items ():
264
- mapping = {}
265
- for dep_src in dependencies :
266
- mapping [basename (dep_src ).encode ("utf-8" )] = basename (
267
- resolve_dll_target (dep_src , dll , checksum )
268
- ).encode ("utf-8" )
269
- with open (dll , mode = "rb" ) as f :
270
- data = f .read ()
271
- print (
272
- "Rewriting\n \t " ,
273
- "\n \t " .join ([k .decode ("utf-8" ) for k in mapping .keys ()]),
274
- "\n \t ->\n \t " ,
275
- "\n \t " .join ([v .decode ("utf-8" ) for v in mapping .values ()]),
276
- "\n in" ,
277
- dll ,
278
- )
279
- data = redll (data , mapping )
280
- with open (dll , mode = "wb" ) as f :
281
- f .write (data )
282
-
283
- os .makedirs (output_dir , exist_ok = True )
284
- if exists (whl_tgt := join (output_dir , whl )):
285
- os .unlink (whl_tgt )
286
- shutil .make_archive (whl_tgt , "zip" , name )
287
- os .rename (f"{ whl_tgt } .zip" , whl_tgt )
288
-
289
-
290
149
def repair_wheels ():
291
150
if sys .platform == "win32" :
292
- ensure_installed ("machomachomangler" )
293
- ensure_installed ("pefile" )
294
- repair_wheels_windows ("wheelhouse" , glob ("*.whl" ))
151
+ ensure_installed ("delvewheel" )
152
+ env = os .environ .copy ()
153
+ env ["PYTHONUTF8" ] = "1"
154
+ subprocess .check_call (
155
+ [
156
+ sys .executable ,
157
+ "-m" ,
158
+ "delvewheel" ,
159
+ "repair" ,
160
+ "-v" ,
161
+ "--exclude" ,
162
+ "python-native.dll" ,
163
+ "-w" ,
164
+ "wheelhouse" ,
165
+ * glob ("*.whl" ),
166
+ ],
167
+ env = env ,
168
+ )
295
169
elif sys .platform == "linux" :
296
170
ensure_installed ("auditwheel" )
297
171
subprocess .check_call (
0 commit comments