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/bcppcompiler.py
4799 views
1
"""distutils.bcppcompiler
2
3
Contains BorlandCCompiler, an implementation of the abstract CCompiler class
4
for the Borland C++ compiler.
5
"""
6
7
# This implementation by Lyle Johnson, based on the original msvccompiler.py
8
# module and using the directions originally published by Gordon Williams.
9
10
# XXX looks like there's a LOT of overlap between these two classes:
11
# someone should sit down and factor out the common code as
12
# WindowsCCompiler! --GPW
13
14
15
import os
16
from distutils.errors import \
17
DistutilsExecError, \
18
CompileError, LibError, LinkError, UnknownFileError
19
from distutils.ccompiler import \
20
CCompiler, gen_preprocess_options
21
from distutils.file_util import write_file
22
from distutils.dep_util import newer
23
from distutils import log
24
25
class BCPPCompiler(CCompiler) :
26
"""Concrete class that implements an interface to the Borland C/C++
27
compiler, as defined by the CCompiler abstract class.
28
"""
29
30
compiler_type = 'bcpp'
31
32
# Just set this so CCompiler's constructor doesn't barf. We currently
33
# don't use the 'set_executables()' bureaucracy provided by CCompiler,
34
# as it really isn't necessary for this sort of single-compiler class.
35
# Would be nice to have a consistent interface with UnixCCompiler,
36
# though, so it's worth thinking about.
37
executables = {}
38
39
# Private class data (need to distinguish C from C++ source for compiler)
40
_c_extensions = ['.c']
41
_cpp_extensions = ['.cc', '.cpp', '.cxx']
42
43
# Needed for the filename generation methods provided by the
44
# base class, CCompiler.
45
src_extensions = _c_extensions + _cpp_extensions
46
obj_extension = '.obj'
47
static_lib_extension = '.lib'
48
shared_lib_extension = '.dll'
49
static_lib_format = shared_lib_format = '%s%s'
50
exe_extension = '.exe'
51
52
53
def __init__ (self,
54
verbose=0,
55
dry_run=0,
56
force=0):
57
58
super().__init__(verbose, dry_run, force)
59
60
# These executables are assumed to all be in the path.
61
# Borland doesn't seem to use any special registry settings to
62
# indicate their installation locations.
63
64
self.cc = "bcc32.exe"
65
self.linker = "ilink32.exe"
66
self.lib = "tlib.exe"
67
68
self.preprocess_options = None
69
self.compile_options = ['/tWM', '/O2', '/q', '/g0']
70
self.compile_options_debug = ['/tWM', '/Od', '/q', '/g0']
71
72
self.ldflags_shared = ['/Tpd', '/Gn', '/q', '/x']
73
self.ldflags_shared_debug = ['/Tpd', '/Gn', '/q', '/x']
74
self.ldflags_static = []
75
self.ldflags_exe = ['/Gn', '/q', '/x']
76
self.ldflags_exe_debug = ['/Gn', '/q', '/x','/r']
77
78
79
# -- Worker methods ------------------------------------------------
80
81
def compile(self, sources,
82
output_dir=None, macros=None, include_dirs=None, debug=0,
83
extra_preargs=None, extra_postargs=None, depends=None):
84
85
macros, objects, extra_postargs, pp_opts, build = \
86
self._setup_compile(output_dir, macros, include_dirs, sources,
87
depends, extra_postargs)
88
compile_opts = extra_preargs or []
89
compile_opts.append ('-c')
90
if debug:
91
compile_opts.extend (self.compile_options_debug)
92
else:
93
compile_opts.extend (self.compile_options)
94
95
for obj in objects:
96
try:
97
src, ext = build[obj]
98
except KeyError:
99
continue
100
# XXX why do the normpath here?
101
src = os.path.normpath(src)
102
obj = os.path.normpath(obj)
103
# XXX _setup_compile() did a mkpath() too but before the normpath.
104
# Is it possible to skip the normpath?
105
self.mkpath(os.path.dirname(obj))
106
107
if ext == '.res':
108
# This is already a binary file -- skip it.
109
continue # the 'for' loop
110
if ext == '.rc':
111
# This needs to be compiled to a .res file -- do it now.
112
try:
113
self.spawn (["brcc32", "-fo", obj, src])
114
except DistutilsExecError as msg:
115
raise CompileError(msg)
116
continue # the 'for' loop
117
118
# The next two are both for the real compiler.
119
if ext in self._c_extensions:
120
input_opt = ""
121
elif ext in self._cpp_extensions:
122
input_opt = "-P"
123
else:
124
# Unknown file type -- no extra options. The compiler
125
# will probably fail, but let it just in case this is a
126
# file the compiler recognizes even if we don't.
127
input_opt = ""
128
129
output_opt = "-o" + obj
130
131
# Compiler command line syntax is: "bcc32 [options] file(s)".
132
# Note that the source file names must appear at the end of
133
# the command line.
134
try:
135
self.spawn ([self.cc] + compile_opts + pp_opts +
136
[input_opt, output_opt] +
137
extra_postargs + [src])
138
except DistutilsExecError as msg:
139
raise CompileError(msg)
140
141
return objects
142
143
# compile ()
144
145
146
def create_static_lib (self,
147
objects,
148
output_libname,
149
output_dir=None,
150
debug=0,
151
target_lang=None):
152
153
(objects, output_dir) = self._fix_object_args (objects, output_dir)
154
output_filename = \
155
self.library_filename (output_libname, output_dir=output_dir)
156
157
if self._need_link (objects, output_filename):
158
lib_args = [output_filename, '/u'] + objects
159
if debug:
160
pass # XXX what goes here?
161
try:
162
self.spawn ([self.lib] + lib_args)
163
except DistutilsExecError as msg:
164
raise LibError(msg)
165
else:
166
log.debug("skipping %s (up-to-date)", output_filename)
167
168
# create_static_lib ()
169
170
171
def link (self,
172
target_desc,
173
objects,
174
output_filename,
175
output_dir=None,
176
libraries=None,
177
library_dirs=None,
178
runtime_library_dirs=None,
179
export_symbols=None,
180
debug=0,
181
extra_preargs=None,
182
extra_postargs=None,
183
build_temp=None,
184
target_lang=None):
185
186
# XXX this ignores 'build_temp'! should follow the lead of
187
# msvccompiler.py
188
189
(objects, output_dir) = self._fix_object_args (objects, output_dir)
190
(libraries, library_dirs, runtime_library_dirs) = \
191
self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
192
193
if runtime_library_dirs:
194
log.warn("I don't know what to do with 'runtime_library_dirs': %s",
195
str(runtime_library_dirs))
196
197
if output_dir is not None:
198
output_filename = os.path.join (output_dir, output_filename)
199
200
if self._need_link (objects, output_filename):
201
202
# Figure out linker args based on type of target.
203
if target_desc == CCompiler.EXECUTABLE:
204
startup_obj = 'c0w32'
205
if debug:
206
ld_args = self.ldflags_exe_debug[:]
207
else:
208
ld_args = self.ldflags_exe[:]
209
else:
210
startup_obj = 'c0d32'
211
if debug:
212
ld_args = self.ldflags_shared_debug[:]
213
else:
214
ld_args = self.ldflags_shared[:]
215
216
217
# Create a temporary exports file for use by the linker
218
if export_symbols is None:
219
def_file = ''
220
else:
221
head, tail = os.path.split (output_filename)
222
modname, ext = os.path.splitext (tail)
223
temp_dir = os.path.dirname(objects[0]) # preserve tree structure
224
def_file = os.path.join (temp_dir, '%s.def' % modname)
225
contents = ['EXPORTS']
226
for sym in (export_symbols or []):
227
contents.append(' %s=_%s' % (sym, sym))
228
self.execute(write_file, (def_file, contents),
229
"writing %s" % def_file)
230
231
# Borland C++ has problems with '/' in paths
232
objects2 = map(os.path.normpath, objects)
233
# split objects in .obj and .res files
234
# Borland C++ needs them at different positions in the command line
235
objects = [startup_obj]
236
resources = []
237
for file in objects2:
238
(base, ext) = os.path.splitext(os.path.normcase(file))
239
if ext == '.res':
240
resources.append(file)
241
else:
242
objects.append(file)
243
244
245
for l in library_dirs:
246
ld_args.append("/L%s" % os.path.normpath(l))
247
ld_args.append("/L.") # we sometimes use relative paths
248
249
# list of object files
250
ld_args.extend(objects)
251
252
# XXX the command-line syntax for Borland C++ is a bit wonky;
253
# certain filenames are jammed together in one big string, but
254
# comma-delimited. This doesn't mesh too well with the
255
# Unix-centric attitude (with a DOS/Windows quoting hack) of
256
# 'spawn()', so constructing the argument list is a bit
257
# awkward. Note that doing the obvious thing and jamming all
258
# the filenames and commas into one argument would be wrong,
259
# because 'spawn()' would quote any filenames with spaces in
260
# them. Arghghh!. Apparently it works fine as coded...
261
262
# name of dll/exe file
263
ld_args.extend([',',output_filename])
264
# no map file and start libraries
265
ld_args.append(',,')
266
267
for lib in libraries:
268
# see if we find it and if there is a bcpp specific lib
269
# (xxx_bcpp.lib)
270
libfile = self.find_library_file(library_dirs, lib, debug)
271
if libfile is None:
272
ld_args.append(lib)
273
# probably a BCPP internal library -- don't warn
274
else:
275
# full name which prefers bcpp_xxx.lib over xxx.lib
276
ld_args.append(libfile)
277
278
# some default libraries
279
ld_args.append ('import32')
280
ld_args.append ('cw32mt')
281
282
# def file for export symbols
283
ld_args.extend([',',def_file])
284
# add resource files
285
ld_args.append(',')
286
ld_args.extend(resources)
287
288
289
if extra_preargs:
290
ld_args[:0] = extra_preargs
291
if extra_postargs:
292
ld_args.extend(extra_postargs)
293
294
self.mkpath (os.path.dirname (output_filename))
295
try:
296
self.spawn ([self.linker] + ld_args)
297
except DistutilsExecError as msg:
298
raise LinkError(msg)
299
300
else:
301
log.debug("skipping %s (up-to-date)", output_filename)
302
303
# link ()
304
305
# -- Miscellaneous methods -----------------------------------------
306
307
308
def find_library_file (self, dirs, lib, debug=0):
309
# List of effective library names to try, in order of preference:
310
# xxx_bcpp.lib is better than xxx.lib
311
# and xxx_d.lib is better than xxx.lib if debug is set
312
#
313
# The "_bcpp" suffix is to handle a Python installation for people
314
# with multiple compilers (primarily Distutils hackers, I suspect
315
# ;-). The idea is they'd have one static library for each
316
# compiler they care about, since (almost?) every Windows compiler
317
# seems to have a different format for static libraries.
318
if debug:
319
dlib = (lib + "_d")
320
try_names = (dlib + "_bcpp", lib + "_bcpp", dlib, lib)
321
else:
322
try_names = (lib + "_bcpp", lib)
323
324
for dir in dirs:
325
for name in try_names:
326
libfile = os.path.join(dir, self.library_filename(name))
327
if os.path.exists(libfile):
328
return libfile
329
else:
330
# Oops, didn't find it in *any* of 'dirs'
331
return None
332
333
# overwrite the one from CCompiler to support rc and res-files
334
def object_filenames (self,
335
source_filenames,
336
strip_dir=0,
337
output_dir=''):
338
if output_dir is None: output_dir = ''
339
obj_names = []
340
for src_name in source_filenames:
341
# use normcase to make sure '.rc' is really '.rc' and not '.RC'
342
(base, ext) = os.path.splitext (os.path.normcase(src_name))
343
if ext not in (self.src_extensions + ['.rc','.res']):
344
raise UnknownFileError("unknown file type '%s' (from '%s')" % \
345
(ext, src_name))
346
if strip_dir:
347
base = os.path.basename (base)
348
if ext == '.res':
349
# these can go unchanged
350
obj_names.append (os.path.join (output_dir, base + ext))
351
elif ext == '.rc':
352
# these need to be compiled to .res-files
353
obj_names.append (os.path.join (output_dir, base + '.res'))
354
else:
355
obj_names.append (os.path.join (output_dir,
356
base + self.obj_extension))
357
return obj_names
358
359
# object_filenames ()
360
361
def preprocess (self,
362
source,
363
output_file=None,
364
macros=None,
365
include_dirs=None,
366
extra_preargs=None,
367
extra_postargs=None):
368
369
(_, macros, include_dirs) = \
370
self._fix_compile_args(None, macros, include_dirs)
371
pp_opts = gen_preprocess_options(macros, include_dirs)
372
pp_args = ['cpp32.exe'] + pp_opts
373
if output_file is not None:
374
pp_args.append('-o' + output_file)
375
if extra_preargs:
376
pp_args[:0] = extra_preargs
377
if extra_postargs:
378
pp_args.extend(extra_postargs)
379
pp_args.append(source)
380
381
# We need to preprocess: either we're being forced to, or the
382
# source file is newer than the target (or the target doesn't
383
# exist).
384
if self.force or output_file is None or newer(source, output_file):
385
if output_file:
386
self.mkpath(os.path.dirname(output_file))
387
try:
388
self.spawn(pp_args)
389
except DistutilsExecError as msg:
390
print(msg)
391
raise CompileError(msg)
392
393
# preprocess()
394
395