move sections
[python/dscho.git] / Lib / distutils / msvc9compiler.py
blobd5d7f66528b930ae5d317227fb41573c1f63a5b8
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.
8 """
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
15 __revision__ = "$Id$"
17 import os
18 import subprocess
19 import sys
20 import re
22 from distutils.errors import (DistutilsExecError, DistutilsPlatformError,
23 CompileError, LibError, LinkError)
24 from distutils.ccompiler import CCompiler, gen_lib_options
25 from distutils import log
26 from distutils.util import get_platform
28 import _winreg
30 RegOpenKeyEx = _winreg.OpenKeyEx
31 RegEnumKey = _winreg.EnumKey
32 RegEnumValue = _winreg.EnumValue
33 RegError = _winreg.error
35 HKEYS = (_winreg.HKEY_USERS,
36 _winreg.HKEY_CURRENT_USER,
37 _winreg.HKEY_LOCAL_MACHINE,
38 _winreg.HKEY_CLASSES_ROOT)
40 NATIVE_WIN64 = (sys.platform == 'win32' and sys.maxsize > 2**32)
41 if NATIVE_WIN64:
42 # Visual C++ is a 32-bit application, so we need to look in
43 # the corresponding registry branch, if we're running a
44 # 64-bit Python on Win64
45 VS_BASE = r"Software\Wow6432Node\Microsoft\VisualStudio\%0.1f"
46 VSEXPRESS_BASE = r"Software\Wow6432Node\Microsoft\VCExpress\%0.1f"
47 WINSDK_BASE = r"Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows"
48 NET_BASE = r"Software\Wow6432Node\Microsoft\.NETFramework"
49 else:
50 VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f"
51 VSEXPRESS_BASE = r"Software\Microsoft\VCExpress\%0.1f"
52 WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows"
53 NET_BASE = r"Software\Microsoft\.NETFramework"
55 # A map keyed by get_platform() return values to values accepted by
56 # 'vcvarsall.bat'. Note a cross-compile may combine these (eg, 'x86_amd64' is
57 # the param to cross-compile on x86 targetting amd64.)
58 PLAT_TO_VCVARS = {
59 'win32' : 'x86',
60 'win-amd64' : 'amd64',
61 'win-ia64' : 'ia64',
64 class Reg:
65 """Helper class to read values from the registry
66 """
68 def get_value(cls, path, key):
69 for base in HKEYS:
70 d = cls.read_values(base, path)
71 if d and key in d:
72 return d[key]
73 raise KeyError(key)
74 get_value = classmethod(get_value)
76 def read_keys(cls, base, key):
77 """Return list of registry keys."""
78 try:
79 handle = RegOpenKeyEx(base, key)
80 except RegError:
81 return None
82 L = []
83 i = 0
84 while True:
85 try:
86 k = RegEnumKey(handle, i)
87 except RegError:
88 break
89 L.append(k)
90 i += 1
91 return L
92 read_keys = classmethod(read_keys)
94 def read_values(cls, base, key):
95 """Return dict of registry keys and values.
97 All names are converted to lowercase.
98 """
99 try:
100 handle = RegOpenKeyEx(base, key)
101 except RegError:
102 return None
103 d = {}
104 i = 0
105 while True:
106 try:
107 name, value, type = RegEnumValue(handle, i)
108 except RegError:
109 break
110 name = name.lower()
111 d[cls.convert_mbcs(name)] = cls.convert_mbcs(value)
112 i += 1
113 return d
114 read_values = classmethod(read_values)
116 def convert_mbcs(s):
117 dec = getattr(s, "decode", None)
118 if dec is not None:
119 try:
120 s = dec("mbcs")
121 except UnicodeError:
122 pass
123 return s
124 convert_mbcs = staticmethod(convert_mbcs)
126 class MacroExpander:
128 def __init__(self, version):
129 self.macros = {}
130 self.vsbase = VS_BASE % version
131 self.load_macros(version)
133 def set_macro(self, macro, path, key):
134 self.macros["$(%s)" % macro] = Reg.get_value(path, key)
136 def load_macros(self, version):
137 self.set_macro("VCInstallDir", self.vsbase + r"\Setup\VC", "productdir")
138 self.set_macro("VSInstallDir", self.vsbase + r"\Setup\VS", "productdir")
139 self.set_macro("FrameworkDir", NET_BASE, "installroot")
140 try:
141 if version >= 8.0:
142 self.set_macro("FrameworkSDKDir", NET_BASE,
143 "sdkinstallrootv2.0")
144 else:
145 raise KeyError("sdkinstallrootv2.0")
146 except KeyError:
147 raise DistutilsPlatformError(
148 """Python was built with Visual Studio 2008;
149 extensions must be built with a compiler than can generate compatible binaries.
150 Visual Studio 2008 was not found on this system. If you have Cygwin installed,
151 you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""")
153 if version >= 9.0:
154 self.set_macro("FrameworkVersion", self.vsbase, "clr version")
155 self.set_macro("WindowsSdkDir", WINSDK_BASE, "currentinstallfolder")
156 else:
157 p = r"Software\Microsoft\NET Framework Setup\Product"
158 for base in HKEYS:
159 try:
160 h = RegOpenKeyEx(base, p)
161 except RegError:
162 continue
163 key = RegEnumKey(h, 0)
164 d = Reg.get_value(base, r"%s\%s" % (p, key))
165 self.macros["$(FrameworkVersion)"] = d["version"]
167 def sub(self, s):
168 for k, v in self.macros.items():
169 s = s.replace(k, v)
170 return s
172 def get_build_version():
173 """Return the version of MSVC that was used to build Python.
175 For Python 2.3 and up, the version number is included in
176 sys.version. For earlier versions, assume the compiler is MSVC 6.
178 prefix = "MSC v."
179 i = sys.version.find(prefix)
180 if i == -1:
181 return 6
182 i = i + len(prefix)
183 s, rest = sys.version[i:].split(" ", 1)
184 majorVersion = int(s[:-2]) - 6
185 minorVersion = int(s[2:3]) / 10.0
186 # I don't think paths are affected by minor version in version 6
187 if majorVersion == 6:
188 minorVersion = 0
189 if majorVersion >= 6:
190 return majorVersion + minorVersion
191 # else we don't know what version of the compiler this is
192 return None
194 def normalize_and_reduce_paths(paths):
195 """Return a list of normalized paths with duplicates removed.
197 The current order of paths is maintained.
199 # Paths are normalized so things like: /a and /a/ aren't both preserved.
200 reduced_paths = []
201 for p in paths:
202 np = os.path.normpath(p)
203 # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set.
204 if np not in reduced_paths:
205 reduced_paths.append(np)
206 return reduced_paths
208 def removeDuplicates(variable):
209 """Remove duplicate values of an environment variable.
211 oldList = variable.split(os.pathsep)
212 newList = []
213 for i in oldList:
214 if i not in newList:
215 newList.append(i)
216 newVariable = os.pathsep.join(newList)
217 return newVariable
219 def find_vcvarsall(version):
220 """Find the vcvarsall.bat file
222 At first it tries to find the productdir of VS 2008 in the registry. If
223 that fails it falls back to the VS90COMNTOOLS env var.
225 vsbase = VS_BASE % version
226 try:
227 productdir = Reg.get_value(r"%s\Setup\VC" % vsbase,
228 "productdir")
229 except KeyError:
230 productdir = None
232 # trying Express edition
233 if productdir is None:
234 vsbase = VSEXPRESS_BASE % version
235 try:
236 productdir = Reg.get_value(r"%s\Setup\VC" % vsbase,
237 "productdir")
238 except KeyError:
239 productdir = None
240 log.debug("Unable to find productdir in registry")
242 if not productdir or not os.path.isdir(productdir):
243 toolskey = "VS%0.f0COMNTOOLS" % version
244 toolsdir = os.environ.get(toolskey, None)
246 if toolsdir and os.path.isdir(toolsdir):
247 productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC")
248 productdir = os.path.abspath(productdir)
249 if not os.path.isdir(productdir):
250 log.debug("%s is not a valid directory" % productdir)
251 return None
252 else:
253 log.debug("Env var %s is not set or invalid" % toolskey)
254 if not productdir:
255 log.debug("No productdir found")
256 return None
257 vcvarsall = os.path.join(productdir, "vcvarsall.bat")
258 if os.path.isfile(vcvarsall):
259 return vcvarsall
260 log.debug("Unable to find vcvarsall.bat")
261 return None
263 def query_vcvarsall(version, arch="x86"):
264 """Launch vcvarsall.bat and read the settings from its environment
266 vcvarsall = find_vcvarsall(version)
267 interesting = set(("include", "lib", "libpath", "path"))
268 result = {}
270 if vcvarsall is None:
271 raise DistutilsPlatformError("Unable to find vcvarsall.bat")
272 log.debug("Calling 'vcvarsall.bat %s' (version=%s)", arch, version)
273 popen = subprocess.Popen('"%s" %s & set' % (vcvarsall, arch),
274 stdout=subprocess.PIPE,
275 stderr=subprocess.PIPE)
277 stdout, stderr = popen.communicate()
278 if popen.wait() != 0:
279 raise DistutilsPlatformError(stderr.decode("mbcs"))
281 stdout = stdout.decode("mbcs")
282 for line in stdout.split("\n"):
283 line = Reg.convert_mbcs(line)
284 if '=' not in line:
285 continue
286 line = line.strip()
287 key, value = line.split('=', 1)
288 key = key.lower()
289 if key in interesting:
290 if value.endswith(os.pathsep):
291 value = value[:-1]
292 result[key] = removeDuplicates(value)
294 if len(result) != len(interesting):
295 raise ValueError(str(list(result.keys())))
297 return result
299 # More globals
300 VERSION = get_build_version()
301 if VERSION < 8.0:
302 raise DistutilsPlatformError("VC %0.1f is not supported by this module" % VERSION)
303 # MACROS = MacroExpander(VERSION)
305 class MSVCCompiler(CCompiler) :
306 """Concrete class that implements an interface to Microsoft Visual C++,
307 as defined by the CCompiler abstract class."""
309 compiler_type = 'msvc'
311 # Just set this so CCompiler's constructor doesn't barf. We currently
312 # don't use the 'set_executables()' bureaucracy provided by CCompiler,
313 # as it really isn't necessary for this sort of single-compiler class.
314 # Would be nice to have a consistent interface with UnixCCompiler,
315 # though, so it's worth thinking about.
316 executables = {}
318 # Private class data (need to distinguish C from C++ source for compiler)
319 _c_extensions = ['.c']
320 _cpp_extensions = ['.cc', '.cpp', '.cxx']
321 _rc_extensions = ['.rc']
322 _mc_extensions = ['.mc']
324 # Needed for the filename generation methods provided by the
325 # base class, CCompiler.
326 src_extensions = (_c_extensions + _cpp_extensions +
327 _rc_extensions + _mc_extensions)
328 res_extension = '.res'
329 obj_extension = '.obj'
330 static_lib_extension = '.lib'
331 shared_lib_extension = '.dll'
332 static_lib_format = shared_lib_format = '%s%s'
333 exe_extension = '.exe'
335 def __init__(self, verbose=0, dry_run=0, force=0):
336 CCompiler.__init__ (self, verbose, dry_run, force)
337 self.__version = VERSION
338 self.__root = r"Software\Microsoft\VisualStudio"
339 # self.__macros = MACROS
340 self.__paths = []
341 # target platform (.plat_name is consistent with 'bdist')
342 self.plat_name = None
343 self.__arch = None # deprecated name
344 self.initialized = False
346 def initialize(self, plat_name=None):
347 # multi-init means we would need to check platform same each time...
348 assert not self.initialized, "don't init multiple times"
349 if plat_name is None:
350 plat_name = get_platform()
351 # sanity check for platforms to prevent obscure errors later.
352 ok_plats = 'win32', 'win-amd64', 'win-ia64'
353 if plat_name not in ok_plats:
354 raise DistutilsPlatformError("--plat-name must be one of %s" %
355 (ok_plats,))
357 if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"):
358 # Assume that the SDK set up everything alright; don't try to be
359 # smarter
360 self.cc = "cl.exe"
361 self.linker = "link.exe"
362 self.lib = "lib.exe"
363 self.rc = "rc.exe"
364 self.mc = "mc.exe"
365 else:
366 # On x86, 'vcvars32.bat amd64' creates an env that doesn't work;
367 # to cross compile, you use 'x86_amd64'.
368 # On AMD64, 'vcvars32.bat amd64' is a native build env; to cross
369 # compile use 'x86' (ie, it runs the x86 compiler directly)
370 # No idea how itanium handles this, if at all.
371 if plat_name == get_platform() or plat_name == 'win32':
372 # native build or cross-compile to win32
373 plat_spec = PLAT_TO_VCVARS[plat_name]
374 else:
375 # cross compile from win32 -> some 64bit
376 plat_spec = PLAT_TO_VCVARS[get_platform()] + '_' + \
377 PLAT_TO_VCVARS[plat_name]
379 vc_env = query_vcvarsall(VERSION, plat_spec)
381 # take care to only use strings in the environment.
382 self.__paths = vc_env['path'].encode('mbcs').split(os.pathsep)
383 os.environ['lib'] = vc_env['lib'].encode('mbcs')
384 os.environ['include'] = vc_env['include'].encode('mbcs')
386 if len(self.__paths) == 0:
387 raise DistutilsPlatformError("Python was built with %s, "
388 "and extensions need to be built with the same "
389 "version of the compiler, but it isn't installed."
390 % self.__product)
392 self.cc = self.find_exe("cl.exe")
393 self.linker = self.find_exe("link.exe")
394 self.lib = self.find_exe("lib.exe")
395 self.rc = self.find_exe("rc.exe") # resource compiler
396 self.mc = self.find_exe("mc.exe") # message compiler
397 #self.set_path_env_var('lib')
398 #self.set_path_env_var('include')
400 # extend the MSVC path with the current path
401 try:
402 for p in os.environ['path'].split(';'):
403 self.__paths.append(p)
404 except KeyError:
405 pass
406 self.__paths = normalize_and_reduce_paths(self.__paths)
407 os.environ['path'] = ";".join(self.__paths)
409 self.preprocess_options = None
410 if self.__arch == "x86":
411 self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3',
412 '/DNDEBUG']
413 self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3',
414 '/Z7', '/D_DEBUG']
415 else:
416 # Win64
417 self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GS-' ,
418 '/DNDEBUG']
419 self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-',
420 '/Z7', '/D_DEBUG']
422 self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO']
423 if self.__version >= 7:
424 self.ldflags_shared_debug = [
425 '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG', '/pdb:None'
427 self.ldflags_static = [ '/nologo']
429 self.initialized = True
431 # -- Worker methods ------------------------------------------------
433 def object_filenames(self,
434 source_filenames,
435 strip_dir=0,
436 output_dir=''):
437 # Copied from ccompiler.py, extended to return .res as 'object'-file
438 # for .rc input file
439 if output_dir is None: output_dir = ''
440 obj_names = []
441 for src_name in source_filenames:
442 (base, ext) = os.path.splitext (src_name)
443 base = os.path.splitdrive(base)[1] # Chop off the drive
444 base = base[os.path.isabs(base):] # If abs, chop off leading /
445 if ext not in self.src_extensions:
446 # Better to raise an exception instead of silently continuing
447 # and later complain about sources and targets having
448 # different lengths
449 raise CompileError ("Don't know how to compile %s" % src_name)
450 if strip_dir:
451 base = os.path.basename (base)
452 if ext in self._rc_extensions:
453 obj_names.append (os.path.join (output_dir,
454 base + self.res_extension))
455 elif ext in self._mc_extensions:
456 obj_names.append (os.path.join (output_dir,
457 base + self.res_extension))
458 else:
459 obj_names.append (os.path.join (output_dir,
460 base + self.obj_extension))
461 return obj_names
464 def compile(self, sources,
465 output_dir=None, macros=None, include_dirs=None, debug=0,
466 extra_preargs=None, extra_postargs=None, depends=None):
468 if not self.initialized:
469 self.initialize()
470 compile_info = self._setup_compile(output_dir, macros, include_dirs,
471 sources, depends, extra_postargs)
472 macros, objects, extra_postargs, pp_opts, build = compile_info
474 compile_opts = extra_preargs or []
475 compile_opts.append ('/c')
476 if debug:
477 compile_opts.extend(self.compile_options_debug)
478 else:
479 compile_opts.extend(self.compile_options)
481 for obj in objects:
482 try:
483 src, ext = build[obj]
484 except KeyError:
485 continue
486 if debug:
487 # pass the full pathname to MSVC in debug mode,
488 # this allows the debugger to find the source file
489 # without asking the user to browse for it
490 src = os.path.abspath(src)
492 if ext in self._c_extensions:
493 input_opt = "/Tc" + src
494 elif ext in self._cpp_extensions:
495 input_opt = "/Tp" + src
496 elif ext in self._rc_extensions:
497 # compile .RC to .RES file
498 input_opt = src
499 output_opt = "/fo" + obj
500 try:
501 self.spawn([self.rc] + pp_opts +
502 [output_opt] + [input_opt])
503 except DistutilsExecError, msg:
504 raise CompileError(msg)
505 continue
506 elif ext in self._mc_extensions:
507 # Compile .MC to .RC file to .RES file.
508 # * '-h dir' specifies the directory for the
509 # generated include file
510 # * '-r dir' specifies the target directory of the
511 # generated RC file and the binary message resource
512 # it includes
514 # For now (since there are no options to change this),
515 # we use the source-directory for the include file and
516 # the build directory for the RC file and message
517 # resources. This works at least for win32all.
518 h_dir = os.path.dirname(src)
519 rc_dir = os.path.dirname(obj)
520 try:
521 # first compile .MC to .RC and .H file
522 self.spawn([self.mc] +
523 ['-h', h_dir, '-r', rc_dir] + [src])
524 base, _ = os.path.splitext (os.path.basename (src))
525 rc_file = os.path.join (rc_dir, base + '.rc')
526 # then compile .RC to .RES file
527 self.spawn([self.rc] +
528 ["/fo" + obj] + [rc_file])
530 except DistutilsExecError, msg:
531 raise CompileError(msg)
532 continue
533 else:
534 # how to handle this file?
535 raise CompileError("Don't know how to compile %s to %s"
536 % (src, obj))
538 output_opt = "/Fo" + obj
539 try:
540 self.spawn([self.cc] + compile_opts + pp_opts +
541 [input_opt, output_opt] +
542 extra_postargs)
543 except DistutilsExecError, msg:
544 raise CompileError(msg)
546 return objects
549 def create_static_lib(self,
550 objects,
551 output_libname,
552 output_dir=None,
553 debug=0,
554 target_lang=None):
556 if not self.initialized:
557 self.initialize()
558 (objects, output_dir) = self._fix_object_args(objects, output_dir)
559 output_filename = self.library_filename(output_libname,
560 output_dir=output_dir)
562 if self._need_link(objects, output_filename):
563 lib_args = objects + ['/OUT:' + output_filename]
564 if debug:
565 pass # XXX what goes here?
566 try:
567 self.spawn([self.lib] + lib_args)
568 except DistutilsExecError, msg:
569 raise LibError(msg)
570 else:
571 log.debug("skipping %s (up-to-date)", output_filename)
574 def link(self,
575 target_desc,
576 objects,
577 output_filename,
578 output_dir=None,
579 libraries=None,
580 library_dirs=None,
581 runtime_library_dirs=None,
582 export_symbols=None,
583 debug=0,
584 extra_preargs=None,
585 extra_postargs=None,
586 build_temp=None,
587 target_lang=None):
589 if not self.initialized:
590 self.initialize()
591 (objects, output_dir) = self._fix_object_args(objects, output_dir)
592 fixed_args = self._fix_lib_args(libraries, library_dirs,
593 runtime_library_dirs)
594 (libraries, library_dirs, runtime_library_dirs) = fixed_args
596 if runtime_library_dirs:
597 self.warn ("I don't know what to do with 'runtime_library_dirs': "
598 + str (runtime_library_dirs))
600 lib_opts = gen_lib_options(self,
601 library_dirs, runtime_library_dirs,
602 libraries)
603 if output_dir is not None:
604 output_filename = os.path.join(output_dir, output_filename)
606 if self._need_link(objects, output_filename):
607 if target_desc == CCompiler.EXECUTABLE:
608 if debug:
609 ldflags = self.ldflags_shared_debug[1:]
610 else:
611 ldflags = self.ldflags_shared[1:]
612 else:
613 if debug:
614 ldflags = self.ldflags_shared_debug
615 else:
616 ldflags = self.ldflags_shared
618 export_opts = []
619 for sym in (export_symbols or []):
620 export_opts.append("/EXPORT:" + sym)
622 ld_args = (ldflags + lib_opts + export_opts +
623 objects + ['/OUT:' + output_filename])
625 # The MSVC linker generates .lib and .exp files, which cannot be
626 # suppressed by any linker switches. The .lib files may even be
627 # needed! Make sure they are generated in the temporary build
628 # directory. Since they have different names for debug and release
629 # builds, they can go into the same directory.
630 build_temp = os.path.dirname(objects[0])
631 if export_symbols is not None:
632 (dll_name, dll_ext) = os.path.splitext(
633 os.path.basename(output_filename))
634 implib_file = os.path.join(
635 build_temp,
636 self.library_filename(dll_name))
637 ld_args.append ('/IMPLIB:' + implib_file)
639 # Embedded manifests are recommended - see MSDN article titled
640 # "How to: Embed a Manifest Inside a C/C++ Application"
641 # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx)
642 # Ask the linker to generate the manifest in the temp dir, so
643 # we can embed it later.
644 temp_manifest = os.path.join(
645 build_temp,
646 os.path.basename(output_filename) + ".manifest")
647 ld_args.append('/MANIFESTFILE:' + temp_manifest)
649 if extra_preargs:
650 ld_args[:0] = extra_preargs
651 if extra_postargs:
652 ld_args.extend(extra_postargs)
654 self.mkpath(os.path.dirname(output_filename))
655 try:
656 self.spawn([self.linker] + ld_args)
657 except DistutilsExecError, msg:
658 raise LinkError(msg)
660 # embed the manifest
661 # XXX - this is somewhat fragile - if mt.exe fails, distutils
662 # will still consider the DLL up-to-date, but it will not have a
663 # manifest. Maybe we should link to a temp file? OTOH, that
664 # implies a build environment error that shouldn't go undetected.
665 if target_desc == CCompiler.EXECUTABLE:
666 mfid = 1
667 else:
668 mfid = 2
669 self._remove_visual_c_ref(temp_manifest)
670 out_arg = '-outputresource:%s;%s' % (output_filename, mfid)
671 try:
672 self.spawn(['mt.exe', '-nologo', '-manifest',
673 temp_manifest, out_arg])
674 except DistutilsExecError, msg:
675 raise LinkError(msg)
676 else:
677 log.debug("skipping %s (up-to-date)", output_filename)
679 def _remove_visual_c_ref(self, manifest_file):
680 try:
681 # Remove references to the Visual C runtime, so they will
682 # fall through to the Visual C dependency of Python.exe.
683 # This way, when installed for a restricted user (e.g.
684 # runtimes are not in WinSxS folder, but in Python's own
685 # folder), the runtimes do not need to be in every folder
686 # with .pyd's.
687 manifest_f = open(manifest_file)
688 try:
689 manifest_buf = manifest_f.read()
690 finally:
691 manifest_f.close()
692 pattern = re.compile(
693 r"""<assemblyIdentity.*?name=("|')Microsoft\."""\
694 r"""VC\d{2}\.CRT("|').*?(/>|</assemblyIdentity>)""",
695 re.DOTALL)
696 manifest_buf = re.sub(pattern, "", manifest_buf)
697 pattern = "<dependentAssembly>\s*</dependentAssembly>"
698 manifest_buf = re.sub(pattern, "", manifest_buf)
699 manifest_f = open(manifest_file, 'w')
700 try:
701 manifest_f.write(manifest_buf)
702 finally:
703 manifest_f.close()
704 except IOError:
705 pass
707 # -- Miscellaneous methods -----------------------------------------
708 # These are all used by the 'gen_lib_options() function, in
709 # ccompiler.py.
711 def library_dir_option(self, dir):
712 return "/LIBPATH:" + dir
714 def runtime_library_dir_option(self, dir):
715 raise DistutilsPlatformError(
716 "don't know how to set runtime library search path for MSVC++")
718 def library_option(self, lib):
719 return self.library_filename(lib)
722 def find_library_file(self, dirs, lib, debug=0):
723 # Prefer a debugging library if found (and requested), but deal
724 # with it if we don't have one.
725 if debug:
726 try_names = [lib + "_d", lib]
727 else:
728 try_names = [lib]
729 for dir in dirs:
730 for name in try_names:
731 libfile = os.path.join(dir, self.library_filename (name))
732 if os.path.exists(libfile):
733 return libfile
734 else:
735 # Oops, didn't find it in *any* of 'dirs'
736 return None
738 # Helper methods for using the MSVC registry settings
740 def find_exe(self, exe):
741 """Return path to an MSVC executable program.
743 Tries to find the program in several places: first, one of the
744 MSVC program search paths from the registry; next, the directories
745 in the PATH environment variable. If any of those work, return an
746 absolute path that is known to exist. If none of them work, just
747 return the original program name, 'exe'.
749 for p in self.__paths:
750 fn = os.path.join(os.path.abspath(p), exe)
751 if os.path.isfile(fn):
752 return fn
754 # didn't find it; try existing path
755 for p in os.environ['Path'].split(';'):
756 fn = os.path.join(os.path.abspath(p),exe)
757 if os.path.isfile(fn):
758 return fn
760 return exe