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