Merged revisions 73336 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r73336 | tarek.ziade | 2009-06-10 20:49:50 +0200 (Wed, 10 Jun 2009) | 1 line Distutils: started code cleanup and test coverage for cygwinccompiler ........
This commit is contained in:
parent
fde29be4d7
commit
015c8103b1
|
@ -47,12 +47,19 @@ cygwin in no-cygwin mode).
|
|||
|
||||
__revision__ = "$Id$"
|
||||
|
||||
import os,sys,copy
|
||||
import os
|
||||
import sys
|
||||
import copy
|
||||
from subprocess import Popen, PIPE
|
||||
import re
|
||||
|
||||
from distutils.ccompiler import gen_preprocess_options, gen_lib_options
|
||||
from distutils.unixccompiler import UnixCCompiler
|
||||
from distutils.file_util import write_file
|
||||
from distutils.errors import DistutilsExecError, CompileError, UnknownFileError
|
||||
from distutils import log
|
||||
from distutils.version import LooseVersion
|
||||
from distutils.spawn import find_executable
|
||||
|
||||
def get_msvcr():
|
||||
"""Include the appropriate MSVC runtime library if Python was built
|
||||
|
@ -347,16 +354,16 @@ CONFIG_H_NOTOK = "not ok"
|
|||
CONFIG_H_UNCERTAIN = "uncertain"
|
||||
|
||||
def check_config_h():
|
||||
"""Check if the current Python installation appears amenable to building
|
||||
extensions with GCC.
|
||||
|
||||
Returns a tuple (status, details), where 'status' is one of the following
|
||||
constants:
|
||||
|
||||
- CONFIG_H_OK: all is well, go ahead and compile
|
||||
- CONFIG_H_NOTOK: doesn't look good
|
||||
- CONFIG_H_UNCERTAIN: not sure -- unable to read pyconfig.h
|
||||
|
||||
"""Check if the current Python installation (specifically, pyconfig.h)
|
||||
appears amenable to building extensions with GCC. Returns a tuple
|
||||
(status, details), where 'status' is one of the following constants:
|
||||
CONFIG_H_OK
|
||||
all is well, go ahead and compile
|
||||
CONFIG_H_NOTOK
|
||||
doesn't look good
|
||||
CONFIG_H_UNCERTAIN
|
||||
not sure -- unable to read pyconfig.h
|
||||
'details' is a human-readable string explaining the situation.
|
||||
|
||||
Note there are two ways to conclude "OK": either 'sys.version' contains
|
||||
|
@ -368,76 +375,49 @@ def check_config_h():
|
|||
# "pyconfig.h" check -- should probably be renamed...
|
||||
|
||||
from distutils import sysconfig
|
||||
# if sys.version contains GCC then python was compiled with
|
||||
# GCC, and the pyconfig.h file should be OK
|
||||
if sys.version.find("GCC") >= 0:
|
||||
return (CONFIG_H_OK, "sys.version mentions 'GCC'")
|
||||
|
||||
# if sys.version contains GCC then python was compiled with GCC, and the
|
||||
# pyconfig.h file should be OK
|
||||
if "GCC" in sys.version:
|
||||
return CONFIG_H_OK, "sys.version mentions 'GCC'"
|
||||
|
||||
# let's see if __GNUC__ is mentioned in python.h
|
||||
fn = sysconfig.get_config_h_filename()
|
||||
try:
|
||||
# It would probably better to read single lines to search.
|
||||
# But we do this only once, and it is fast enough
|
||||
f = open(fn)
|
||||
s = f.read()
|
||||
f.close()
|
||||
|
||||
with open(fn) as config_h:
|
||||
if "__GNUC__" in config_h.read():
|
||||
return CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn
|
||||
else:
|
||||
return CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn
|
||||
except IOError as exc:
|
||||
# if we can't read this file, we cannot say it is wrong
|
||||
# the compiler will complain later about this file as missing
|
||||
return (CONFIG_H_UNCERTAIN,
|
||||
"couldn't read '%s': %s" % (fn, exc.strerror))
|
||||
|
||||
else:
|
||||
# "pyconfig.h" contains an "#ifdef __GNUC__" or something similar
|
||||
if s.find("__GNUC__") >= 0:
|
||||
return (CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn)
|
||||
else:
|
||||
return (CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn)
|
||||
RE_VERSION = re.compile('(\d+\.\d+(\.\d+)*)')
|
||||
|
||||
def _find_exe_version(cmd):
|
||||
"""Find the version of an executable by running `cmd` in the shell.
|
||||
|
||||
If the command is not found, or the output does not match
|
||||
`RE_VERSION`, returns None.
|
||||
"""
|
||||
executable = cmd.split()[0]
|
||||
if find_executable(executable) is None:
|
||||
return None
|
||||
out = Popen(cmd, shell=True, stdout=PIPE).stdout
|
||||
try:
|
||||
out_string = out.read()
|
||||
finally:
|
||||
out.close()
|
||||
result = RE_VERSION.search(out_string)
|
||||
if result is None:
|
||||
return None
|
||||
return LooseVersion(result.group(1))
|
||||
|
||||
def get_versions():
|
||||
""" Try to find out the versions of gcc, ld and dllwrap.
|
||||
If not possible it returns None for it.
|
||||
"""
|
||||
from distutils.version import LooseVersion
|
||||
from distutils.spawn import find_executable
|
||||
import re
|
||||
|
||||
gcc_exe = find_executable('gcc')
|
||||
if gcc_exe:
|
||||
out = os.popen(gcc_exe + ' -dumpversion','r')
|
||||
out_string = out.read()
|
||||
out.close()
|
||||
result = re.search('(\d+\.\d+(\.\d+)*)', out_string, re.ASCII)
|
||||
if result:
|
||||
gcc_version = LooseVersion(result.group(1))
|
||||
else:
|
||||
gcc_version = None
|
||||
else:
|
||||
gcc_version = None
|
||||
ld_exe = find_executable('ld')
|
||||
if ld_exe:
|
||||
out = os.popen(ld_exe + ' -v','r')
|
||||
out_string = out.read()
|
||||
out.close()
|
||||
result = re.search('(\d+\.\d+(\.\d+)*)', out_string, re.ASCII)
|
||||
if result:
|
||||
ld_version = LooseVersion(result.group(1))
|
||||
else:
|
||||
ld_version = None
|
||||
else:
|
||||
ld_version = None
|
||||
dllwrap_exe = find_executable('dllwrap')
|
||||
if dllwrap_exe:
|
||||
out = os.popen(dllwrap_exe + ' --version','r')
|
||||
out_string = out.read()
|
||||
out.close()
|
||||
result = re.search(' (\d+\.\d+(\.\d+)*)', out_string, re.ASCII)
|
||||
if result:
|
||||
dllwrap_version = LooseVersion(result.group(1))
|
||||
else:
|
||||
dllwrap_version = None
|
||||
else:
|
||||
dllwrap_version = None
|
||||
return (gcc_version, ld_version, dllwrap_version)
|
||||
If not possible it returns None for it.
|
||||
"""
|
||||
commands = ['gcc -dumpversion', 'ld -v', 'dllwrap --version']
|
||||
return tuple([_find_exe_version(cmd) for cmd in commands])
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
"""Tests for distutils.cygwinccompiler."""
|
||||
import unittest
|
||||
import sys
|
||||
import os
|
||||
from io import StringIO
|
||||
import subprocess
|
||||
|
||||
from distutils import cygwinccompiler
|
||||
from distutils.cygwinccompiler import (CygwinCCompiler, check_config_h,
|
||||
CONFIG_H_OK, CONFIG_H_NOTOK,
|
||||
CONFIG_H_UNCERTAIN, get_versions)
|
||||
from distutils.tests import support
|
||||
|
||||
class FakePopen(object):
|
||||
test_class = None
|
||||
|
||||
def __init__(self, cmd, shell, stdout):
|
||||
self.cmd = cmd.split()[0]
|
||||
exes = self.test_class._exes
|
||||
if self.cmd in exes:
|
||||
self.stdout = StringIO(exes[self.cmd])
|
||||
else:
|
||||
self.stdout = os.popen(cmd, 'r')
|
||||
|
||||
|
||||
class CygwinCCompilerTestCase(support.TempdirManager,
|
||||
unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(CygwinCCompilerTestCase, self).setUp()
|
||||
self.version = sys.version
|
||||
self.python_h = os.path.join(self.mkdtemp(), 'python.h')
|
||||
from distutils import sysconfig
|
||||
self.old_get_config_h_filename = sysconfig.get_config_h_filename
|
||||
sysconfig.get_config_h_filename = self._get_config_h_filename
|
||||
self.old_find_executable = cygwinccompiler.find_executable
|
||||
cygwinccompiler.find_executable = self._find_executable
|
||||
self._exes = {}
|
||||
self.old_popen = cygwinccompiler.Popen
|
||||
FakePopen.test_class = self
|
||||
cygwinccompiler.Popen = FakePopen
|
||||
|
||||
def tearDown(self):
|
||||
sys.version = self.version
|
||||
from distutils import sysconfig
|
||||
sysconfig.get_config_h_filename = self.old_get_config_h_filename
|
||||
cygwinccompiler.find_executable = self.old_find_executable
|
||||
cygwinccompiler.Popen = self.old_popen
|
||||
super(CygwinCCompilerTestCase, self).tearDown()
|
||||
|
||||
def _get_config_h_filename(self):
|
||||
return self.python_h
|
||||
|
||||
def _find_executable(self, name):
|
||||
if name in self._exes:
|
||||
return name
|
||||
return None
|
||||
|
||||
def test_check_config_h(self):
|
||||
|
||||
# check_config_h looks for "GCC" in sys.version first
|
||||
# returns CONFIG_H_OK if found
|
||||
sys.version = ('2.6.1 (r261:67515, Dec 6 2008, 16:42:21) \n[GCC '
|
||||
'4.0.1 (Apple Computer, Inc. build 5370)]')
|
||||
|
||||
self.assertEquals(check_config_h()[0], CONFIG_H_OK)
|
||||
|
||||
# then it tries to see if it can find "__GNUC__" in pyconfig.h
|
||||
sys.version = 'something without the *CC word'
|
||||
|
||||
# if the file doesn't exist it returns CONFIG_H_UNCERTAIN
|
||||
self.assertEquals(check_config_h()[0], CONFIG_H_UNCERTAIN)
|
||||
|
||||
# if it exists but does not contain __GNUC__, it returns CONFIG_H_NOTOK
|
||||
self.write_file(self.python_h, 'xxx')
|
||||
self.assertEquals(check_config_h()[0], CONFIG_H_NOTOK)
|
||||
|
||||
# and CONFIG_H_OK if __GNUC__ is found
|
||||
self.write_file(self.python_h, 'xxx __GNUC__ xxx')
|
||||
self.assertEquals(check_config_h()[0], CONFIG_H_OK)
|
||||
|
||||
def test_get_versions(self):
|
||||
|
||||
# get_versions calls distutils.spawn.find_executable on
|
||||
# 'gcc', 'ld' and 'dllwrap'
|
||||
self.assertEquals(get_versions(), (None, None, None))
|
||||
|
||||
# Let's fake we have 'gcc' and it returns '3.4.5'
|
||||
self._exes['gcc'] = 'gcc (GCC) 3.4.5 (mingw special)\nFSF'
|
||||
res = get_versions()
|
||||
self.assertEquals(str(res[0]), '3.4.5')
|
||||
|
||||
# and let's see what happens when the version
|
||||
# doesn't match the regular expression
|
||||
# (\d+\.\d+(\.\d+)*)
|
||||
self._exes['gcc'] = 'very strange output'
|
||||
res = get_versions()
|
||||
self.assertEquals(res[0], None)
|
||||
|
||||
# same thing for ld
|
||||
self._exes['ld'] = 'GNU ld version 2.17.50 20060824'
|
||||
res = get_versions()
|
||||
self.assertEquals(str(res[1]), '2.17.50')
|
||||
self._exes['ld'] = '@(#)PROGRAM:ld PROJECT:ld64-77'
|
||||
res = get_versions()
|
||||
self.assertEquals(res[1], None)
|
||||
|
||||
# and dllwrap
|
||||
self._exes['dllwrap'] = 'GNU dllwrap 2.17.50 20060824\nFSF'
|
||||
res = get_versions()
|
||||
self.assertEquals(str(res[2]), '2.17.50')
|
||||
self._exes['dllwrap'] = 'Cheese Wrap'
|
||||
res = get_versions()
|
||||
self.assertEquals(res[2], None)
|
||||
|
||||
def test_suite():
|
||||
return unittest.makeSuite(CygwinCCompilerTestCase)
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_support.run_unittest(test_suite())
|
Loading…
Reference in New Issue