]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/distutils/bcppcompiler.py
1 """distutils.bcppcompiler
3 Contains BorlandCCompiler, an implementation of the abstract CCompiler class
4 for the Borland C++ compiler.
7 # This implementation by Lyle Johnson, based on the original msvccompiler.py
8 # module and using the directions originally published by Gordon Williams.
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
14 # This module should be kept compatible with Python 1.5.2.
20 from distutils
.errors
import \
21 DistutilsExecError
, DistutilsPlatformError
, \
22 CompileError
, LibError
, LinkError
, UnknownFileError
23 from distutils
.ccompiler
import \
24 CCompiler
, gen_preprocess_options
, gen_lib_options
25 from distutils
.file_util
import write_file
26 from distutils
.dep_util
import newer
27 from distutils
import log
29 class BCPPCompiler(CCompiler
) :
30 """Concrete class that implements an interface to the Borland C/C++
31 compiler, as defined by the CCompiler abstract class.
34 compiler_type
= 'bcpp'
36 # Just set this so CCompiler's constructor doesn't barf. We currently
37 # don't use the 'set_executables()' bureaucracy provided by CCompiler,
38 # as it really isn't necessary for this sort of single-compiler class.
39 # Would be nice to have a consistent interface with UnixCCompiler,
40 # though, so it's worth thinking about.
43 # Private class data (need to distinguish C from C++ source for compiler)
44 _c_extensions
= ['.c']
45 _cpp_extensions
= ['.cc', '.cpp', '.cxx']
47 # Needed for the filename generation methods provided by the
48 # base class, CCompiler.
49 src_extensions
= _c_extensions
+ _cpp_extensions
50 obj_extension
= '.obj'
51 static_lib_extension
= '.lib'
52 shared_lib_extension
= '.dll'
53 static_lib_format
= shared_lib_format
= '%s%s'
54 exe_extension
= '.exe'
62 CCompiler
.__init
__ (self
, verbose
, dry_run
, force
)
64 # These executables are assumed to all be in the path.
65 # Borland doesn't seem to use any special registry settings to
66 # indicate their installation locations.
69 self
.linker
= "ilink32.exe"
72 self
.preprocess_options
= None
73 self
.compile_options
= ['/tWM', '/O2', '/q', '/g0']
74 self
.compile_options_debug
= ['/tWM', '/Od', '/q', '/g0']
76 self
.ldflags_shared
= ['/Tpd', '/Gn', '/q', '/x']
77 self
.ldflags_shared_debug
= ['/Tpd', '/Gn', '/q', '/x']
78 self
.ldflags_static
= []
79 self
.ldflags_exe
= ['/Gn', '/q', '/x']
80 self
.ldflags_exe_debug
= ['/Gn', '/q', '/x','/r']
83 # -- Worker methods ------------------------------------------------
85 def compile(self
, sources
,
86 output_dir
=None, macros
=None, include_dirs
=None, debug
=0,
87 extra_preargs
=None, extra_postargs
=None, depends
=None):
89 macros
, objects
, extra_postargs
, pp_opts
, build
= \
90 self
._setup
_compile
(output_dir
, macros
, include_dirs
, sources
,
91 depends
, extra_postargs
)
92 compile_opts
= extra_preargs
or []
93 compile_opts
.append ('-c')
95 compile_opts
.extend (self
.compile_options_debug
)
97 compile_opts
.extend (self
.compile_options
)
99 for obj
, (src
, ext
) in build
.items():
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
))
108 # This is already a binary file -- skip it.
109 continue # the 'for' loop
111 # This needs to be compiled to a .res file -- do it now.
113 self
.spawn (["brcc32", "-fo", obj
, src
])
114 except DistutilsExecError
, msg
:
115 raise CompileError
, msg
116 continue # the 'for' loop
118 # The next two are both for the real compiler.
119 if ext
in self
._c
_extensions
:
121 elif ext
in self
._cpp
_extensions
:
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.
129 output_opt
= "-o" + obj
131 # Compiler command line syntax is: "bcc32 [options] file(s)".
132 # Note that the source file names must appear at the end of
135 self
.spawn ([self
.cc
] + compile_opts
+ pp_opts
+
136 [input_opt
, output_opt
] +
137 extra_postargs
+ [src
])
138 except DistutilsExecError
, msg
:
139 raise CompileError
, msg
146 def create_static_lib (self
,
153 (objects
, output_dir
) = self
._fix
_object
_args
(objects
, output_dir
)
155 self
.library_filename (output_libname
, output_dir
=output_dir
)
157 if self
._need
_link
(objects
, output_filename
):
158 lib_args
= [output_filename
, '/u'] + objects
160 pass # XXX what goes here?
162 self
.spawn ([self
.lib
] + lib_args
)
163 except DistutilsExecError
, msg
:
166 log
.debug("skipping %s (up-to-date)", output_filename
)
168 # create_static_lib ()
178 runtime_library_dirs
=None,
186 # XXX this ignores 'build_temp'! should follow the lead of
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
)
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
))
197 if output_dir
is not None:
198 output_filename
= os
.path
.join (output_dir
, output_filename
)
200 if self
._need
_link
(objects
, output_filename
):
202 # Figure out linker args based on type of target.
203 if target_desc
== CCompiler
.EXECUTABLE
:
204 startup_obj
= 'c0w32'
206 ld_args
= self
.ldflags_exe_debug
[:]
208 ld_args
= self
.ldflags_exe
[:]
210 startup_obj
= 'c0d32'
212 ld_args
= self
.ldflags_shared_debug
[:]
214 ld_args
= self
.ldflags_shared
[:]
217 # Create a temporary exports file for use by the linker
218 if export_symbols
is None:
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
)
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
]
237 for file in objects2
:
238 (base
, ext
) = os
.path
.splitext(os
.path
.normcase(file))
240 resources
.append(file)
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
249 # list of object files
250 ld_args
.extend(objects
)
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...
262 # name of dll/exe file
263 ld_args
.extend([',',output_filename
])
264 # no map file and start libraries
267 for lib
in libraries
:
268 # see if we find it and if there is a bcpp specific lib
270 libfile
= self
.find_library_file(library_dirs
, lib
, debug
)
273 # probably a BCPP internal library -- don't warn
275 # full name which prefers bcpp_xxx.lib over xxx.lib
276 ld_args
.append(libfile
)
278 # some default libraries
279 ld_args
.append ('import32')
280 ld_args
.append ('cw32mt')
282 # def file for export symbols
283 ld_args
.extend([',',def_file
])
286 ld_args
.extend(resources
)
290 ld_args
[:0] = extra_preargs
292 ld_args
.extend(extra_postargs
)
294 self
.mkpath (os
.path
.dirname (output_filename
))
296 self
.spawn ([self
.linker
] + ld_args
)
297 except DistutilsExecError
, msg
:
301 log
.debug("skipping %s (up-to-date)", output_filename
)
305 # -- Miscellaneous methods -----------------------------------------
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
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.
320 try_names
= (dlib
+ "_bcpp", lib
+ "_bcpp", dlib
, lib
)
322 try_names
= (lib
+ "_bcpp", lib
)
325 for name
in try_names
:
326 libfile
= os
.path
.join(dir, self
.library_filename(name
))
327 if os
.path
.exists(libfile
):
330 # Oops, didn't find it in *any* of 'dirs'
333 # overwrite the one from CCompiler to support rc and res-files
334 def object_filenames (self
,
338 if output_dir
is None: output_dir
= ''
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
, \
345 "unknown file type '%s' (from '%s')" % \
348 base
= os
.path
.basename (base
)
350 # these can go unchanged
351 obj_names
.append (os
.path
.join (output_dir
, base
+ ext
))
353 # these need to be compiled to .res-files
354 obj_names
.append (os
.path
.join (output_dir
, base
+ '.res'))
356 obj_names
.append (os
.path
.join (output_dir
,
357 base
+ self
.obj_extension
))
360 # object_filenames ()
362 def preprocess (self
,
368 extra_postargs
=None):
370 (_
, macros
, include_dirs
) = \
371 self
._fix
_compile
_args
(None, macros
, include_dirs
)
372 pp_opts
= gen_preprocess_options(macros
, include_dirs
)
373 pp_args
= ['cpp32.exe'] + pp_opts
374 if output_file
is not None:
375 pp_args
.append('-o' + output_file
)
377 pp_args
[:0] = extra_preargs
379 pp_args
.extend(extra_postargs
)
380 pp_args
.append(source
)
382 # We need to preprocess: either we're being forced to, or the
383 # source file is newer than the target (or the target doesn't
385 if self
.force
or output_file
is None or newer(source
, output_file
):
387 self
.mkpath(os
.path
.dirname(output_file
))
390 except DistutilsExecError
, msg
:
392 raise CompileError
, msg