@@ -194,6 +194,14 @@ def _find_exe(exe, paths=None):
194194 'win-arm64' : 'x86_arm64'
195195}
196196
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+
197205# A set containing the DLLs that are guaranteed to be available for
198206# all micro versions of this Python version. Known extension
199207# dependencies that are not in this set will be copied to the output
@@ -231,11 +239,12 @@ class MSVCCompiler(CCompiler) :
231239 exe_extension = '.exe'
232240
233241
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 ):
235243 CCompiler .__init__ (self , verbose , dry_run , force )
236244 # target platform (.plat_name is consistent with 'bdist')
237245 self .plat_name = None
238246 self .initialized = False
247+ self .use_clang_cl = use_clang_cl
239248
240249 def initialize (self , plat_name = None ):
241250 # multi-init means we would need to check platform same each time...
@@ -257,7 +266,10 @@ def initialize(self, plat_name=None):
257266
258267 self ._paths = vc_env .get ('path' , '' )
259268 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 )
261273 self .linker = _find_exe ("link.exe" , paths )
262274 self .lib = _find_exe ("lib.exe" , paths )
263275 self .rc = _find_exe ("rc.exe" , paths ) # resource compiler
@@ -295,6 +307,16 @@ def initialize(self, plat_name=None):
295307 ldflags_debug = [
296308 '/nologo' , '/INCREMENTAL:NO' , '/LTCG' , '/DEBUG:FULL'
297309 ]
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' )
298320
299321 self .ldflags_exe = [* ldflags , '/MANIFEST:EMBED,ID=1' ]
300322 self .ldflags_exe_debug = [* ldflags_debug , '/MANIFEST:EMBED,ID=1' ]
@@ -587,3 +609,10 @@ def find_library_file(self, dirs, lib, debug=0):
587609 else :
588610 # Oops, didn't find it in *any* of 'dirs'
589611 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