14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport sys
24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport os
34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport tempfile
44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport shutil
54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom StringIO import StringIO
64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport textwrap
74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom distutils.core import Extension, Distribution
94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom distutils.command.build_ext import build_ext
104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom distutils import sysconfig
114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom distutils.tests import support
124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom distutils.errors import DistutilsSetupError, CompileError
134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport unittest
154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom test import test_support
164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# http://bugs.python.org/issue4373
184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Don't load the xx module more than once.
194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmALREADY_TESTED = False
204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef _get_source_filename():
224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    srcdir = sysconfig.get_config_var('srcdir')
234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    if srcdir is None:
244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return os.path.join(sysconfig.project_base, 'Modules', 'xxmodule.c')
254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return os.path.join(srcdir, 'Modules', 'xxmodule.c')
264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm_XX_MODULE_PATH = _get_source_filename()
284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass BuildExtTestCase(support.TempdirManager,
304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       support.LoggingSilencer,
314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       unittest.TestCase):
324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def setUp(self):
334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Create a simple test environment
344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Note that we're making changes to sys.path
354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        super(BuildExtTestCase, self).setUp()
364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.tmp_dir = tempfile.mkdtemp(prefix="pythontest_")
374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if os.path.exists(_XX_MODULE_PATH):
384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.sys_path = sys.path[:]
394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            sys.path.append(self.tmp_dir)
404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            shutil.copy(_XX_MODULE_PATH, self.tmp_dir)
414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def tearDown(self):
434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Get everything back to normal
444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if os.path.exists(_XX_MODULE_PATH):
454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            test_support.unload('xx')
464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            sys.path[:] = self.sys_path
474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # XXX on Windows the test leaves a directory
484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # with xx module in TEMP
494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        shutil.rmtree(self.tmp_dir, os.name == 'nt' or
504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                    sys.platform == 'cygwin')
514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        super(BuildExtTestCase, self).tearDown()
524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def _fixup_command(self, cmd):
544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # When Python was build with --enable-shared, -L. is not good enough
554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # to find the libpython<blah>.so.  This is because regrtest runs it
564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # under a tempdir, not in the top level where the .so lives.  By the
574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # time we've gotten here, Python's already been chdir'd to the
584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # tempdir.
594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #
604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # To further add to the fun, we can't just add library_dirs to the
614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Extension() instance because that doesn't get plumbed through to the
624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # final compiler command.
634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if (sysconfig.get_config_var('Py_ENABLE_SHARED') and
644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            not sys.platform.startswith('win')):
654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            runshared = sysconfig.get_config_var('RUNSHARED')
664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if runshared is None:
674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                cmd.library_dirs = ['.']
684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else:
694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                name, equals, value = runshared.partition('=')
704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                cmd.library_dirs = value.split(os.pathsep)
714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    @unittest.skipIf(not os.path.exists(_XX_MODULE_PATH),
734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                     'xxmodule.c not found')
744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_build_ext(self):
754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        global ALREADY_TESTED
764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        xx_c = os.path.join(self.tmp_dir, 'xxmodule.c')
774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        xx_ext = Extension('xx', [xx_c])
784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dist = Distribution({'name': 'xx', 'ext_modules': [xx_ext]})
794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dist.package_dir = self.tmp_dir
804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._fixup_command(cmd)
824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if os.name == "nt":
834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # On Windows, we must build a debug version iff running
844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # a debug build of Python
854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cmd.debug = sys.executable.endswith("_d.exe")
864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.build_lib = self.tmp_dir
874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.build_temp = self.tmp_dir
884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        old_stdout = sys.stdout
904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if not test_support.verbose:
914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # silence compiler output
924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            sys.stdout = StringIO()
934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cmd.ensure_finalized()
954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cmd.run()
964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        finally:
974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            sys.stdout = old_stdout
984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if ALREADY_TESTED:
1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return
1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ALREADY_TESTED = True
1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import xx
1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for attr in ('error', 'foo', 'new', 'roj'):
1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertTrue(hasattr(xx, attr))
1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(xx.foo(2, 5), 7)
1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(xx.foo(13,15), 28)
1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(xx.new().demo(), None)
1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        doc = 'This is a template module just for instruction.'
1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(xx.__doc__, doc)
1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(isinstance(xx.Null(), xx.Null))
1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(isinstance(xx.Str(), xx.Str))
1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_solaris_enable_shared(self):
1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dist = Distribution({'name': 'xx'})
1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        old = sys.platform
1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        sys.platform = 'sunos' # fooling finalize_options
1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        from distutils.sysconfig import  _config_vars
1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        old_var = _config_vars.get('Py_ENABLE_SHARED')
1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        _config_vars['Py_ENABLE_SHARED'] = 1
1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cmd.ensure_finalized()
1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        finally:
1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            sys.platform = old
1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            if old_var is None:
1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                del _config_vars['Py_ENABLE_SHARED']
1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else:
1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                _config_vars['Py_ENABLE_SHARED'] = old_var
1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # make sure we get some library dirs under solaris
1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(len(cmd.library_dirs) > 0)
1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_finalize_options(self):
1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Make sure Python's include directories (for Python.h, pyconfig.h,
1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # etc.) are in the include search path.
1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        modules = [Extension('foo', ['xxx'])]
1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dist = Distribution({'name': 'xx', 'ext_modules': modules})
1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.finalize_options()
1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        from distutils import sysconfig
1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        py_include = sysconfig.get_python_inc()
1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(py_include in cmd.include_dirs)
1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        plat_py_include = sysconfig.get_python_inc(plat_specific=1)
1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(plat_py_include in cmd.include_dirs)
1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # make sure cmd.libraries is turned into a list
1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # if it's a string
1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.libraries = 'my_lib'
1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.finalize_options()
1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cmd.libraries, ['my_lib'])
1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # make sure cmd.library_dirs is turned into a list
1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # if it's a string
1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.library_dirs = 'my_lib_dir'
1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.finalize_options()
1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue('my_lib_dir' in cmd.library_dirs)
1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # make sure rpath is turned into a list
1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # if it's a list of os.pathsep's paths
1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.rpath = os.pathsep.join(['one', 'two'])
1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.finalize_options()
1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cmd.rpath, ['one', 'two'])
1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # XXX more tests to perform for win32
1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # make sure define is turned into 2-tuples
1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # strings if they are ','-separated strings
1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.define = 'one,two'
1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.finalize_options()
1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cmd.define, [('one', '1'), ('two', '1')])
1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # make sure undef is turned into a list of
1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # strings if they are ','-separated strings
1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.undef = 'one,two'
1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.finalize_options()
1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cmd.undef, ['one', 'two'])
1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # make sure swig_opts is turned into a list
1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.swig_opts = None
1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.finalize_options()
1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cmd.swig_opts, [])
1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.swig_opts = '1 2'
1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.finalize_options()
1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cmd.swig_opts, ['1', '2'])
2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_check_extensions_list(self):
2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dist = Distribution()
2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.finalize_options()
2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        #'extensions' option must be a list of Extension instances
2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, 'foo')
2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # each element of 'ext_modules' option must be an
2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # Extension instance or 2-tuple
2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        exts = [('bar', 'foo', 'bar'), 'foo']
2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # first element of each tuple in 'ext_modules'
2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # must be the extension name (a string) and match
2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # a python dotted-separated name
2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        exts = [('foo-bar', '')]
2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # second element of each tuple in 'ext_modules'
2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # must be a ary (build info)
2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        exts = [('foo.bar', '')]
2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # ok this one should pass
2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        exts = [('foo.bar', {'sources': [''], 'libraries': 'foo',
2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             'some': 'bar'})]
2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.check_extensions_list(exts)
2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ext = exts[0]
2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(isinstance(ext, Extension))
2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # check_extensions_list adds in ext the values passed
2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # when they are in ('include_dirs', 'library_dirs', 'libraries'
2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # 'extra_objects', 'extra_compile_args', 'extra_link_args')
2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(ext.libraries, 'foo')
2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(not hasattr(ext, 'some'))
2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # 'macros' element of build info dict must be 1- or 2-tuple
2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        exts = [('foo.bar', {'sources': [''], 'libraries': 'foo',
2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                'some': 'bar', 'macros': [('1', '2', '3'), 'foo']})]
2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        exts[0][1]['macros'] = [('1', '2'), ('3',)]
2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.check_extensions_list(exts)
2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(exts[0].undef_macros, ['3'])
2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(exts[0].define_macros, [('1', '2')])
2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_get_source_files(self):
2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        modules = [Extension('foo', ['xxx'])]
2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dist = Distribution({'name': 'xx', 'ext_modules': modules})
2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.ensure_finalized()
2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cmd.get_source_files(), ['xxx'])
2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_compiler_option(self):
2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # cmd.compiler is an option and
2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # should not be overriden by a compiler instance
2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # when the command is run
2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dist = Distribution()
2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.compiler = 'unix'
2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.ensure_finalized()
2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.run()
2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(cmd.compiler, 'unix')
2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_get_outputs(self):
2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        tmp_dir = self.mkdtemp()
2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        c_file = os.path.join(tmp_dir, 'foo.c')
2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.write_file(c_file, 'void initfoo(void) {};\n')
2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ext = Extension('foo', [c_file])
2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dist = Distribution({'name': 'xx',
2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                             'ext_modules': [ext]})
2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._fixup_command(cmd)
2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.ensure_finalized()
2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(len(cmd.get_outputs()), 1)
2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if os.name == "nt":
2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cmd.debug = sys.executable.endswith("_d.exe")
2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.build_lib = os.path.join(self.tmp_dir, 'build')
2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.build_temp = os.path.join(self.tmp_dir, 'tempt')
2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # issue #5977 : distutils build_ext.get_outputs
2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # returns wrong result with --inplace
2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        other_tmp_dir = os.path.realpath(self.mkdtemp())
2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        old_wd = os.getcwd()
2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        os.chdir(other_tmp_dir)
2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cmd.inplace = 1
2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cmd.run()
2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            so_file = cmd.get_outputs()[0]
2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        finally:
2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            os.chdir(old_wd)
2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(os.path.exists(so_file))
2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(os.path.splitext(so_file)[-1],
2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         sysconfig.get_config_var('SO'))
2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        so_dir = os.path.dirname(so_file)
2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(so_dir, other_tmp_dir)
3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.compiler = None
3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.inplace = 0
3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.run()
3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        so_file = cmd.get_outputs()[0]
3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertTrue(os.path.exists(so_file))
3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(os.path.splitext(so_file)[-1],
3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                         sysconfig.get_config_var('SO'))
3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        so_dir = os.path.dirname(so_file)
3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(so_dir, cmd.build_lib)
3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # inplace = 0, cmd.package = 'bar'
3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        build_py = cmd.get_finalized_command('build_py')
3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        build_py.package_dir = {'': 'bar'}
3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        path = cmd.get_ext_fullpath('foo')
3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # checking that the last directory is the build_dir
3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        path = os.path.split(path)[0]
3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(path, cmd.build_lib)
3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # inplace = 1, cmd.package = 'bar'
3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.inplace = 1
3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        other_tmp_dir = os.path.realpath(self.mkdtemp())
3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        old_wd = os.getcwd()
3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        os.chdir(other_tmp_dir)
3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            path = cmd.get_ext_fullpath('foo')
3254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        finally:
3264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            os.chdir(old_wd)
3274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # checking that the last directory is bar
3284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        path = os.path.split(path)[0]
3294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        lastdir = os.path.split(path)[-1]
3304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(lastdir, 'bar')
3314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_ext_fullpath(self):
3334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ext = sysconfig.get_config_vars()['SO']
3344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dist = Distribution()
3354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
3364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.inplace = 1
3374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.distribution.package_dir = {'': 'src'}
3384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.distribution.packages = ['lxml', 'lxml.html']
3394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        curdir = os.getcwd()
3404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        wanted = os.path.join(curdir, 'src', 'lxml', 'etree' + ext)
3414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        path = cmd.get_ext_fullpath('lxml.etree')
3424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(wanted, path)
3434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # building lxml.etree not inplace
3454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.inplace = 0
3464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.build_lib = os.path.join(curdir, 'tmpdir')
3474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        wanted = os.path.join(curdir, 'tmpdir', 'lxml', 'etree' + ext)
3484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        path = cmd.get_ext_fullpath('lxml.etree')
3494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(wanted, path)
3504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # building twisted.runner.portmap not inplace
3524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        build_py = cmd.get_finalized_command('build_py')
3534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        build_py.package_dir = {}
3544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.distribution.packages = ['twisted', 'twisted.runner.portmap']
3554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        path = cmd.get_ext_fullpath('twisted.runner.portmap')
3564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        wanted = os.path.join(curdir, 'tmpdir', 'twisted', 'runner',
3574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                              'portmap' + ext)
3584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(wanted, path)
3594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # building twisted.runner.portmap inplace
3614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.inplace = 1
3624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        path = cmd.get_ext_fullpath('twisted.runner.portmap')
3634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        wanted = os.path.join(curdir, 'twisted', 'runner', 'portmap' + ext)
3644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(wanted, path)
3654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_build_ext_inplace(self):
3674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        etree_c = os.path.join(self.tmp_dir, 'lxml.etree.c')
3684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        etree_ext = Extension('lxml.etree', [etree_c])
3694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dist = Distribution({'name': 'lxml', 'ext_modules': [etree_ext]})
3704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
3714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.ensure_finalized()
3724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.inplace = 1
3734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.distribution.package_dir = {'': 'src'}
3744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.distribution.packages = ['lxml', 'lxml.html']
3754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        curdir = os.getcwd()
3764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ext = sysconfig.get_config_var("SO")
3774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        wanted = os.path.join(curdir, 'src', 'lxml', 'etree' + ext)
3784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        path = cmd.get_ext_fullpath('lxml.etree')
3794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(wanted, path)
3804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_setuptools_compat(self):
3824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        import distutils.core, distutils.extension, distutils.command.build_ext
3834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        saved_ext = distutils.extension.Extension
3844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
3854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # on some platforms, it loads the deprecated "dl" module
3864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            test_support.import_module('setuptools_build_ext', deprecated=True)
3874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # theses import patch Distutils' Extension class
3894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            from setuptools_build_ext import build_ext as setuptools_build_ext
3904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            from setuptools_extension import Extension
3914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            etree_c = os.path.join(self.tmp_dir, 'lxml.etree.c')
3934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            etree_ext = Extension('lxml.etree', [etree_c])
3944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            dist = Distribution({'name': 'lxml', 'ext_modules': [etree_ext]})
3954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cmd = setuptools_build_ext(dist)
3964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cmd.ensure_finalized()
3974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cmd.inplace = 1
3984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cmd.distribution.package_dir = {'': 'src'}
3994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cmd.distribution.packages = ['lxml', 'lxml.html']
4004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            curdir = os.getcwd()
4014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            ext = sysconfig.get_config_var("SO")
4024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            wanted = os.path.join(curdir, 'src', 'lxml', 'etree' + ext)
4034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            path = cmd.get_ext_fullpath('lxml.etree')
4044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.assertEqual(wanted, path)
4054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        finally:
4064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            # restoring Distutils' Extension class otherwise its broken
4074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            distutils.extension.Extension = saved_ext
4084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            distutils.core.Extension = saved_ext
4094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            distutils.command.build_ext.Extension = saved_ext
4104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_build_ext_path_with_os_sep(self):
4124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dist = Distribution({'name': 'UpdateManager'})
4134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
4144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.ensure_finalized()
4154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ext = sysconfig.get_config_var("SO")
4164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ext_name = os.path.join('UpdateManager', 'fdsend')
4174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ext_path = cmd.get_ext_fullpath(ext_name)
4184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        wanted = os.path.join(cmd.build_lib, 'UpdateManager', 'fdsend' + ext)
4194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(ext_path, wanted)
4204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_build_ext_path_cross_platform(self):
4224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if sys.platform != 'win32':
4234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return
4244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dist = Distribution({'name': 'UpdateManager'})
4254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
4264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.ensure_finalized()
4274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ext = sysconfig.get_config_var("SO")
4284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # this needs to work even under win32
4294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ext_name = 'UpdateManager/fdsend'
4304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        ext_path = cmd.get_ext_fullpath(ext_name)
4314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        wanted = os.path.join(cmd.build_lib, 'UpdateManager', 'fdsend' + ext)
4324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(ext_path, wanted)
4334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    @unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for MacOSX')
4354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_deployment_target(self):
4364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._try_compile_deployment_target()
4374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        orig_environ = os.environ
4394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        os.environ = orig_environ.copy()
4404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.addCleanup(setattr, os, 'environ', orig_environ)
4414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        os.environ['MACOSX_DEPLOYMENT_TARGET']='10.1'
4434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self._try_compile_deployment_target()
4444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def _try_compile_deployment_target(self):
4474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        deptarget_c = os.path.join(self.tmp_dir, 'deptargetmodule.c')
4484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        with open(deptarget_c, 'w') as fp:
4504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            fp.write(textwrap.dedent('''\
4514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                #include <AvailabilityMacros.h>
4524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                int dummy;
4544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                #if TARGET != MAC_OS_X_VERSION_MIN_REQUIRED
4564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                #error "Unexpected target"
4574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm               #endif
4584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            '''))
4604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
4624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        target = tuple(map(int, target.split('.')))
4634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        target = '%02d%01d0' % target
4644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        deptarget_ext = Extension(
4664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'deptarget',
4674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            [deptarget_c],
4684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            extra_compile_args=['-DTARGET=%s'%(target,)],
4694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        )
4704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dist = Distribution({
4714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'name': 'deptarget',
4724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            'ext_modules': [deptarget_ext]
4734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        })
4744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        dist.package_dir = self.tmp_dir
4754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd = build_ext(dist)
4764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.build_lib = self.tmp_dir
4774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        cmd.build_temp = self.tmp_dir
4784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
4804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            old_stdout = sys.stdout
4814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cmd.ensure_finalized()
4824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            cmd.run()
4834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except CompileError:
4854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.fail("Wrong deployment target during compilation")
4864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef test_suite():
4884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return unittest.makeSuite(BuildExtTestCase)
4894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
4904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmif __name__ == '__main__':
4914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    test_support.run_unittest(test_suite())
492