4747
4848__revision__ = "$Id$"
4949
50- import os ,sys ,copy
50+ import os
51+ import sys
52+ import copy
53+ from subprocess import Popen , PIPE
54+ import re
55+
5156from distutils .ccompiler import gen_preprocess_options , gen_lib_options
5257from distutils .unixccompiler import UnixCCompiler
5358from distutils .file_util import write_file
5459from distutils .errors import DistutilsExecError , CompileError , UnknownFileError
5560from distutils import log
61+ from distutils .version import LooseVersion
62+ from distutils .spawn import find_executable
5663
5764def get_msvcr ():
5865 """Include the appropriate MSVC runtime library if Python was built
@@ -347,16 +354,16 @@ def __init__ (self,
347354CONFIG_H_UNCERTAIN = "uncertain"
348355
349356def check_config_h ():
357+ """Check if the current Python installation appears amenable to building
358+ extensions with GCC.
359+
360+ Returns a tuple (status, details), where 'status' is one of the following
361+ constants:
362+
363+ - CONFIG_H_OK: all is well, go ahead and compile
364+ - CONFIG_H_NOTOK: doesn't look good
365+ - CONFIG_H_UNCERTAIN: not sure -- unable to read pyconfig.h
350366
351- """Check if the current Python installation (specifically, pyconfig.h)
352- appears amenable to building extensions with GCC. Returns a tuple
353- (status, details), where 'status' is one of the following constants:
354- CONFIG_H_OK
355- all is well, go ahead and compile
356- CONFIG_H_NOTOK
357- doesn't look good
358- CONFIG_H_UNCERTAIN
359- not sure -- unable to read pyconfig.h
360367 'details' is a human-readable string explaining the situation.
361368
362369 Note there are two ways to conclude "OK": either 'sys.version' contains
@@ -368,76 +375,49 @@ def check_config_h():
368375 # "pyconfig.h" check -- should probably be renamed...
369376
370377 from distutils import sysconfig
371- # if sys.version contains GCC then python was compiled with
372- # GCC, and the pyconfig.h file should be OK
373- if sys .version .find ("GCC" ) >= 0 :
374- return (CONFIG_H_OK , "sys.version mentions 'GCC'" )
375378
379+ # if sys.version contains GCC then python was compiled with GCC, and the
380+ # pyconfig.h file should be OK
381+ if "GCC" in sys .version :
382+ return CONFIG_H_OK , "sys.version mentions 'GCC'"
383+
384+ # let's see if __GNUC__ is mentioned in python.h
376385 fn = sysconfig .get_config_h_filename ()
377386 try :
378- # It would probably better to read single lines to search.
379- # But we do this only once, and it is fast enough
380- f = open (fn )
381- s = f .read ()
382- f .close ()
383-
387+ with open (fn ) as config_h :
388+ if "__GNUC__" in config_h .read ():
389+ return CONFIG_H_OK , "'%s' mentions '__GNUC__'" % fn
390+ else :
391+ return CONFIG_H_NOTOK , "'%s' does not mention '__GNUC__'" % fn
384392 except IOError as exc :
385- # if we can't read this file, we cannot say it is wrong
386- # the compiler will complain later about this file as missing
387393 return (CONFIG_H_UNCERTAIN ,
388394 "couldn't read '%s': %s" % (fn , exc .strerror ))
389395
390- else :
391- # "pyconfig.h" contains an "#ifdef __GNUC__" or something similar
392- if s .find ("__GNUC__" ) >= 0 :
393- return (CONFIG_H_OK , "'%s' mentions '__GNUC__'" % fn )
394- else :
395- return (CONFIG_H_NOTOK , "'%s' does not mention '__GNUC__'" % fn )
396+ RE_VERSION = re .compile ('(\d+\.\d+(\.\d+)*)' )
396397
398+ def _find_exe_version (cmd ):
399+ """Find the version of an executable by running `cmd` in the shell.
397400
401+ If the command is not found, or the output does not match
402+ `RE_VERSION`, returns None.
403+ """
404+ executable = cmd .split ()[0 ]
405+ if find_executable (executable ) is None :
406+ return None
407+ out = Popen (cmd , shell = True , stdout = PIPE ).stdout
408+ try :
409+ out_string = out .read ()
410+ finally :
411+ out .close ()
412+ result = RE_VERSION .search (out_string )
413+ if result is None :
414+ return None
415+ return LooseVersion (result .group (1 ))
398416
399417def get_versions ():
400418 """ Try to find out the versions of gcc, ld and dllwrap.
401- If not possible it returns None for it.
402- """
403- from distutils .version import LooseVersion
404- from distutils .spawn import find_executable
405- import re
406419
407- gcc_exe = find_executable ('gcc' )
408- if gcc_exe :
409- out = os .popen (gcc_exe + ' -dumpversion' ,'r' )
410- out_string = out .read ()
411- out .close ()
412- result = re .search ('(\d+\.\d+(\.\d+)*)' , out_string , re .ASCII )
413- if result :
414- gcc_version = LooseVersion (result .group (1 ))
415- else :
416- gcc_version = None
417- else :
418- gcc_version = None
419- ld_exe = find_executable ('ld' )
420- if ld_exe :
421- out = os .popen (ld_exe + ' -v' ,'r' )
422- out_string = out .read ()
423- out .close ()
424- result = re .search ('(\d+\.\d+(\.\d+)*)' , out_string , re .ASCII )
425- if result :
426- ld_version = LooseVersion (result .group (1 ))
427- else :
428- ld_version = None
429- else :
430- ld_version = None
431- dllwrap_exe = find_executable ('dllwrap' )
432- if dllwrap_exe :
433- out = os .popen (dllwrap_exe + ' --version' ,'r' )
434- out_string = out .read ()
435- out .close ()
436- result = re .search (' (\d+\.\d+(\.\d+)*)' , out_string , re .ASCII )
437- if result :
438- dllwrap_version = LooseVersion (result .group (1 ))
439- else :
440- dllwrap_version = None
441- else :
442- dllwrap_version = None
443- return (gcc_version , ld_version , dllwrap_version )
420+ If not possible it returns None for it.
421+ """
422+ commands = ['gcc -dumpversion' , 'ld -v' , 'dllwrap --version' ]
423+ return tuple ([_find_exe_version (cmd ) for cmd in commands ])
0 commit comments