~ubuntu-branches/ubuntu/quantal/python2.7/quantal

« back to all changes in this revision

Viewing changes to Lib/distutils/tests/test_build_ext.py

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2012-03-09 19:28:43 UTC
  • mto: (36.1.11 sid)
  • mto: This revision was merged to the branch mainline in revision 51.
  • Revision ID: package-import@ubuntu.com-20120309192843-n84bbtrkfxw34p6n
Tags: upstream-2.7.3~rc1
ImportĀ upstreamĀ versionĀ 2.7.3~rc1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
import sys
2
2
import os
3
 
import tempfile
4
 
import shutil
5
3
from StringIO import StringIO
6
4
import textwrap
7
5
 
9
7
from distutils.command.build_ext import build_ext
10
8
from distutils import sysconfig
11
9
from distutils.tests import support
12
 
from distutils.errors import DistutilsSetupError, CompileError
 
10
from distutils.errors import (DistutilsSetupError, CompileError,
 
11
                              DistutilsPlatformError)
13
12
 
14
13
import unittest
15
14
from test import test_support
18
17
# Don't load the xx module more than once.
19
18
ALREADY_TESTED = False
20
19
 
21
 
def _get_source_filename():
22
 
    srcdir = sysconfig.get_config_var('srcdir')
23
 
    if srcdir is None:
24
 
        return os.path.join(sysconfig.project_base, 'Modules', 'xxmodule.c')
25
 
    return os.path.join(srcdir, 'Modules', 'xxmodule.c')
26
 
 
27
 
_XX_MODULE_PATH = _get_source_filename()
28
20
 
29
21
class BuildExtTestCase(support.TempdirManager,
30
22
                       support.LoggingSilencer,
31
23
                       unittest.TestCase):
32
24
    def setUp(self):
33
 
        # Create a simple test environment
34
 
        # Note that we're making changes to sys.path
35
25
        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)
 
26
        self.tmp_dir = self.mkdtemp()
 
27
        self.xx_created = False
 
28
        sys.path.append(self.tmp_dir)
 
29
        self.addCleanup(sys.path.remove, self.tmp_dir)
 
30
        if sys.version > "2.6":
 
31
            import site
 
32
            self.old_user_base = site.USER_BASE
 
33
            site.USER_BASE = self.mkdtemp()
 
34
            from distutils.command import build_ext
 
35
            build_ext.USER_BASE = site.USER_BASE
41
36
 
42
37
    def tearDown(self):
43
 
        # Get everything back to normal
44
 
        if os.path.exists(_XX_MODULE_PATH):
 
38
        if self.xx_created:
45
39
            test_support.unload('xx')
46
 
            sys.path[:] = self.sys_path
47
40
            # XXX on Windows the test leaves a directory
48
41
            # with xx module in TEMP
49
 
        shutil.rmtree(self.tmp_dir, os.name == 'nt' or
50
 
                                    sys.platform == 'cygwin')
51
42
        super(BuildExtTestCase, self).tearDown()
52
43
 
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
58
 
        # tempdir.
59
 
        #
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')
66
 
            if runshared is None:
67
 
                cmd.library_dirs = ['.']
68
 
            else:
69
 
                name, equals, value = runshared.partition('=')
70
 
                cmd.library_dirs = value.split(os.pathsep)
71
 
 
72
 
    @unittest.skipIf(not os.path.exists(_XX_MODULE_PATH),
73
 
                     'xxmodule.c not found')
74
44
    def test_build_ext(self):
75
45
        global ALREADY_TESTED
 
46
        support.copy_xxmodule_c(self.tmp_dir)
 
47
        self.xx_created = True
76
48
        xx_c = os.path.join(self.tmp_dir, 'xxmodule.c')
77
49
        xx_ext = Extension('xx', [xx_c])
78
50
        dist = Distribution({'name': 'xx', 'ext_modules': [xx_ext]})
79
51
        dist.package_dir = self.tmp_dir
80
52
        cmd = build_ext(dist)
81
 
        self._fixup_command(cmd)
82
 
        if os.name == "nt":
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")
 
53
        support.fixup_build_ext(cmd)
86
54
        cmd.build_lib = self.tmp_dir
87
55
        cmd.build_temp = self.tmp_dir
88
56
 
135
103
        # make sure we get some library dirs under solaris
136
104
        self.assertTrue(len(cmd.library_dirs) > 0)
137
105
 
 
106
    def test_user_site(self):
 
107
        # site.USER_SITE was introduced in 2.6
 
108
        if sys.version < '2.6':
 
109
            return
 
110
 
 
111
        import site
 
112
        dist = Distribution({'name': 'xx'})
 
113
        cmd = build_ext(dist)
 
114
 
 
115
        # making sure the user option is there
 
116
        options = [name for name, short, label in
 
117
                   cmd.user_options]
 
118
        self.assertIn('user', options)
 
119
 
 
120
        # setting a value
 
121
        cmd.user = 1
 
122
 
 
123
        # setting user based lib and include
 
124
        lib = os.path.join(site.USER_BASE, 'lib')
 
125
        incl = os.path.join(site.USER_BASE, 'include')
 
126
        os.mkdir(lib)
 
127
        os.mkdir(incl)
 
128
 
 
129
        cmd.ensure_finalized()
 
130
 
 
131
        # see if include_dirs and library_dirs were set
 
132
        self.assertIn(lib, cmd.library_dirs)
 
133
        self.assertIn(lib, cmd.rpath)
 
134
        self.assertIn(incl, cmd.include_dirs)
 
135
 
138
136
    def test_finalize_options(self):
139
137
        # Make sure Python's include directories (for Python.h, pyconfig.h,
140
138
        # etc.) are in the include search path.
143
141
        cmd = build_ext(dist)
144
142
        cmd.finalize_options()
145
143
 
146
 
        from distutils import sysconfig
147
144
        py_include = sysconfig.get_python_inc()
148
145
        self.assertTrue(py_include in cmd.include_dirs)
149
146
 
153
150
        # make sure cmd.libraries is turned into a list
154
151
        # if it's a string
155
152
        cmd = build_ext(dist)
156
 
        cmd.libraries = 'my_lib'
 
153
        cmd.libraries = 'my_lib, other_lib lastlib'
157
154
        cmd.finalize_options()
158
 
        self.assertEqual(cmd.libraries, ['my_lib'])
 
155
        self.assertEqual(cmd.libraries, ['my_lib', 'other_lib', 'lastlib'])
159
156
 
160
157
        # make sure cmd.library_dirs is turned into a list
161
158
        # if it's a string
162
159
        cmd = build_ext(dist)
163
 
        cmd.library_dirs = 'my_lib_dir'
 
160
        cmd.library_dirs = 'my_lib_dir%sother_lib_dir' % os.pathsep
164
161
        cmd.finalize_options()
165
 
        self.assertTrue('my_lib_dir' in cmd.library_dirs)
 
162
        self.assertIn('my_lib_dir', cmd.library_dirs)
 
163
        self.assertIn('other_lib_dir', cmd.library_dirs)
166
164
 
167
165
        # make sure rpath is turned into a list
168
 
        # if it's a list of os.pathsep's paths
 
166
        # if it's a string
169
167
        cmd = build_ext(dist)
170
 
        cmd.rpath = os.pathsep.join(['one', 'two'])
 
168
        cmd.rpath = 'one%stwo' % os.pathsep
171
169
        cmd.finalize_options()
172
170
        self.assertEqual(cmd.rpath, ['one', 'two'])
173
171
 
271
269
        dist = Distribution({'name': 'xx',
272
270
                             'ext_modules': [ext]})
273
271
        cmd = build_ext(dist)
274
 
        self._fixup_command(cmd)
 
272
        support.fixup_build_ext(cmd)
275
273
        cmd.ensure_finalized()
276
274
        self.assertEqual(len(cmd.get_outputs()), 1)
277
275
 
278
 
        if os.name == "nt":
279
 
            cmd.debug = sys.executable.endswith("_d.exe")
280
 
 
281
276
        cmd.build_lib = os.path.join(self.tmp_dir, 'build')
282
277
        cmd.build_temp = os.path.join(self.tmp_dir, 'tempt')
283
278
 
432
427
        self.assertEqual(ext_path, wanted)
433
428
 
434
429
    @unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for MacOSX')
435
 
    def test_deployment_target(self):
436
 
        self._try_compile_deployment_target()
437
 
 
 
430
    def test_deployment_target_default(self):
 
431
        # Issue 9516: Test that, in the absence of the environment variable,
 
432
        # an extension module is compiled with the same deployment target as
 
433
        #  the interpreter.
 
434
        self._try_compile_deployment_target('==', None)
 
435
 
 
436
    @unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for MacOSX')
 
437
    def test_deployment_target_too_low(self):
 
438
        # Issue 9516: Test that an extension module is not allowed to be
 
439
        # compiled with a deployment target less than that of the interpreter.
 
440
        self.assertRaises(DistutilsPlatformError,
 
441
            self._try_compile_deployment_target, '>', '10.1')
 
442
 
 
443
    @unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for MacOSX')
 
444
    def test_deployment_target_higher_ok(self):
 
445
        # Issue 9516: Test that an extension module can be compiled with a
 
446
        # deployment target higher than that of the interpreter: the ext
 
447
        # module may depend on some newer OS feature.
 
448
        deptarget = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
 
449
        if deptarget:
 
450
            # increment the minor version number (i.e. 10.6 -> 10.7)
 
451
            deptarget = [int(x) for x in deptarget.split('.')]
 
452
            deptarget[-1] += 1
 
453
            deptarget = '.'.join(str(i) for i in deptarget)
 
454
            self._try_compile_deployment_target('<', deptarget)
 
455
 
 
456
    def _try_compile_deployment_target(self, operator, target):
438
457
        orig_environ = os.environ
439
458
        os.environ = orig_environ.copy()
440
459
        self.addCleanup(setattr, os, 'environ', orig_environ)
441
460
 
442
 
        os.environ['MACOSX_DEPLOYMENT_TARGET']='10.1'
443
 
        self._try_compile_deployment_target()
444
 
 
445
 
 
446
 
    def _try_compile_deployment_target(self):
 
461
        if target is None:
 
462
            if os.environ.get('MACOSX_DEPLOYMENT_TARGET'):
 
463
                del os.environ['MACOSX_DEPLOYMENT_TARGET']
 
464
        else:
 
465
            os.environ['MACOSX_DEPLOYMENT_TARGET'] = target
 
466
 
447
467
        deptarget_c = os.path.join(self.tmp_dir, 'deptargetmodule.c')
448
468
 
449
469
        with open(deptarget_c, 'w') as fp:
452
472
 
453
473
                int dummy;
454
474
 
455
 
                #if TARGET != MAC_OS_X_VERSION_MIN_REQUIRED
 
475
                #if TARGET %s MAC_OS_X_VERSION_MIN_REQUIRED
 
476
                #else
456
477
                #error "Unexpected target"
457
 
               #endif
458
 
 
459
 
            '''))
460
 
 
 
478
                #endif
 
479
 
 
480
            ''' % operator))
 
481
 
 
482
        # get the deployment target that the interpreter was built with
461
483
        target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
462
484
        target = tuple(map(int, target.split('.')))
463
485
        target = '%02d%01d0' % target
464
 
 
465
486
        deptarget_ext = Extension(
466
487
            'deptarget',
467
488
            [deptarget_c],
477
498
        cmd.build_temp = self.tmp_dir
478
499
 
479
500
        try:
480
 
            old_stdout = sys.stdout
481
501
            cmd.ensure_finalized()
482
502
            cmd.run()
483
 
 
484
503
        except CompileError:
485
504
            self.fail("Wrong deployment target during compilation")
486
505