]>
git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Python/Python-2.7.2/Lib/distutils/tests/test_build_ext.py
6543965cbb3a4e24bc09cb75b232ef2d48a95e19
5 from StringIO
import StringIO
8 from distutils
.core
import Extension
, Distribution
9 from distutils
.command
.build_ext
import build_ext
10 from distutils
import sysconfig
11 from distutils
.tests
import support
12 from distutils
.errors
import DistutilsSetupError
, CompileError
15 from test
import test_support
17 # http://bugs.python.org/issue4373
18 # Don't load the xx module more than once.
19 ALREADY_TESTED
= False
21 def _get_source_filename():
22 srcdir
= sysconfig
.get_config_var('srcdir')
24 return os
.path
.join(sysconfig
.project_base
, 'Modules', 'xxmodule.c')
25 return os
.path
.join(srcdir
, 'Modules', 'xxmodule.c')
27 _XX_MODULE_PATH
= _get_source_filename()
29 class BuildExtTestCase(support
.TempdirManager
,
30 support
.LoggingSilencer
,
33 # Create a simple test environment
34 # Note that we're making changes to sys.path
35 super(BuildExtTestCase
, self
).setUp()
36 self
.tmp_dir
= tempfile
.mkdtemp(prefix
="pythontest_")
37 if os
.path
.exists(_XX_MODULE_PATH
):
38 self
.sys_path
= sys
.path
[:]
39 sys
.path
.append(self
.tmp_dir
)
40 shutil
.copy(_XX_MODULE_PATH
, self
.tmp_dir
)
43 # Get everything back to normal
44 if os
.path
.exists(_XX_MODULE_PATH
):
45 test_support
.unload('xx')
46 sys
.path
[:] = self
.sys_path
47 # XXX on Windows the test leaves a directory
48 # with xx module in TEMP
49 shutil
.rmtree(self
.tmp_dir
, os
.name
== 'nt' or
50 sys
.platform
== 'cygwin')
51 super(BuildExtTestCase
, self
).tearDown()
53 def _fixup_command(self
, cmd
):
54 # When Python was build with --enable-shared, -L. is not good enough
55 # to find the libpython<blah>.so. This is because regrtest runs it
56 # under a tempdir, not in the top level where the .so lives. By the
57 # time we've gotten here, Python's already been chdir'd to the
60 # To further add to the fun, we can't just add library_dirs to the
61 # Extension() instance because that doesn't get plumbed through to the
62 # final compiler command.
63 if (sysconfig
.get_config_var('Py_ENABLE_SHARED') and
64 not sys
.platform
.startswith('win')):
65 runshared
= sysconfig
.get_config_var('RUNSHARED')
67 cmd
.library_dirs
= ['.']
69 name
, equals
, value
= runshared
.partition('=')
70 cmd
.library_dirs
= value
.split(os
.pathsep
)
72 @unittest.skipIf(not os
.path
.exists(_XX_MODULE_PATH
),
73 'xxmodule.c not found')
74 def test_build_ext(self
):
76 xx_c
= os
.path
.join(self
.tmp_dir
, 'xxmodule.c')
77 xx_ext
= Extension('xx', [xx_c
])
78 dist
= Distribution({'name': 'xx', 'ext_modules': [xx_ext
]})
79 dist
.package_dir
= self
.tmp_dir
81 self
._fixup
_command
(cmd
)
83 # On Windows, we must build a debug version iff running
84 # a debug build of Python
85 cmd
.debug
= sys
.executable
.endswith("_d.exe")
86 cmd
.build_lib
= self
.tmp_dir
87 cmd
.build_temp
= self
.tmp_dir
89 old_stdout
= sys
.stdout
90 if not test_support
.verbose
:
91 # silence compiler output
92 sys
.stdout
= StringIO()
94 cmd
.ensure_finalized()
97 sys
.stdout
= old_stdout
102 ALREADY_TESTED
= True
106 for attr
in ('error', 'foo', 'new', 'roj'):
107 self
.assertTrue(hasattr(xx
, attr
))
109 self
.assertEqual(xx
.foo(2, 5), 7)
110 self
.assertEqual(xx
.foo(13,15), 28)
111 self
.assertEqual(xx
.new().demo(), None)
112 doc
= 'This is a template module just for instruction.'
113 self
.assertEqual(xx
.__doc
__, doc
)
114 self
.assertTrue(isinstance(xx
.Null(), xx
.Null
))
115 self
.assertTrue(isinstance(xx
.Str(), xx
.Str
))
117 def test_solaris_enable_shared(self
):
118 dist
= Distribution({'name': 'xx'})
119 cmd
= build_ext(dist
)
122 sys
.platform
= 'sunos' # fooling finalize_options
123 from distutils
.sysconfig
import _config_vars
124 old_var
= _config_vars
.get('Py_ENABLE_SHARED')
125 _config_vars
['Py_ENABLE_SHARED'] = 1
127 cmd
.ensure_finalized()
131 del _config_vars
['Py_ENABLE_SHARED']
133 _config_vars
['Py_ENABLE_SHARED'] = old_var
135 # make sure we get some library dirs under solaris
136 self
.assertTrue(len(cmd
.library_dirs
) > 0)
138 def test_finalize_options(self
):
139 # Make sure Python's include directories (for Python.h, pyconfig.h,
140 # etc.) are in the include search path.
141 modules
= [Extension('foo', ['xxx'])]
142 dist
= Distribution({'name': 'xx', 'ext_modules': modules
})
143 cmd
= build_ext(dist
)
144 cmd
.finalize_options()
146 from distutils
import sysconfig
147 py_include
= sysconfig
.get_python_inc()
148 self
.assertTrue(py_include
in cmd
.include_dirs
)
150 plat_py_include
= sysconfig
.get_python_inc(plat_specific
=1)
151 self
.assertTrue(plat_py_include
in cmd
.include_dirs
)
153 # make sure cmd.libraries is turned into a list
155 cmd
= build_ext(dist
)
156 cmd
.libraries
= 'my_lib'
157 cmd
.finalize_options()
158 self
.assertEqual(cmd
.libraries
, ['my_lib'])
160 # make sure cmd.library_dirs is turned into a list
162 cmd
= build_ext(dist
)
163 cmd
.library_dirs
= 'my_lib_dir'
164 cmd
.finalize_options()
165 self
.assertTrue('my_lib_dir' in cmd
.library_dirs
)
167 # make sure rpath is turned into a list
168 # if it's a list of os.pathsep's paths
169 cmd
= build_ext(dist
)
170 cmd
.rpath
= os
.pathsep
.join(['one', 'two'])
171 cmd
.finalize_options()
172 self
.assertEqual(cmd
.rpath
, ['one', 'two'])
174 # XXX more tests to perform for win32
176 # make sure define is turned into 2-tuples
177 # strings if they are ','-separated strings
178 cmd
= build_ext(dist
)
179 cmd
.define
= 'one,two'
180 cmd
.finalize_options()
181 self
.assertEqual(cmd
.define
, [('one', '1'), ('two', '1')])
183 # make sure undef is turned into a list of
184 # strings if they are ','-separated strings
185 cmd
= build_ext(dist
)
186 cmd
.undef
= 'one,two'
187 cmd
.finalize_options()
188 self
.assertEqual(cmd
.undef
, ['one', 'two'])
190 # make sure swig_opts is turned into a list
191 cmd
= build_ext(dist
)
193 cmd
.finalize_options()
194 self
.assertEqual(cmd
.swig_opts
, [])
196 cmd
= build_ext(dist
)
197 cmd
.swig_opts
= '1 2'
198 cmd
.finalize_options()
199 self
.assertEqual(cmd
.swig_opts
, ['1', '2'])
201 def test_check_extensions_list(self
):
202 dist
= Distribution()
203 cmd
= build_ext(dist
)
204 cmd
.finalize_options()
206 #'extensions' option must be a list of Extension instances
207 self
.assertRaises(DistutilsSetupError
, cmd
.check_extensions_list
, 'foo')
209 # each element of 'ext_modules' option must be an
210 # Extension instance or 2-tuple
211 exts
= [('bar', 'foo', 'bar'), 'foo']
212 self
.assertRaises(DistutilsSetupError
, cmd
.check_extensions_list
, exts
)
214 # first element of each tuple in 'ext_modules'
215 # must be the extension name (a string) and match
216 # a python dotted-separated name
217 exts
= [('foo-bar', '')]
218 self
.assertRaises(DistutilsSetupError
, cmd
.check_extensions_list
, exts
)
220 # second element of each tuple in 'ext_modules'
221 # must be a ary (build info)
222 exts
= [('foo.bar', '')]
223 self
.assertRaises(DistutilsSetupError
, cmd
.check_extensions_list
, exts
)
225 # ok this one should pass
226 exts
= [('foo.bar', {'sources': [''], 'libraries': 'foo',
228 cmd
.check_extensions_list(exts
)
230 self
.assertTrue(isinstance(ext
, Extension
))
232 # check_extensions_list adds in ext the values passed
233 # when they are in ('include_dirs', 'library_dirs', 'libraries'
234 # 'extra_objects', 'extra_compile_args', 'extra_link_args')
235 self
.assertEqual(ext
.libraries
, 'foo')
236 self
.assertTrue(not hasattr(ext
, 'some'))
238 # 'macros' element of build info dict must be 1- or 2-tuple
239 exts
= [('foo.bar', {'sources': [''], 'libraries': 'foo',
240 'some': 'bar', 'macros': [('1', '2', '3'), 'foo']})]
241 self
.assertRaises(DistutilsSetupError
, cmd
.check_extensions_list
, exts
)
243 exts
[0][1]['macros'] = [('1', '2'), ('3',)]
244 cmd
.check_extensions_list(exts
)
245 self
.assertEqual(exts
[0].undef_macros
, ['3'])
246 self
.assertEqual(exts
[0].define_macros
, [('1', '2')])
248 def test_get_source_files(self
):
249 modules
= [Extension('foo', ['xxx'])]
250 dist
= Distribution({'name': 'xx', 'ext_modules': modules
})
251 cmd
= build_ext(dist
)
252 cmd
.ensure_finalized()
253 self
.assertEqual(cmd
.get_source_files(), ['xxx'])
255 def test_compiler_option(self
):
256 # cmd.compiler is an option and
257 # should not be overriden by a compiler instance
258 # when the command is run
259 dist
= Distribution()
260 cmd
= build_ext(dist
)
261 cmd
.compiler
= 'unix'
262 cmd
.ensure_finalized()
264 self
.assertEqual(cmd
.compiler
, 'unix')
266 def test_get_outputs(self
):
267 tmp_dir
= self
.mkdtemp()
268 c_file
= os
.path
.join(tmp_dir
, 'foo.c')
269 self
.write_file(c_file
, 'void initfoo(void) {};\n')
270 ext
= Extension('foo', [c_file
])
271 dist
= Distribution({'name': 'xx',
272 'ext_modules': [ext
]})
273 cmd
= build_ext(dist
)
274 self
._fixup
_command
(cmd
)
275 cmd
.ensure_finalized()
276 self
.assertEqual(len(cmd
.get_outputs()), 1)
279 cmd
.debug
= sys
.executable
.endswith("_d.exe")
281 cmd
.build_lib
= os
.path
.join(self
.tmp_dir
, 'build')
282 cmd
.build_temp
= os
.path
.join(self
.tmp_dir
, 'tempt')
284 # issue #5977 : distutils build_ext.get_outputs
285 # returns wrong result with --inplace
286 other_tmp_dir
= os
.path
.realpath(self
.mkdtemp())
288 os
.chdir(other_tmp_dir
)
292 so_file
= cmd
.get_outputs()[0]
295 self
.assertTrue(os
.path
.exists(so_file
))
296 self
.assertEqual(os
.path
.splitext(so_file
)[-1],
297 sysconfig
.get_config_var('SO'))
298 so_dir
= os
.path
.dirname(so_file
)
299 self
.assertEqual(so_dir
, other_tmp_dir
)
303 so_file
= cmd
.get_outputs()[0]
304 self
.assertTrue(os
.path
.exists(so_file
))
305 self
.assertEqual(os
.path
.splitext(so_file
)[-1],
306 sysconfig
.get_config_var('SO'))
307 so_dir
= os
.path
.dirname(so_file
)
308 self
.assertEqual(so_dir
, cmd
.build_lib
)
310 # inplace = 0, cmd.package = 'bar'
311 build_py
= cmd
.get_finalized_command('build_py')
312 build_py
.package_dir
= {'': 'bar'}
313 path
= cmd
.get_ext_fullpath('foo')
314 # checking that the last directory is the build_dir
315 path
= os
.path
.split(path
)[0]
316 self
.assertEqual(path
, cmd
.build_lib
)
318 # inplace = 1, cmd.package = 'bar'
320 other_tmp_dir
= os
.path
.realpath(self
.mkdtemp())
322 os
.chdir(other_tmp_dir
)
324 path
= cmd
.get_ext_fullpath('foo')
327 # checking that the last directory is bar
328 path
= os
.path
.split(path
)[0]
329 lastdir
= os
.path
.split(path
)[-1]
330 self
.assertEqual(lastdir
, 'bar')
332 def test_ext_fullpath(self
):
333 ext
= sysconfig
.get_config_vars()['SO']
334 dist
= Distribution()
335 cmd
= build_ext(dist
)
337 cmd
.distribution
.package_dir
= {'': 'src'}
338 cmd
.distribution
.packages
= ['lxml', 'lxml.html']
340 wanted
= os
.path
.join(curdir
, 'src', 'lxml', 'etree' + ext
)
341 path
= cmd
.get_ext_fullpath('lxml.etree')
342 self
.assertEqual(wanted
, path
)
344 # building lxml.etree not inplace
346 cmd
.build_lib
= os
.path
.join(curdir
, 'tmpdir')
347 wanted
= os
.path
.join(curdir
, 'tmpdir', 'lxml', 'etree' + ext
)
348 path
= cmd
.get_ext_fullpath('lxml.etree')
349 self
.assertEqual(wanted
, path
)
351 # building twisted.runner.portmap not inplace
352 build_py
= cmd
.get_finalized_command('build_py')
353 build_py
.package_dir
= {}
354 cmd
.distribution
.packages
= ['twisted', 'twisted.runner.portmap']
355 path
= cmd
.get_ext_fullpath('twisted.runner.portmap')
356 wanted
= os
.path
.join(curdir
, 'tmpdir', 'twisted', 'runner',
358 self
.assertEqual(wanted
, path
)
360 # building twisted.runner.portmap inplace
362 path
= cmd
.get_ext_fullpath('twisted.runner.portmap')
363 wanted
= os
.path
.join(curdir
, 'twisted', 'runner', 'portmap' + ext
)
364 self
.assertEqual(wanted
, path
)
366 def test_build_ext_inplace(self
):
367 etree_c
= os
.path
.join(self
.tmp_dir
, 'lxml.etree.c')
368 etree_ext
= Extension('lxml.etree', [etree_c
])
369 dist
= Distribution({'name': 'lxml', 'ext_modules': [etree_ext
]})
370 cmd
= build_ext(dist
)
371 cmd
.ensure_finalized()
373 cmd
.distribution
.package_dir
= {'': 'src'}
374 cmd
.distribution
.packages
= ['lxml', 'lxml.html']
376 ext
= sysconfig
.get_config_var("SO")
377 wanted
= os
.path
.join(curdir
, 'src', 'lxml', 'etree' + ext
)
378 path
= cmd
.get_ext_fullpath('lxml.etree')
379 self
.assertEqual(wanted
, path
)
381 def test_setuptools_compat(self
):
382 import distutils
.core
, distutils
.extension
, distutils
.command
.build_ext
383 saved_ext
= distutils
.extension
.Extension
385 # on some platforms, it loads the deprecated "dl" module
386 test_support
.import_module('setuptools_build_ext', deprecated
=True)
388 # theses import patch Distutils' Extension class
389 from setuptools_build_ext
import build_ext
as setuptools_build_ext
390 from setuptools_extension
import Extension
392 etree_c
= os
.path
.join(self
.tmp_dir
, 'lxml.etree.c')
393 etree_ext
= Extension('lxml.etree', [etree_c
])
394 dist
= Distribution({'name': 'lxml', 'ext_modules': [etree_ext
]})
395 cmd
= setuptools_build_ext(dist
)
396 cmd
.ensure_finalized()
398 cmd
.distribution
.package_dir
= {'': 'src'}
399 cmd
.distribution
.packages
= ['lxml', 'lxml.html']
401 ext
= sysconfig
.get_config_var("SO")
402 wanted
= os
.path
.join(curdir
, 'src', 'lxml', 'etree' + ext
)
403 path
= cmd
.get_ext_fullpath('lxml.etree')
404 self
.assertEqual(wanted
, path
)
406 # restoring Distutils' Extension class otherwise its broken
407 distutils
.extension
.Extension
= saved_ext
408 distutils
.core
.Extension
= saved_ext
409 distutils
.command
.build_ext
.Extension
= saved_ext
411 def test_build_ext_path_with_os_sep(self
):
412 dist
= Distribution({'name': 'UpdateManager'})
413 cmd
= build_ext(dist
)
414 cmd
.ensure_finalized()
415 ext
= sysconfig
.get_config_var("SO")
416 ext_name
= os
.path
.join('UpdateManager', 'fdsend')
417 ext_path
= cmd
.get_ext_fullpath(ext_name
)
418 wanted
= os
.path
.join(cmd
.build_lib
, 'UpdateManager', 'fdsend' + ext
)
419 self
.assertEqual(ext_path
, wanted
)
421 def test_build_ext_path_cross_platform(self
):
422 if sys
.platform
!= 'win32':
424 dist
= Distribution({'name': 'UpdateManager'})
425 cmd
= build_ext(dist
)
426 cmd
.ensure_finalized()
427 ext
= sysconfig
.get_config_var("SO")
428 # this needs to work even under win32
429 ext_name
= 'UpdateManager/fdsend'
430 ext_path
= cmd
.get_ext_fullpath(ext_name
)
431 wanted
= os
.path
.join(cmd
.build_lib
, 'UpdateManager', 'fdsend' + ext
)
432 self
.assertEqual(ext_path
, wanted
)
434 @unittest.skipUnless(sys
.platform
== 'darwin', 'test only relevant for MacOSX')
435 def test_deployment_target(self
):
436 self
._try
_compile
_deployment
_target
()
438 orig_environ
= os
.environ
439 os
.environ
= orig_environ
.copy()
440 self
.addCleanup(setattr, os
, 'environ', orig_environ
)
442 os
.environ
['MACOSX_DEPLOYMENT_TARGET']='10.1'
443 self
._try
_compile
_deployment
_target
()
446 def _try_compile_deployment_target(self
):
447 deptarget_c
= os
.path
.join(self
.tmp_dir
, 'deptargetmodule.c')
449 with
open(deptarget_c
, 'w') as fp
:
450 fp
.write(textwrap
.dedent('''\
451 #include <AvailabilityMacros.h>
455 #if TARGET != MAC_OS_X_VERSION_MIN_REQUIRED
456 #error "Unexpected target"
461 target
= sysconfig
.get_config_var('MACOSX_DEPLOYMENT_TARGET')
462 target
= tuple(map(int, target
.split('.')))
463 target
= '%02d%01d0' % target
465 deptarget_ext
= Extension(
468 extra_compile_args
=['-DTARGET=%s'%(target
,)],
470 dist
= Distribution({
472 'ext_modules': [deptarget_ext
]
474 dist
.package_dir
= self
.tmp_dir
475 cmd
= build_ext(dist
)
476 cmd
.build_lib
= self
.tmp_dir
477 cmd
.build_temp
= self
.tmp_dir
480 old_stdout
= sys
.stdout
481 cmd
.ensure_finalized()
485 self
.fail("Wrong deployment target during compilation")
488 return unittest
.makeSuite(BuildExtTestCase
)
490 if __name__
== '__main__':
491 test_support
.run_unittest(test_suite())