Commit 015c8103 authored by Tarek Ziadé's avatar Tarek Ziadé

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
........
parent fde29be4
...@@ -47,12 +47,19 @@ cygwin in no-cygwin mode). ...@@ -47,12 +47,19 @@ cygwin in no-cygwin mode).
__revision__ = "$Id$" __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.ccompiler import gen_preprocess_options, gen_lib_options
from distutils.unixccompiler import UnixCCompiler from distutils.unixccompiler import UnixCCompiler
from distutils.file_util import write_file from distutils.file_util import write_file
from distutils.errors import DistutilsExecError, CompileError, UnknownFileError from distutils.errors import DistutilsExecError, CompileError, UnknownFileError
from distutils import log from distutils import log
from distutils.version import LooseVersion
from distutils.spawn import find_executable
def get_msvcr(): def get_msvcr():
"""Include the appropriate MSVC runtime library if Python was built """Include the appropriate MSVC runtime library if Python was built
...@@ -347,16 +354,16 @@ CONFIG_H_NOTOK = "not ok" ...@@ -347,16 +354,16 @@ CONFIG_H_NOTOK = "not ok"
CONFIG_H_UNCERTAIN = "uncertain" CONFIG_H_UNCERTAIN = "uncertain"
def check_config_h(): 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. 'details' is a human-readable string explaining the situation.
Note there are two ways to conclude "OK": either 'sys.version' contains Note there are two ways to conclude "OK": either 'sys.version' contains
...@@ -368,76 +375,49 @@ def check_config_h(): ...@@ -368,76 +375,49 @@ def check_config_h():
# "pyconfig.h" check -- should probably be renamed... # "pyconfig.h" check -- should probably be renamed...
from distutils import sysconfig 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() fn = sysconfig.get_config_h_filename()
try: try:
# It would probably better to read single lines to search. with open(fn) as config_h:
# But we do this only once, and it is fast enough if "__GNUC__" in config_h.read():
f = open(fn) return CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn
s = f.read() else:
f.close() return CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn
except IOError as exc: 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, return (CONFIG_H_UNCERTAIN,
"couldn't read '%s': %s" % (fn, exc.strerror)) "couldn't read '%s': %s" % (fn, exc.strerror))
else: RE_VERSION = re.compile('(\d+\.\d+(\.\d+)*)')
# "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)
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(): def get_versions():
""" Try to find out the versions of gcc, ld and dllwrap. """ 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 not possible it returns None for it.
if gcc_exe: """
out = os.popen(gcc_exe + ' -dumpversion','r') commands = ['gcc -dumpversion', 'ld -v', 'dllwrap --version']
out_string = out.read() return tuple([_find_exe_version(cmd) for cmd in commands])
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)
"""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())
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment