4545# * mingw gcc 3.2/ld 2.13 works
4646# (ld supports -shared)
4747
48- __revision__ = "$Id$"
48+ # This module should be kept compatible with Python 2.1.
4949
50- import os
51- import sys
52- import copy
53- import re
54- from warnings import warn
50+ __revision__ = "$Id$"
5551
52+ import os ,sys ,copy
53+ from distutils .ccompiler import gen_preprocess_options , gen_lib_options
5654from distutils .unixccompiler import UnixCCompiler
5755from distutils .file_util import write_file
5856from distutils .errors import DistutilsExecError , CompileError , UnknownFileError
59- from distutils . util import get_compiler_versions
57+ from distutils import log
6058
6159def get_msvcr ():
6260 """Include the appropriate MSVC runtime library if Python was built
@@ -81,9 +79,8 @@ def get_msvcr():
8179 raise ValueError ("Unknown MS Compiler version %s " % msc_ver )
8280
8381
84- class CygwinCCompiler (UnixCCompiler ):
85- """ Handles the Cygwin port of the GNU C compiler to Windows.
86- """
82+ class CygwinCCompiler (UnixCCompiler ):
83+
8784 compiler_type = 'cygwin'
8885 obj_extension = ".o"
8986 static_lib_extension = ".a"
@@ -92,11 +89,11 @@ class CygwinCCompiler(UnixCCompiler):
9289 shared_lib_format = "%s%s"
9390 exe_extension = ".exe"
9491
95- def __init__ (self , verbose = 0 , dry_run = 0 , force = 0 ):
92+ def __init__ (self , verbose = 0 , dry_run = 0 , force = 0 ):
9693
97- UnixCCompiler .__init__ (self , verbose , dry_run , force )
94+ UnixCCompiler .__init__ (self , verbose , dry_run , force )
9895
99- status , details = check_config_h ()
96+ ( status , details ) = check_config_h ()
10097 self .debug_print ("Python's GCC status: %s (details: %s)" %
10198 (status , details ))
10299 if status is not CONFIG_H_OK :
@@ -107,7 +104,7 @@ def __init__(self, verbose=0, dry_run=0, force=0):
107104 % details )
108105
109106 self .gcc_version , self .ld_version , self .dllwrap_version = \
110- get_compiler_versions ()
107+ get_versions ()
111108 self .debug_print (self .compiler_type + ": gcc %s, ld %s, dllwrap %s\n " %
112109 (self .gcc_version ,
113110 self .ld_version ,
@@ -151,8 +148,10 @@ def __init__(self, verbose=0, dry_run=0, force=0):
151148 # with MSVC 7.0 or later.
152149 self .dll_libraries = get_msvcr ()
153150
151+ # __init__ ()
152+
153+
154154 def _compile (self , obj , src , ext , cc_args , extra_postargs , pp_opts ):
155- """Compiles the source by spawing GCC and windres if needed."""
156155 if ext == '.rc' or ext == '.res' :
157156 # gcc needs '.res' and '.rc' compiled to object files !!!
158157 try :
@@ -166,11 +165,21 @@ def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
166165 except DistutilsExecError , msg :
167166 raise CompileError , msg
168167
169- def link (self , target_desc , objects , output_filename , output_dir = None ,
170- libraries = None , library_dirs = None , runtime_library_dirs = None ,
171- export_symbols = None , debug = 0 , extra_preargs = None ,
172- extra_postargs = None , build_temp = None , target_lang = None ):
173- """Link the objects."""
168+ def link (self ,
169+ target_desc ,
170+ objects ,
171+ output_filename ,
172+ output_dir = None ,
173+ libraries = None ,
174+ library_dirs = None ,
175+ runtime_library_dirs = None ,
176+ export_symbols = None ,
177+ debug = 0 ,
178+ extra_preargs = None ,
179+ extra_postargs = None ,
180+ build_temp = None ,
181+ target_lang = None ):
182+
174183 # use separate copies, so we can modify the lists
175184 extra_preargs = copy .copy (extra_preargs or [])
176185 libraries = copy .copy (libraries or [])
@@ -235,44 +244,64 @@ def link(self, target_desc, objects, output_filename, output_dir=None,
235244 if not debug :
236245 extra_preargs .append ("-s" )
237246
238- UnixCCompiler .link (self , target_desc , objects , output_filename ,
239- output_dir , libraries , library_dirs ,
247+ UnixCCompiler .link (self ,
248+ target_desc ,
249+ objects ,
250+ output_filename ,
251+ output_dir ,
252+ libraries ,
253+ library_dirs ,
240254 runtime_library_dirs ,
241255 None , # export_symbols, we do this in our def-file
242- debug , extra_preargs , extra_postargs , build_temp ,
256+ debug ,
257+ extra_preargs ,
258+ extra_postargs ,
259+ build_temp ,
243260 target_lang )
244261
262+ # link ()
263+
245264 # -- Miscellaneous methods -----------------------------------------
246265
247- def object_filenames (self , source_filenames , strip_dir = 0 , output_dir = '' ):
248- """Adds supports for rc and res files."""
249- if output_dir is None :
250- output_dir = ''
266+ # overwrite the one from CCompiler to support rc and res-files
267+ def object_filenames (self ,
268+ source_filenames ,
269+ strip_dir = 0 ,
270+ output_dir = '' ):
271+ if output_dir is None : output_dir = ''
251272 obj_names = []
252273 for src_name in source_filenames :
253274 # use normcase to make sure '.rc' is really '.rc' and not '.RC'
254- base , ext = os .path .splitext (os .path .normcase (src_name ))
275+ ( base , ext ) = os .path .splitext (os .path .normcase (src_name ))
255276 if ext not in (self .src_extensions + ['.rc' ,'.res' ]):
256277 raise UnknownFileError , \
257- "unknown file type '%s' (from '%s')" % (ext , src_name )
278+ "unknown file type '%s' (from '%s')" % \
279+ (ext , src_name )
258280 if strip_dir :
259281 base = os .path .basename (base )
260- if ext in ( '.res' , '.rc' ) :
282+ if ext == '.res' or ext == '.rc' :
261283 # these need to be compiled to object files
262- obj_names .append (os .path .join (output_dir ,
263- base + ext + self .obj_extension ))
284+ obj_names .append (os .path .join (output_dir ,
285+ base + ext + self .obj_extension ))
264286 else :
265- obj_names .append (os .path .join (output_dir ,
266- base + self .obj_extension ))
287+ obj_names .append (os .path .join (output_dir ,
288+ base + self .obj_extension ))
267289 return obj_names
268290
291+ # object_filenames ()
292+
293+ # class CygwinCCompiler
294+
295+
269296# the same as cygwin plus some additional parameters
270- class Mingw32CCompiler (CygwinCCompiler ):
271- """ Handles the Mingw32 port of the GNU C compiler to Windows.
272- """
297+ class Mingw32CCompiler (CygwinCCompiler ):
298+
273299 compiler_type = 'mingw32'
274300
275- def __init__ (self , verbose = 0 , dry_run = 0 , force = 0 ):
301+ def __init__ (self ,
302+ verbose = 0 ,
303+ dry_run = 0 ,
304+ force = 0 ):
276305
277306 CygwinCCompiler .__init__ (self , verbose , dry_run , force )
278307
@@ -308,6 +337,10 @@ def __init__(self, verbose=0, dry_run=0, force=0):
308337 # with MSVC 7.0 or later.
309338 self .dll_libraries = get_msvcr ()
310339
340+ # __init__ ()
341+
342+ # class Mingw32CCompiler
343+
311344# Because these compilers aren't configured in Python's pyconfig.h file by
312345# default, we should at least warn the user if he is using a unmodified
313346# version.
@@ -317,16 +350,16 @@ def __init__(self, verbose=0, dry_run=0, force=0):
317350CONFIG_H_UNCERTAIN = "uncertain"
318351
319352def check_config_h ():
320- """Check if the current Python installation appears amenable to building
321- extensions with GCC.
322-
323- Returns a tuple (status, details), where 'status' is one of the following
324- constants:
325-
326- - CONFIG_H_OK: all is well, go ahead and compile
327- - CONFIG_H_NOTOK: doesn't look good
328- - CONFIG_H_UNCERTAIN: not sure -- unable to read pyconfig.h
329353
354+ """Check if the current Python installation (specifically, pyconfig.h)
355+ appears amenable to building extensions with GCC. Returns a tuple
356+ (status, details), where 'status' is one of the following constants:
357+ CONFIG_H_OK
358+ all is well, go ahead and compile
359+ CONFIG_H_NOTOK
360+ doesn't look good
361+ CONFIG_H_UNCERTAIN
362+ not sure -- unable to read pyconfig.h
330363 'details' is a human-readable string explaining the situation.
331364
332365 Note there are two ways to conclude "OK": either 'sys.version' contains
@@ -337,45 +370,78 @@ def check_config_h():
337370 # XXX since this function also checks sys.version, it's not strictly a
338371 # "pyconfig.h" check -- should probably be renamed...
339372
340- _sysconfig = __import__ ('sysconfig' )
373+ from distutils import sysconfig
374+ import string
375+ # if sys.version contains GCC then python was compiled with
376+ # GCC, and the pyconfig.h file should be OK
377+ if string .find (sys .version ,"GCC" ) >= 0 :
378+ return (CONFIG_H_OK , "sys.version mentions 'GCC'" )
341379
342- # if sys.version contains GCC then python was compiled with GCC, and the
343- # pyconfig.h file should be OK
344- if "GCC" in sys .version :
345- return CONFIG_H_OK , "sys.version mentions 'GCC'"
346-
347- # let's see if __GNUC__ is mentioned in python.h
348- fn = _sysconfig .get_config_h_filename ()
380+ fn = sysconfig .get_config_h_filename ()
349381 try :
350- with open (fn ) as config_h :
351- if "__GNUC__" in config_h .read ():
352- return CONFIG_H_OK , "'%s' mentions '__GNUC__'" % fn
353- else :
354- return CONFIG_H_NOTOK , "'%s' does not mention '__GNUC__'" % fn
382+ # It would probably better to read single lines to search.
383+ # But we do this only once, and it is fast enough
384+ f = open (fn )
385+ s = f .read ()
386+ f .close ()
387+
355388 except IOError , exc :
389+ # if we can't read this file, we cannot say it is wrong
390+ # the compiler will complain later about this file as missing
356391 return (CONFIG_H_UNCERTAIN ,
357392 "couldn't read '%s': %s" % (fn , exc .strerror ))
358393
359- class _Deprecated_SRE_Pattern (object ):
360- def __init__ (self , pattern ):
361- self .pattern = pattern
394+ else :
395+ # "pyconfig.h" contains an "#ifdef __GNUC__" or something similar
396+ if string .find (s ,"__GNUC__" ) >= 0 :
397+ return (CONFIG_H_OK , "'%s' mentions '__GNUC__'" % fn )
398+ else :
399+ return (CONFIG_H_NOTOK , "'%s' does not mention '__GNUC__'" % fn )
362400
363- def __getattr__ (self , name ):
364- if name in ('findall' , 'finditer' , 'match' , 'scanner' , 'search' ,
365- 'split' , 'sub' , 'subn' ):
366- warn ("'distutils.cygwinccompiler.RE_VERSION' is deprecated "
367- "and will be removed in the next version" , DeprecationWarning )
368- return getattr (self .pattern , name )
369401
370- RE_VERSION = _Deprecated_SRE_Pattern (re .compile ('(\d+\.\d+(\.\d+)*)' ))
371402
372403def get_versions ():
373404 """ Try to find out the versions of gcc, ld and dllwrap.
374-
375- If not possible it returns None for it.
405+ If not possible it returns None for it.
376406 """
377- warn ("'distutils.cygwinccompiler.get_versions' is deprecated "
378- "use 'distutils.util.get_compiler_versions' instead" ,
379- DeprecationWarning )
380-
381- return get_compiler_versions ()
407+ from distutils .version import LooseVersion
408+ from distutils .spawn import find_executable
409+ import re
410+
411+ gcc_exe = find_executable ('gcc' )
412+ if gcc_exe :
413+ out = os .popen (gcc_exe + ' -dumpversion' ,'r' )
414+ out_string = out .read ()
415+ out .close ()
416+ result = re .search ('(\d+\.\d+(\.\d+)*)' ,out_string )
417+ if result :
418+ gcc_version = LooseVersion (result .group (1 ))
419+ else :
420+ gcc_version = None
421+ else :
422+ gcc_version = None
423+ ld_exe = find_executable ('ld' )
424+ if ld_exe :
425+ out = os .popen (ld_exe + ' -v' ,'r' )
426+ out_string = out .read ()
427+ out .close ()
428+ result = re .search ('(\d+\.\d+(\.\d+)*)' ,out_string )
429+ if result :
430+ ld_version = LooseVersion (result .group (1 ))
431+ else :
432+ ld_version = None
433+ else :
434+ ld_version = None
435+ dllwrap_exe = find_executable ('dllwrap' )
436+ if dllwrap_exe :
437+ out = os .popen (dllwrap_exe + ' --version' ,'r' )
438+ out_string = out .read ()
439+ out .close ()
440+ result = re .search (' (\d+\.\d+(\.\d+)*)' ,out_string )
441+ if result :
442+ dllwrap_version = LooseVersion (result .group (1 ))
443+ else :
444+ dllwrap_version = None
445+ else :
446+ dllwrap_version = None
447+ return (gcc_version , ld_version , dllwrap_version )
0 commit comments