@@ -194,6 +194,14 @@ def _find_exe(exe, paths=None):
194
194
'win-arm64' : 'x86_arm64'
195
195
}
196
196
197
+ # A map keyed by get_platform() return values to value accepted by
198
+ # clang as the triple.
199
+ PLAT_TO_LLVM_TARGETS = {
200
+ 'win32' : 'i686' ,
201
+ 'win-amd64' : 'x86_64' ,
202
+ 'win-arm64' : 'aarch64' ,
203
+ }
204
+
197
205
# A set containing the DLLs that are guaranteed to be available for
198
206
# all micro versions of this Python version. Known extension
199
207
# dependencies that are not in this set will be copied to the output
@@ -231,11 +239,12 @@ class MSVCCompiler(CCompiler) :
231
239
exe_extension = '.exe'
232
240
233
241
234
- def __init__ (self , verbose = 0 , dry_run = 0 , force = 0 ):
242
+ def __init__ (self , verbose = 0 , dry_run = 0 , force = 0 , use_clang_cl = False ):
235
243
CCompiler .__init__ (self , verbose , dry_run , force )
236
244
# target platform (.plat_name is consistent with 'bdist')
237
245
self .plat_name = None
238
246
self .initialized = False
247
+ self .use_clang_cl = use_clang_cl
239
248
240
249
def initialize (self , plat_name = None ):
241
250
# multi-init means we would need to check platform same each time...
@@ -257,7 +266,10 @@ def initialize(self, plat_name=None):
257
266
258
267
self ._paths = vc_env .get ('path' , '' )
259
268
paths = self ._paths .split (os .pathsep )
260
- self .cc = _find_exe ("cl.exe" , paths )
269
+ if self .use_clang_cl :
270
+ self .cc = _find_exe ("clang-cl.exe" )
271
+ else :
272
+ self .cc = _find_exe ("cl.exe" , paths )
261
273
self .linker = _find_exe ("link.exe" , paths )
262
274
self .lib = _find_exe ("lib.exe" , paths )
263
275
self .rc = _find_exe ("rc.exe" , paths ) # resource compiler
@@ -295,6 +307,16 @@ def initialize(self, plat_name=None):
295
307
ldflags_debug = [
296
308
'/nologo' , '/INCREMENTAL:NO' , '/LTCG' , '/DEBUG:FULL'
297
309
]
310
+ if self .use_clang_cl :
311
+ # Add target for clang
312
+ target_flag = "{}-pc-windows-msvc" .format (PLAT_TO_LLVM_TARGETS [plat_name ])
313
+ self .compile_options .append (target_flag )
314
+ self .compile_options_debug .append (target_flag )
315
+ # Remove whole program optimization flags to avoid warnings about
316
+ # unrecognized options
317
+ self .compile_options .remove ('/GL' )
318
+ ldflags .remove ('/LTCG' )
319
+ ldflags_debug .remove ('/LTCG' )
298
320
299
321
self .ldflags_exe = [* ldflags , '/MANIFEST:EMBED,ID=1' ]
300
322
self .ldflags_exe_debug = [* ldflags_debug , '/MANIFEST:EMBED,ID=1' ]
@@ -587,3 +609,10 @@ def find_library_file(self, dirs, lib, debug=0):
587
609
else :
588
610
# Oops, didn't find it in *any* of 'dirs'
589
611
return None
612
+
613
+
614
+ class ClangMSVCCompiler (MSVCCompiler ):
615
+ compiler_type = 'clang-cl'
616
+
617
+ def __init__ (self , verbose = 0 , dry_run = 0 , force = 0 ):
618
+ MSVCCompiler .__init__ (self , verbose , dry_run , force , True )
0 commit comments