blob: 090eacfb2c3e022d1b3acd0cd0254a58c18da426 [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 Araujo2a57a362012-02-15 18:12:12 +0100190 self.assertIn('my_lib_dir', cmd.library_dirs)
191 self.assertIn('other_lib_dir', cmd.library_dirs)
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000192
193 # make sure rpath is turned into a list
Éric Araujob2f5c0a2012-02-15 16:44:37 +0100194 # if it's a string
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000195 cmd = build_ext(dist)
Éric Araujob2f5c0a2012-02-15 16:44:37 +0100196 cmd.rpath = 'one%stwo' % os.pathsep
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000197 cmd.finalize_options()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000198 self.assertEqual(cmd.rpath, ['one', 'two'])
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000199
200 # XXX more tests to perform for win32
201
202 # make sure define is turned into 2-tuples
203 # strings if they are ','-separated strings
204 cmd = build_ext(dist)
205 cmd.define = 'one,two'
206 cmd.finalize_options()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000207 self.assertEqual(cmd.define, [('one', '1'), ('two', '1')])
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000208
209 # make sure undef is turned into a list of
210 # strings if they are ','-separated strings
211 cmd = build_ext(dist)
212 cmd.undef = 'one,two'
213 cmd.finalize_options()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000214 self.assertEqual(cmd.undef, ['one', 'two'])
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000215
216 # make sure swig_opts is turned into a list
217 cmd = build_ext(dist)
218 cmd.swig_opts = None
219 cmd.finalize_options()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000220 self.assertEqual(cmd.swig_opts, [])
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000221
222 cmd = build_ext(dist)
223 cmd.swig_opts = '1 2'
224 cmd.finalize_options()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000225 self.assertEqual(cmd.swig_opts, ['1', '2'])
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000226
227 def test_check_extensions_list(self):
228 dist = Distribution()
229 cmd = build_ext(dist)
230 cmd.finalize_options()
231
232 #'extensions' option must be a list of Extension instances
Barry Warsaw8cf4eae2010-10-16 01:04:07 +0000233 self.assertRaises(DistutilsSetupError,
234 cmd.check_extensions_list, 'foo')
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000235
236 # each element of 'ext_modules' option must be an
237 # Extension instance or 2-tuple
238 exts = [('bar', 'foo', 'bar'), 'foo']
239 self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
240
241 # first element of each tuple in 'ext_modules'
242 # must be the extension name (a string) and match
243 # a python dotted-separated name
244 exts = [('foo-bar', '')]
245 self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
246
247 # second element of each tuple in 'ext_modules'
248 # must be a ary (build info)
249 exts = [('foo.bar', '')]
250 self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
251
252 # ok this one should pass
253 exts = [('foo.bar', {'sources': [''], 'libraries': 'foo',
254 'some': 'bar'})]
255 cmd.check_extensions_list(exts)
256 ext = exts[0]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000257 self.assertTrue(isinstance(ext, Extension))
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000258
259 # check_extensions_list adds in ext the values passed
260 # when they are in ('include_dirs', 'library_dirs', 'libraries'
261 # 'extra_objects', 'extra_compile_args', 'extra_link_args')
Ezio Melottib3aedd42010-11-20 19:04:17 +0000262 self.assertEqual(ext.libraries, 'foo')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000263 self.assertTrue(not hasattr(ext, 'some'))
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000264
265 # 'macros' element of build info dict must be 1- or 2-tuple
266 exts = [('foo.bar', {'sources': [''], 'libraries': 'foo',
267 'some': 'bar', 'macros': [('1', '2', '3'), 'foo']})]
268 self.assertRaises(DistutilsSetupError, cmd.check_extensions_list, exts)
269
270 exts[0][1]['macros'] = [('1', '2'), ('3',)]
271 cmd.check_extensions_list(exts)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000272 self.assertEqual(exts[0].undef_macros, ['3'])
273 self.assertEqual(exts[0].define_macros, [('1', '2')])
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000274
275 def test_get_source_files(self):
276 modules = [Extension('foo', ['xxx'], optional=False)]
277 dist = Distribution({'name': 'xx', 'ext_modules': modules})
278 cmd = build_ext(dist)
279 cmd.ensure_finalized()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000280 self.assertEqual(cmd.get_source_files(), ['xxx'])
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000281
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000282 def test_compiler_option(self):
283 # cmd.compiler is an option and
284 # should not be overriden by a compiler instance
285 # when the command is run
286 dist = Distribution()
287 cmd = build_ext(dist)
288 cmd.compiler = 'unix'
289 cmd.ensure_finalized()
290 cmd.run()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000291 self.assertEqual(cmd.compiler, 'unix')
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000292
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000293 def test_get_outputs(self):
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000294 tmp_dir = self.mkdtemp()
295 c_file = os.path.join(tmp_dir, 'foo.c')
Victor Stinner3e2b7172010-11-09 09:32:19 +0000296 self.write_file(c_file, 'void PyInit_foo(void) {}\n')
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000297 ext = Extension('foo', [c_file], optional=False)
298 dist = Distribution({'name': 'xx',
299 'ext_modules': [ext]})
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000300 cmd = build_ext(dist)
Éric Araujo6e3ad872011-08-21 17:02:07 +0200301 fixup_build_ext(cmd)
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000302 cmd.ensure_finalized()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000303 self.assertEqual(len(cmd.get_outputs()), 1)
Tarek Ziadé06fbee12009-05-10 10:34:01 +0000304
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000305 cmd.build_lib = os.path.join(self.tmp_dir, 'build')
306 cmd.build_temp = os.path.join(self.tmp_dir, 'tempt')
307
308 # issue #5977 : distutils build_ext.get_outputs
309 # returns wrong result with --inplace
Tarek Ziadé4210c6e2009-05-14 20:20:47 +0000310 other_tmp_dir = os.path.realpath(self.mkdtemp())
311 old_wd = os.getcwd()
312 os.chdir(other_tmp_dir)
313 try:
314 cmd.inplace = 1
315 cmd.run()
316 so_file = cmd.get_outputs()[0]
317 finally:
318 os.chdir(old_wd)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000319 self.assertTrue(os.path.exists(so_file))
Barry Warsaw35f3a2c2010-09-03 18:30:30 +0000320 so_ext = sysconfig.get_config_var('SO')
321 self.assertTrue(so_file.endswith(so_ext))
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000322 so_dir = os.path.dirname(so_file)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000323 self.assertEqual(so_dir, other_tmp_dir)
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000324
325 cmd.inplace = 0
Tarek Ziadé36797272010-07-22 12:50:05 +0000326 cmd.compiler = None
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000327 cmd.run()
328 so_file = cmd.get_outputs()[0]
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000329 self.assertTrue(os.path.exists(so_file))
Barry Warsaw35f3a2c2010-09-03 18:30:30 +0000330 self.assertTrue(so_file.endswith(so_ext))
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000331 so_dir = os.path.dirname(so_file)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000332 self.assertEqual(so_dir, cmd.build_lib)
Tarek Ziadéff0e5002009-05-12 17:14:01 +0000333
Tarek Ziadé822eb842009-05-19 16:22:57 +0000334 # inplace = 0, cmd.package = 'bar'
Tarek Ziadée10d6de2009-07-03 08:33:28 +0000335 build_py = cmd.get_finalized_command('build_py')
336 build_py.package_dir = {'': 'bar'}
Tarek Ziadé822eb842009-05-19 16:22:57 +0000337 path = cmd.get_ext_fullpath('foo')
Tarek Ziadé0156f912009-06-29 16:19:22 +0000338 # checking that the last directory is the build_dir
Tarek Ziadé822eb842009-05-19 16:22:57 +0000339 path = os.path.split(path)[0]
Ezio Melottib3aedd42010-11-20 19:04:17 +0000340 self.assertEqual(path, cmd.build_lib)
Tarek Ziadé822eb842009-05-19 16:22:57 +0000341
342 # inplace = 1, cmd.package = 'bar'
343 cmd.inplace = 1
344 other_tmp_dir = os.path.realpath(self.mkdtemp())
345 old_wd = os.getcwd()
346 os.chdir(other_tmp_dir)
347 try:
348 path = cmd.get_ext_fullpath('foo')
349 finally:
350 os.chdir(old_wd)
351 # checking that the last directory is bar
352 path = os.path.split(path)[0]
353 lastdir = os.path.split(path)[-1]
Ezio Melottib3aedd42010-11-20 19:04:17 +0000354 self.assertEqual(lastdir, 'bar')
Tarek Ziadé822eb842009-05-19 16:22:57 +0000355
Tarek Ziadée10d6de2009-07-03 08:33:28 +0000356 def test_ext_fullpath(self):
Tarek Ziadéb7815e32009-07-10 09:14:31 +0000357 ext = sysconfig.get_config_vars()['SO']
Tarek Ziadée10d6de2009-07-03 08:33:28 +0000358 # building lxml.etree inplace
359 #etree_c = os.path.join(self.tmp_dir, 'lxml.etree.c')
360 #etree_ext = Extension('lxml.etree', [etree_c])
361 #dist = Distribution({'name': 'lxml', 'ext_modules': [etree_ext]})
362 dist = Distribution()
Tarek Ziadé0156f912009-06-29 16:19:22 +0000363 cmd = build_ext(dist)
364 cmd.inplace = 1
365 cmd.distribution.package_dir = {'': 'src'}
366 cmd.distribution.packages = ['lxml', 'lxml.html']
367 curdir = os.getcwd()
Tarek Ziadéb7815e32009-07-10 09:14:31 +0000368 wanted = os.path.join(curdir, 'src', 'lxml', 'etree' + ext)
Tarek Ziadé0156f912009-06-29 16:19:22 +0000369 path = cmd.get_ext_fullpath('lxml.etree')
Ezio Melottib3aedd42010-11-20 19:04:17 +0000370 self.assertEqual(wanted, path)
Tarek Ziadé0156f912009-06-29 16:19:22 +0000371
Tarek Ziadée10d6de2009-07-03 08:33:28 +0000372 # building lxml.etree not inplace
373 cmd.inplace = 0
374 cmd.build_lib = os.path.join(curdir, 'tmpdir')
Tarek Ziadéb7815e32009-07-10 09:14:31 +0000375 wanted = os.path.join(curdir, 'tmpdir', 'lxml', 'etree' + ext)
Tarek Ziadée10d6de2009-07-03 08:33:28 +0000376 path = cmd.get_ext_fullpath('lxml.etree')
Ezio Melottib3aedd42010-11-20 19:04:17 +0000377 self.assertEqual(wanted, path)
Tarek Ziadée10d6de2009-07-03 08:33:28 +0000378
379 # building twisted.runner.portmap not inplace
380 build_py = cmd.get_finalized_command('build_py')
381 build_py.package_dir = {}
382 cmd.distribution.packages = ['twisted', 'twisted.runner.portmap']
383 path = cmd.get_ext_fullpath('twisted.runner.portmap')
384 wanted = os.path.join(curdir, 'tmpdir', 'twisted', 'runner',
Tarek Ziadéb7815e32009-07-10 09:14:31 +0000385 'portmap' + ext)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000386 self.assertEqual(wanted, path)
Tarek Ziadée10d6de2009-07-03 08:33:28 +0000387
388 # building twisted.runner.portmap inplace
389 cmd.inplace = 1
390 path = cmd.get_ext_fullpath('twisted.runner.portmap')
Tarek Ziadéb7815e32009-07-10 09:14:31 +0000391 wanted = os.path.join(curdir, 'twisted', 'runner', 'portmap' + ext)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000392 self.assertEqual(wanted, path)
Tarek Ziadée10d6de2009-07-03 08:33:28 +0000393
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200394
395 @unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for MacOSX')
Ned Deilyd13007f2011-06-28 19:43:15 -0700396 def test_deployment_target_default(self):
397 # Issue 9516: Test that, in the absence of the environment variable,
398 # an extension module is compiled with the same deployment target as
399 # the interpreter.
400 self._try_compile_deployment_target('==', None)
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200401
Ned Deilyd13007f2011-06-28 19:43:15 -0700402 @unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for MacOSX')
403 def test_deployment_target_too_low(self):
404 # Issue 9516: Test that an extension module is not allowed to be
405 # compiled with a deployment target less than that of the interpreter.
406 self.assertRaises(DistutilsPlatformError,
407 self._try_compile_deployment_target, '>', '10.1')
408
409 @unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for MacOSX')
410 def test_deployment_target_higher_ok(self):
411 # Issue 9516: Test that an extension module can be compiled with a
412 # deployment target higher than that of the interpreter: the ext
413 # module may depend on some newer OS feature.
414 deptarget = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
415 if deptarget:
416 # increment the minor version number (i.e. 10.6 -> 10.7)
417 deptarget = [int(x) for x in deptarget.split('.')]
418 deptarget[-1] += 1
419 deptarget = '.'.join(str(i) for i in deptarget)
420 self._try_compile_deployment_target('<', deptarget)
421
422 def _try_compile_deployment_target(self, operator, target):
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200423 orig_environ = os.environ
424 os.environ = orig_environ.copy()
425 self.addCleanup(setattr, os, 'environ', orig_environ)
426
Ned Deilyd13007f2011-06-28 19:43:15 -0700427 if target is None:
428 if os.environ.get('MACOSX_DEPLOYMENT_TARGET'):
429 del os.environ['MACOSX_DEPLOYMENT_TARGET']
430 else:
431 os.environ['MACOSX_DEPLOYMENT_TARGET'] = target
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200432
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200433 deptarget_c = os.path.join(self.tmp_dir, 'deptargetmodule.c')
434
435 with open(deptarget_c, 'w') as fp:
436 fp.write(textwrap.dedent('''\
437 #include <AvailabilityMacros.h>
438
439 int dummy;
440
Ned Deilyd13007f2011-06-28 19:43:15 -0700441 #if TARGET %s MAC_OS_X_VERSION_MIN_REQUIRED
442 #else
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200443 #error "Unexpected target"
444 #endif
445
Ned Deilyd13007f2011-06-28 19:43:15 -0700446 ''' % operator))
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200447
Ned Deilyd13007f2011-06-28 19:43:15 -0700448 # get the deployment target that the interpreter was built with
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200449 target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
450 target = tuple(map(int, target.split('.')))
451 target = '%02d%01d0' % target
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200452 deptarget_ext = Extension(
453 'deptarget',
454 [deptarget_c],
455 extra_compile_args=['-DTARGET=%s'%(target,)],
456 )
457 dist = Distribution({
458 'name': 'deptarget',
459 'ext_modules': [deptarget_ext]
460 })
461 dist.package_dir = self.tmp_dir
462 cmd = build_ext(dist)
463 cmd.build_lib = self.tmp_dir
464 cmd.build_temp = self.tmp_dir
465
466 try:
467 old_stdout = sys.stdout
468 if not support.verbose:
469 # silence compiler output
470 sys.stdout = StringIO()
471 try:
472 cmd.ensure_finalized()
473 cmd.run()
474 finally:
475 sys.stdout = old_stdout
476
477 except CompileError:
478 self.fail("Wrong deployment target during compilation")
479
480
Georg Brandlb533e262008-05-25 18:19:30 +0000481def test_suite():
Éric Araujodef15da2011-08-20 06:27:18 +0200482 return unittest.makeSuite(BuildExtTestCase)
Georg Brandlb533e262008-05-25 18:19:30 +0000483
484if __name__ == '__main__':
485 support.run_unittest(test_suite())