test_build_ext.py revision 1f70b878c4b890c66bdb90d8c9ddb59dee0b48df
188e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandlimport sys
288e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandlimport os
388e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandlfrom StringIO import StringIO
4a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussorenimport textwrap
588e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl
688e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandlfrom distutils.core import Extension, Distribution
788e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandlfrom distutils.command.build_ext import build_ext
8b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadéfrom distutils import sysconfig
91369900619d943d05342e7b781f1f3fb45ece4c9Tarek Ziadéfrom distutils.tests import support
10053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deilyfrom distutils.errors import (DistutilsSetupError, CompileError,
11053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily                              DistutilsPlatformError)
1288e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl
1388e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandlimport unittest
1488e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandlfrom test import test_support
1588e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl
166f1d93149505c5b69578549a440175c5b32942b7Tarek Ziadé# http://bugs.python.org/issue4373
176f1d93149505c5b69578549a440175c5b32942b7Tarek Ziadé# Don't load the xx module more than once.
186f1d93149505c5b69578549a440175c5b32942b7Tarek ZiadéALREADY_TESTED = False
196f1d93149505c5b69578549a440175c5b32942b7Tarek Ziadé
20a52f1c62eb8cce9fb7f78687b854d1d8c4dbe39fNeil Schemenauer
219e47ce49a06075adbc391e04b4457707fa3892a7Tarek Ziadéclass BuildExtTestCase(support.TempdirManager,
229e47ce49a06075adbc391e04b4457707fa3892a7Tarek Ziadé                       support.LoggingSilencer,
239e47ce49a06075adbc391e04b4457707fa3892a7Tarek Ziadé                       unittest.TestCase):
2488e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl    def setUp(self):
25dda92f7f02dbc0de94112599129d9d93192278d9Tarek Ziadé        super(BuildExtTestCase, self).setUp()
2604612d60929d5cda8d4cd215dfa2fc050d20b530Éric Araujo        self.tmp_dir = self.mkdtemp()
2704612d60929d5cda8d4cd215dfa2fc050d20b530Éric Araujo        self.xx_created = False
2804612d60929d5cda8d4cd215dfa2fc050d20b530Éric Araujo        sys.path.append(self.tmp_dir)
2904612d60929d5cda8d4cd215dfa2fc050d20b530Éric Araujo        self.addCleanup(sys.path.remove, self.tmp_dir)
30c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        if sys.version > "2.6":
31c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo            import site
32c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo            self.old_user_base = site.USER_BASE
33c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo            site.USER_BASE = self.mkdtemp()
34c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo            from distutils.command import build_ext
35c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo            build_ext.USER_BASE = site.USER_BASE
36ef253ac84e6fd11770ff78c56015a0e61c991fc4Tarek Ziadé
37ef253ac84e6fd11770ff78c56015a0e61c991fc4Tarek Ziadé    def tearDown(self):
3804612d60929d5cda8d4cd215dfa2fc050d20b530Éric Araujo        if self.xx_created:
39ef253ac84e6fd11770ff78c56015a0e61c991fc4Tarek Ziadé            test_support.unload('xx')
40ef253ac84e6fd11770ff78c56015a0e61c991fc4Tarek Ziadé            # XXX on Windows the test leaves a directory
41ef253ac84e6fd11770ff78c56015a0e61c991fc4Tarek Ziadé            # with xx module in TEMP
42ef253ac84e6fd11770ff78c56015a0e61c991fc4Tarek Ziadé        super(BuildExtTestCase, self).tearDown()
4388e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl
4488e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl    def test_build_ext(self):
456f1d93149505c5b69578549a440175c5b32942b7Tarek Ziadé        global ALREADY_TESTED
4604612d60929d5cda8d4cd215dfa2fc050d20b530Éric Araujo        support.copy_xxmodule_c(self.tmp_dir)
4704612d60929d5cda8d4cd215dfa2fc050d20b530Éric Araujo        self.xx_created = True
4888e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl        xx_c = os.path.join(self.tmp_dir, 'xxmodule.c')
4988e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl        xx_ext = Extension('xx', [xx_c])
5088e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl        dist = Distribution({'name': 'xx', 'ext_modules': [xx_ext]})
5188e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl        dist.package_dir = self.tmp_dir
5288e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl        cmd = build_ext(dist)
5304612d60929d5cda8d4cd215dfa2fc050d20b530Éric Araujo        support.fixup_build_ext(cmd)
5488e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl        cmd.build_lib = self.tmp_dir
5588e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl        cmd.build_temp = self.tmp_dir
5688e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl
5788e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl        old_stdout = sys.stdout
5888e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl        if not test_support.verbose:
5988e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl            # silence compiler output
6088e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl            sys.stdout = StringIO()
6188e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl        try:
6288e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl            cmd.ensure_finalized()
6388e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl            cmd.run()
6488e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl        finally:
6588e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl            sys.stdout = old_stdout
6688e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl
676f1d93149505c5b69578549a440175c5b32942b7Tarek Ziadé        if ALREADY_TESTED:
6857bc6da7c4327aa870fbf5292c1b05a9ac3bfe19Serhiy Storchaka            self.skipTest('Already tested in %s' % ALREADY_TESTED)
696f1d93149505c5b69578549a440175c5b32942b7Tarek Ziadé        else:
7057bc6da7c4327aa870fbf5292c1b05a9ac3bfe19Serhiy Storchaka            ALREADY_TESTED = type(self).__name__
716f1d93149505c5b69578549a440175c5b32942b7Tarek Ziadé
7288e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl        import xx
7388e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl
7488e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl        for attr in ('error', 'foo', 'new', 'roj'):
752623a37852153363335956afab010cb0beb7e74eEzio Melotti            self.assertTrue(hasattr(xx, attr))
7688e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl
772623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(xx.foo(2, 5), 7)
782623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(xx.foo(13,15), 28)
792623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(xx.new().demo(), None)
8072121c6c302d0e177d3f738f51685e0664343cccSerhiy Storchaka        if test_support.HAVE_DOCSTRINGS:
8172121c6c302d0e177d3f738f51685e0664343cccSerhiy Storchaka            doc = 'This is a template module just for instruction.'
8272121c6c302d0e177d3f738f51685e0664343cccSerhiy Storchaka            self.assertEqual(xx.__doc__, doc)
8325a23efcda0dc3e245eefa8c9a3f96b4baee6303Serhiy Storchaka        self.assertIsInstance(xx.Null(), xx.Null)
8425a23efcda0dc3e245eefa8c9a3f96b4baee6303Serhiy Storchaka        self.assertIsInstance(xx.Str(), xx.Str)
8588e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl
860d4fd3493eb95a49ac0dee5c8607b1426432ab83Tarek Ziadé    def test_solaris_enable_shared(self):
870d4fd3493eb95a49ac0dee5c8607b1426432ab83Tarek Ziadé        dist = Distribution({'name': 'xx'})
880d4fd3493eb95a49ac0dee5c8607b1426432ab83Tarek Ziadé        cmd = build_ext(dist)
890d4fd3493eb95a49ac0dee5c8607b1426432ab83Tarek Ziadé        old = sys.platform
900d4fd3493eb95a49ac0dee5c8607b1426432ab83Tarek Ziadé
910d4fd3493eb95a49ac0dee5c8607b1426432ab83Tarek Ziadé        sys.platform = 'sunos' # fooling finalize_options
92b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        from distutils.sysconfig import  _config_vars
93b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        old_var = _config_vars.get('Py_ENABLE_SHARED')
94b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        _config_vars['Py_ENABLE_SHARED'] = 1
950d4fd3493eb95a49ac0dee5c8607b1426432ab83Tarek Ziadé        try:
960d4fd3493eb95a49ac0dee5c8607b1426432ab83Tarek Ziadé            cmd.ensure_finalized()
970d4fd3493eb95a49ac0dee5c8607b1426432ab83Tarek Ziadé        finally:
980d4fd3493eb95a49ac0dee5c8607b1426432ab83Tarek Ziadé            sys.platform = old
990d4fd3493eb95a49ac0dee5c8607b1426432ab83Tarek Ziadé            if old_var is None:
100b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé                del _config_vars['Py_ENABLE_SHARED']
1010d4fd3493eb95a49ac0dee5c8607b1426432ab83Tarek Ziadé            else:
102b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé                _config_vars['Py_ENABLE_SHARED'] = old_var
1030d4fd3493eb95a49ac0dee5c8607b1426432ab83Tarek Ziadé
104972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        # make sure we get some library dirs under solaris
10525a23efcda0dc3e245eefa8c9a3f96b4baee6303Serhiy Storchaka        self.assertGreater(len(cmd.library_dirs), 0)
1069e47ce49a06075adbc391e04b4457707fa3892a7Tarek Ziadé
10757bc6da7c4327aa870fbf5292c1b05a9ac3bfe19Serhiy Storchaka    @unittest.skipIf(sys.version < '2.6',
10857bc6da7c4327aa870fbf5292c1b05a9ac3bfe19Serhiy Storchaka                     'site.USER_SITE was introduced in 2.6')
109c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo    def test_user_site(self):
110c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        import site
111c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        dist = Distribution({'name': 'xx'})
112c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        cmd = build_ext(dist)
113c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo
114c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        # making sure the user option is there
115c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        options = [name for name, short, label in
116c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo                   cmd.user_options]
117c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        self.assertIn('user', options)
118c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo
119c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        # setting a value
120c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        cmd.user = 1
121c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo
122c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        # setting user based lib and include
123c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        lib = os.path.join(site.USER_BASE, 'lib')
124c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        incl = os.path.join(site.USER_BASE, 'include')
125c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        os.mkdir(lib)
126c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        os.mkdir(incl)
127c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo
128c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        cmd.ensure_finalized()
129c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo
130c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        # see if include_dirs and library_dirs were set
131c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        self.assertIn(lib, cmd.library_dirs)
132c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        self.assertIn(lib, cmd.rpath)
133c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo        self.assertIn(incl, cmd.include_dirs)
134c811fb2d56e3c5847ac5c5a6d59bbc8b75e8effaÉric Araujo
135d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé    def test_finalize_options(self):
136d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # Make sure Python's include directories (for Python.h, pyconfig.h,
137d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # etc.) are in the include search path.
138b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        modules = [Extension('foo', ['xxx'])]
139d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        dist = Distribution({'name': 'xx', 'ext_modules': modules})
140d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd = build_ext(dist)
141d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd.finalize_options()
142d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
143b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        py_include = sysconfig.get_python_inc()
14425a23efcda0dc3e245eefa8c9a3f96b4baee6303Serhiy Storchaka        self.assertIn(py_include, cmd.include_dirs)
145d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
146b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        plat_py_include = sysconfig.get_python_inc(plat_specific=1)
14725a23efcda0dc3e245eefa8c9a3f96b4baee6303Serhiy Storchaka        self.assertIn(plat_py_include, cmd.include_dirs)
148d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
149d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # make sure cmd.libraries is turned into a list
150d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # if it's a string
151d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd = build_ext(dist)
152e897a7472ded10a29ffcf046d021cd7fdc1ac94eÉric Araujo        cmd.libraries = 'my_lib, other_lib lastlib'
153d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd.finalize_options()
154e897a7472ded10a29ffcf046d021cd7fdc1ac94eÉric Araujo        self.assertEqual(cmd.libraries, ['my_lib', 'other_lib', 'lastlib'])
155d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
156d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # make sure cmd.library_dirs is turned into a list
157d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # if it's a string
158d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd = build_ext(dist)
159e897a7472ded10a29ffcf046d021cd7fdc1ac94eÉric Araujo        cmd.library_dirs = 'my_lib_dir%sother_lib_dir' % os.pathsep
160d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd.finalize_options()
161c82da813c1406bc7e3878bf1d960d4765bcb0d89Éric Araujo        self.assertIn('my_lib_dir', cmd.library_dirs)
162c82da813c1406bc7e3878bf1d960d4765bcb0d89Éric Araujo        self.assertIn('other_lib_dir', cmd.library_dirs)
163d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
164d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # make sure rpath is turned into a list
165e897a7472ded10a29ffcf046d021cd7fdc1ac94eÉric Araujo        # if it's a string
166d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd = build_ext(dist)
167e897a7472ded10a29ffcf046d021cd7fdc1ac94eÉric Araujo        cmd.rpath = 'one%stwo' % os.pathsep
168d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd.finalize_options()
1692623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(cmd.rpath, ['one', 'two'])
170d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
171d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # XXX more tests to perform for win32
172d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
173d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # make sure define is turned into 2-tuples
174d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # strings if they are ','-separated strings
175d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd = build_ext(dist)
176d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd.define = 'one,two'
177d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd.finalize_options()
1782623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(cmd.define, [('one', '1'), ('two', '1')])
179d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
180d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # make sure undef is turned into a list of
181d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # strings if they are ','-separated strings
182d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd = build_ext(dist)
183d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd.undef = 'one,two'
184d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd.finalize_options()
1852623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(cmd.undef, ['one', 'two'])
186d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
187d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # make sure swig_opts is turned into a list
188d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd = build_ext(dist)
189d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd.swig_opts = None
190d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd.finalize_options()
1912623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(cmd.swig_opts, [])
192d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
193d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd = build_ext(dist)
194d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd.swig_opts = '1 2'
195d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd.finalize_options()
1962623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(cmd.swig_opts, ['1', '2'])
197d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
198d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé    def test_check_extensions_list(self):
199d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        dist = Distribution()
200d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd = build_ext(dist)
201d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd.finalize_options()
202d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
203d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        #'extensions' option must be a list of Extension instances
204d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, 'foo')
205d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
206d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # each element of 'ext_modules' option must be an
207d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # Extension instance or 2-tuple
208d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        exts = [('bar', 'foo', 'bar'), 'foo']
209d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
210d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
211d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # first element of each tuple in 'ext_modules'
212d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # must be the extension name (a string) and match
213d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # a python dotted-separated name
214d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        exts = [('foo-bar', '')]
215d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
216d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
217d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # second element of each tuple in 'ext_modules'
218d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # must be a ary (build info)
219d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        exts = [('foo.bar', '')]
220d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
221d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
222d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # ok this one should pass
223d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        exts = [('foo.bar', {'sources': [''], 'libraries': 'foo',
224d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé                             'some': 'bar'})]
225d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd.check_extensions_list(exts)
226d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        ext = exts[0]
22725a23efcda0dc3e245eefa8c9a3f96b4baee6303Serhiy Storchaka        self.assertIsInstance(ext, Extension)
228d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
229d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # check_extensions_list adds in ext the values passed
230d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # when they are in ('include_dirs', 'library_dirs', 'libraries'
231d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # 'extra_objects', 'extra_compile_args', 'extra_link_args')
2322623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(ext.libraries, 'foo')
23325a23efcda0dc3e245eefa8c9a3f96b4baee6303Serhiy Storchaka        self.assertFalse(hasattr(ext, 'some'))
234d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
235d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        # 'macros' element of build info dict must be 1- or 2-tuple
236d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        exts = [('foo.bar', {'sources': [''], 'libraries': 'foo',
237d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé                'some': 'bar', 'macros': [('1', '2', '3'), 'foo']})]
238d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
239d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
240d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        exts[0][1]['macros'] = [('1', '2'), ('3',)]
241d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd.check_extensions_list(exts)
2422623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(exts[0].undef_macros, ['3'])
2432623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(exts[0].define_macros, [('1', '2')])
244d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
245d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé    def test_get_source_files(self):
246b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        modules = [Extension('foo', ['xxx'])]
247d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        dist = Distribution({'name': 'xx', 'ext_modules': modules})
248d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd = build_ext(dist)
249d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd.ensure_finalized()
2502623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(cmd.get_source_files(), ['xxx'])
251d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
252972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé    def test_compiler_option(self):
253972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        # cmd.compiler is an option and
254972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        # should not be overriden by a compiler instance
255972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        # when the command is run
256972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        dist = Distribution()
257972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        cmd = build_ext(dist)
258972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        cmd.compiler = 'unix'
259972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        cmd.ensure_finalized()
260972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        cmd.run()
2612623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(cmd.compiler, 'unix')
262972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé
263d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé    def test_get_outputs(self):
264972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        tmp_dir = self.mkdtemp()
265972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        c_file = os.path.join(tmp_dir, 'foo.c')
2666633a6606b935fa1160293029f59eb892e7aed4fHirokazu Yamamoto        self.write_file(c_file, 'void initfoo(void) {};\n')
267b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        ext = Extension('foo', [c_file])
268972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        dist = Distribution({'name': 'xx',
269972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé                             'ext_modules': [ext]})
270d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd = build_ext(dist)
27104612d60929d5cda8d4cd215dfa2fc050d20b530Éric Araujo        support.fixup_build_ext(cmd)
272d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé        cmd.ensure_finalized()
2732623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(len(cmd.get_outputs()), 1)
274d5d83424d235783ddaa1a98a82278805d05c437bTarek Ziadé
275972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        cmd.build_lib = os.path.join(self.tmp_dir, 'build')
276972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        cmd.build_temp = os.path.join(self.tmp_dir, 'tempt')
277972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé
278972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        # issue #5977 : distutils build_ext.get_outputs
279972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        # returns wrong result with --inplace
280cbb4f9ef58ec7673f7c64b16496879b914b0972aTarek Ziadé        other_tmp_dir = os.path.realpath(self.mkdtemp())
281cbb4f9ef58ec7673f7c64b16496879b914b0972aTarek Ziadé        old_wd = os.getcwd()
282cbb4f9ef58ec7673f7c64b16496879b914b0972aTarek Ziadé        os.chdir(other_tmp_dir)
283cbb4f9ef58ec7673f7c64b16496879b914b0972aTarek Ziadé        try:
284cbb4f9ef58ec7673f7c64b16496879b914b0972aTarek Ziadé            cmd.inplace = 1
285cbb4f9ef58ec7673f7c64b16496879b914b0972aTarek Ziadé            cmd.run()
286cbb4f9ef58ec7673f7c64b16496879b914b0972aTarek Ziadé            so_file = cmd.get_outputs()[0]
287cbb4f9ef58ec7673f7c64b16496879b914b0972aTarek Ziadé        finally:
288cbb4f9ef58ec7673f7c64b16496879b914b0972aTarek Ziadé            os.chdir(old_wd)
2892623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertTrue(os.path.exists(so_file))
2902623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(os.path.splitext(so_file)[-1],
2912623a37852153363335956afab010cb0beb7e74eEzio Melotti                         sysconfig.get_config_var('SO'))
292972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        so_dir = os.path.dirname(so_file)
2932623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(so_dir, other_tmp_dir)
294b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        cmd.compiler = None
295972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        cmd.inplace = 0
296972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        cmd.run()
297972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        so_file = cmd.get_outputs()[0]
2982623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertTrue(os.path.exists(so_file))
2992623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(os.path.splitext(so_file)[-1],
3002623a37852153363335956afab010cb0beb7e74eEzio Melotti                         sysconfig.get_config_var('SO'))
301972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé        so_dir = os.path.dirname(so_file)
3022623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(so_dir, cmd.build_lib)
303972480d999b83f5d245cb4662122e9d25c54701eTarek Ziadé
3047d7127dd84189bf9325ef3fc5f3c18359fa34f30Tarek Ziadé        # inplace = 0, cmd.package = 'bar'
30565ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé        build_py = cmd.get_finalized_command('build_py')
30665ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé        build_py.package_dir = {'': 'bar'}
3077d7127dd84189bf9325ef3fc5f3c18359fa34f30Tarek Ziadé        path = cmd.get_ext_fullpath('foo')
3083fbcc60eb859b00f4310e028da0ba6edba35f7c8Tarek Ziadé        # checking that the last directory is the build_dir
3097d7127dd84189bf9325ef3fc5f3c18359fa34f30Tarek Ziadé        path = os.path.split(path)[0]
3102623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(path, cmd.build_lib)
3117d7127dd84189bf9325ef3fc5f3c18359fa34f30Tarek Ziadé
3127d7127dd84189bf9325ef3fc5f3c18359fa34f30Tarek Ziadé        # inplace = 1, cmd.package = 'bar'
3137d7127dd84189bf9325ef3fc5f3c18359fa34f30Tarek Ziadé        cmd.inplace = 1
3147d7127dd84189bf9325ef3fc5f3c18359fa34f30Tarek Ziadé        other_tmp_dir = os.path.realpath(self.mkdtemp())
3157d7127dd84189bf9325ef3fc5f3c18359fa34f30Tarek Ziadé        old_wd = os.getcwd()
3167d7127dd84189bf9325ef3fc5f3c18359fa34f30Tarek Ziadé        os.chdir(other_tmp_dir)
3177d7127dd84189bf9325ef3fc5f3c18359fa34f30Tarek Ziadé        try:
3187d7127dd84189bf9325ef3fc5f3c18359fa34f30Tarek Ziadé            path = cmd.get_ext_fullpath('foo')
3197d7127dd84189bf9325ef3fc5f3c18359fa34f30Tarek Ziadé        finally:
3207d7127dd84189bf9325ef3fc5f3c18359fa34f30Tarek Ziadé            os.chdir(old_wd)
3217d7127dd84189bf9325ef3fc5f3c18359fa34f30Tarek Ziadé        # checking that the last directory is bar
3227d7127dd84189bf9325ef3fc5f3c18359fa34f30Tarek Ziadé        path = os.path.split(path)[0]
3237d7127dd84189bf9325ef3fc5f3c18359fa34f30Tarek Ziadé        lastdir = os.path.split(path)[-1]
3242623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(lastdir, 'bar')
3257d7127dd84189bf9325ef3fc5f3c18359fa34f30Tarek Ziadé
32665ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé    def test_ext_fullpath(self):
3278c40001175f354b6e05d38a7f403afb5686c6013Tarek Ziadé        ext = sysconfig.get_config_vars()['SO']
32865ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé        dist = Distribution()
3293fbcc60eb859b00f4310e028da0ba6edba35f7c8Tarek Ziadé        cmd = build_ext(dist)
3303fbcc60eb859b00f4310e028da0ba6edba35f7c8Tarek Ziadé        cmd.inplace = 1
3313fbcc60eb859b00f4310e028da0ba6edba35f7c8Tarek Ziadé        cmd.distribution.package_dir = {'': 'src'}
3323fbcc60eb859b00f4310e028da0ba6edba35f7c8Tarek Ziadé        cmd.distribution.packages = ['lxml', 'lxml.html']
3333fbcc60eb859b00f4310e028da0ba6edba35f7c8Tarek Ziadé        curdir = os.getcwd()
3348c40001175f354b6e05d38a7f403afb5686c6013Tarek Ziadé        wanted = os.path.join(curdir, 'src', 'lxml', 'etree' + ext)
3353fbcc60eb859b00f4310e028da0ba6edba35f7c8Tarek Ziadé        path = cmd.get_ext_fullpath('lxml.etree')
3362623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(wanted, path)
3373fbcc60eb859b00f4310e028da0ba6edba35f7c8Tarek Ziadé
33865ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé        # building lxml.etree not inplace
33965ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé        cmd.inplace = 0
34065ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé        cmd.build_lib = os.path.join(curdir, 'tmpdir')
3418c40001175f354b6e05d38a7f403afb5686c6013Tarek Ziadé        wanted = os.path.join(curdir, 'tmpdir', 'lxml', 'etree' + ext)
34265ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé        path = cmd.get_ext_fullpath('lxml.etree')
3432623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(wanted, path)
34465ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé
34565ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé        # building twisted.runner.portmap not inplace
34665ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé        build_py = cmd.get_finalized_command('build_py')
34765ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé        build_py.package_dir = {}
34865ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé        cmd.distribution.packages = ['twisted', 'twisted.runner.portmap']
34965ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé        path = cmd.get_ext_fullpath('twisted.runner.portmap')
35065ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé        wanted = os.path.join(curdir, 'tmpdir', 'twisted', 'runner',
3518c40001175f354b6e05d38a7f403afb5686c6013Tarek Ziadé                              'portmap' + ext)
3522623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(wanted, path)
35365ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé
35465ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé        # building twisted.runner.portmap inplace
35565ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé        cmd.inplace = 1
35665ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé        path = cmd.get_ext_fullpath('twisted.runner.portmap')
3578c40001175f354b6e05d38a7f403afb5686c6013Tarek Ziadé        wanted = os.path.join(curdir, 'twisted', 'runner', 'portmap' + ext)
3582623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(wanted, path)
35965ec61ed06d7b28da05fa834c65ffa7c13005d2bTarek Ziadé
360b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé    def test_build_ext_inplace(self):
361b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        etree_c = os.path.join(self.tmp_dir, 'lxml.etree.c')
362b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        etree_ext = Extension('lxml.etree', [etree_c])
363b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        dist = Distribution({'name': 'lxml', 'ext_modules': [etree_ext]})
364e670e5ad5b7ef6b464fb264b688d96b9b9f71b53Tarek Ziadé        cmd = build_ext(dist)
365b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        cmd.ensure_finalized()
366b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        cmd.inplace = 1
367b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        cmd.distribution.package_dir = {'': 'src'}
368b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        cmd.distribution.packages = ['lxml', 'lxml.html']
369b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        curdir = os.getcwd()
370b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        ext = sysconfig.get_config_var("SO")
371b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        wanted = os.path.join(curdir, 'src', 'lxml', 'etree' + ext)
372b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        path = cmd.get_ext_fullpath('lxml.etree')
3732623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(wanted, path)
374b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé
375b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé    def test_setuptools_compat(self):
3765501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé        import distutils.core, distutils.extension, distutils.command.build_ext
3775501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé        saved_ext = distutils.extension.Extension
3785501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé        try:
3793f5d146323fe306de7ddccb2506a7161554cc330Florent Xicluna            # on some platforms, it loads the deprecated "dl" module
3803f5d146323fe306de7ddccb2506a7161554cc330Florent Xicluna            test_support.import_module('setuptools_build_ext', deprecated=True)
3813f5d146323fe306de7ddccb2506a7161554cc330Florent Xicluna
3825501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            # theses import patch Distutils' Extension class
3835501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            from setuptools_build_ext import build_ext as setuptools_build_ext
3845501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            from setuptools_extension import Extension
3855501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé
3865501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            etree_c = os.path.join(self.tmp_dir, 'lxml.etree.c')
3875501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            etree_ext = Extension('lxml.etree', [etree_c])
3885501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            dist = Distribution({'name': 'lxml', 'ext_modules': [etree_ext]})
3895501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            cmd = setuptools_build_ext(dist)
3905501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            cmd.ensure_finalized()
3915501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            cmd.inplace = 1
3925501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            cmd.distribution.package_dir = {'': 'src'}
3935501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            cmd.distribution.packages = ['lxml', 'lxml.html']
3945501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            curdir = os.getcwd()
3955501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            ext = sysconfig.get_config_var("SO")
3965501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            wanted = os.path.join(curdir, 'src', 'lxml', 'etree' + ext)
3975501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            path = cmd.get_ext_fullpath('lxml.etree')
3982623a37852153363335956afab010cb0beb7e74eEzio Melotti            self.assertEqual(wanted, path)
3995501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé        finally:
4005501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            # restoring Distutils' Extension class otherwise its broken
4015501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            distutils.extension.Extension = saved_ext
4025501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            distutils.core.Extension = saved_ext
4035501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé            distutils.command.build_ext.Extension = saved_ext
404b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé
405b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé    def test_build_ext_path_with_os_sep(self):
406b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        dist = Distribution({'name': 'UpdateManager'})
407b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        cmd = build_ext(dist)
408b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        cmd.ensure_finalized()
409b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        ext = sysconfig.get_config_var("SO")
410b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        ext_name = os.path.join('UpdateManager', 'fdsend')
411b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        ext_path = cmd.get_ext_fullpath(ext_name)
412b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        wanted = os.path.join(cmd.build_lib, 'UpdateManager', 'fdsend' + ext)
4132623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(ext_path, wanted)
414b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé
41557bc6da7c4327aa870fbf5292c1b05a9ac3bfe19Serhiy Storchaka    @unittest.skipUnless(sys.platform == 'win32', 'these tests require Windows')
416b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé    def test_build_ext_path_cross_platform(self):
417b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        dist = Distribution({'name': 'UpdateManager'})
418b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        cmd = build_ext(dist)
419b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        cmd.ensure_finalized()
420b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        ext = sysconfig.get_config_var("SO")
421b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        # this needs to work even under win32
422b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        ext_name = 'UpdateManager/fdsend'
423b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        ext_path = cmd.get_ext_fullpath(ext_name)
424b30868a391b85d24b7d1abe41c137a9d75bfcebcTarek Ziadé        wanted = os.path.join(cmd.build_lib, 'UpdateManager', 'fdsend' + ext)
4252623a37852153363335956afab010cb0beb7e74eEzio Melotti        self.assertEqual(ext_path, wanted)
426e670e5ad5b7ef6b464fb264b688d96b9b9f71b53Tarek Ziadé
427a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren    @unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for MacOSX')
428053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily    def test_deployment_target_default(self):
429053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily        # Issue 9516: Test that, in the absence of the environment variable,
430053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily        # an extension module is compiled with the same deployment target as
431053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily        #  the interpreter.
432053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily        self._try_compile_deployment_target('==', None)
433a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren
434053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily    @unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for MacOSX')
435053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily    def test_deployment_target_too_low(self):
436053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily        # Issue 9516: Test that an extension module is not allowed to be
437053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily        # compiled with a deployment target less than that of the interpreter.
438053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily        self.assertRaises(DistutilsPlatformError,
439053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily            self._try_compile_deployment_target, '>', '10.1')
440053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily
441053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily    @unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for MacOSX')
442053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily    def test_deployment_target_higher_ok(self):
443053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily        # Issue 9516: Test that an extension module can be compiled with a
444053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily        # deployment target higher than that of the interpreter: the ext
445053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily        # module may depend on some newer OS feature.
446053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily        deptarget = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
447053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily        if deptarget:
448053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily            # increment the minor version number (i.e. 10.6 -> 10.7)
449053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily            deptarget = [int(x) for x in deptarget.split('.')]
450053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily            deptarget[-1] += 1
451053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily            deptarget = '.'.join(str(i) for i in deptarget)
452053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily            self._try_compile_deployment_target('<', deptarget)
453053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily
454053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily    def _try_compile_deployment_target(self, operator, target):
455a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren        orig_environ = os.environ
456a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren        os.environ = orig_environ.copy()
457a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren        self.addCleanup(setattr, os, 'environ', orig_environ)
458a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren
459053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily        if target is None:
460053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily            if os.environ.get('MACOSX_DEPLOYMENT_TARGET'):
461053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily                del os.environ['MACOSX_DEPLOYMENT_TARGET']
462053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily        else:
463053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily            os.environ['MACOSX_DEPLOYMENT_TARGET'] = target
464a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren
465a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren        deptarget_c = os.path.join(self.tmp_dir, 'deptargetmodule.c')
466a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren
467a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren        with open(deptarget_c, 'w') as fp:
468a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren            fp.write(textwrap.dedent('''\
469a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren                #include <AvailabilityMacros.h>
470a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren
471a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren                int dummy;
472a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren
473053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily                #if TARGET %s MAC_OS_X_VERSION_MIN_REQUIRED
474053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily                #else
475a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren                #error "Unexpected target"
476053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily                #endif
477a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren
478053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily            ''' % operator))
479a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren
480053c6ad6b7ee88d9076a91f47aa53dc7155d00ceNed Deily        # get the deployment target that the interpreter was built with
481a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren        target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
4821f70b878c4b890c66bdb90d8c9ddb59dee0b48dfNed Deily        target = tuple(map(int, target.split('.')[0:2]))
4831f70b878c4b890c66bdb90d8c9ddb59dee0b48dfNed Deily        # format the target value as defined in the Apple
4841f70b878c4b890c66bdb90d8c9ddb59dee0b48dfNed Deily        # Availability Macros.  We can't use the macro names since
4851f70b878c4b890c66bdb90d8c9ddb59dee0b48dfNed Deily        # at least one value we test with will not exist yet.
4861f70b878c4b890c66bdb90d8c9ddb59dee0b48dfNed Deily        if target[1] < 10:
4871f70b878c4b890c66bdb90d8c9ddb59dee0b48dfNed Deily            # for 10.1 through 10.9.x -> "10n0"
4881f70b878c4b890c66bdb90d8c9ddb59dee0b48dfNed Deily            target = '%02d%01d0' % target
4891f70b878c4b890c66bdb90d8c9ddb59dee0b48dfNed Deily        else:
4901f70b878c4b890c66bdb90d8c9ddb59dee0b48dfNed Deily            # for 10.10 and beyond -> "10nn00"
4911f70b878c4b890c66bdb90d8c9ddb59dee0b48dfNed Deily            target = '%02d%02d00' % target
492a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren        deptarget_ext = Extension(
493a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren            'deptarget',
494a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren            [deptarget_c],
495a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren            extra_compile_args=['-DTARGET=%s'%(target,)],
496a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren        )
497a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren        dist = Distribution({
498a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren            'name': 'deptarget',
499a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren            'ext_modules': [deptarget_ext]
500a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren        })
501a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren        dist.package_dir = self.tmp_dir
502a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren        cmd = build_ext(dist)
503a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren        cmd.build_lib = self.tmp_dir
504a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren        cmd.build_temp = self.tmp_dir
505a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren
506a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren        try:
507a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren            cmd.ensure_finalized()
508a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren            cmd.run()
509a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren        except CompileError:
510a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren            self.fail("Wrong deployment target during compilation")
511a70286b71d6b98c14275c26f6ca1f0507c1bc56bRonald Oussoren
51288e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandldef test_suite():
5135501e6a7da371a851478a939d974ecebbc84e2ddTarek Ziadé    return unittest.makeSuite(BuildExtTestCase)
51488e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl
51588e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandlif __name__ == '__main__':
51688e2acf038b717199655d8206e4a5deaa0a0eb1aGeorg Brandl    test_support.run_unittest(test_suite())
517