blob: 87cceee22d7cded765e1d1da285b3c4b741477a0 [file] [log] [blame]
Georg Brandlb533e262008-05-25 18:19:30 +00001import sys
2import os
Georg Brandlb533e262008-05-25 18:19:30 +00003from io import StringIO
Ronald Oussoren222e89a2011-05-15 16:46:11 +02004import textwrap
Georg Brandlb533e262008-05-25 18:19:30 +00005
Barry Warsaw8cf4eae2010-10-16 01:04:07 +00006from distutils.core import Distribution
Georg Brandlb533e262008-05-25 18:19:30 +00007from distutils.command.build_ext import build_ext
Tarek Ziadé36797272010-07-22 12:50:05 +00008from distutils import sysconfig
Éric Araujodef15da2011-08-20 06:27:18 +02009from distutils.tests.support import (TempdirManager, LoggingSilencer,
Éric Araujo6e3ad872011-08-21 17:02:07 +020010 copy_xxmodule_c, fixup_build_ext)
Tarek Ziadéb2e36f12009-03-31 22:37:55 +000011from distutils.extension import Extension
Barry Warsaw8cf4eae2010-10-16 01:04:07 +000012from distutils.errors import (
Ned Deilyd13007f2011-06-28 19:43:15 -070013 CompileError, DistutilsPlatformError, DistutilsSetupError,
14 UnknownFileError)
Georg Brandlb533e262008-05-25 18:19:30 +000015
16import unittest
17from test import support
18
Christian Heimes3e7e0692008-11-25 21:21:32 +000019# http://bugs.python.org/issue4373
20# Don't load the xx module more than once.
21ALREADY_TESTED = False
22
Neil Schemenauerd8f63bb2009-02-06 21:42:05 +000023
Tarek Ziadé36797272010-07-22 12:50:05 +000024class BuildExtTestCase(TempdirManager,
25 LoggingSilencer,
26 unittest.TestCase):
Georg Brandlb533e262008-05-25 18:19:30 +000027 def setUp(self):
28 # Create a simple test environment
29 # Note that we're making changes to sys.path
Tarek Ziadé38e3d512009-02-27 12:58:56 +000030 super(BuildExtTestCase, self).setUp()
Tarek Ziadéc1375d52009-02-14 14:35:51 +000031 self.tmp_dir = self.mkdtemp()
Tarek Ziadé36797272010-07-22 12:50:05 +000032 self.sys_path = sys.path, sys.path[:]
33 sys.path.append(self.tmp_dir)
Tarek Ziadé38e3d512009-02-27 12:58:56 +000034 if sys.version > "2.6":
35 import site
36 self.old_user_base = site.USER_BASE
37 site.USER_BASE = self.mkdtemp()
38 from distutils.command import build_ext
39 build_ext.USER_BASE = site.USER_BASE
Georg Brandlb533e262008-05-25 18:19:30 +000040
41 def test_build_ext(self):
Christian Heimes3e7e0692008-11-25 21:21:32 +000042 global ALREADY_TESTED
Éric Araujodef15da2011-08-20 06:27:18 +020043 copy_xxmodule_c(self.tmp_dir)
Georg Brandlb533e262008-05-25 18:19:30 +000044 xx_c = os.path.join(self.tmp_dir, 'xxmodule.c')
45 xx_ext = Extension('xx', [xx_c])
46 dist = Distribution({'name': 'xx', 'ext_modules': [xx_ext]})
47 dist.package_dir = self.tmp_dir
48 cmd = build_ext(dist)
Éric Araujo6e3ad872011-08-21 17:02:07 +020049 fixup_build_ext(cmd)
Georg Brandlb533e262008-05-25 18:19:30 +000050 cmd.build_lib = self.tmp_dir
51 cmd.build_temp = self.tmp_dir
52
53 old_stdout = sys.stdout
54 if not support.verbose:
55 # silence compiler output
56 sys.stdout = StringIO()
57 try:
58 cmd.ensure_finalized()
59 cmd.run()
60 finally:
61 sys.stdout = old_stdout
62
Christian Heimes3e7e0692008-11-25 21:21:32 +000063 if ALREADY_TESTED:
64 return
65 else:
66 ALREADY_TESTED = True
67
Georg Brandlb533e262008-05-25 18:19:30 +000068 import xx
69
70 for attr in ('error', 'foo', 'new', 'roj'):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000071 self.assertTrue(hasattr(xx, attr))
Georg Brandlb533e262008-05-25 18:19:30 +000072
Ezio Melottib3aedd42010-11-20 19:04:17 +000073 self.assertEqual(xx.foo(2, 5), 7)
74 self.assertEqual(xx.foo(13,15), 28)
75 self.assertEqual(xx.new().demo(), None)
Georg Brandlb533e262008-05-25 18:19:30 +000076 doc = 'This is a template module just for instruction.'
Ezio Melottib3aedd42010-11-20 19:04:17 +000077 self.assertEqual(xx.__doc__, doc)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000078 self.assertTrue(isinstance(xx.Null(), xx.Null))
79 self.assertTrue(isinstance(xx.Str(), xx.Str))
Georg Brandlb533e262008-05-25 18:19:30 +000080
Tarek Ziadé36797272010-07-22 12:50:05 +000081 def tearDown(self):
82 # Get everything back to normal
83 support.unload('xx')
84 sys.path = self.sys_path[0]
85 sys.path[:] = self.sys_path[1]
86 if sys.version > "2.6":
87 import site
88 site.USER_BASE = self.old_user_base
89 from distutils.command import build_ext
90 build_ext.USER_BASE = self.old_user_base
91 super(BuildExtTestCase, self).tearDown()
92
Tarek Ziadé5874ef12009-02-05 22:56:14 +000093 def test_solaris_enable_shared(self):
94 dist = Distribution({'name': 'xx'})
95 cmd = build_ext(dist)
96 old = sys.platform
97
98 sys.platform = 'sunos' # fooling finalize_options
Tarek Ziadé36797272010-07-22 12:50:05 +000099 from distutils.sysconfig import _config_vars
100 old_var = _config_vars.get('Py_ENABLE_SHARED')
101 _config_vars['Py_ENABLE_SHARED'] = 1
Tarek Ziadé5874ef12009-02-05 22:56:14 +0000102 try:
103 cmd.ensure_finalized()
104 finally:
105 sys.platform = old
106 if old_var is None:
Tarek Ziadé36797272010-07-22 12:50:05 +0000107 del _config_vars['Py_ENABLE_SHARED']
Tarek Ziadé5874ef12009-02-05 22:56:14 +0000108 else:
Tarek Ziadé36797272010-07-22 12:50:05 +0000109 _config_vars['Py_ENABLE_SHARED'] = old_var
Tarek Ziadé5874ef12009-02-05 22:56:14 +0000110
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000111 # make sure we get some library dirs under solaris
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000112 self.assertTrue(len(cmd.library_dirs) > 0)
Tarek Ziadé5874ef12009-02-05 22:56:14 +0000113
Tarek Ziadé38e3d512009-02-27 12:58:56 +0000114 def test_user_site(self):
115 # site.USER_SITE was introduced in 2.6
116 if sys.version < '2.6':
117 return
118
119 import site
120 dist = Distribution({'name': 'xx'})
121 cmd = build_ext(dist)
122
Tarek Ziadébe720e02009-05-09 11:55:12 +0000123 # making sure the user option is there
Tarek Ziadé38e3d512009-02-27 12:58:56 +0000124 options = [name for name, short, lable in
125 cmd.user_options]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000126 self.assertTrue('user' in options)
Tarek Ziadé38e3d512009-02-27 12:58:56 +0000127
128 # setting a value
129 cmd.user = 1
130
131 # setting user based lib and include
132 lib = os.path.join(site.USER_BASE, 'lib')
133 incl = os.path.join(site.USER_BASE, 'include')
134 os.mkdir(lib)
135 os.mkdir(incl)
136
137 # let's run finalize
138 cmd.ensure_finalized()
139
140 # see if include_dirs and library_dirs
141 # were set
Éric Araujo6e3ad872011-08-21 17:02:07 +0200142 self.assertIn(lib, cmd.library_dirs)
143 self.assertIn(lib, cmd.rpath)
144 self.assertIn(incl, cmd.include_dirs)
Tarek Ziadé38e3d512009-02-27 12:58:56 +0000145
Tarek Ziadéb2e36f12009-03-31 22:37:55 +0000146 def test_optional_extension(self):
147
148 # this extension will fail, but let's ignore this failure
149 # with the optional argument.
150 modules = [Extension('foo', ['xxx'], optional=False)]
151 dist = Distribution({'name': 'xx', 'ext_modules': modules})
152 cmd = build_ext(dist)
153 cmd.ensure_finalized()
Tarek Ziadé30911292009-03-31 22:50:54 +0000154 self.assertRaises((UnknownFileError, CompileError),
155 cmd.run) # should raise an error
Tarek Ziadéb2e36f12009-03-31 22:37:55 +0000156
157 modules = [Extension('foo', ['xxx'], optional=True)]
158 dist = Distribution({'name': 'xx', 'ext_modules': modules})
159 cmd = build_ext(dist)
160 cmd.ensure_finalized()
161 cmd.run() # should pass
162
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000163 def test_finalize_options(self):
164 # Make sure Python's include directories (for Python.h, pyconfig.h,
165 # etc.) are in the include search path.
166 modules = [Extension('foo', ['xxx'], optional=False)]
167 dist = Distribution({'name': 'xx', 'ext_modules': modules})
168 cmd = build_ext(dist)
169 cmd.finalize_options()
170
Tarek Ziadé36797272010-07-22 12:50:05 +0000171 from distutils import sysconfig
172 py_include = sysconfig.get_python_inc()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000173 self.assertTrue(py_include in cmd.include_dirs)
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000174
Tarek Ziadé36797272010-07-22 12:50:05 +0000175 plat_py_include = sysconfig.get_python_inc(plat_specific=1)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000176 self.assertTrue(plat_py_include in cmd.include_dirs)
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000177
178 # make sure cmd.libraries is turned into a list
179 # if it's a string
180 cmd = build_ext(dist)
Éric Araujob2f5c0a2012-02-15 16:44:37 +0100181 cmd.libraries = 'my_lib, other_lib lastlib'
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000182 cmd.finalize_options()
Éric Araujob2f5c0a2012-02-15 16:44:37 +0100183 self.assertEqual(cmd.libraries, ['my_lib', 'other_lib', 'lastlib'])
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000184
185 # make sure cmd.library_dirs is turned into a list
186 # if it's a string
187 cmd = build_ext(dist)
Éric Araujob2f5c0a2012-02-15 16:44:37 +0100188 cmd.library_dirs = 'my_lib_dir%sother_lib_dir' % os.pathsep
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000189 cmd.finalize_options()
Éric Araujob2f5c0a2012-02-15 16:44:37 +0100190 self.assertEqual(cmd.library_dirs, ['my_lib_dir', 'other_lib_dir'])
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000191
192 # make sure rpath is turned into a list
Éric Araujob2f5c0a2012-02-15 16:44:37 +0100193 # if it's a string
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000194 cmd = build_ext(dist)
Éric Araujob2f5c0a2012-02-15 16:44:37 +0100195 cmd.rpath = 'one%stwo' % os.pathsep
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000196 cmd.finalize_options()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000197 self.assertEqual(cmd.rpath, ['one', 'two'])
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000198
199 # XXX more tests to perform for win32
200
201 # make sure define is turned into 2-tuples
202 # strings if they are ','-separated strings
203 cmd = build_ext(dist)
204 cmd.define = 'one,two'
205 cmd.finalize_options()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000206 self.assertEqual(cmd.define, [('one', '1'), ('two', '1')])
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000207
208 # make sure undef is turned into a list of
209 # strings if they are ','-separated strings
210 cmd = build_ext(dist)
211 cmd.undef = 'one,two'
212 cmd.finalize_options()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000213 self.assertEqual(cmd.undef, ['one', 'two'])
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000214
215 # make sure swig_opts is turned into a list
216 cmd = build_ext(dist)
217 cmd.swig_opts = None
218 cmd.finalize_options()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000219 self.assertEqual(cmd.swig_opts, [])
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000220
221 cmd = build_ext(dist)
222 cmd.swig_opts = '1 2'
223 cmd.finalize_options()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000224 self.assertEqual(cmd.swig_opts, ['1', '2'])
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000225
226 def test_check_extensions_list(self):
227 dist = Distribution()
228 cmd = build_ext(dist)
229 cmd.finalize_options()
230
231 #'extensions' option must be a list of Extension instances
Barry Warsaw8cf4eae2010-10-16 01:04:07 +0000232 self.assertRaises(DistutilsSetupError,
233 cmd.check_extensions_list, 'foo')
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000234
235 # each element of 'ext_modules' option must be an
236 # Extension instance or 2-tuple
237 exts = [('bar', 'foo', 'bar'), 'foo']
238 self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
239
240 # first element of each tuple in 'ext_modules'
241 # must be the extension name (a string) and match
242 # a python dotted-separated name
243 exts = [('foo-bar', '')]
244 self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
245
246 # second element of each tuple in 'ext_modules'
247 # must be a ary (build info)
248 exts = [('foo.bar', '')]
249 self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
250
251 # ok this one should pass
252 exts = [('foo.bar', {'sources': [''], 'libraries': 'foo',
253 'some': 'bar'})]
254 cmd.check_extensions_list(exts)
255 ext = exts[0]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000256 self.assertTrue(isinstance(ext, Extension))
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000257
258 # check_extensions_list adds in ext the values passed
259 # when they are in ('include_dirs', 'library_dirs', 'libraries'
260 # 'extra_objects', 'extra_compile_args', 'extra_link_args')
Ezio Melottib3aedd42010-11-20 19:04:17 +0000261 self.assertEqual(ext.libraries, 'foo')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000262 self.assertTrue(not hasattr(ext, 'some'))
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000263
264 # 'macros' element of build info dict must be 1- or 2-tuple
265 exts = [('foo.bar', {'sources': [''], 'libraries': 'foo',
266 'some': 'bar', 'macros': [('1', '2', '3'), 'foo']})]
267 self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
268
269 exts[0][1]['macros'] = [('1', '2'), ('3',)]
270 cmd.check_extensions_list(exts)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000271 self.assertEqual(exts[0].undef_macros, ['3'])
272 self.assertEqual(exts[0].define_macros, [('1', '2')])
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000273
274 def test_get_source_files(self):
275 modules = [Extension('foo', ['xxx'], optional=False)]
276 dist = Distribution({'name': 'xx', 'ext_modules': modules})
277 cmd = build_ext(dist)
278 cmd.ensure_finalized()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000279 self.assertEqual(cmd.get_source_files(), ['xxx'])
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000280
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000281 def test_compiler_option(self):
282 # cmd.compiler is an option and
283 # should not be overriden by a compiler instance
284 # when the command is run
285 dist = Distribution()
286 cmd = build_ext(dist)
287 cmd.compiler = 'unix'
288 cmd.ensure_finalized()
289 cmd.run()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000290 self.assertEqual(cmd.compiler, 'unix')
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000291
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000292 def test_get_outputs(self):
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000293 tmp_dir = self.mkdtemp()
294 c_file = os.path.join(tmp_dir, 'foo.c')
Victor Stinner3e2b7172010-11-09 09:32:19 +0000295 self.write_file(c_file, 'void PyInit_foo(void) {}\n')
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000296 ext = Extension('foo', [c_file], optional=False)
297 dist = Distribution({'name': 'xx',
298 'ext_modules': [ext]})
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000299 cmd = build_ext(dist)
Éric Araujo6e3ad872011-08-21 17:02:07 +0200300 fixup_build_ext(cmd)
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000301 cmd.ensure_finalized()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000302 self.assertEqual(len(cmd.get_outputs()), 1)
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000303
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000304 cmd.build_lib = os.path.join(self.tmp_dir, 'build')
305 cmd.build_temp = os.path.join(self.tmp_dir, 'tempt')
306
307 # issue #5977 : distutils build_ext.get_outputs
308 # returns wrong result with --inplace
Tarek Ziadé4210c6e2009-05-14 20:20:47 +0000309 other_tmp_dir = os.path.realpath(self.mkdtemp())
310 old_wd = os.getcwd()
311 os.chdir(other_tmp_dir)
312 try:
313 cmd.inplace = 1
314 cmd.run()
315 so_file = cmd.get_outputs()[0]
316 finally:
317 os.chdir(old_wd)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000318 self.assertTrue(os.path.exists(so_file))
Barry Warsaw35f3a2c2010-09-03 18:30:30 +0000319 so_ext = sysconfig.get_config_var('SO')
320 self.assertTrue(so_file.endswith(so_ext))
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000321 so_dir = os.path.dirname(so_file)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000322 self.assertEqual(so_dir, other_tmp_dir)
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000323
324 cmd.inplace = 0
Tarek Ziadé36797272010-07-22 12:50:05 +0000325 cmd.compiler = None
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000326 cmd.run()
327 so_file = cmd.get_outputs()[0]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000328 self.assertTrue(os.path.exists(so_file))
Barry Warsaw35f3a2c2010-09-03 18:30:30 +0000329 self.assertTrue(so_file.endswith(so_ext))
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000330 so_dir = os.path.dirname(so_file)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000331 self.assertEqual(so_dir, cmd.build_lib)
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000332
Tarek Ziadé822eb842009-05-19 16:22:57 +0000333 # inplace = 0, cmd.package = 'bar'
Tarek Ziadée10d6de2009-07-03 08:33:28 +0000334 build_py = cmd.get_finalized_command('build_py')
335 build_py.package_dir = {'': 'bar'}
Tarek Ziadé822eb842009-05-19 16:22:57 +0000336 path = cmd.get_ext_fullpath('foo')
Tarek Ziadé0156f912009-06-29 16:19:22 +0000337 # checking that the last directory is the build_dir
Tarek Ziadé822eb842009-05-19 16:22:57 +0000338 path = os.path.split(path)[0]
Ezio Melottib3aedd42010-11-20 19:04:17 +0000339 self.assertEqual(path, cmd.build_lib)
Tarek Ziadé822eb842009-05-19 16:22:57 +0000340
341 # inplace = 1, cmd.package = 'bar'
342 cmd.inplace = 1
343 other_tmp_dir = os.path.realpath(self.mkdtemp())
344 old_wd = os.getcwd()
345 os.chdir(other_tmp_dir)
346 try:
347 path = cmd.get_ext_fullpath('foo')
348 finally:
349 os.chdir(old_wd)
350 # checking that the last directory is bar
351 path = os.path.split(path)[0]
352 lastdir = os.path.split(path)[-1]
Ezio Melottib3aedd42010-11-20 19:04:17 +0000353 self.assertEqual(lastdir, 'bar')
Tarek Ziadé822eb842009-05-19 16:22:57 +0000354
Tarek Ziadée10d6de2009-07-03 08:33:28 +0000355 def test_ext_fullpath(self):
Tarek Ziadéb7815e32009-07-10 09:14:31 +0000356 ext = sysconfig.get_config_vars()['SO']
Tarek Ziadée10d6de2009-07-03 08:33:28 +0000357 # building lxml.etree inplace
358 #etree_c = os.path.join(self.tmp_dir, 'lxml.etree.c')
359 #etree_ext = Extension('lxml.etree', [etree_c])
360 #dist = Distribution({'name': 'lxml', 'ext_modules': [etree_ext]})
361 dist = Distribution()
Tarek Ziadé0156f912009-06-29 16:19:22 +0000362 cmd = build_ext(dist)
363 cmd.inplace = 1
364 cmd.distribution.package_dir = {'': 'src'}
365 cmd.distribution.packages = ['lxml', 'lxml.html']
366 curdir = os.getcwd()
Tarek Ziadéb7815e32009-07-10 09:14:31 +0000367 wanted = os.path.join(curdir, 'src', 'lxml', 'etree' + ext)
Tarek Ziadé0156f912009-06-29 16:19:22 +0000368 path = cmd.get_ext_fullpath('lxml.etree')
Ezio Melottib3aedd42010-11-20 19:04:17 +0000369 self.assertEqual(wanted, path)
Tarek Ziadé0156f912009-06-29 16:19:22 +0000370
Tarek Ziadée10d6de2009-07-03 08:33:28 +0000371 # building lxml.etree not inplace
372 cmd.inplace = 0
373 cmd.build_lib = os.path.join(curdir, 'tmpdir')
Tarek Ziadéb7815e32009-07-10 09:14:31 +0000374 wanted = os.path.join(curdir, 'tmpdir', 'lxml', 'etree' + ext)
Tarek Ziadée10d6de2009-07-03 08:33:28 +0000375 path = cmd.get_ext_fullpath('lxml.etree')
Ezio Melottib3aedd42010-11-20 19:04:17 +0000376 self.assertEqual(wanted, path)
Tarek Ziadée10d6de2009-07-03 08:33:28 +0000377
378 # building twisted.runner.portmap not inplace
379 build_py = cmd.get_finalized_command('build_py')
380 build_py.package_dir = {}
381 cmd.distribution.packages = ['twisted', 'twisted.runner.portmap']
382 path = cmd.get_ext_fullpath('twisted.runner.portmap')
383 wanted = os.path.join(curdir, 'tmpdir', 'twisted', 'runner',
Tarek Ziadéb7815e32009-07-10 09:14:31 +0000384 'portmap' + ext)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000385 self.assertEqual(wanted, path)
Tarek Ziadée10d6de2009-07-03 08:33:28 +0000386
387 # building twisted.runner.portmap inplace
388 cmd.inplace = 1
389 path = cmd.get_ext_fullpath('twisted.runner.portmap')
Tarek Ziadéb7815e32009-07-10 09:14:31 +0000390 wanted = os.path.join(curdir, 'twisted', 'runner', 'portmap' + ext)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000391 self.assertEqual(wanted, path)
Tarek Ziadée10d6de2009-07-03 08:33:28 +0000392
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200393
394 @unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for MacOSX')
Ned Deilyd13007f2011-06-28 19:43:15 -0700395 def test_deployment_target_default(self):
396 # Issue 9516: Test that, in the absence of the environment variable,
397 # an extension module is compiled with the same deployment target as
398 # the interpreter.
399 self._try_compile_deployment_target('==', None)
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200400
Ned Deilyd13007f2011-06-28 19:43:15 -0700401 @unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for MacOSX')
402 def test_deployment_target_too_low(self):
403 # Issue 9516: Test that an extension module is not allowed to be
404 # compiled with a deployment target less than that of the interpreter.
405 self.assertRaises(DistutilsPlatformError,
406 self._try_compile_deployment_target, '>', '10.1')
407
408 @unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for MacOSX')
409 def test_deployment_target_higher_ok(self):
410 # Issue 9516: Test that an extension module can be compiled with a
411 # deployment target higher than that of the interpreter: the ext
412 # module may depend on some newer OS feature.
413 deptarget = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
414 if deptarget:
415 # increment the minor version number (i.e. 10.6 -> 10.7)
416 deptarget = [int(x) for x in deptarget.split('.')]
417 deptarget[-1] += 1
418 deptarget = '.'.join(str(i) for i in deptarget)
419 self._try_compile_deployment_target('<', deptarget)
420
421 def _try_compile_deployment_target(self, operator, target):
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200422 orig_environ = os.environ
423 os.environ = orig_environ.copy()
424 self.addCleanup(setattr, os, 'environ', orig_environ)
425
Ned Deilyd13007f2011-06-28 19:43:15 -0700426 if target is None:
427 if os.environ.get('MACOSX_DEPLOYMENT_TARGET'):
428 del os.environ['MACOSX_DEPLOYMENT_TARGET']
429 else:
430 os.environ['MACOSX_DEPLOYMENT_TARGET'] = target
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200431
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200432 deptarget_c = os.path.join(self.tmp_dir, 'deptargetmodule.c')
433
434 with open(deptarget_c, 'w') as fp:
435 fp.write(textwrap.dedent('''\
436 #include <AvailabilityMacros.h>
437
438 int dummy;
439
Ned Deilyd13007f2011-06-28 19:43:15 -0700440 #if TARGET %s MAC_OS_X_VERSION_MIN_REQUIRED
441 #else
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200442 #error "Unexpected target"
443 #endif
444
Ned Deilyd13007f2011-06-28 19:43:15 -0700445 ''' % operator))
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200446
Ned Deilyd13007f2011-06-28 19:43:15 -0700447 # get the deployment target that the interpreter was built with
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200448 target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
449 target = tuple(map(int, target.split('.')))
450 target = '%02d%01d0' % target
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200451 deptarget_ext = Extension(
452 'deptarget',
453 [deptarget_c],
454 extra_compile_args=['-DTARGET=%s'%(target,)],
455 )
456 dist = Distribution({
457 'name': 'deptarget',
458 'ext_modules': [deptarget_ext]
459 })
460 dist.package_dir = self.tmp_dir
461 cmd = build_ext(dist)
462 cmd.build_lib = self.tmp_dir
463 cmd.build_temp = self.tmp_dir
464
465 try:
466 old_stdout = sys.stdout
467 if not support.verbose:
468 # silence compiler output
469 sys.stdout = StringIO()
470 try:
471 cmd.ensure_finalized()
472 cmd.run()
473 finally:
474 sys.stdout = old_stdout
475
476 except CompileError:
477 self.fail("Wrong deployment target during compilation")
478
479
Georg Brandlb533e262008-05-25 18:19:30 +0000480def test_suite():
Éric Araujodef15da2011-08-20 06:27:18 +0200481 return unittest.makeSuite(BuildExtTestCase)
Georg Brandlb533e262008-05-25 18:19:30 +0000482
483if __name__ == '__main__':
484 support.run_unittest(test_suite())