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