@@ -176,21 +176,37 @@ def _get_vc_env(plat_spec):
176176 return env
177177
178178
179- def _find_exe (exe , paths = None ):
179+ def _find_exe (exe , paths = None , clangcl = False ):
180180 """Return path to an MSVC executable program.
181181
182182 Tries to find the program in several places: first, one of the
183183 MSVC program search paths from the registry; next, the directories
184184 in the PATH environment variable. If any of those work, return an
185185 absolute path that is known to exist. If none of them work, just
186186 return the original program name, 'exe'.
187+
188+ If clangcl is set to true, look for the LLVM clang-cl executables,
189+ as well as look for them without the extension (eg. on Linux)
187190 """
191+ if clangcl :
192+ if exe == 'cl.exe' :
193+ exe = 'clang-{}' .format (exe )
194+ elif exe == 'link.exe' :
195+ exe = 'lld-{}' .format (exe )
196+ elif exe == 'mc.exe' :
197+ exe = 'llvm-ml.exe'
198+ else :
199+ exe = 'llvm-{}' .format (exe )
188200 if not paths :
189201 paths = os .getenv ('path' ).split (os .pathsep )
190202 for p in paths :
191203 fn = os .path .join (os .path .abspath (p ), exe )
192204 if os .path .isfile (fn ):
193205 return fn
206+ elif clangcl :
207+ fn = os .path .splitext (fn )[0 ]
208+ if os .path .isfile (fn ):
209+ return fn
194210 return exe
195211
196212
@@ -201,6 +217,13 @@ def _find_exe(exe, paths=None):
201217 'win-arm64' : 'arm64' ,
202218}
203219
220+ _clang_targets = {
221+ 'win32' : 'i686' ,
222+ 'win-amd64' : 'x86_64' ,
223+ 'win-arm32' : 'armv7' ,
224+ 'win-arm64' : 'aarch64' ,
225+ }
226+
204227
205228def _get_vcvars_spec (host_platform , platform ):
206229 """
@@ -298,14 +321,16 @@ def initialize(self, plat_name: str | None = None) -> None:
298321 )
299322 self ._configure (vc_env )
300323
324+ clangcl = True if self .compiler_type == "clangcl" else False
325+
301326 self ._paths = vc_env .get ('path' , '' )
302327 paths = self ._paths .split (os .pathsep )
303- self .cc = _find_exe ("cl.exe" , paths )
304- self .linker = _find_exe ("link.exe" , paths )
305- self .lib = _find_exe ("lib.exe" , paths )
306- self .rc = _find_exe ("rc.exe" , paths ) # resource compiler
307- self .mc = _find_exe ("mc.exe" , paths ) # message compiler
308- self .mt = _find_exe ("mt.exe" , paths ) # message compiler
328+ self .cc = _find_exe ("cl.exe" , paths , clangcl )
329+ self .linker = _find_exe ("link.exe" , paths , clangcl )
330+ self .lib = _find_exe ("lib.exe" , paths , clangcl )
331+ self .rc = _find_exe ("rc.exe" , paths , clangcl ) # resource compiler
332+ self .mc = _find_exe ("mc.exe" , paths , clangcl ) # message compiler
333+ self .mt = _find_exe ("mt.exe" , paths , clangcl ) # message compiler
309334
310335 self .preprocess_options = None
311336 # bpo-38597: Always compile with dynamic linking
@@ -322,6 +347,12 @@ def initialize(self, plat_name: str | None = None) -> None:
322347 '/D_DEBUG' ,
323348 ]
324349
350+ if clangcl :
351+ target = '--target={}-windows-msvc' .format (_clang_targets [plat_name ])
352+ self .compile_options .remove ('/GL' )
353+ self .compile_options += ['/FA' , target ]
354+ self .compile_options_debug += ['/FA' , target ]
355+
325356 ldflags = ['/nologo' , '/INCREMENTAL:NO' , '/LTCG' ]
326357
327358 ldflags_debug = ['/nologo' , '/INCREMENTAL:NO' , '/LTCG' , '/DEBUG:FULL' ]
@@ -437,7 +468,11 @@ def compile( # noqa: C901
437468 rc_dir = os .path .dirname (obj )
438469 try :
439470 # first compile .MC to .RC and .H file
440- self .spawn ([self .mc , '-h' , h_dir , '-r' , rc_dir , src ])
471+ mc_cmd = [self .mc ]
472+ if clangcl and '64' in plat_name :
473+ mc_cmd .append ('--m64' )
474+ mc_cmd += ['-h' , h_dir , '-r' , rc_dir , src ]
475+ self .spawn (mc_cmd )
441476 base , _ = os .path .splitext (os .path .basename (src ))
442477 rc_file = os .path .join (rc_dir , base + '.rc' )
443478 # then compile .RC to .RES file
@@ -612,3 +647,8 @@ def find_library_file(self, dirs, lib, debug=False):
612647 else :
613648 # Oops, didn't find it in *any* of 'dirs'
614649 return None
650+
651+
652+ class ClangCLCompiler (Compiler ):
653+
654+ compiler_type = 'clangcl'
0 commit comments