Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wiseplat
GitHub Repository: wiseplat/python-code
Path: blob/master/ invest-robot-contest_TinkoffBotTwitch-main/venv/lib/python3.8/site-packages/numpy/distutils/mingw32ccompiler.py
7763 views
1
"""
2
Support code for building Python extensions on Windows.
3
4
# NT stuff
5
# 1. Make sure libpython<version>.a exists for gcc. If not, build it.
6
# 2. Force windows to use gcc (we're struggling with MSVC and g77 support)
7
# 3. Force windows to use g77
8
9
"""
10
import os
11
import platform
12
import sys
13
import subprocess
14
import re
15
import textwrap
16
17
# Overwrite certain distutils.ccompiler functions:
18
import numpy.distutils.ccompiler # noqa: F401
19
from numpy.distutils import log
20
# NT stuff
21
# 1. Make sure libpython<version>.a exists for gcc. If not, build it.
22
# 2. Force windows to use gcc (we're struggling with MSVC and g77 support)
23
# --> this is done in numpy/distutils/ccompiler.py
24
# 3. Force windows to use g77
25
26
import distutils.cygwinccompiler
27
from distutils.unixccompiler import UnixCCompiler
28
from distutils.msvccompiler import get_build_version as get_build_msvc_version
29
from distutils.errors import UnknownFileError
30
from numpy.distutils.misc_util import (msvc_runtime_library,
31
msvc_runtime_version,
32
msvc_runtime_major,
33
get_build_architecture)
34
35
def get_msvcr_replacement():
36
"""Replacement for outdated version of get_msvcr from cygwinccompiler"""
37
msvcr = msvc_runtime_library()
38
return [] if msvcr is None else [msvcr]
39
40
# monkey-patch cygwinccompiler with our updated version from misc_util
41
# to avoid getting an exception raised on Python 3.5
42
distutils.cygwinccompiler.get_msvcr = get_msvcr_replacement
43
44
# Useful to generate table of symbols from a dll
45
_START = re.compile(r'\[Ordinal/Name Pointer\] Table')
46
_TABLE = re.compile(r'^\s+\[([\s*[0-9]*)\] ([a-zA-Z0-9_]*)')
47
48
# the same as cygwin plus some additional parameters
49
class Mingw32CCompiler(distutils.cygwinccompiler.CygwinCCompiler):
50
""" A modified MingW32 compiler compatible with an MSVC built Python.
51
52
"""
53
54
compiler_type = 'mingw32'
55
56
def __init__ (self,
57
verbose=0,
58
dry_run=0,
59
force=0):
60
61
distutils.cygwinccompiler.CygwinCCompiler.__init__ (self, verbose,
62
dry_run, force)
63
64
# **changes: eric jones 4/11/01
65
# 1. Check for import library on Windows. Build if it doesn't exist.
66
67
build_import_library()
68
69
# Check for custom msvc runtime library on Windows. Build if it doesn't exist.
70
msvcr_success = build_msvcr_library()
71
msvcr_dbg_success = build_msvcr_library(debug=True)
72
if msvcr_success or msvcr_dbg_success:
73
# add preprocessor statement for using customized msvcr lib
74
self.define_macro('NPY_MINGW_USE_CUSTOM_MSVCR')
75
76
# Define the MSVC version as hint for MinGW
77
msvcr_version = msvc_runtime_version()
78
if msvcr_version:
79
self.define_macro('__MSVCRT_VERSION__', '0x%04i' % msvcr_version)
80
81
# MS_WIN64 should be defined when building for amd64 on windows,
82
# but python headers define it only for MS compilers, which has all
83
# kind of bad consequences, like using Py_ModuleInit4 instead of
84
# Py_ModuleInit4_64, etc... So we add it here
85
if get_build_architecture() == 'AMD64':
86
self.set_executables(
87
compiler='gcc -g -DDEBUG -DMS_WIN64 -O0 -Wall',
88
compiler_so='gcc -g -DDEBUG -DMS_WIN64 -O0 -Wall '
89
'-Wstrict-prototypes',
90
linker_exe='gcc -g',
91
linker_so='gcc -g -shared')
92
else:
93
self.set_executables(
94
compiler='gcc -O2 -Wall',
95
compiler_so='gcc -O2 -Wall -Wstrict-prototypes',
96
linker_exe='g++ ',
97
linker_so='g++ -shared')
98
# added for python2.3 support
99
# we can't pass it through set_executables because pre 2.2 would fail
100
self.compiler_cxx = ['g++']
101
102
# Maybe we should also append -mthreads, but then the finished dlls
103
# need another dll (mingwm10.dll see Mingw32 docs) (-mthreads: Support
104
# thread-safe exception handling on `Mingw32')
105
106
# no additional libraries needed
107
#self.dll_libraries=[]
108
return
109
110
# __init__ ()
111
112
def link(self,
113
target_desc,
114
objects,
115
output_filename,
116
output_dir,
117
libraries,
118
library_dirs,
119
runtime_library_dirs,
120
export_symbols = None,
121
debug=0,
122
extra_preargs=None,
123
extra_postargs=None,
124
build_temp=None,
125
target_lang=None):
126
# Include the appropriate MSVC runtime library if Python was built
127
# with MSVC >= 7.0 (MinGW standard is msvcrt)
128
runtime_library = msvc_runtime_library()
129
if runtime_library:
130
if not libraries:
131
libraries = []
132
libraries.append(runtime_library)
133
args = (self,
134
target_desc,
135
objects,
136
output_filename,
137
output_dir,
138
libraries,
139
library_dirs,
140
runtime_library_dirs,
141
None, #export_symbols, we do this in our def-file
142
debug,
143
extra_preargs,
144
extra_postargs,
145
build_temp,
146
target_lang)
147
func = UnixCCompiler.link
148
func(*args[:func.__code__.co_argcount])
149
return
150
151
def object_filenames (self,
152
source_filenames,
153
strip_dir=0,
154
output_dir=''):
155
if output_dir is None: output_dir = ''
156
obj_names = []
157
for src_name in source_filenames:
158
# use normcase to make sure '.rc' is really '.rc' and not '.RC'
159
(base, ext) = os.path.splitext (os.path.normcase(src_name))
160
161
# added these lines to strip off windows drive letters
162
# without it, .o files are placed next to .c files
163
# instead of the build directory
164
drv, base = os.path.splitdrive(base)
165
if drv:
166
base = base[1:]
167
168
if ext not in (self.src_extensions + ['.rc', '.res']):
169
raise UnknownFileError(
170
"unknown file type '%s' (from '%s')" % \
171
(ext, src_name))
172
if strip_dir:
173
base = os.path.basename (base)
174
if ext == '.res' or ext == '.rc':
175
# these need to be compiled to object files
176
obj_names.append (os.path.join (output_dir,
177
base + ext + self.obj_extension))
178
else:
179
obj_names.append (os.path.join (output_dir,
180
base + self.obj_extension))
181
return obj_names
182
183
# object_filenames ()
184
185
186
def find_python_dll():
187
# We can't do much here:
188
# - find it in the virtualenv (sys.prefix)
189
# - find it in python main dir (sys.base_prefix, if in a virtualenv)
190
# - sys.real_prefix is main dir for virtualenvs in Python 2.7
191
# - in system32,
192
# - ortherwise (Sxs), I don't know how to get it.
193
stems = [sys.prefix]
194
if hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix:
195
stems.append(sys.base_prefix)
196
elif hasattr(sys, 'real_prefix') and sys.real_prefix != sys.prefix:
197
stems.append(sys.real_prefix)
198
199
sub_dirs = ['', 'lib', 'bin']
200
# generate possible combinations of directory trees and sub-directories
201
lib_dirs = []
202
for stem in stems:
203
for folder in sub_dirs:
204
lib_dirs.append(os.path.join(stem, folder))
205
206
# add system directory as well
207
if 'SYSTEMROOT' in os.environ:
208
lib_dirs.append(os.path.join(os.environ['SYSTEMROOT'], 'System32'))
209
210
# search in the file system for possible candidates
211
major_version, minor_version = tuple(sys.version_info[:2])
212
implementation = platform.python_implementation()
213
if implementation == 'CPython':
214
dllname = f'python{major_version}{minor_version}.dll'
215
elif implementation == 'PyPy':
216
dllname = f'libpypy{major_version}-c.dll'
217
else:
218
dllname = 'Unknown platform {implementation}'
219
print("Looking for %s" % dllname)
220
for folder in lib_dirs:
221
dll = os.path.join(folder, dllname)
222
if os.path.exists(dll):
223
return dll
224
225
raise ValueError("%s not found in %s" % (dllname, lib_dirs))
226
227
def dump_table(dll):
228
st = subprocess.check_output(["objdump.exe", "-p", dll])
229
return st.split(b'\n')
230
231
def generate_def(dll, dfile):
232
"""Given a dll file location, get all its exported symbols and dump them
233
into the given def file.
234
235
The .def file will be overwritten"""
236
dump = dump_table(dll)
237
for i in range(len(dump)):
238
if _START.match(dump[i].decode()):
239
break
240
else:
241
raise ValueError("Symbol table not found")
242
243
syms = []
244
for j in range(i+1, len(dump)):
245
m = _TABLE.match(dump[j].decode())
246
if m:
247
syms.append((int(m.group(1).strip()), m.group(2)))
248
else:
249
break
250
251
if len(syms) == 0:
252
log.warn('No symbols found in %s' % dll)
253
254
with open(dfile, 'w') as d:
255
d.write('LIBRARY %s\n' % os.path.basename(dll))
256
d.write(';CODE PRELOAD MOVEABLE DISCARDABLE\n')
257
d.write(';DATA PRELOAD SINGLE\n')
258
d.write('\nEXPORTS\n')
259
for s in syms:
260
#d.write('@%d %s\n' % (s[0], s[1]))
261
d.write('%s\n' % s[1])
262
263
def find_dll(dll_name):
264
265
arch = {'AMD64' : 'amd64',
266
'Intel' : 'x86'}[get_build_architecture()]
267
268
def _find_dll_in_winsxs(dll_name):
269
# Walk through the WinSxS directory to find the dll.
270
winsxs_path = os.path.join(os.environ.get('WINDIR', r'C:\WINDOWS'),
271
'winsxs')
272
if not os.path.exists(winsxs_path):
273
return None
274
for root, dirs, files in os.walk(winsxs_path):
275
if dll_name in files and arch in root:
276
return os.path.join(root, dll_name)
277
return None
278
279
def _find_dll_in_path(dll_name):
280
# First, look in the Python directory, then scan PATH for
281
# the given dll name.
282
for path in [sys.prefix] + os.environ['PATH'].split(';'):
283
filepath = os.path.join(path, dll_name)
284
if os.path.exists(filepath):
285
return os.path.abspath(filepath)
286
287
return _find_dll_in_winsxs(dll_name) or _find_dll_in_path(dll_name)
288
289
def build_msvcr_library(debug=False):
290
if os.name != 'nt':
291
return False
292
293
# If the version number is None, then we couldn't find the MSVC runtime at
294
# all, because we are running on a Python distribution which is customed
295
# compiled; trust that the compiler is the same as the one available to us
296
# now, and that it is capable of linking with the correct runtime without
297
# any extra options.
298
msvcr_ver = msvc_runtime_major()
299
if msvcr_ver is None:
300
log.debug('Skip building import library: '
301
'Runtime is not compiled with MSVC')
302
return False
303
304
# Skip using a custom library for versions < MSVC 8.0
305
if msvcr_ver < 80:
306
log.debug('Skip building msvcr library:'
307
' custom functionality not present')
308
return False
309
310
msvcr_name = msvc_runtime_library()
311
if debug:
312
msvcr_name += 'd'
313
314
# Skip if custom library already exists
315
out_name = "lib%s.a" % msvcr_name
316
out_file = os.path.join(sys.prefix, 'libs', out_name)
317
if os.path.isfile(out_file):
318
log.debug('Skip building msvcr library: "%s" exists' %
319
(out_file,))
320
return True
321
322
# Find the msvcr dll
323
msvcr_dll_name = msvcr_name + '.dll'
324
dll_file = find_dll(msvcr_dll_name)
325
if not dll_file:
326
log.warn('Cannot build msvcr library: "%s" not found' %
327
msvcr_dll_name)
328
return False
329
330
def_name = "lib%s.def" % msvcr_name
331
def_file = os.path.join(sys.prefix, 'libs', def_name)
332
333
log.info('Building msvcr library: "%s" (from %s)' \
334
% (out_file, dll_file))
335
336
# Generate a symbol definition file from the msvcr dll
337
generate_def(dll_file, def_file)
338
339
# Create a custom mingw library for the given symbol definitions
340
cmd = ['dlltool', '-d', def_file, '-l', out_file]
341
retcode = subprocess.call(cmd)
342
343
# Clean up symbol definitions
344
os.remove(def_file)
345
346
return (not retcode)
347
348
def build_import_library():
349
if os.name != 'nt':
350
return
351
352
arch = get_build_architecture()
353
if arch == 'AMD64':
354
return _build_import_library_amd64()
355
elif arch == 'Intel':
356
return _build_import_library_x86()
357
else:
358
raise ValueError("Unhandled arch %s" % arch)
359
360
def _check_for_import_lib():
361
"""Check if an import library for the Python runtime already exists."""
362
major_version, minor_version = tuple(sys.version_info[:2])
363
364
# patterns for the file name of the library itself
365
patterns = ['libpython%d%d.a',
366
'libpython%d%d.dll.a',
367
'libpython%d.%d.dll.a']
368
369
# directory trees that may contain the library
370
stems = [sys.prefix]
371
if hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix:
372
stems.append(sys.base_prefix)
373
elif hasattr(sys, 'real_prefix') and sys.real_prefix != sys.prefix:
374
stems.append(sys.real_prefix)
375
376
# possible subdirectories within those trees where it is placed
377
sub_dirs = ['libs', 'lib']
378
379
# generate a list of candidate locations
380
candidates = []
381
for pat in patterns:
382
filename = pat % (major_version, minor_version)
383
for stem_dir in stems:
384
for folder in sub_dirs:
385
candidates.append(os.path.join(stem_dir, folder, filename))
386
387
# test the filesystem to see if we can find any of these
388
for fullname in candidates:
389
if os.path.isfile(fullname):
390
# already exists, in location given
391
return (True, fullname)
392
393
# needs to be built, preferred location given first
394
return (False, candidates[0])
395
396
def _build_import_library_amd64():
397
out_exists, out_file = _check_for_import_lib()
398
if out_exists:
399
log.debug('Skip building import library: "%s" exists', out_file)
400
return
401
402
# get the runtime dll for which we are building import library
403
dll_file = find_python_dll()
404
log.info('Building import library (arch=AMD64): "%s" (from %s)' %
405
(out_file, dll_file))
406
407
# generate symbol list from this library
408
def_name = "python%d%d.def" % tuple(sys.version_info[:2])
409
def_file = os.path.join(sys.prefix, 'libs', def_name)
410
generate_def(dll_file, def_file)
411
412
# generate import library from this symbol list
413
cmd = ['dlltool', '-d', def_file, '-l', out_file]
414
subprocess.check_call(cmd)
415
416
def _build_import_library_x86():
417
""" Build the import libraries for Mingw32-gcc on Windows
418
"""
419
out_exists, out_file = _check_for_import_lib()
420
if out_exists:
421
log.debug('Skip building import library: "%s" exists', out_file)
422
return
423
424
lib_name = "python%d%d.lib" % tuple(sys.version_info[:2])
425
lib_file = os.path.join(sys.prefix, 'libs', lib_name)
426
if not os.path.isfile(lib_file):
427
# didn't find library file in virtualenv, try base distribution, too,
428
# and use that instead if found there. for Python 2.7 venvs, the base
429
# directory is in attribute real_prefix instead of base_prefix.
430
if hasattr(sys, 'base_prefix'):
431
base_lib = os.path.join(sys.base_prefix, 'libs', lib_name)
432
elif hasattr(sys, 'real_prefix'):
433
base_lib = os.path.join(sys.real_prefix, 'libs', lib_name)
434
else:
435
base_lib = '' # os.path.isfile('') == False
436
437
if os.path.isfile(base_lib):
438
lib_file = base_lib
439
else:
440
log.warn('Cannot build import library: "%s" not found', lib_file)
441
return
442
log.info('Building import library (ARCH=x86): "%s"', out_file)
443
444
from numpy.distutils import lib2def
445
446
def_name = "python%d%d.def" % tuple(sys.version_info[:2])
447
def_file = os.path.join(sys.prefix, 'libs', def_name)
448
nm_output = lib2def.getnm(
449
lib2def.DEFAULT_NM + [lib_file], shell=False)
450
dlist, flist = lib2def.parse_nm(nm_output)
451
with open(def_file, 'w') as fid:
452
lib2def.output_def(dlist, flist, lib2def.DEF_HEADER, fid)
453
454
dll_name = find_python_dll ()
455
456
cmd = ["dlltool",
457
"--dllname", dll_name,
458
"--def", def_file,
459
"--output-lib", out_file]
460
status = subprocess.check_output(cmd)
461
if status:
462
log.warn('Failed to build import library for gcc. Linking will fail.')
463
return
464
465
#=====================================
466
# Dealing with Visual Studio MANIFESTS
467
#=====================================
468
469
# Functions to deal with visual studio manifests. Manifest are a mechanism to
470
# enforce strong DLL versioning on windows, and has nothing to do with
471
# distutils MANIFEST. manifests are XML files with version info, and used by
472
# the OS loader; they are necessary when linking against a DLL not in the
473
# system path; in particular, official python 2.6 binary is built against the
474
# MS runtime 9 (the one from VS 2008), which is not available on most windows
475
# systems; python 2.6 installer does install it in the Win SxS (Side by side)
476
# directory, but this requires the manifest for this to work. This is a big
477
# mess, thanks MS for a wonderful system.
478
479
# XXX: ideally, we should use exactly the same version as used by python. I
480
# submitted a patch to get this version, but it was only included for python
481
# 2.6.1 and above. So for versions below, we use a "best guess".
482
_MSVCRVER_TO_FULLVER = {}
483
if sys.platform == 'win32':
484
try:
485
import msvcrt
486
# I took one version in my SxS directory: no idea if it is the good
487
# one, and we can't retrieve it from python
488
_MSVCRVER_TO_FULLVER['80'] = "8.0.50727.42"
489
_MSVCRVER_TO_FULLVER['90'] = "9.0.21022.8"
490
# Value from msvcrt.CRT_ASSEMBLY_VERSION under Python 3.3.0
491
# on Windows XP:
492
_MSVCRVER_TO_FULLVER['100'] = "10.0.30319.460"
493
crt_ver = getattr(msvcrt, 'CRT_ASSEMBLY_VERSION', None)
494
if crt_ver is not None: # Available at least back to Python 3.3
495
maj, min = re.match(r'(\d+)\.(\d)', crt_ver).groups()
496
_MSVCRVER_TO_FULLVER[maj + min] = crt_ver
497
del maj, min
498
del crt_ver
499
except ImportError:
500
# If we are here, means python was not built with MSVC. Not sure what
501
# to do in that case: manifest building will fail, but it should not be
502
# used in that case anyway
503
log.warn('Cannot import msvcrt: using manifest will not be possible')
504
505
def msvc_manifest_xml(maj, min):
506
"""Given a major and minor version of the MSVCR, returns the
507
corresponding XML file."""
508
try:
509
fullver = _MSVCRVER_TO_FULLVER[str(maj * 10 + min)]
510
except KeyError:
511
raise ValueError("Version %d,%d of MSVCRT not supported yet" %
512
(maj, min)) from None
513
# Don't be fooled, it looks like an XML, but it is not. In particular, it
514
# should not have any space before starting, and its size should be
515
# divisible by 4, most likely for alignment constraints when the xml is
516
# embedded in the binary...
517
# This template was copied directly from the python 2.6 binary (using
518
# strings.exe from mingw on python.exe).
519
template = textwrap.dedent("""\
520
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
521
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
522
<security>
523
<requestedPrivileges>
524
<requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
525
</requestedPrivileges>
526
</security>
527
</trustInfo>
528
<dependency>
529
<dependentAssembly>
530
<assemblyIdentity type="win32" name="Microsoft.VC%(maj)d%(min)d.CRT" version="%(fullver)s" processorArchitecture="*" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
531
</dependentAssembly>
532
</dependency>
533
</assembly>""")
534
535
return template % {'fullver': fullver, 'maj': maj, 'min': min}
536
537
def manifest_rc(name, type='dll'):
538
"""Return the rc file used to generate the res file which will be embedded
539
as manifest for given manifest file name, of given type ('dll' or
540
'exe').
541
542
Parameters
543
----------
544
name : str
545
name of the manifest file to embed
546
type : str {'dll', 'exe'}
547
type of the binary which will embed the manifest
548
549
"""
550
if type == 'dll':
551
rctype = 2
552
elif type == 'exe':
553
rctype = 1
554
else:
555
raise ValueError("Type %s not supported" % type)
556
557
return """\
558
#include "winuser.h"
559
%d RT_MANIFEST %s""" % (rctype, name)
560
561
def check_embedded_msvcr_match_linked(msver):
562
"""msver is the ms runtime version used for the MANIFEST."""
563
# check msvcr major version are the same for linking and
564
# embedding
565
maj = msvc_runtime_major()
566
if maj:
567
if not maj == int(msver):
568
raise ValueError(
569
"Discrepancy between linked msvcr " \
570
"(%d) and the one about to be embedded " \
571
"(%d)" % (int(msver), maj))
572
573
def configtest_name(config):
574
base = os.path.basename(config._gen_temp_sourcefile("yo", [], "c"))
575
return os.path.splitext(base)[0]
576
577
def manifest_name(config):
578
# Get configest name (including suffix)
579
root = configtest_name(config)
580
exext = config.compiler.exe_extension
581
return root + exext + ".manifest"
582
583
def rc_name(config):
584
# Get configtest name (including suffix)
585
root = configtest_name(config)
586
return root + ".rc"
587
588
def generate_manifest(config):
589
msver = get_build_msvc_version()
590
if msver is not None:
591
if msver >= 8:
592
check_embedded_msvcr_match_linked(msver)
593
ma_str, mi_str = str(msver).split('.')
594
# Write the manifest file
595
manxml = msvc_manifest_xml(int(ma_str), int(mi_str))
596
with open(manifest_name(config), "w") as man:
597
config.temp_files.append(manifest_name(config))
598
man.write(manxml)
599
600