(root)/
Python-3.11.7/
Lib/
test/
test_sysconfig.py
       1  import unittest
       2  import sys
       3  import os
       4  import subprocess
       5  import shutil
       6  from copy import copy
       7  
       8  from test.support import (
       9      captured_stdout, PythonSymlink, requires_subprocess, is_wasi
      10  )
      11  from test.support.import_helper import import_module
      12  from test.support.os_helper import (TESTFN, unlink, skip_unless_symlink,
      13                                      change_cwd)
      14  from test.support.warnings_helper import check_warnings
      15  
      16  import sysconfig
      17  from sysconfig import (get_paths, get_platform, get_config_vars,
      18                         get_path, get_path_names, _INSTALL_SCHEMES,
      19                         get_default_scheme, get_scheme_names, get_config_var,
      20                         _expand_vars, _get_preferred_schemes, _main)
      21  import _osx_support
      22  
      23  
      24  HAS_USER_BASE = sysconfig._HAS_USER_BASE
      25  
      26  
      27  class ESC[4;38;5;81mTestSysConfig(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      28  
      29      def setUp(self):
      30          super(TestSysConfig, self).setUp()
      31          self.sys_path = sys.path[:]
      32          # patching os.uname
      33          if hasattr(os, 'uname'):
      34              self.uname = os.uname
      35              self._uname = os.uname()
      36          else:
      37              self.uname = None
      38              self._set_uname(('',)*5)
      39          os.uname = self._get_uname
      40          # saving the environment
      41          self.name = os.name
      42          self.platform = sys.platform
      43          self.version = sys.version
      44          self.sep = os.sep
      45          self.join = os.path.join
      46          self.isabs = os.path.isabs
      47          self.splitdrive = os.path.splitdrive
      48          self._config_vars = sysconfig._CONFIG_VARS, copy(sysconfig._CONFIG_VARS)
      49          self._added_envvars = []
      50          self._changed_envvars = []
      51          for var in ('MACOSX_DEPLOYMENT_TARGET', 'PATH'):
      52              if var in os.environ:
      53                  self._changed_envvars.append((var, os.environ[var]))
      54              else:
      55                  self._added_envvars.append(var)
      56  
      57      def tearDown(self):
      58          sys.path[:] = self.sys_path
      59          self._cleanup_testfn()
      60          if self.uname is not None:
      61              os.uname = self.uname
      62          else:
      63              del os.uname
      64          os.name = self.name
      65          sys.platform = self.platform
      66          sys.version = self.version
      67          os.sep = self.sep
      68          os.path.join = self.join
      69          os.path.isabs = self.isabs
      70          os.path.splitdrive = self.splitdrive
      71          sysconfig._CONFIG_VARS = self._config_vars[0]
      72          sysconfig._CONFIG_VARS.clear()
      73          sysconfig._CONFIG_VARS.update(self._config_vars[1])
      74          for var, value in self._changed_envvars:
      75              os.environ[var] = value
      76          for var in self._added_envvars:
      77              os.environ.pop(var, None)
      78  
      79          super(TestSysConfig, self).tearDown()
      80  
      81      def _set_uname(self, uname):
      82          self._uname = os.uname_result(uname)
      83  
      84      def _get_uname(self):
      85          return self._uname
      86  
      87      def _cleanup_testfn(self):
      88          path = TESTFN
      89          if os.path.isfile(path):
      90              os.remove(path)
      91          elif os.path.isdir(path):
      92              shutil.rmtree(path)
      93  
      94      def test_get_path_names(self):
      95          self.assertEqual(get_path_names(), sysconfig._SCHEME_KEYS)
      96  
      97      def test_get_paths(self):
      98          scheme = get_paths()
      99          default_scheme = get_default_scheme()
     100          wanted = _expand_vars(default_scheme, None)
     101          wanted = sorted(wanted.items())
     102          scheme = sorted(scheme.items())
     103          self.assertEqual(scheme, wanted)
     104  
     105      def test_get_path(self):
     106          config_vars = get_config_vars()
     107          if os.name == 'nt':
     108              # On Windows, we replace the native platlibdir name with the
     109              # default so that POSIX schemes resolve correctly
     110              config_vars = config_vars | {'platlibdir': 'lib'}
     111          for scheme in _INSTALL_SCHEMES:
     112              for name in _INSTALL_SCHEMES[scheme]:
     113                  expected = _INSTALL_SCHEMES[scheme][name].format(**config_vars)
     114                  self.assertEqual(
     115                      os.path.normpath(get_path(name, scheme)),
     116                      os.path.normpath(expected),
     117                  )
     118  
     119      def test_get_default_scheme(self):
     120          self.assertIn(get_default_scheme(), _INSTALL_SCHEMES)
     121  
     122      def test_get_preferred_schemes(self):
     123          expected_schemes = {'prefix', 'home', 'user'}
     124  
     125          # Windows.
     126          os.name = 'nt'
     127          schemes = _get_preferred_schemes()
     128          self.assertIsInstance(schemes, dict)
     129          self.assertEqual(set(schemes), expected_schemes)
     130  
     131          # Mac and Linux, shared library build.
     132          os.name = 'posix'
     133          schemes = _get_preferred_schemes()
     134          self.assertIsInstance(schemes, dict)
     135          self.assertEqual(set(schemes), expected_schemes)
     136  
     137          # Mac, framework build.
     138          os.name = 'posix'
     139          sys.platform = 'darwin'
     140          sys._framework = True
     141          self.assertIsInstance(schemes, dict)
     142          self.assertEqual(set(schemes), expected_schemes)
     143  
     144      def test_posix_venv_scheme(self):
     145          # The following directories were hardcoded in the venv module
     146          # before bpo-45413, here we assert the posix_venv scheme does not regress
     147          binpath = 'bin'
     148          incpath = 'include'
     149          libpath = os.path.join('lib',
     150                                 'python%d.%d' % sys.version_info[:2],
     151                                 'site-packages')
     152  
     153          # Resolve the paths in prefix
     154          binpath = os.path.join(sys.prefix, binpath)
     155          incpath = os.path.join(sys.prefix, incpath)
     156          libpath = os.path.join(sys.prefix, libpath)
     157  
     158          self.assertEqual(binpath, sysconfig.get_path('scripts', scheme='posix_venv'))
     159          self.assertEqual(libpath, sysconfig.get_path('purelib', scheme='posix_venv'))
     160  
     161          # The include directory on POSIX isn't exactly the same as before,
     162          # but it is "within"
     163          sysconfig_includedir = sysconfig.get_path('include', scheme='posix_venv')
     164          self.assertTrue(sysconfig_includedir.startswith(incpath + os.sep))
     165  
     166      def test_nt_venv_scheme(self):
     167          # The following directories were hardcoded in the venv module
     168          # before bpo-45413, here we assert the posix_venv scheme does not regress
     169          binpath = 'Scripts'
     170          incpath = 'Include'
     171          libpath = os.path.join('Lib', 'site-packages')
     172  
     173          # Resolve the paths in prefix
     174          binpath = os.path.join(sys.prefix, binpath)
     175          incpath = os.path.join(sys.prefix, incpath)
     176          libpath = os.path.join(sys.prefix, libpath)
     177  
     178          self.assertEqual(binpath, sysconfig.get_path('scripts', scheme='nt_venv'))
     179          self.assertEqual(incpath, sysconfig.get_path('include', scheme='nt_venv'))
     180          self.assertEqual(libpath, sysconfig.get_path('purelib', scheme='nt_venv'))
     181  
     182      def test_venv_scheme(self):
     183          if sys.platform == 'win32':
     184              self.assertEqual(
     185                  sysconfig.get_path('scripts', scheme='venv'),
     186                  sysconfig.get_path('scripts', scheme='nt_venv')
     187              )
     188              self.assertEqual(
     189                  sysconfig.get_path('include', scheme='venv'),
     190                  sysconfig.get_path('include', scheme='nt_venv')
     191              )
     192              self.assertEqual(
     193                  sysconfig.get_path('purelib', scheme='venv'),
     194                  sysconfig.get_path('purelib', scheme='nt_venv')
     195              )
     196          else:
     197              self.assertEqual(
     198                  sysconfig.get_path('scripts', scheme='venv'),
     199                  sysconfig.get_path('scripts', scheme='posix_venv')
     200              )
     201              self.assertEqual(
     202                  sysconfig.get_path('include', scheme='venv'),
     203                  sysconfig.get_path('include', scheme='posix_venv')
     204              )
     205              self.assertEqual(
     206                  sysconfig.get_path('purelib', scheme='venv'),
     207                  sysconfig.get_path('purelib', scheme='posix_venv')
     208              )
     209  
     210      def test_get_config_vars(self):
     211          cvars = get_config_vars()
     212          self.assertIsInstance(cvars, dict)
     213          self.assertTrue(cvars)
     214  
     215      def test_get_platform(self):
     216          # windows XP, 32bits
     217          os.name = 'nt'
     218          sys.version = ('2.4.4 (#71, Oct 18 2006, 08:34:43) '
     219                         '[MSC v.1310 32 bit (Intel)]')
     220          sys.platform = 'win32'
     221          self.assertEqual(get_platform(), 'win32')
     222  
     223          # windows XP, amd64
     224          os.name = 'nt'
     225          sys.version = ('2.4.4 (#71, Oct 18 2006, 08:34:43) '
     226                         '[MSC v.1310 32 bit (Amd64)]')
     227          sys.platform = 'win32'
     228          self.assertEqual(get_platform(), 'win-amd64')
     229  
     230          # macbook
     231          os.name = 'posix'
     232          sys.version = ('2.5 (r25:51918, Sep 19 2006, 08:49:13) '
     233                         '\n[GCC 4.0.1 (Apple Computer, Inc. build 5341)]')
     234          sys.platform = 'darwin'
     235          self._set_uname(('Darwin', 'macziade', '8.11.1',
     236                     ('Darwin Kernel Version 8.11.1: '
     237                      'Wed Oct 10 18:23:28 PDT 2007; '
     238                      'root:xnu-792.25.20~1/RELEASE_I386'), 'PowerPC'))
     239          _osx_support._remove_original_values(get_config_vars())
     240          get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.3'
     241  
     242          get_config_vars()['CFLAGS'] = ('-fno-strict-aliasing -DNDEBUG -g '
     243                                         '-fwrapv -O3 -Wall -Wstrict-prototypes')
     244  
     245          maxint = sys.maxsize
     246          try:
     247              sys.maxsize = 2147483647
     248              self.assertEqual(get_platform(), 'macosx-10.3-ppc')
     249              sys.maxsize = 9223372036854775807
     250              self.assertEqual(get_platform(), 'macosx-10.3-ppc64')
     251          finally:
     252              sys.maxsize = maxint
     253  
     254          self._set_uname(('Darwin', 'macziade', '8.11.1',
     255                     ('Darwin Kernel Version 8.11.1: '
     256                      'Wed Oct 10 18:23:28 PDT 2007; '
     257                      'root:xnu-792.25.20~1/RELEASE_I386'), 'i386'))
     258          _osx_support._remove_original_values(get_config_vars())
     259          get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.3'
     260  
     261          get_config_vars()['CFLAGS'] = ('-fno-strict-aliasing -DNDEBUG -g '
     262                                         '-fwrapv -O3 -Wall -Wstrict-prototypes')
     263          maxint = sys.maxsize
     264          try:
     265              sys.maxsize = 2147483647
     266              self.assertEqual(get_platform(), 'macosx-10.3-i386')
     267              sys.maxsize = 9223372036854775807
     268              self.assertEqual(get_platform(), 'macosx-10.3-x86_64')
     269          finally:
     270              sys.maxsize = maxint
     271  
     272          # macbook with fat binaries (fat, universal or fat64)
     273          _osx_support._remove_original_values(get_config_vars())
     274          get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.4'
     275          get_config_vars()['CFLAGS'] = ('-arch ppc -arch i386 -isysroot '
     276                                         '/Developer/SDKs/MacOSX10.4u.sdk  '
     277                                         '-fno-strict-aliasing -fno-common '
     278                                         '-dynamic -DNDEBUG -g -O3')
     279  
     280          self.assertEqual(get_platform(), 'macosx-10.4-fat')
     281  
     282          _osx_support._remove_original_values(get_config_vars())
     283          get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch i386 -isysroot '
     284                                         '/Developer/SDKs/MacOSX10.4u.sdk  '
     285                                         '-fno-strict-aliasing -fno-common '
     286                                         '-dynamic -DNDEBUG -g -O3')
     287  
     288          self.assertEqual(get_platform(), 'macosx-10.4-intel')
     289  
     290          _osx_support._remove_original_values(get_config_vars())
     291          get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch ppc -arch i386 -isysroot '
     292                                         '/Developer/SDKs/MacOSX10.4u.sdk  '
     293                                         '-fno-strict-aliasing -fno-common '
     294                                         '-dynamic -DNDEBUG -g -O3')
     295          self.assertEqual(get_platform(), 'macosx-10.4-fat3')
     296  
     297          _osx_support._remove_original_values(get_config_vars())
     298          get_config_vars()['CFLAGS'] = ('-arch ppc64 -arch x86_64 -arch ppc -arch i386 -isysroot '
     299                                         '/Developer/SDKs/MacOSX10.4u.sdk  '
     300                                         '-fno-strict-aliasing -fno-common '
     301                                         '-dynamic -DNDEBUG -g -O3')
     302          self.assertEqual(get_platform(), 'macosx-10.4-universal')
     303  
     304          _osx_support._remove_original_values(get_config_vars())
     305          get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch ppc64 -isysroot '
     306                                         '/Developer/SDKs/MacOSX10.4u.sdk  '
     307                                         '-fno-strict-aliasing -fno-common '
     308                                         '-dynamic -DNDEBUG -g -O3')
     309  
     310          self.assertEqual(get_platform(), 'macosx-10.4-fat64')
     311  
     312          for arch in ('ppc', 'i386', 'x86_64', 'ppc64'):
     313              _osx_support._remove_original_values(get_config_vars())
     314              get_config_vars()['CFLAGS'] = ('-arch %s -isysroot '
     315                                             '/Developer/SDKs/MacOSX10.4u.sdk  '
     316                                             '-fno-strict-aliasing -fno-common '
     317                                             '-dynamic -DNDEBUG -g -O3' % arch)
     318  
     319              self.assertEqual(get_platform(), 'macosx-10.4-%s' % arch)
     320  
     321          # linux debian sarge
     322          os.name = 'posix'
     323          sys.version = ('2.3.5 (#1, Jul  4 2007, 17:28:59) '
     324                         '\n[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)]')
     325          sys.platform = 'linux2'
     326          self._set_uname(('Linux', 'aglae', '2.6.21.1dedibox-r7',
     327                      '#1 Mon Apr 30 17:25:38 CEST 2007', 'i686'))
     328  
     329          self.assertEqual(get_platform(), 'linux-i686')
     330  
     331          # XXX more platforms to tests here
     332  
     333      @unittest.skipIf(is_wasi, "Incompatible with WASI mapdir and OOT builds")
     334      def test_get_config_h_filename(self):
     335          config_h = sysconfig.get_config_h_filename()
     336          self.assertTrue(os.path.isfile(config_h), config_h)
     337  
     338      def test_get_scheme_names(self):
     339          wanted = ['nt', 'posix_home', 'posix_prefix', 'posix_venv', 'nt_venv', 'venv']
     340          if HAS_USER_BASE:
     341              wanted.extend(['nt_user', 'osx_framework_user', 'posix_user'])
     342          self.assertEqual(get_scheme_names(), tuple(sorted(wanted)))
     343  
     344      @skip_unless_symlink
     345      @requires_subprocess()
     346      def test_symlink(self): # Issue 7880
     347          with PythonSymlink() as py:
     348              cmd = "-c", "import sysconfig; print(sysconfig.get_platform())"
     349              self.assertEqual(py.call_real(*cmd), py.call_link(*cmd))
     350  
     351      def test_user_similar(self):
     352          # Issue #8759: make sure the posix scheme for the users
     353          # is similar to the global posix_prefix one
     354          base = get_config_var('base')
     355          if HAS_USER_BASE:
     356              user = get_config_var('userbase')
     357          # the global scheme mirrors the distinction between prefix and
     358          # exec-prefix but not the user scheme, so we have to adapt the paths
     359          # before comparing (issue #9100)
     360          adapt = sys.base_prefix != sys.base_exec_prefix
     361          for name in ('stdlib', 'platstdlib', 'purelib', 'platlib'):
     362              global_path = get_path(name, 'posix_prefix')
     363              if adapt:
     364                  global_path = global_path.replace(sys.exec_prefix, sys.base_prefix)
     365                  base = base.replace(sys.exec_prefix, sys.base_prefix)
     366              elif sys.base_prefix != sys.prefix:
     367                  # virtual environment? Likewise, we have to adapt the paths
     368                  # before comparing
     369                  global_path = global_path.replace(sys.base_prefix, sys.prefix)
     370                  base = base.replace(sys.base_prefix, sys.prefix)
     371              if HAS_USER_BASE:
     372                  user_path = get_path(name, 'posix_user')
     373                  expected = os.path.normpath(global_path.replace(base, user, 1))
     374                  # bpo-44860: platlib of posix_user doesn't use sys.platlibdir,
     375                  # whereas posix_prefix does.
     376                  if name == 'platlib':
     377                      # Replace "/lib64/python3.11/site-packages" suffix
     378                      # with "/lib/python3.11/site-packages".
     379                      py_version_short = sysconfig.get_python_version()
     380                      suffix = f'python{py_version_short}/site-packages'
     381                      expected = expected.replace(f'/{sys.platlibdir}/{suffix}',
     382                                                  f'/lib/{suffix}')
     383                  self.assertEqual(user_path, expected)
     384  
     385      def test_main(self):
     386          # just making sure _main() runs and returns things in the stdout
     387          with captured_stdout() as output:
     388              _main()
     389          self.assertTrue(len(output.getvalue().split('\n')) > 0)
     390  
     391      @unittest.skipIf(sys.platform == "win32", "Does not apply to Windows")
     392      def test_ldshared_value(self):
     393          ldflags = sysconfig.get_config_var('LDFLAGS')
     394          ldshared = sysconfig.get_config_var('LDSHARED')
     395  
     396          self.assertIn(ldflags, ldshared)
     397  
     398      @unittest.skipUnless(sys.platform == "darwin", "test only relevant on MacOSX")
     399      @requires_subprocess()
     400      def test_platform_in_subprocess(self):
     401          my_platform = sysconfig.get_platform()
     402  
     403          # Test without MACOSX_DEPLOYMENT_TARGET in the environment
     404  
     405          env = os.environ.copy()
     406          if 'MACOSX_DEPLOYMENT_TARGET' in env:
     407              del env['MACOSX_DEPLOYMENT_TARGET']
     408  
     409          p = subprocess.Popen([
     410                  sys.executable, '-c',
     411                  'import sysconfig; print(sysconfig.get_platform())',
     412              ],
     413              stdout=subprocess.PIPE,
     414              stderr=subprocess.DEVNULL,
     415              env=env)
     416          test_platform = p.communicate()[0].strip()
     417          test_platform = test_platform.decode('utf-8')
     418          status = p.wait()
     419  
     420          self.assertEqual(status, 0)
     421          self.assertEqual(my_platform, test_platform)
     422  
     423          # Test with MACOSX_DEPLOYMENT_TARGET in the environment, and
     424          # using a value that is unlikely to be the default one.
     425          env = os.environ.copy()
     426          env['MACOSX_DEPLOYMENT_TARGET'] = '10.1'
     427  
     428          p = subprocess.Popen([
     429                  sys.executable, '-c',
     430                  'import sysconfig; print(sysconfig.get_platform())',
     431              ],
     432              stdout=subprocess.PIPE,
     433              stderr=subprocess.DEVNULL,
     434              env=env)
     435          test_platform = p.communicate()[0].strip()
     436          test_platform = test_platform.decode('utf-8')
     437          status = p.wait()
     438  
     439          self.assertEqual(status, 0)
     440          self.assertEqual(my_platform, test_platform)
     441  
     442      @unittest.skipIf(is_wasi, "Incompatible with WASI mapdir and OOT builds")
     443      def test_srcdir(self):
     444          # See Issues #15322, #15364.
     445          srcdir = sysconfig.get_config_var('srcdir')
     446  
     447          self.assertTrue(os.path.isabs(srcdir), srcdir)
     448          self.assertTrue(os.path.isdir(srcdir), srcdir)
     449  
     450          if sysconfig._PYTHON_BUILD:
     451              # The python executable has not been installed so srcdir
     452              # should be a full source checkout.
     453              Python_h = os.path.join(srcdir, 'Include', 'Python.h')
     454              self.assertTrue(os.path.exists(Python_h), Python_h)
     455              # <srcdir>/PC/pyconfig.h always exists even if unused on POSIX.
     456              pyconfig_h = os.path.join(srcdir, 'PC', 'pyconfig.h')
     457              self.assertTrue(os.path.exists(pyconfig_h), pyconfig_h)
     458              pyconfig_h_in = os.path.join(srcdir, 'pyconfig.h.in')
     459              self.assertTrue(os.path.exists(pyconfig_h_in), pyconfig_h_in)
     460          elif os.name == 'posix':
     461              makefile_dir = os.path.dirname(sysconfig.get_makefile_filename())
     462              # Issue #19340: srcdir has been realpath'ed already
     463              makefile_dir = os.path.realpath(makefile_dir)
     464              self.assertEqual(makefile_dir, srcdir)
     465  
     466      def test_srcdir_independent_of_cwd(self):
     467          # srcdir should be independent of the current working directory
     468          # See Issues #15322, #15364.
     469          srcdir = sysconfig.get_config_var('srcdir')
     470          with change_cwd(os.pardir):
     471              srcdir2 = sysconfig.get_config_var('srcdir')
     472          self.assertEqual(srcdir, srcdir2)
     473  
     474      @unittest.skipIf(sysconfig.get_config_var('EXT_SUFFIX') is None,
     475                       'EXT_SUFFIX required for this test')
     476      def test_EXT_SUFFIX_in_vars(self):
     477          import _imp
     478          if not _imp.extension_suffixes():
     479              self.skipTest("stub loader has no suffixes")
     480          vars = sysconfig.get_config_vars()
     481          self.assertEqual(vars['EXT_SUFFIX'], _imp.extension_suffixes()[0])
     482  
     483      @unittest.skipUnless(sys.platform == 'linux' and
     484                           hasattr(sys.implementation, '_multiarch'),
     485                           'multiarch-specific test')
     486      def test_triplet_in_ext_suffix(self):
     487          ctypes = import_module('ctypes')
     488          import platform, re
     489          machine = platform.machine()
     490          suffix = sysconfig.get_config_var('EXT_SUFFIX')
     491          if re.match('(aarch64|arm|mips|ppc|powerpc|s390|sparc)', machine):
     492              self.assertTrue('linux' in suffix, suffix)
     493          if re.match('(i[3-6]86|x86_64)$', machine):
     494              if ctypes.sizeof(ctypes.c_char_p()) == 4:
     495                  expected_suffixes = 'i386-linux-gnu.so', 'x86_64-linux-gnux32.so', 'i386-linux-musl.so'
     496              else: # 8 byte pointer size
     497                  expected_suffixes = 'x86_64-linux-gnu.so', 'x86_64-linux-musl.so'
     498              self.assertTrue(suffix.endswith(expected_suffixes),
     499                              f'unexpected suffix {suffix!r}')
     500  
     501      @unittest.skipUnless(sys.platform == 'darwin', 'OS X-specific test')
     502      def test_osx_ext_suffix(self):
     503          suffix = sysconfig.get_config_var('EXT_SUFFIX')
     504          self.assertTrue(suffix.endswith('-darwin.so'), suffix)
     505  
     506  class ESC[4;38;5;81mMakefileTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     507  
     508      @unittest.skipIf(sys.platform.startswith('win'),
     509                       'Test is not Windows compatible')
     510      @unittest.skipIf(is_wasi, "Incompatible with WASI mapdir and OOT builds")
     511      def test_get_makefile_filename(self):
     512          makefile = sysconfig.get_makefile_filename()
     513          self.assertTrue(os.path.isfile(makefile), makefile)
     514  
     515      def test_parse_makefile(self):
     516          self.addCleanup(unlink, TESTFN)
     517          with open(TESTFN, "w") as makefile:
     518              print("var1=a$(VAR2)", file=makefile)
     519              print("VAR2=b$(var3)", file=makefile)
     520              print("var3=42", file=makefile)
     521              print("var4=$/invalid", file=makefile)
     522              print("var5=dollar$$5", file=makefile)
     523              print("var6=${var3}/lib/python3.5/config-$(VAR2)$(var5)"
     524                    "-x86_64-linux-gnu", file=makefile)
     525          vars = sysconfig._parse_makefile(TESTFN)
     526          self.assertEqual(vars, {
     527              'var1': 'ab42',
     528              'VAR2': 'b42',
     529              'var3': 42,
     530              'var4': '$/invalid',
     531              'var5': 'dollar$5',
     532              'var6': '42/lib/python3.5/config-b42dollar$5-x86_64-linux-gnu',
     533          })
     534  
     535  
     536  if __name__ == "__main__":
     537      unittest.main()