]>
crepu.dev Git - config.git/blob - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/setuptools/_distutils/msvc9compiler.py
1 """distutils.msvc9compiler
3 Contains MSVCCompiler, an implementation of the abstract CCompiler class
4 for the Microsoft Visual Studio 2008.
6 The module is compatible with VS 2005 and VS 2008. You can find legacy support
7 for older versions of VS in distutils.msvccompiler.
10 # Written by Perry Stoll
11 # hacked by Robin Becker and Thomas Heller to do a better job of
12 # finding DevStudio (through the registry)
13 # ported to VS2005 and VS 2008 by Christian Heimes
23 DistutilsPlatformError
,
28 from .ccompiler
import CCompiler
, gen_lib_options
30 from .util
import get_platform
35 "msvc9compiler is deprecated and slated to be removed "
36 "in the future. Please discontinue use or file an issue "
37 "with pypa/distutils describing your use case.",
41 RegOpenKeyEx
= winreg
.OpenKeyEx
42 RegEnumKey
= winreg
.EnumKey
43 RegEnumValue
= winreg
.EnumValue
44 RegError
= winreg
.error
48 winreg
.HKEY_CURRENT_USER
,
49 winreg
.HKEY_LOCAL_MACHINE
,
50 winreg
.HKEY_CLASSES_ROOT
,
53 NATIVE_WIN64
= sys
.platform
== 'win32' and sys
.maxsize
> 2**32
55 # Visual C++ is a 32-bit application, so we need to look in
56 # the corresponding registry branch, if we're running a
57 # 64-bit Python on Win64
58 VS_BASE
= r
"Software\Wow6432Node\Microsoft\VisualStudio\%0.1f"
59 WINSDK_BASE
= r
"Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows"
60 NET_BASE
= r
"Software\Wow6432Node\Microsoft\.NETFramework"
62 VS_BASE
= r
"Software\Microsoft\VisualStudio\%0.1f"
63 WINSDK_BASE
= r
"Software\Microsoft\Microsoft SDKs\Windows"
64 NET_BASE
= r
"Software\Microsoft\.NETFramework"
66 # A map keyed by get_platform() return values to values accepted by
67 # 'vcvarsall.bat'. Note a cross-compile may combine these (eg, 'x86_amd64' is
68 # the param to cross-compile on x86 targeting amd64.)
76 """Helper class to read values from the registry"""
78 def get_value(cls
, path
, key
):
80 d
= cls
.read_values(base
, path
)
85 get_value
= classmethod(get_value
)
87 def read_keys(cls
, base
, key
):
88 """Return list of registry keys."""
90 handle
= RegOpenKeyEx(base
, key
)
97 k
= RegEnumKey(handle
, i
)
104 read_keys
= classmethod(read_keys
)
106 def read_values(cls
, base
, key
):
107 """Return dict of registry keys and values.
109 All names are converted to lowercase.
112 handle
= RegOpenKeyEx(base
, key
)
119 name
, value
, type = RegEnumValue(handle
, i
)
123 d
[cls
.convert_mbcs(name
)] = cls
.convert_mbcs(value
)
127 read_values
= classmethod(read_values
)
130 dec
= getattr(s
, "decode", None)
138 convert_mbcs
= staticmethod(convert_mbcs
)
142 def __init__(self
, version
):
144 self
.vsbase
= VS_BASE
% version
145 self
.load_macros(version
)
147 def set_macro(self
, macro
, path
, key
):
148 self
.macros
["$(%s)" % macro
] = Reg
.get_value(path
, key
)
150 def load_macros(self
, version
):
151 self
.set_macro("VCInstallDir", self
.vsbase
+ r
"\Setup\VC", "productdir")
152 self
.set_macro("VSInstallDir", self
.vsbase
+ r
"\Setup\VS", "productdir")
153 self
.set_macro("FrameworkDir", NET_BASE
, "installroot")
156 self
.set_macro("FrameworkSDKDir", NET_BASE
, "sdkinstallrootv2.0")
158 raise KeyError("sdkinstallrootv2.0")
160 raise DistutilsPlatformError(
161 """Python was built with Visual Studio 2008;
162 extensions must be built with a compiler than can generate compatible binaries.
163 Visual Studio 2008 was not found on this system. If you have Cygwin installed,
164 you can try compiling with MingW32, by passing "-c mingw32" to setup.py."""
168 self
.set_macro("FrameworkVersion", self
.vsbase
, "clr version")
169 self
.set_macro("WindowsSdkDir", WINSDK_BASE
, "currentinstallfolder")
171 p
= r
"Software\Microsoft\NET Framework Setup\Product"
174 h
= RegOpenKeyEx(base
, p
)
177 key
= RegEnumKey(h
, 0)
178 d
= Reg
.get_value(base
, r
"{}\{}".format(p
, key
))
179 self
.macros
["$(FrameworkVersion)"] = d
["version"]
182 for k
, v
in self
.macros
.items():
187 def get_build_version():
188 """Return the version of MSVC that was used to build Python.
190 For Python 2.3 and up, the version number is included in
191 sys.version. For earlier versions, assume the compiler is MSVC 6.
194 i
= sys
.version
.find(prefix
)
198 s
, rest
= sys
.version
[i
:].split(" ", 1)
199 majorVersion
= int(s
[:-2]) - 6
200 if majorVersion
>= 13:
201 # v13 was skipped and should be v14
203 minorVersion
= int(s
[2:3]) / 10.0
204 # I don't think paths are affected by minor version in version 6
205 if majorVersion
== 6:
207 if majorVersion
>= 6:
208 return majorVersion
+ minorVersion
209 # else we don't know what version of the compiler this is
213 def normalize_and_reduce_paths(paths
):
214 """Return a list of normalized paths with duplicates removed.
216 The current order of paths is maintained.
218 # Paths are normalized so things like: /a and /a/ aren't both preserved.
221 np
= os
.path
.normpath(p
)
222 # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set.
223 if np
not in reduced_paths
:
224 reduced_paths
.append(np
)
228 def removeDuplicates(variable
):
229 """Remove duplicate values of an environment variable."""
230 oldList
= variable
.split(os
.pathsep
)
235 newVariable
= os
.pathsep
.join(newList
)
239 def find_vcvarsall(version
):
240 """Find the vcvarsall.bat file
242 At first it tries to find the productdir of VS 2008 in the registry. If
243 that fails it falls back to the VS90COMNTOOLS env var.
245 vsbase
= VS_BASE
% version
247 productdir
= Reg
.get_value(r
"%s\Setup\VC" % vsbase
, "productdir")
249 log
.debug("Unable to find productdir in registry")
252 if not productdir
or not os
.path
.isdir(productdir
):
253 toolskey
= "VS%0.f0COMNTOOLS" % version
254 toolsdir
= os
.environ
.get(toolskey
, None)
256 if toolsdir
and os
.path
.isdir(toolsdir
):
257 productdir
= os
.path
.join(toolsdir
, os
.pardir
, os
.pardir
, "VC")
258 productdir
= os
.path
.abspath(productdir
)
259 if not os
.path
.isdir(productdir
):
260 log
.debug("%s is not a valid directory" % productdir
)
263 log
.debug("Env var %s is not set or invalid" % toolskey
)
265 log
.debug("No productdir found")
267 vcvarsall
= os
.path
.join(productdir
, "vcvarsall.bat")
268 if os
.path
.isfile(vcvarsall
):
270 log
.debug("Unable to find vcvarsall.bat")
274 def query_vcvarsall(version
, arch
="x86"):
275 """Launch vcvarsall.bat and read the settings from its environment"""
276 vcvarsall
= find_vcvarsall(version
)
277 interesting
= {"include", "lib", "libpath", "path"}
280 if vcvarsall
is None:
281 raise DistutilsPlatformError("Unable to find vcvarsall.bat")
282 log
.debug("Calling 'vcvarsall.bat %s' (version=%s)", arch
, version
)
283 popen
= subprocess
.Popen(
284 '"{}" {} & set'.format(vcvarsall
, arch
),
285 stdout
=subprocess
.PIPE
,
286 stderr
=subprocess
.PIPE
,
289 stdout
, stderr
= popen
.communicate()
290 if popen
.wait() != 0:
291 raise DistutilsPlatformError(stderr
.decode("mbcs"))
293 stdout
= stdout
.decode("mbcs")
294 for line
in stdout
.split("\n"):
295 line
= Reg
.convert_mbcs(line
)
299 key
, value
= line
.split('=', 1)
301 if key
in interesting
:
302 if value
.endswith(os
.pathsep
):
304 result
[key
] = removeDuplicates(value
)
310 if len(result
) != len(interesting
):
311 raise ValueError(str(list(result
.keys())))
317 VERSION
= get_build_version()
318 # MACROS = MacroExpander(VERSION)
321 class MSVCCompiler(CCompiler
):
322 """Concrete class that implements an interface to Microsoft Visual C++,
323 as defined by the CCompiler abstract class."""
325 compiler_type
= 'msvc'
327 # Just set this so CCompiler's constructor doesn't barf. We currently
328 # don't use the 'set_executables()' bureaucracy provided by CCompiler,
329 # as it really isn't necessary for this sort of single-compiler class.
330 # Would be nice to have a consistent interface with UnixCCompiler,
331 # though, so it's worth thinking about.
334 # Private class data (need to distinguish C from C++ source for compiler)
335 _c_extensions
= ['.c']
336 _cpp_extensions
= ['.cc', '.cpp', '.cxx']
337 _rc_extensions
= ['.rc']
338 _mc_extensions
= ['.mc']
340 # Needed for the filename generation methods provided by the
341 # base class, CCompiler.
342 src_extensions
= _c_extensions
+ _cpp_extensions
+ _rc_extensions
+ _mc_extensions
343 res_extension
= '.res'
344 obj_extension
= '.obj'
345 static_lib_extension
= '.lib'
346 shared_lib_extension
= '.dll'
347 static_lib_format
= shared_lib_format
= '%s%s'
348 exe_extension
= '.exe'
350 def __init__(self
, verbose
=0, dry_run
=0, force
=0):
351 super().__init
__(verbose
, dry_run
, force
)
352 self
.__version
= VERSION
353 self
.__root
= r
"Software\Microsoft\VisualStudio"
354 # self.__macros = MACROS
356 # target platform (.plat_name is consistent with 'bdist')
357 self
.plat_name
= None
358 self
.__arch
= None # deprecated name
359 self
.initialized
= False
361 def initialize(self
, plat_name
=None): # noqa: C901
362 # multi-init means we would need to check platform same each time...
363 assert not self
.initialized
, "don't init multiple times"
364 if self
.__version
< 8.0:
365 raise DistutilsPlatformError(
366 "VC %0.1f is not supported by this module" % self
.__version
368 if plat_name
is None:
369 plat_name
= get_platform()
370 # sanity check for platforms to prevent obscure errors later.
371 ok_plats
= 'win32', 'win-amd64'
372 if plat_name
not in ok_plats
:
373 raise DistutilsPlatformError(
374 "--plat-name must be one of {}".format(ok_plats
)
378 "DISTUTILS_USE_SDK" in os
.environ
379 and "MSSdk" in os
.environ
380 and self
.find_exe("cl.exe")
382 # Assume that the SDK set up everything alright; don't try to be
385 self
.linker
= "link.exe"
390 # On x86, 'vcvars32.bat amd64' creates an env that doesn't work;
391 # to cross compile, you use 'x86_amd64'.
392 # On AMD64, 'vcvars32.bat amd64' is a native build env; to cross
393 # compile use 'x86' (ie, it runs the x86 compiler directly)
394 if plat_name
== get_platform() or plat_name
== 'win32':
395 # native build or cross-compile to win32
396 plat_spec
= PLAT_TO_VCVARS
[plat_name
]
398 # cross compile from win32 -> some 64bit
400 PLAT_TO_VCVARS
[get_platform()] + '_' + PLAT_TO_VCVARS
[plat_name
]
403 vc_env
= query_vcvarsall(VERSION
, plat_spec
)
405 self
.__paths
= vc_env
['path'].split(os
.pathsep
)
406 os
.environ
['lib'] = vc_env
['lib']
407 os
.environ
['include'] = vc_env
['include']
409 if len(self
.__paths
) == 0:
410 raise DistutilsPlatformError(
411 "Python was built with %s, "
412 "and extensions need to be built with the same "
413 "version of the compiler, but it isn't installed." % self
.__product
416 self
.cc
= self
.find_exe("cl.exe")
417 self
.linker
= self
.find_exe("link.exe")
418 self
.lib
= self
.find_exe("lib.exe")
419 self
.rc
= self
.find_exe("rc.exe") # resource compiler
420 self
.mc
= self
.find_exe("mc.exe") # message compiler
421 # self.set_path_env_var('lib')
422 # self.set_path_env_var('include')
424 # extend the MSVC path with the current path
426 for p
in os
.environ
['path'].split(';'):
427 self
.__paths
.append(p
)
430 self
.__paths
= normalize_and_reduce_paths(self
.__paths
)
431 os
.environ
['path'] = ";".join(self
.__paths
)
433 self
.preprocess_options
= None
434 if self
.__arch
== "x86":
435 self
.compile_options
= ['/nologo', '/O2', '/MD', '/W3', '/DNDEBUG']
436 self
.compile_options_debug
= [
446 self
.compile_options
= ['/nologo', '/O2', '/MD', '/W3', '/GS-', '/DNDEBUG']
447 self
.compile_options_debug
= [
457 self
.ldflags_shared
= ['/DLL', '/nologo', '/INCREMENTAL:NO']
458 if self
.__version
>= 7:
459 self
.ldflags_shared_debug
= ['/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG']
460 self
.ldflags_static
= ['/nologo']
462 self
.initialized
= True
464 # -- Worker methods ------------------------------------------------
466 def object_filenames(self
, source_filenames
, strip_dir
=0, output_dir
=''):
467 # Copied from ccompiler.py, extended to return .res as 'object'-file
469 if output_dir
is None:
472 for src_name
in source_filenames
:
473 (base
, ext
) = os
.path
.splitext(src_name
)
474 base
= os
.path
.splitdrive(base
)[1] # Chop off the drive
475 base
= base
[os
.path
.isabs(base
) :] # If abs, chop off leading /
476 if ext
not in self
.src_extensions
:
477 # Better to raise an exception instead of silently continuing
478 # and later complain about sources and targets having
480 raise CompileError("Don't know how to compile %s" % src_name
)
482 base
= os
.path
.basename(base
)
483 if ext
in self
._rc
_extensions
:
484 obj_names
.append(os
.path
.join(output_dir
, base
+ self
.res_extension
))
485 elif ext
in self
._mc
_extensions
:
486 obj_names
.append(os
.path
.join(output_dir
, base
+ self
.res_extension
))
488 obj_names
.append(os
.path
.join(output_dir
, base
+ self
.obj_extension
))
491 def compile( # noqa: C901
503 if not self
.initialized
:
505 compile_info
= self
._setup
_compile
(
506 output_dir
, macros
, include_dirs
, sources
, depends
, extra_postargs
508 macros
, objects
, extra_postargs
, pp_opts
, build
= compile_info
510 compile_opts
= extra_preargs
or []
511 compile_opts
.append('/c')
513 compile_opts
.extend(self
.compile_options_debug
)
515 compile_opts
.extend(self
.compile_options
)
519 src
, ext
= build
[obj
]
523 # pass the full pathname to MSVC in debug mode,
524 # this allows the debugger to find the source file
525 # without asking the user to browse for it
526 src
= os
.path
.abspath(src
)
528 if ext
in self
._c
_extensions
:
529 input_opt
= "/Tc" + src
530 elif ext
in self
._cpp
_extensions
:
531 input_opt
= "/Tp" + src
532 elif ext
in self
._rc
_extensions
:
533 # compile .RC to .RES file
535 output_opt
= "/fo" + obj
537 self
.spawn([self
.rc
] + pp_opts
+ [output_opt
] + [input_opt
])
538 except DistutilsExecError
as msg
:
539 raise CompileError(msg
)
541 elif ext
in self
._mc
_extensions
:
542 # Compile .MC to .RC file to .RES file.
543 # * '-h dir' specifies the directory for the
544 # generated include file
545 # * '-r dir' specifies the target directory of the
546 # generated RC file and the binary message resource
549 # For now (since there are no options to change this),
550 # we use the source-directory for the include file and
551 # the build directory for the RC file and message
552 # resources. This works at least for win32all.
553 h_dir
= os
.path
.dirname(src
)
554 rc_dir
= os
.path
.dirname(obj
)
556 # first compile .MC to .RC and .H file
557 self
.spawn([self
.mc
] + ['-h', h_dir
, '-r', rc_dir
] + [src
])
558 base
, _
= os
.path
.splitext(os
.path
.basename(src
))
559 rc_file
= os
.path
.join(rc_dir
, base
+ '.rc')
560 # then compile .RC to .RES file
561 self
.spawn([self
.rc
] + ["/fo" + obj
] + [rc_file
])
563 except DistutilsExecError
as msg
:
564 raise CompileError(msg
)
567 # how to handle this file?
569 "Don't know how to compile {} to {}".format(src
, obj
)
572 output_opt
= "/Fo" + obj
578 + [input_opt
, output_opt
]
581 except DistutilsExecError
as msg
:
582 raise CompileError(msg
)
586 def create_static_lib(
587 self
, objects
, output_libname
, output_dir
=None, debug
=0, target_lang
=None
590 if not self
.initialized
:
592 (objects
, output_dir
) = self
._fix
_object
_args
(objects
, output_dir
)
593 output_filename
= self
.library_filename(output_libname
, output_dir
=output_dir
)
595 if self
._need
_link
(objects
, output_filename
):
596 lib_args
= objects
+ ['/OUT:' + output_filename
]
598 pass # XXX what goes here?
600 self
.spawn([self
.lib
] + lib_args
)
601 except DistutilsExecError
as msg
:
604 log
.debug("skipping %s (up-to-date)", output_filename
)
606 def link( # noqa: C901
614 runtime_library_dirs
=None,
623 if not self
.initialized
:
625 (objects
, output_dir
) = self
._fix
_object
_args
(objects
, output_dir
)
626 fixed_args
= self
._fix
_lib
_args
(libraries
, library_dirs
, runtime_library_dirs
)
627 (libraries
, library_dirs
, runtime_library_dirs
) = fixed_args
629 if runtime_library_dirs
:
631 "I don't know what to do with 'runtime_library_dirs': "
632 + str(runtime_library_dirs
)
635 lib_opts
= gen_lib_options(self
, library_dirs
, runtime_library_dirs
, libraries
)
636 if output_dir
is not None:
637 output_filename
= os
.path
.join(output_dir
, output_filename
)
639 if self
._need
_link
(objects
, output_filename
):
640 if target_desc
== CCompiler
.EXECUTABLE
:
642 ldflags
= self
.ldflags_shared_debug
[1:]
644 ldflags
= self
.ldflags_shared
[1:]
647 ldflags
= self
.ldflags_shared_debug
649 ldflags
= self
.ldflags_shared
652 for sym
in export_symbols
or []:
653 export_opts
.append("/EXPORT:" + sym
)
656 ldflags
+ lib_opts
+ export_opts
+ objects
+ ['/OUT:' + output_filename
]
659 # The MSVC linker generates .lib and .exp files, which cannot be
660 # suppressed by any linker switches. The .lib files may even be
661 # needed! Make sure they are generated in the temporary build
662 # directory. Since they have different names for debug and release
663 # builds, they can go into the same directory.
664 build_temp
= os
.path
.dirname(objects
[0])
665 if export_symbols
is not None:
666 (dll_name
, dll_ext
) = os
.path
.splitext(
667 os
.path
.basename(output_filename
)
669 implib_file
= os
.path
.join(build_temp
, self
.library_filename(dll_name
))
670 ld_args
.append('/IMPLIB:' + implib_file
)
672 self
.manifest_setup_ldargs(output_filename
, build_temp
, ld_args
)
675 ld_args
[:0] = extra_preargs
677 ld_args
.extend(extra_postargs
)
679 self
.mkpath(os
.path
.dirname(output_filename
))
681 self
.spawn([self
.linker
] + ld_args
)
682 except DistutilsExecError
as msg
:
686 # XXX - this is somewhat fragile - if mt.exe fails, distutils
687 # will still consider the DLL up-to-date, but it will not have a
688 # manifest. Maybe we should link to a temp file? OTOH, that
689 # implies a build environment error that shouldn't go undetected.
690 mfinfo
= self
.manifest_get_embed_info(target_desc
, ld_args
)
691 if mfinfo
is not None:
692 mffilename
, mfid
= mfinfo
693 out_arg
= '-outputresource:{};{}'.format(output_filename
, mfid
)
695 self
.spawn(['mt.exe', '-nologo', '-manifest', mffilename
, out_arg
])
696 except DistutilsExecError
as msg
:
699 log
.debug("skipping %s (up-to-date)", output_filename
)
701 def manifest_setup_ldargs(self
, output_filename
, build_temp
, ld_args
):
702 # If we need a manifest at all, an embedded manifest is recommended.
703 # See MSDN article titled
704 # "How to: Embed a Manifest Inside a C/C++ Application"
705 # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx)
706 # Ask the linker to generate the manifest in the temp dir, so
707 # we can check it, and possibly embed it, later.
708 temp_manifest
= os
.path
.join(
709 build_temp
, os
.path
.basename(output_filename
) + ".manifest"
711 ld_args
.append('/MANIFESTFILE:' + temp_manifest
)
713 def manifest_get_embed_info(self
, target_desc
, ld_args
):
714 # If a manifest should be embedded, return a tuple of
715 # (manifest_filename, resource_id). Returns None if no manifest
716 # should be embedded. See http://bugs.python.org/issue7833 for why
717 # we want to avoid any manifest for extension modules if we can)
719 if arg
.startswith("/MANIFESTFILE:"):
720 temp_manifest
= arg
.split(":", 1)[1]
723 # no /MANIFESTFILE so nothing to do.
725 if target_desc
== CCompiler
.EXECUTABLE
:
726 # by default, executables always get the manifest with the
730 # Extension modules try and avoid any manifest if possible.
732 temp_manifest
= self
._remove
_visual
_c
_ref
(temp_manifest
)
733 if temp_manifest
is None:
735 return temp_manifest
, mfid
737 def _remove_visual_c_ref(self
, manifest_file
):
739 # Remove references to the Visual C runtime, so they will
740 # fall through to the Visual C dependency of Python.exe.
741 # This way, when installed for a restricted user (e.g.
742 # runtimes are not in WinSxS folder, but in Python's own
743 # folder), the runtimes do not need to be in every folder
745 # Returns either the filename of the modified manifest or
746 # None if no manifest should be embedded.
747 manifest_f
= open(manifest_file
)
749 manifest_buf
= manifest_f
.read()
752 pattern
= re
.compile(
753 r
"""<assemblyIdentity.*?name=("|')Microsoft\."""
754 r
"""VC\d{2}\.CRT("|').*?(/>|</assemblyIdentity>)""",
757 manifest_buf
= re
.sub(pattern
, "", manifest_buf
)
758 pattern
= r
"<dependentAssembly>\s*</dependentAssembly>"
759 manifest_buf
= re
.sub(pattern
, "", manifest_buf
)
760 # Now see if any other assemblies are referenced - if not, we
761 # don't want a manifest embedded.
762 pattern
= re
.compile(
763 r
"""<assemblyIdentity.*?name=(?:"|')(.+?)(?:"|')"""
764 r
""".*?(?:/>|</assemblyIdentity>)""",
767 if re
.search(pattern
, manifest_buf
) is None:
770 manifest_f
= open(manifest_file
, 'w')
772 manifest_f
.write(manifest_buf
)
779 # -- Miscellaneous methods -----------------------------------------
780 # These are all used by the 'gen_lib_options() function, in
783 def library_dir_option(self
, dir):
784 return "/LIBPATH:" + dir
786 def runtime_library_dir_option(self
, dir):
787 raise DistutilsPlatformError(
788 "don't know how to set runtime library search path for MSVC++"
791 def library_option(self
, lib
):
792 return self
.library_filename(lib
)
794 def find_library_file(self
, dirs
, lib
, debug
=0):
795 # Prefer a debugging library if found (and requested), but deal
796 # with it if we don't have one.
798 try_names
= [lib
+ "_d", lib
]
802 for name
in try_names
:
803 libfile
= os
.path
.join(dir, self
.library_filename(name
))
804 if os
.path
.exists(libfile
):
807 # Oops, didn't find it in *any* of 'dirs'
810 # Helper methods for using the MSVC registry settings
812 def find_exe(self
, exe
):
813 """Return path to an MSVC executable program.
815 Tries to find the program in several places: first, one of the
816 MSVC program search paths from the registry; next, the directories
817 in the PATH environment variable. If any of those work, return an
818 absolute path that is known to exist. If none of them work, just
819 return the original program name, 'exe'.
821 for p
in self
.__paths
:
822 fn
= os
.path
.join(os
.path
.abspath(p
), exe
)
823 if os
.path
.isfile(fn
):
826 # didn't find it; try existing path
827 for p
in os
.environ
['Path'].split(';'):
828 fn
= os
.path
.join(os
.path
.abspath(p
), exe
)
829 if os
.path
.isfile(fn
):