Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4240648

Browse files
committed
Big patch from Rene Liebscher to simplify the CCompiler API and
implementations. Details: * replace 'link_shared_object()', 'link_shared_lib()', and 'link_executable()' with 'link()', which is (roughly) the union of the three methods it replaces * in all implementation classes (UnixCCompiler, MSVCCompiler, etc.), ditch the old 'link_*()' methods and replace them with 'link()' * in the abstract base class (CCompiler), add the old 'link_*()' methods as wrappers around the new 'link()' (they also print a warning of the deprecated interface) Also increases consistency between MSVCCompiler and BCPPCompiler, hopefully to make it easier to factor out the mythical WindowsCCompiler class. Details: * use 'self.linker' instead of 'self.link' * add ability to compile resource files to BCPPCompiler * added (redundant?) 'object_filename()' method to BCPPCompiler * only generate a .def file if 'export_symbols' defined
1 parent 3ad4e74 commit 4240648

5 files changed

Lines changed: 409 additions & 430 deletions

File tree

Lib/distutils/bcppcompiler.py

Lines changed: 123 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def __init__ (self,
6363
# indicate their installation locations.
6464

6565
self.cc = "bcc32.exe"
66-
self.link = "ilink32.exe"
66+
self.linker = "ilink32.exe"
6767
self.lib = "tlib.exe"
6868

6969
self.preprocess_options = None
@@ -73,6 +73,8 @@ def __init__ (self,
7373
self.ldflags_shared = ['/Tpd', '/Gn', '/q', '/x']
7474
self.ldflags_shared_debug = ['/Tpd', '/Gn', '/q', '/x']
7575
self.ldflags_static = []
76+
self.ldflags_exe = ['/Gn', '/q', '/x']
77+
self.ldflags_exe_debug = ['/Gn', '/q', '/x','/r']
7678

7779

7880
# -- Worker methods ------------------------------------------------
@@ -108,16 +110,33 @@ def compile (self,
108110
if skip_sources[src]:
109111
self.announce ("skipping %s (%s up-to-date)" % (src, obj))
110112
else:
113+
src = os.path.normpath(src)
114+
obj = os.path.normpath(obj)
115+
self.mkpath(os.path.dirname(obj))
116+
117+
if ext == '.res':
118+
# This is already a binary file -- skip it.
119+
continue # the 'for' loop
120+
if ext == '.rc':
121+
# This needs to be compiled to a .res file -- do it now.
122+
try:
123+
self.spawn (["brcc32", "-fo", obj, src])
124+
except DistutilsExecError, msg:
125+
raise CompileError, msg
126+
continue # the 'for' loop
127+
128+
# The next two are both for the real compiler.
111129
if ext in self._c_extensions:
112130
input_opt = ""
113131
elif ext in self._cpp_extensions:
114132
input_opt = "-P"
133+
else:
134+
# Unknown file type -- no extra options. The compiler
135+
# will probably fail, but let it just in case this is a
136+
# file the compiler recognizes even if we don't.
137+
input_opt = ""
115138

116-
src = os.path.normpath(src)
117-
obj = os.path.normpath(obj)
118-
119139
output_opt = "-o" + obj
120-
self.mkpath(os.path.dirname(obj))
121140

122141
# Compiler command line syntax is: "bcc32 [options] file(s)".
123142
# Note that the source file names must appear at the end of
@@ -163,45 +182,20 @@ def create_static_lib (self,
163182

164183
# create_static_lib ()
165184

166-
167-
def link_shared_lib (self,
168-
objects,
169-
output_libname,
170-
output_dir=None,
171-
libraries=None,
172-
library_dirs=None,
173-
runtime_library_dirs=None,
174-
export_symbols=None,
175-
debug=0,
176-
extra_preargs=None,
177-
extra_postargs=None,
178-
build_temp=None):
179-
180-
self.link_shared_object (objects,
181-
self.shared_library_name(output_libname),
182-
output_dir=output_dir,
183-
libraries=libraries,
184-
library_dirs=library_dirs,
185-
runtime_library_dirs=runtime_library_dirs,
186-
export_symbols=export_symbols,
187-
debug=debug,
188-
extra_preargs=extra_preargs,
189-
extra_postargs=extra_postargs,
190-
build_temp=build_temp)
191-
192185

193-
def link_shared_object (self,
194-
objects,
195-
output_filename,
196-
output_dir=None,
197-
libraries=None,
198-
library_dirs=None,
199-
runtime_library_dirs=None,
200-
export_symbols=None,
201-
debug=0,
202-
extra_preargs=None,
203-
extra_postargs=None,
204-
build_temp=None):
186+
def link (self,
187+
target_desc,
188+
objects,
189+
output_filename,
190+
output_dir=None,
191+
libraries=None,
192+
library_dirs=None,
193+
runtime_library_dirs=None,
194+
export_symbols=None,
195+
debug=0,
196+
extra_preargs=None,
197+
extra_postargs=None,
198+
build_temp=None):
205199

206200
# XXX this ignores 'build_temp'! should follow the lead of
207201
# msvccompiler.py
@@ -213,45 +207,61 @@ def link_shared_object (self,
213207
if runtime_library_dirs:
214208
self.warn ("I don't know what to do with 'runtime_library_dirs': "
215209
+ str (runtime_library_dirs))
216-
210+
217211
if output_dir is not None:
218212
output_filename = os.path.join (output_dir, output_filename)
219213

220214
if self._need_link (objects, output_filename):
221215

222-
if debug:
223-
ld_args = self.ldflags_shared_debug[:]
216+
# Figure out linker args based on type of target.
217+
if target_desc == CCompiler.EXECUTABLE:
218+
startup_obj = 'c0w32'
219+
if debug:
220+
ld_args = self.ldflags_exe_debug[:]
221+
else:
222+
ld_args = self.ldflags_exe[:]
224223
else:
225-
ld_args = self.ldflags_shared[:]
224+
startup_obj = 'c0d32'
225+
if debug:
226+
ld_args = self.ldflags_shared_debug[:]
227+
else:
228+
ld_args = self.ldflags_shared[:]
229+
226230

227231
# Create a temporary exports file for use by the linker
228-
head, tail = os.path.split (output_filename)
229-
modname, ext = os.path.splitext (tail)
230-
temp_dir = os.path.dirname(objects[0]) # preserve tree structure
231-
def_file = os.path.join (temp_dir, '%s.def' % modname)
232-
contents = ['EXPORTS']
233-
for sym in (export_symbols or []):
234-
contents.append(' %s=_%s' % (sym, sym))
235-
self.execute(write_file, (def_file, contents),
236-
"writing %s" % def_file)
232+
if export_symbols is None:
233+
def_file = ''
234+
else:
235+
head, tail = os.path.split (output_filename)
236+
modname, ext = os.path.splitext (tail)
237+
temp_dir = os.path.dirname(objects[0]) # preserve tree structure
238+
def_file = os.path.join (temp_dir, '%s.def' % modname)
239+
contents = ['EXPORTS']
240+
for sym in (export_symbols or []):
241+
contents.append(' %s=_%s' % (sym, sym))
242+
self.execute(write_file, (def_file, contents),
243+
"writing %s" % def_file)
237244

238245
# Borland C++ has problems with '/' in paths
239-
objects = map(os.path.normpath, objects)
240-
startup_obj = 'c0d32'
241-
objects.insert(0, startup_obj)
242-
243-
# either exchange python15.lib in the python libs directory against
244-
# a Borland-like one, or create one with name bcpp_python15.lib
245-
# there and remove the pragmas from config.h
246-
libraries.append ('import32')
247-
libraries.append ('cw32mt')
248-
249-
# Start building command line flags and options.
250-
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+
251259
for l in library_dirs:
252260
ld_args.append("/L%s" % os.path.normpath(l))
253-
254-
ld_args.extend(objects) # list of object files
261+
ld_args.append("/L.") # we sometimes use relative paths
262+
263+
# list of object files
264+
ld_args.extend(objects)
255265

256266
# XXX the command-line syntax for Borland C++ is a bit wonky;
257267
# certain filenames are jammed together in one big string, but
@@ -263,14 +273,14 @@ def link_shared_object (self,
263273
# because 'spawn()' would quote any filenames with spaces in
264274
# them. Arghghh!. Apparently it works fine as coded...
265275

266-
# name of dll file
276+
# name of dll/exe file
267277
ld_args.extend([',',output_filename])
268278
# no map file and start libraries
269279
ld_args.append(',,')
270280

271281
for lib in libraries:
272282
# see if we find it and if there is a bcpp specific lib
273-
# (bcpp_xxx.lib)
283+
# (xxx_bcpp.lib)
274284
libfile = self.find_library_file(library_dirs, lib, debug)
275285
if libfile is None:
276286
ld_args.append(lib)
@@ -279,8 +289,17 @@ def link_shared_object (self,
279289
else:
280290
# full name which prefers bcpp_xxx.lib over xxx.lib
281291
ld_args.append(libfile)
292+
293+
# some default libraries
294+
ld_args.append ('import32')
295+
ld_args.append ('cw32mt')
296+
282297
# def file for export symbols
283298
ld_args.extend([',',def_file])
299+
# add resource files
300+
ld_args.append(',')
301+
ld_args.extend(resources)
302+
284303

285304
if extra_preargs:
286305
ld_args[:0] = extra_preargs
@@ -289,88 +308,24 @@ def link_shared_object (self,
289308

290309
self.mkpath (os.path.dirname (output_filename))
291310
try:
292-
self.spawn ([self.link] + ld_args)
311+
self.spawn ([self.linker] + ld_args)
293312
except DistutilsExecError, msg:
294313
raise LinkError, msg
295314

296315
else:
297316
self.announce ("skipping %s (up-to-date)" % output_filename)
298317

299-
# link_shared_object ()
300-
301-
302-
def link_executable (self,
303-
objects,
304-
output_progname,
305-
output_dir=None,
306-
libraries=None,
307-
library_dirs=None,
308-
runtime_library_dirs=None,
309-
debug=0,
310-
extra_preargs=None,
311-
extra_postargs=None):
312-
313-
(objects, output_dir) = self._fix_object_args (objects, output_dir)
314-
(libraries, library_dirs, runtime_library_dirs) = \
315-
self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
316-
317-
if runtime_library_dirs:
318-
self.warn ("I don't know what to do with 'runtime_library_dirs': "
319-
+ str (runtime_library_dirs))
320-
321-
lib_opts = gen_lib_options (self,
322-
library_dirs, runtime_library_dirs,
323-
libraries)
324-
output_filename = output_progname + self.exe_extension
325-
if output_dir is not None:
326-
output_filename = os.path.join (output_dir, output_filename)
327-
328-
if self._need_link (objects, output_filename):
329-
330-
if debug:
331-
ldflags = self.ldflags_shared_debug[1:]
332-
else:
333-
ldflags = self.ldflags_shared[1:]
334-
335-
ld_args = ldflags + lib_opts + \
336-
objects + ['/OUT:' + output_filename]
337-
338-
if extra_preargs:
339-
ld_args[:0] = extra_preargs
340-
if extra_postargs:
341-
ld_args.extend (extra_postargs)
342-
343-
self.mkpath (os.path.dirname (output_filename))
344-
try:
345-
self.spawn ([self.link] + ld_args)
346-
except DistutilsExecError, msg:
347-
raise LinkError, msg
348-
else:
349-
self.announce ("skipping %s (up-to-date)" % output_filename)
350-
318+
# link ()
351319

352320
# -- Miscellaneous methods -----------------------------------------
353-
# These are all used by the 'gen_lib_options() function, in
354-
# ccompiler.py.
355-
356-
def library_dir_option (self, dir):
357-
return "-L" + dir
358-
359-
def runtime_library_dir_option (self, dir):
360-
raise DistutilsPlatformError, \
361-
("don't know how to set runtime library search path "
362-
"for Borland C++")
363-
364-
def library_option (self, lib):
365-
return self.library_filename (lib)
366321

367322

368323
def find_library_file (self, dirs, lib, debug=0):
369324
# List of effective library names to try, in order of preference:
370-
# bcpp_xxx.lib is better than xxx.lib
325+
# xxx_bcpp.lib is better than xxx.lib
371326
# and xxx_d.lib is better than xxx.lib if debug is set
372327
#
373-
# The "bcpp_" prefix is to handle a Python installation for people
328+
# The "_bcpp" suffix is to handle a Python installation for people
374329
# with multiple compilers (primarily Distutils hackers, I suspect
375330
# ;-). The idea is they'd have one static library for each
376331
# compiler they care about, since (almost?) every Windows compiler
@@ -390,3 +345,31 @@ def find_library_file (self, dirs, lib, debug=0):
390345
# Oops, didn't find it in *any* of 'dirs'
391346
return None
392347

348+
# overwrite the one from CCompiler to support rc and res-files
349+
def object_filenames (self,
350+
source_filenames,
351+
strip_dir=0,
352+
output_dir=''):
353+
if output_dir is None: output_dir = ''
354+
obj_names = []
355+
for src_name in source_filenames:
356+
# use normcase to make sure '.rc' is really '.rc' and not '.RC'
357+
(base, ext) = os.path.splitext (os.path.normcase(src_name))
358+
if ext not in (self.src_extensions + ['.rc','.res']):
359+
raise UnknownFileError, \
360+
"unknown file type '%s' (from '%s')" % \
361+
(ext, src_name)
362+
if strip_dir:
363+
base = os.path.basename (base)
364+
if ext == '.res':
365+
# these can go unchanged
366+
obj_names.append (os.path.join (output_dir, base + ext))
367+
elif ext == '.rc':
368+
# these need to be compiled to .res-files
369+
obj_names.append (os.path.join (output_dir, base + '.res'))
370+
else:
371+
obj_names.append (os.path.join (output_dir,
372+
base + self.obj_extension))
373+
return obj_names
374+
375+
# object_filenames ()

0 commit comments

Comments
 (0)