]> crepu.dev Git - config.git/blame - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/setuptools/_distutils/msvc9compiler.py
Actualizado el Readme
[config.git] / djavu-asus / elpy / rpc-venv / lib / python3.11 / site-packages / setuptools / _distutils / msvc9compiler.py
CommitLineData
53e6db90
DC
1"""distutils.msvc9compiler
2
3Contains MSVCCompiler, an implementation of the abstract CCompiler class
4for the Microsoft Visual Studio 2008.
5
6The module is compatible with VS 2005 and VS 2008. You can find legacy support
7for older versions of VS in distutils.msvccompiler.
8"""
9
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
14
15import os
16import subprocess
17import sys
18import re
19import warnings
20
21from .errors import (
22 DistutilsExecError,
23 DistutilsPlatformError,
24 CompileError,
25 LibError,
26 LinkError,
27)
28from .ccompiler import CCompiler, gen_lib_options
29from ._log import log
30from .util import get_platform
31
32import winreg
33
34warnings.warn(
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.",
38 DeprecationWarning,
39)
40
41RegOpenKeyEx = winreg.OpenKeyEx
42RegEnumKey = winreg.EnumKey
43RegEnumValue = winreg.EnumValue
44RegError = winreg.error
45
46HKEYS = (
47 winreg.HKEY_USERS,
48 winreg.HKEY_CURRENT_USER,
49 winreg.HKEY_LOCAL_MACHINE,
50 winreg.HKEY_CLASSES_ROOT,
51)
52
53NATIVE_WIN64 = sys.platform == 'win32' and sys.maxsize > 2**32
54if NATIVE_WIN64:
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"
61else:
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"
65
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.)
69PLAT_TO_VCVARS = {
70 'win32': 'x86',
71 'win-amd64': 'amd64',
72}
73
74
75class Reg:
76 """Helper class to read values from the registry"""
77
78 def get_value(cls, path, key):
79 for base in HKEYS:
80 d = cls.read_values(base, path)
81 if d and key in d:
82 return d[key]
83 raise KeyError(key)
84
85 get_value = classmethod(get_value)
86
87 def read_keys(cls, base, key):
88 """Return list of registry keys."""
89 try:
90 handle = RegOpenKeyEx(base, key)
91 except RegError:
92 return None
93 L = []
94 i = 0
95 while True:
96 try:
97 k = RegEnumKey(handle, i)
98 except RegError:
99 break
100 L.append(k)
101 i += 1
102 return L
103
104 read_keys = classmethod(read_keys)
105
106 def read_values(cls, base, key):
107 """Return dict of registry keys and values.
108
109 All names are converted to lowercase.
110 """
111 try:
112 handle = RegOpenKeyEx(base, key)
113 except RegError:
114 return None
115 d = {}
116 i = 0
117 while True:
118 try:
119 name, value, type = RegEnumValue(handle, i)
120 except RegError:
121 break
122 name = name.lower()
123 d[cls.convert_mbcs(name)] = cls.convert_mbcs(value)
124 i += 1
125 return d
126
127 read_values = classmethod(read_values)
128
129 def convert_mbcs(s):
130 dec = getattr(s, "decode", None)
131 if dec is not None:
132 try:
133 s = dec("mbcs")
134 except UnicodeError:
135 pass
136 return s
137
138 convert_mbcs = staticmethod(convert_mbcs)
139
140
141class MacroExpander:
142 def __init__(self, version):
143 self.macros = {}
144 self.vsbase = VS_BASE % version
145 self.load_macros(version)
146
147 def set_macro(self, macro, path, key):
148 self.macros["$(%s)" % macro] = Reg.get_value(path, key)
149
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")
154 try:
155 if version >= 8.0:
156 self.set_macro("FrameworkSDKDir", NET_BASE, "sdkinstallrootv2.0")
157 else:
158 raise KeyError("sdkinstallrootv2.0")
159 except KeyError:
160 raise DistutilsPlatformError(
161 """Python was built with Visual Studio 2008;
162extensions must be built with a compiler than can generate compatible binaries.
163Visual Studio 2008 was not found on this system. If you have Cygwin installed,
164you can try compiling with MingW32, by passing "-c mingw32" to setup.py."""
165 )
166
167 if version >= 9.0:
168 self.set_macro("FrameworkVersion", self.vsbase, "clr version")
169 self.set_macro("WindowsSdkDir", WINSDK_BASE, "currentinstallfolder")
170 else:
171 p = r"Software\Microsoft\NET Framework Setup\Product"
172 for base in HKEYS:
173 try:
174 h = RegOpenKeyEx(base, p)
175 except RegError:
176 continue
177 key = RegEnumKey(h, 0)
178 d = Reg.get_value(base, r"{}\{}".format(p, key))
179 self.macros["$(FrameworkVersion)"] = d["version"]
180
181 def sub(self, s):
182 for k, v in self.macros.items():
183 s = s.replace(k, v)
184 return s
185
186
187def get_build_version():
188 """Return the version of MSVC that was used to build Python.
189
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.
192 """
193 prefix = "MSC v."
194 i = sys.version.find(prefix)
195 if i == -1:
196 return 6
197 i = i + len(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
202 majorVersion += 1
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:
206 minorVersion = 0
207 if majorVersion >= 6:
208 return majorVersion + minorVersion
209 # else we don't know what version of the compiler this is
210 return None
211
212
213def normalize_and_reduce_paths(paths):
214 """Return a list of normalized paths with duplicates removed.
215
216 The current order of paths is maintained.
217 """
218 # Paths are normalized so things like: /a and /a/ aren't both preserved.
219 reduced_paths = []
220 for p in paths:
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)
225 return reduced_paths
226
227
228def removeDuplicates(variable):
229 """Remove duplicate values of an environment variable."""
230 oldList = variable.split(os.pathsep)
231 newList = []
232 for i in oldList:
233 if i not in newList:
234 newList.append(i)
235 newVariable = os.pathsep.join(newList)
236 return newVariable
237
238
239def find_vcvarsall(version):
240 """Find the vcvarsall.bat file
241
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.
244 """
245 vsbase = VS_BASE % version
246 try:
247 productdir = Reg.get_value(r"%s\Setup\VC" % vsbase, "productdir")
248 except KeyError:
249 log.debug("Unable to find productdir in registry")
250 productdir = None
251
252 if not productdir or not os.path.isdir(productdir):
253 toolskey = "VS%0.f0COMNTOOLS" % version
254 toolsdir = os.environ.get(toolskey, None)
255
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)
261 return None
262 else:
263 log.debug("Env var %s is not set or invalid" % toolskey)
264 if not productdir:
265 log.debug("No productdir found")
266 return None
267 vcvarsall = os.path.join(productdir, "vcvarsall.bat")
268 if os.path.isfile(vcvarsall):
269 return vcvarsall
270 log.debug("Unable to find vcvarsall.bat")
271 return None
272
273
274def 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"}
278 result = {}
279
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,
287 )
288 try:
289 stdout, stderr = popen.communicate()
290 if popen.wait() != 0:
291 raise DistutilsPlatformError(stderr.decode("mbcs"))
292
293 stdout = stdout.decode("mbcs")
294 for line in stdout.split("\n"):
295 line = Reg.convert_mbcs(line)
296 if '=' not in line:
297 continue
298 line = line.strip()
299 key, value = line.split('=', 1)
300 key = key.lower()
301 if key in interesting:
302 if value.endswith(os.pathsep):
303 value = value[:-1]
304 result[key] = removeDuplicates(value)
305
306 finally:
307 popen.stdout.close()
308 popen.stderr.close()
309
310 if len(result) != len(interesting):
311 raise ValueError(str(list(result.keys())))
312
313 return result
314
315
316# More globals
317VERSION = get_build_version()
318# MACROS = MacroExpander(VERSION)
319
320
321class MSVCCompiler(CCompiler):
322 """Concrete class that implements an interface to Microsoft Visual C++,
323 as defined by the CCompiler abstract class."""
324
325 compiler_type = 'msvc'
326
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.
332 executables = {}
333
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']
339
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'
349
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
355 self.__paths = []
356 # target platform (.plat_name is consistent with 'bdist')
357 self.plat_name = None
358 self.__arch = None # deprecated name
359 self.initialized = False
360
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
367 )
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)
375 )
376
377 if (
378 "DISTUTILS_USE_SDK" in os.environ
379 and "MSSdk" in os.environ
380 and self.find_exe("cl.exe")
381 ):
382 # Assume that the SDK set up everything alright; don't try to be
383 # smarter
384 self.cc = "cl.exe"
385 self.linker = "link.exe"
386 self.lib = "lib.exe"
387 self.rc = "rc.exe"
388 self.mc = "mc.exe"
389 else:
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]
397 else:
398 # cross compile from win32 -> some 64bit
399 plat_spec = (
400 PLAT_TO_VCVARS[get_platform()] + '_' + PLAT_TO_VCVARS[plat_name]
401 )
402
403 vc_env = query_vcvarsall(VERSION, plat_spec)
404
405 self.__paths = vc_env['path'].split(os.pathsep)
406 os.environ['lib'] = vc_env['lib']
407 os.environ['include'] = vc_env['include']
408
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
414 )
415
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')
423
424 # extend the MSVC path with the current path
425 try:
426 for p in os.environ['path'].split(';'):
427 self.__paths.append(p)
428 except KeyError:
429 pass
430 self.__paths = normalize_and_reduce_paths(self.__paths)
431 os.environ['path'] = ";".join(self.__paths)
432
433 self.preprocess_options = None
434 if self.__arch == "x86":
435 self.compile_options = ['/nologo', '/O2', '/MD', '/W3', '/DNDEBUG']
436 self.compile_options_debug = [
437 '/nologo',
438 '/Od',
439 '/MDd',
440 '/W3',
441 '/Z7',
442 '/D_DEBUG',
443 ]
444 else:
445 # Win64
446 self.compile_options = ['/nologo', '/O2', '/MD', '/W3', '/GS-', '/DNDEBUG']
447 self.compile_options_debug = [
448 '/nologo',
449 '/Od',
450 '/MDd',
451 '/W3',
452 '/GS-',
453 '/Z7',
454 '/D_DEBUG',
455 ]
456
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']
461
462 self.initialized = True
463
464 # -- Worker methods ------------------------------------------------
465
466 def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
467 # Copied from ccompiler.py, extended to return .res as 'object'-file
468 # for .rc input file
469 if output_dir is None:
470 output_dir = ''
471 obj_names = []
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
479 # different lengths
480 raise CompileError("Don't know how to compile %s" % src_name)
481 if strip_dir:
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))
487 else:
488 obj_names.append(os.path.join(output_dir, base + self.obj_extension))
489 return obj_names
490
491 def compile( # noqa: C901
492 self,
493 sources,
494 output_dir=None,
495 macros=None,
496 include_dirs=None,
497 debug=0,
498 extra_preargs=None,
499 extra_postargs=None,
500 depends=None,
501 ):
502
503 if not self.initialized:
504 self.initialize()
505 compile_info = self._setup_compile(
506 output_dir, macros, include_dirs, sources, depends, extra_postargs
507 )
508 macros, objects, extra_postargs, pp_opts, build = compile_info
509
510 compile_opts = extra_preargs or []
511 compile_opts.append('/c')
512 if debug:
513 compile_opts.extend(self.compile_options_debug)
514 else:
515 compile_opts.extend(self.compile_options)
516
517 for obj in objects:
518 try:
519 src, ext = build[obj]
520 except KeyError:
521 continue
522 if debug:
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)
527
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
534 input_opt = src
535 output_opt = "/fo" + obj
536 try:
537 self.spawn([self.rc] + pp_opts + [output_opt] + [input_opt])
538 except DistutilsExecError as msg:
539 raise CompileError(msg)
540 continue
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
547 # it includes
548 #
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)
555 try:
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])
562
563 except DistutilsExecError as msg:
564 raise CompileError(msg)
565 continue
566 else:
567 # how to handle this file?
568 raise CompileError(
569 "Don't know how to compile {} to {}".format(src, obj)
570 )
571
572 output_opt = "/Fo" + obj
573 try:
574 self.spawn(
575 [self.cc]
576 + compile_opts
577 + pp_opts
578 + [input_opt, output_opt]
579 + extra_postargs
580 )
581 except DistutilsExecError as msg:
582 raise CompileError(msg)
583
584 return objects
585
586 def create_static_lib(
587 self, objects, output_libname, output_dir=None, debug=0, target_lang=None
588 ):
589
590 if not self.initialized:
591 self.initialize()
592 (objects, output_dir) = self._fix_object_args(objects, output_dir)
593 output_filename = self.library_filename(output_libname, output_dir=output_dir)
594
595 if self._need_link(objects, output_filename):
596 lib_args = objects + ['/OUT:' + output_filename]
597 if debug:
598 pass # XXX what goes here?
599 try:
600 self.spawn([self.lib] + lib_args)
601 except DistutilsExecError as msg:
602 raise LibError(msg)
603 else:
604 log.debug("skipping %s (up-to-date)", output_filename)
605
606 def link( # noqa: C901
607 self,
608 target_desc,
609 objects,
610 output_filename,
611 output_dir=None,
612 libraries=None,
613 library_dirs=None,
614 runtime_library_dirs=None,
615 export_symbols=None,
616 debug=0,
617 extra_preargs=None,
618 extra_postargs=None,
619 build_temp=None,
620 target_lang=None,
621 ):
622
623 if not self.initialized:
624 self.initialize()
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
628
629 if runtime_library_dirs:
630 self.warn(
631 "I don't know what to do with 'runtime_library_dirs': "
632 + str(runtime_library_dirs)
633 )
634
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)
638
639 if self._need_link(objects, output_filename):
640 if target_desc == CCompiler.EXECUTABLE:
641 if debug:
642 ldflags = self.ldflags_shared_debug[1:]
643 else:
644 ldflags = self.ldflags_shared[1:]
645 else:
646 if debug:
647 ldflags = self.ldflags_shared_debug
648 else:
649 ldflags = self.ldflags_shared
650
651 export_opts = []
652 for sym in export_symbols or []:
653 export_opts.append("/EXPORT:" + sym)
654
655 ld_args = (
656 ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename]
657 )
658
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)
668 )
669 implib_file = os.path.join(build_temp, self.library_filename(dll_name))
670 ld_args.append('/IMPLIB:' + implib_file)
671
672 self.manifest_setup_ldargs(output_filename, build_temp, ld_args)
673
674 if extra_preargs:
675 ld_args[:0] = extra_preargs
676 if extra_postargs:
677 ld_args.extend(extra_postargs)
678
679 self.mkpath(os.path.dirname(output_filename))
680 try:
681 self.spawn([self.linker] + ld_args)
682 except DistutilsExecError as msg:
683 raise LinkError(msg)
684
685 # embed the manifest
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)
694 try:
695 self.spawn(['mt.exe', '-nologo', '-manifest', mffilename, out_arg])
696 except DistutilsExecError as msg:
697 raise LinkError(msg)
698 else:
699 log.debug("skipping %s (up-to-date)", output_filename)
700
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"
710 )
711 ld_args.append('/MANIFESTFILE:' + temp_manifest)
712
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)
718 for arg in ld_args:
719 if arg.startswith("/MANIFESTFILE:"):
720 temp_manifest = arg.split(":", 1)[1]
721 break
722 else:
723 # no /MANIFESTFILE so nothing to do.
724 return None
725 if target_desc == CCompiler.EXECUTABLE:
726 # by default, executables always get the manifest with the
727 # CRT referenced.
728 mfid = 1
729 else:
730 # Extension modules try and avoid any manifest if possible.
731 mfid = 2
732 temp_manifest = self._remove_visual_c_ref(temp_manifest)
733 if temp_manifest is None:
734 return None
735 return temp_manifest, mfid
736
737 def _remove_visual_c_ref(self, manifest_file):
738 try:
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
744 # with .pyd's.
745 # Returns either the filename of the modified manifest or
746 # None if no manifest should be embedded.
747 manifest_f = open(manifest_file)
748 try:
749 manifest_buf = manifest_f.read()
750 finally:
751 manifest_f.close()
752 pattern = re.compile(
753 r"""<assemblyIdentity.*?name=("|')Microsoft\."""
754 r"""VC\d{2}\.CRT("|').*?(/>|</assemblyIdentity>)""",
755 re.DOTALL,
756 )
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>)""",
765 re.DOTALL,
766 )
767 if re.search(pattern, manifest_buf) is None:
768 return None
769
770 manifest_f = open(manifest_file, 'w')
771 try:
772 manifest_f.write(manifest_buf)
773 return manifest_file
774 finally:
775 manifest_f.close()
776 except OSError:
777 pass
778
779 # -- Miscellaneous methods -----------------------------------------
780 # These are all used by the 'gen_lib_options() function, in
781 # ccompiler.py.
782
783 def library_dir_option(self, dir):
784 return "/LIBPATH:" + dir
785
786 def runtime_library_dir_option(self, dir):
787 raise DistutilsPlatformError(
788 "don't know how to set runtime library search path for MSVC++"
789 )
790
791 def library_option(self, lib):
792 return self.library_filename(lib)
793
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.
797 if debug:
798 try_names = [lib + "_d", lib]
799 else:
800 try_names = [lib]
801 for dir in dirs:
802 for name in try_names:
803 libfile = os.path.join(dir, self.library_filename(name))
804 if os.path.exists(libfile):
805 return libfile
806 else:
807 # Oops, didn't find it in *any* of 'dirs'
808 return None
809
810 # Helper methods for using the MSVC registry settings
811
812 def find_exe(self, exe):
813 """Return path to an MSVC executable program.
814
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'.
820 """
821 for p in self.__paths:
822 fn = os.path.join(os.path.abspath(p), exe)
823 if os.path.isfile(fn):
824 return fn
825
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):
830 return fn
831
832 return exe