xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/sysconfig.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Worker"""Access to Python's configuration information."""
2*cda5da8dSAndroid Build Coastguard Worker
3*cda5da8dSAndroid Build Coastguard Workerimport os
4*cda5da8dSAndroid Build Coastguard Workerimport sys
5*cda5da8dSAndroid Build Coastguard Workerfrom os.path import pardir, realpath
6*cda5da8dSAndroid Build Coastguard Worker
7*cda5da8dSAndroid Build Coastguard Worker__all__ = [
8*cda5da8dSAndroid Build Coastguard Worker    'get_config_h_filename',
9*cda5da8dSAndroid Build Coastguard Worker    'get_config_var',
10*cda5da8dSAndroid Build Coastguard Worker    'get_config_vars',
11*cda5da8dSAndroid Build Coastguard Worker    'get_makefile_filename',
12*cda5da8dSAndroid Build Coastguard Worker    'get_path',
13*cda5da8dSAndroid Build Coastguard Worker    'get_path_names',
14*cda5da8dSAndroid Build Coastguard Worker    'get_paths',
15*cda5da8dSAndroid Build Coastguard Worker    'get_platform',
16*cda5da8dSAndroid Build Coastguard Worker    'get_python_version',
17*cda5da8dSAndroid Build Coastguard Worker    'get_scheme_names',
18*cda5da8dSAndroid Build Coastguard Worker    'parse_config_h',
19*cda5da8dSAndroid Build Coastguard Worker]
20*cda5da8dSAndroid Build Coastguard Worker
21*cda5da8dSAndroid Build Coastguard Worker# Keys for get_config_var() that are never converted to Python integers.
22*cda5da8dSAndroid Build Coastguard Worker_ALWAYS_STR = {
23*cda5da8dSAndroid Build Coastguard Worker    'MACOSX_DEPLOYMENT_TARGET',
24*cda5da8dSAndroid Build Coastguard Worker}
25*cda5da8dSAndroid Build Coastguard Worker
26*cda5da8dSAndroid Build Coastguard Worker_INSTALL_SCHEMES = {
27*cda5da8dSAndroid Build Coastguard Worker    'posix_prefix': {
28*cda5da8dSAndroid Build Coastguard Worker        'stdlib': '{installed_base}/{platlibdir}/python{py_version_short}',
29*cda5da8dSAndroid Build Coastguard Worker        'platstdlib': '{platbase}/{platlibdir}/python{py_version_short}',
30*cda5da8dSAndroid Build Coastguard Worker        'purelib': '{base}/lib/python{py_version_short}/site-packages',
31*cda5da8dSAndroid Build Coastguard Worker        'platlib': '{platbase}/{platlibdir}/python{py_version_short}/site-packages',
32*cda5da8dSAndroid Build Coastguard Worker        'include':
33*cda5da8dSAndroid Build Coastguard Worker            '{installed_base}/include/python{py_version_short}{abiflags}',
34*cda5da8dSAndroid Build Coastguard Worker        'platinclude':
35*cda5da8dSAndroid Build Coastguard Worker            '{installed_platbase}/include/python{py_version_short}{abiflags}',
36*cda5da8dSAndroid Build Coastguard Worker        'scripts': '{base}/bin',
37*cda5da8dSAndroid Build Coastguard Worker        'data': '{base}',
38*cda5da8dSAndroid Build Coastguard Worker        },
39*cda5da8dSAndroid Build Coastguard Worker    'posix_home': {
40*cda5da8dSAndroid Build Coastguard Worker        'stdlib': '{installed_base}/lib/python',
41*cda5da8dSAndroid Build Coastguard Worker        'platstdlib': '{base}/lib/python',
42*cda5da8dSAndroid Build Coastguard Worker        'purelib': '{base}/lib/python',
43*cda5da8dSAndroid Build Coastguard Worker        'platlib': '{base}/lib/python',
44*cda5da8dSAndroid Build Coastguard Worker        'include': '{installed_base}/include/python',
45*cda5da8dSAndroid Build Coastguard Worker        'platinclude': '{installed_base}/include/python',
46*cda5da8dSAndroid Build Coastguard Worker        'scripts': '{base}/bin',
47*cda5da8dSAndroid Build Coastguard Worker        'data': '{base}',
48*cda5da8dSAndroid Build Coastguard Worker        },
49*cda5da8dSAndroid Build Coastguard Worker    'nt': {
50*cda5da8dSAndroid Build Coastguard Worker        'stdlib': '{installed_base}/Lib',
51*cda5da8dSAndroid Build Coastguard Worker        'platstdlib': '{base}/Lib',
52*cda5da8dSAndroid Build Coastguard Worker        'purelib': '{base}/Lib/site-packages',
53*cda5da8dSAndroid Build Coastguard Worker        'platlib': '{base}/Lib/site-packages',
54*cda5da8dSAndroid Build Coastguard Worker        'include': '{installed_base}/Include',
55*cda5da8dSAndroid Build Coastguard Worker        'platinclude': '{installed_base}/Include',
56*cda5da8dSAndroid Build Coastguard Worker        'scripts': '{base}/Scripts',
57*cda5da8dSAndroid Build Coastguard Worker        'data': '{base}',
58*cda5da8dSAndroid Build Coastguard Worker        },
59*cda5da8dSAndroid Build Coastguard Worker    # Downstream distributors can overwrite the default install scheme.
60*cda5da8dSAndroid Build Coastguard Worker    # This is done to support downstream modifications where distributors change
61*cda5da8dSAndroid Build Coastguard Worker    # the installation layout (eg. different site-packages directory).
62*cda5da8dSAndroid Build Coastguard Worker    # So, distributors will change the default scheme to one that correctly
63*cda5da8dSAndroid Build Coastguard Worker    # represents their layout.
64*cda5da8dSAndroid Build Coastguard Worker    # This presents an issue for projects/people that need to bootstrap virtual
65*cda5da8dSAndroid Build Coastguard Worker    # environments, like virtualenv. As distributors might now be customizing
66*cda5da8dSAndroid Build Coastguard Worker    # the default install scheme, there is no guarantee that the information
67*cda5da8dSAndroid Build Coastguard Worker    # returned by sysconfig.get_default_scheme/get_paths is correct for
68*cda5da8dSAndroid Build Coastguard Worker    # a virtual environment, the only guarantee we have is that it is correct
69*cda5da8dSAndroid Build Coastguard Worker    # for the *current* environment. When bootstrapping a virtual environment,
70*cda5da8dSAndroid Build Coastguard Worker    # we need to know its layout, so that we can place the files in the
71*cda5da8dSAndroid Build Coastguard Worker    # correct locations.
72*cda5da8dSAndroid Build Coastguard Worker    # The "*_venv" install scheme is a scheme to bootstrap virtual environments,
73*cda5da8dSAndroid Build Coastguard Worker    # essentially identical to the default posix_prefix/nt schemes.
74*cda5da8dSAndroid Build Coastguard Worker    # Downstream distributors who patch posix_prefix/nt scheme are encouraged to
75*cda5da8dSAndroid Build Coastguard Worker    # leave the following schemes unchanged
76*cda5da8dSAndroid Build Coastguard Worker    'posix_venv': {
77*cda5da8dSAndroid Build Coastguard Worker        'stdlib': '{installed_base}/{platlibdir}/python{py_version_short}',
78*cda5da8dSAndroid Build Coastguard Worker        'platstdlib': '{platbase}/{platlibdir}/python{py_version_short}',
79*cda5da8dSAndroid Build Coastguard Worker        'purelib': '{base}/lib/python{py_version_short}/site-packages',
80*cda5da8dSAndroid Build Coastguard Worker        'platlib': '{platbase}/{platlibdir}/python{py_version_short}/site-packages',
81*cda5da8dSAndroid Build Coastguard Worker        'include':
82*cda5da8dSAndroid Build Coastguard Worker            '{installed_base}/include/python{py_version_short}{abiflags}',
83*cda5da8dSAndroid Build Coastguard Worker        'platinclude':
84*cda5da8dSAndroid Build Coastguard Worker            '{installed_platbase}/include/python{py_version_short}{abiflags}',
85*cda5da8dSAndroid Build Coastguard Worker        'scripts': '{base}/bin',
86*cda5da8dSAndroid Build Coastguard Worker        'data': '{base}',
87*cda5da8dSAndroid Build Coastguard Worker        },
88*cda5da8dSAndroid Build Coastguard Worker    'nt_venv': {
89*cda5da8dSAndroid Build Coastguard Worker        'stdlib': '{installed_base}/Lib',
90*cda5da8dSAndroid Build Coastguard Worker        'platstdlib': '{base}/Lib',
91*cda5da8dSAndroid Build Coastguard Worker        'purelib': '{base}/Lib/site-packages',
92*cda5da8dSAndroid Build Coastguard Worker        'platlib': '{base}/Lib/site-packages',
93*cda5da8dSAndroid Build Coastguard Worker        'include': '{installed_base}/Include',
94*cda5da8dSAndroid Build Coastguard Worker        'platinclude': '{installed_base}/Include',
95*cda5da8dSAndroid Build Coastguard Worker        'scripts': '{base}/Scripts',
96*cda5da8dSAndroid Build Coastguard Worker        'data': '{base}',
97*cda5da8dSAndroid Build Coastguard Worker        },
98*cda5da8dSAndroid Build Coastguard Worker    }
99*cda5da8dSAndroid Build Coastguard Worker
100*cda5da8dSAndroid Build Coastguard Worker# For the OS-native venv scheme, we essentially provide an alias:
101*cda5da8dSAndroid Build Coastguard Workerif os.name == 'nt':
102*cda5da8dSAndroid Build Coastguard Worker    _INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['nt_venv']
103*cda5da8dSAndroid Build Coastguard Workerelse:
104*cda5da8dSAndroid Build Coastguard Worker    _INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['posix_venv']
105*cda5da8dSAndroid Build Coastguard Worker
106*cda5da8dSAndroid Build Coastguard Worker
107*cda5da8dSAndroid Build Coastguard Worker# NOTE: site.py has copy of this function.
108*cda5da8dSAndroid Build Coastguard Worker# Sync it when modify this function.
109*cda5da8dSAndroid Build Coastguard Workerdef _getuserbase():
110*cda5da8dSAndroid Build Coastguard Worker    env_base = os.environ.get("PYTHONUSERBASE", None)
111*cda5da8dSAndroid Build Coastguard Worker    if env_base:
112*cda5da8dSAndroid Build Coastguard Worker        return env_base
113*cda5da8dSAndroid Build Coastguard Worker
114*cda5da8dSAndroid Build Coastguard Worker    # Emscripten, VxWorks, and WASI have no home directories
115*cda5da8dSAndroid Build Coastguard Worker    if sys.platform in {"emscripten", "vxworks", "wasi"}:
116*cda5da8dSAndroid Build Coastguard Worker        return None
117*cda5da8dSAndroid Build Coastguard Worker
118*cda5da8dSAndroid Build Coastguard Worker    def joinuser(*args):
119*cda5da8dSAndroid Build Coastguard Worker        return os.path.expanduser(os.path.join(*args))
120*cda5da8dSAndroid Build Coastguard Worker
121*cda5da8dSAndroid Build Coastguard Worker    if os.name == "nt":
122*cda5da8dSAndroid Build Coastguard Worker        base = os.environ.get("APPDATA") or "~"
123*cda5da8dSAndroid Build Coastguard Worker        return joinuser(base, "Python")
124*cda5da8dSAndroid Build Coastguard Worker
125*cda5da8dSAndroid Build Coastguard Worker    if sys.platform == "darwin" and sys._framework:
126*cda5da8dSAndroid Build Coastguard Worker        return joinuser("~", "Library", sys._framework,
127*cda5da8dSAndroid Build Coastguard Worker                        f"{sys.version_info[0]}.{sys.version_info[1]}")
128*cda5da8dSAndroid Build Coastguard Worker
129*cda5da8dSAndroid Build Coastguard Worker    return joinuser("~", ".local")
130*cda5da8dSAndroid Build Coastguard Worker
131*cda5da8dSAndroid Build Coastguard Worker_HAS_USER_BASE = (_getuserbase() is not None)
132*cda5da8dSAndroid Build Coastguard Worker
133*cda5da8dSAndroid Build Coastguard Workerif _HAS_USER_BASE:
134*cda5da8dSAndroid Build Coastguard Worker    _INSTALL_SCHEMES |= {
135*cda5da8dSAndroid Build Coastguard Worker        # NOTE: When modifying "purelib" scheme, update site._get_path() too.
136*cda5da8dSAndroid Build Coastguard Worker        'nt_user': {
137*cda5da8dSAndroid Build Coastguard Worker            'stdlib': '{userbase}/Python{py_version_nodot_plat}',
138*cda5da8dSAndroid Build Coastguard Worker            'platstdlib': '{userbase}/Python{py_version_nodot_plat}',
139*cda5da8dSAndroid Build Coastguard Worker            'purelib': '{userbase}/Python{py_version_nodot_plat}/site-packages',
140*cda5da8dSAndroid Build Coastguard Worker            'platlib': '{userbase}/Python{py_version_nodot_plat}/site-packages',
141*cda5da8dSAndroid Build Coastguard Worker            'include': '{userbase}/Python{py_version_nodot_plat}/Include',
142*cda5da8dSAndroid Build Coastguard Worker            'scripts': '{userbase}/Python{py_version_nodot_plat}/Scripts',
143*cda5da8dSAndroid Build Coastguard Worker            'data': '{userbase}',
144*cda5da8dSAndroid Build Coastguard Worker            },
145*cda5da8dSAndroid Build Coastguard Worker        'posix_user': {
146*cda5da8dSAndroid Build Coastguard Worker            'stdlib': '{userbase}/{platlibdir}/python{py_version_short}',
147*cda5da8dSAndroid Build Coastguard Worker            'platstdlib': '{userbase}/{platlibdir}/python{py_version_short}',
148*cda5da8dSAndroid Build Coastguard Worker            'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
149*cda5da8dSAndroid Build Coastguard Worker            'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
150*cda5da8dSAndroid Build Coastguard Worker            'include': '{userbase}/include/python{py_version_short}',
151*cda5da8dSAndroid Build Coastguard Worker            'scripts': '{userbase}/bin',
152*cda5da8dSAndroid Build Coastguard Worker            'data': '{userbase}',
153*cda5da8dSAndroid Build Coastguard Worker            },
154*cda5da8dSAndroid Build Coastguard Worker        'osx_framework_user': {
155*cda5da8dSAndroid Build Coastguard Worker            'stdlib': '{userbase}/lib/python',
156*cda5da8dSAndroid Build Coastguard Worker            'platstdlib': '{userbase}/lib/python',
157*cda5da8dSAndroid Build Coastguard Worker            'purelib': '{userbase}/lib/python/site-packages',
158*cda5da8dSAndroid Build Coastguard Worker            'platlib': '{userbase}/lib/python/site-packages',
159*cda5da8dSAndroid Build Coastguard Worker            'include': '{userbase}/include/python{py_version_short}',
160*cda5da8dSAndroid Build Coastguard Worker            'scripts': '{userbase}/bin',
161*cda5da8dSAndroid Build Coastguard Worker            'data': '{userbase}',
162*cda5da8dSAndroid Build Coastguard Worker            },
163*cda5da8dSAndroid Build Coastguard Worker    }
164*cda5da8dSAndroid Build Coastguard Worker
165*cda5da8dSAndroid Build Coastguard Worker_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
166*cda5da8dSAndroid Build Coastguard Worker                'scripts', 'data')
167*cda5da8dSAndroid Build Coastguard Worker
168*cda5da8dSAndroid Build Coastguard Worker_PY_VERSION = sys.version.split()[0]
169*cda5da8dSAndroid Build Coastguard Worker_PY_VERSION_SHORT = f'{sys.version_info[0]}.{sys.version_info[1]}'
170*cda5da8dSAndroid Build Coastguard Worker_PY_VERSION_SHORT_NO_DOT = f'{sys.version_info[0]}{sys.version_info[1]}'
171*cda5da8dSAndroid Build Coastguard Worker_PREFIX = os.path.normpath(sys.prefix)
172*cda5da8dSAndroid Build Coastguard Worker_BASE_PREFIX = os.path.normpath(sys.base_prefix)
173*cda5da8dSAndroid Build Coastguard Worker_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
174*cda5da8dSAndroid Build Coastguard Worker_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
175*cda5da8dSAndroid Build Coastguard Worker_CONFIG_VARS = None
176*cda5da8dSAndroid Build Coastguard Worker_USER_BASE = None
177*cda5da8dSAndroid Build Coastguard Worker
178*cda5da8dSAndroid Build Coastguard Worker# Regexes needed for parsing Makefile (and similar syntaxes,
179*cda5da8dSAndroid Build Coastguard Worker# like old-style Setup files).
180*cda5da8dSAndroid Build Coastguard Worker_variable_rx = r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)"
181*cda5da8dSAndroid Build Coastguard Worker_findvar1_rx = r"\$\(([A-Za-z][A-Za-z0-9_]*)\)"
182*cda5da8dSAndroid Build Coastguard Worker_findvar2_rx = r"\${([A-Za-z][A-Za-z0-9_]*)}"
183*cda5da8dSAndroid Build Coastguard Worker
184*cda5da8dSAndroid Build Coastguard Worker
185*cda5da8dSAndroid Build Coastguard Workerdef _safe_realpath(path):
186*cda5da8dSAndroid Build Coastguard Worker    try:
187*cda5da8dSAndroid Build Coastguard Worker        return realpath(path)
188*cda5da8dSAndroid Build Coastguard Worker    except OSError:
189*cda5da8dSAndroid Build Coastguard Worker        return path
190*cda5da8dSAndroid Build Coastguard Worker
191*cda5da8dSAndroid Build Coastguard Workerif sys.executable:
192*cda5da8dSAndroid Build Coastguard Worker    _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
193*cda5da8dSAndroid Build Coastguard Workerelse:
194*cda5da8dSAndroid Build Coastguard Worker    # sys.executable can be empty if argv[0] has been changed and Python is
195*cda5da8dSAndroid Build Coastguard Worker    # unable to retrieve the real program name
196*cda5da8dSAndroid Build Coastguard Worker    _PROJECT_BASE = _safe_realpath(os.getcwd())
197*cda5da8dSAndroid Build Coastguard Worker
198*cda5da8dSAndroid Build Coastguard Worker# In a virtual environment, `sys._home` gives us the target directory
199*cda5da8dSAndroid Build Coastguard Worker# `_PROJECT_BASE` for the executable that created it when the virtual
200*cda5da8dSAndroid Build Coastguard Worker# python is an actual executable ('venv --copies' or Windows).
201*cda5da8dSAndroid Build Coastguard Worker_sys_home = getattr(sys, '_home', None)
202*cda5da8dSAndroid Build Coastguard Workerif _sys_home:
203*cda5da8dSAndroid Build Coastguard Worker    _PROJECT_BASE = _sys_home
204*cda5da8dSAndroid Build Coastguard Worker
205*cda5da8dSAndroid Build Coastguard Workerif os.name == 'nt':
206*cda5da8dSAndroid Build Coastguard Worker    # In a source build, the executable is in a subdirectory of the root
207*cda5da8dSAndroid Build Coastguard Worker    # that we want (<root>\PCbuild\<platname>).
208*cda5da8dSAndroid Build Coastguard Worker    # `_BASE_PREFIX` is used as the base installation is where the source
209*cda5da8dSAndroid Build Coastguard Worker    # will be.  The realpath is needed to prevent mount point confusion
210*cda5da8dSAndroid Build Coastguard Worker    # that can occur with just string comparisons.
211*cda5da8dSAndroid Build Coastguard Worker    if _safe_realpath(_PROJECT_BASE).startswith(
212*cda5da8dSAndroid Build Coastguard Worker            _safe_realpath(f'{_BASE_PREFIX}\\PCbuild')):
213*cda5da8dSAndroid Build Coastguard Worker        _PROJECT_BASE = _BASE_PREFIX
214*cda5da8dSAndroid Build Coastguard Worker
215*cda5da8dSAndroid Build Coastguard Worker# set for cross builds
216*cda5da8dSAndroid Build Coastguard Workerif "_PYTHON_PROJECT_BASE" in os.environ:
217*cda5da8dSAndroid Build Coastguard Worker    _PROJECT_BASE = _safe_realpath(os.environ["_PYTHON_PROJECT_BASE"])
218*cda5da8dSAndroid Build Coastguard Worker
219*cda5da8dSAndroid Build Coastguard Workerdef is_python_build(check_home=None):
220*cda5da8dSAndroid Build Coastguard Worker    if check_home is not None:
221*cda5da8dSAndroid Build Coastguard Worker        import warnings
222*cda5da8dSAndroid Build Coastguard Worker        warnings.warn("check_home argument is deprecated and ignored.",
223*cda5da8dSAndroid Build Coastguard Worker                      DeprecationWarning, stacklevel=2)
224*cda5da8dSAndroid Build Coastguard Worker    for fn in ("Setup", "Setup.local"):
225*cda5da8dSAndroid Build Coastguard Worker        if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)):
226*cda5da8dSAndroid Build Coastguard Worker            return True
227*cda5da8dSAndroid Build Coastguard Worker    return False
228*cda5da8dSAndroid Build Coastguard Worker
229*cda5da8dSAndroid Build Coastguard Worker_PYTHON_BUILD = is_python_build()
230*cda5da8dSAndroid Build Coastguard Worker
231*cda5da8dSAndroid Build Coastguard Workerif _PYTHON_BUILD:
232*cda5da8dSAndroid Build Coastguard Worker    for scheme in ('posix_prefix', 'posix_home'):
233*cda5da8dSAndroid Build Coastguard Worker        # On POSIX-y platforms, Python will:
234*cda5da8dSAndroid Build Coastguard Worker        # - Build from .h files in 'headers' (which is only added to the
235*cda5da8dSAndroid Build Coastguard Worker        #   scheme when building CPython)
236*cda5da8dSAndroid Build Coastguard Worker        # - Install .h files to 'include'
237*cda5da8dSAndroid Build Coastguard Worker        scheme = _INSTALL_SCHEMES[scheme]
238*cda5da8dSAndroid Build Coastguard Worker        scheme['headers'] = scheme['include']
239*cda5da8dSAndroid Build Coastguard Worker        scheme['include'] = '{srcdir}/Include'
240*cda5da8dSAndroid Build Coastguard Worker        scheme['platinclude'] = '{projectbase}/.'
241*cda5da8dSAndroid Build Coastguard Worker    del scheme
242*cda5da8dSAndroid Build Coastguard Worker
243*cda5da8dSAndroid Build Coastguard Worker
244*cda5da8dSAndroid Build Coastguard Workerdef _subst_vars(s, local_vars):
245*cda5da8dSAndroid Build Coastguard Worker    try:
246*cda5da8dSAndroid Build Coastguard Worker        return s.format(**local_vars)
247*cda5da8dSAndroid Build Coastguard Worker    except KeyError as var:
248*cda5da8dSAndroid Build Coastguard Worker        try:
249*cda5da8dSAndroid Build Coastguard Worker            return s.format(**os.environ)
250*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
251*cda5da8dSAndroid Build Coastguard Worker            raise AttributeError(f'{var}') from None
252*cda5da8dSAndroid Build Coastguard Worker
253*cda5da8dSAndroid Build Coastguard Workerdef _extend_dict(target_dict, other_dict):
254*cda5da8dSAndroid Build Coastguard Worker    target_keys = target_dict.keys()
255*cda5da8dSAndroid Build Coastguard Worker    for key, value in other_dict.items():
256*cda5da8dSAndroid Build Coastguard Worker        if key in target_keys:
257*cda5da8dSAndroid Build Coastguard Worker            continue
258*cda5da8dSAndroid Build Coastguard Worker        target_dict[key] = value
259*cda5da8dSAndroid Build Coastguard Worker
260*cda5da8dSAndroid Build Coastguard Worker
261*cda5da8dSAndroid Build Coastguard Workerdef _expand_vars(scheme, vars):
262*cda5da8dSAndroid Build Coastguard Worker    res = {}
263*cda5da8dSAndroid Build Coastguard Worker    if vars is None:
264*cda5da8dSAndroid Build Coastguard Worker        vars = {}
265*cda5da8dSAndroid Build Coastguard Worker    _extend_dict(vars, get_config_vars())
266*cda5da8dSAndroid Build Coastguard Worker    if os.name == 'nt':
267*cda5da8dSAndroid Build Coastguard Worker        # On Windows we want to substitute 'lib' for schemes rather
268*cda5da8dSAndroid Build Coastguard Worker        # than the native value (without modifying vars, in case it
269*cda5da8dSAndroid Build Coastguard Worker        # was passed in)
270*cda5da8dSAndroid Build Coastguard Worker        vars = vars | {'platlibdir': 'lib'}
271*cda5da8dSAndroid Build Coastguard Worker
272*cda5da8dSAndroid Build Coastguard Worker    for key, value in _INSTALL_SCHEMES[scheme].items():
273*cda5da8dSAndroid Build Coastguard Worker        if os.name in ('posix', 'nt'):
274*cda5da8dSAndroid Build Coastguard Worker            value = os.path.expanduser(value)
275*cda5da8dSAndroid Build Coastguard Worker        res[key] = os.path.normpath(_subst_vars(value, vars))
276*cda5da8dSAndroid Build Coastguard Worker    return res
277*cda5da8dSAndroid Build Coastguard Worker
278*cda5da8dSAndroid Build Coastguard Worker
279*cda5da8dSAndroid Build Coastguard Workerdef _get_preferred_schemes():
280*cda5da8dSAndroid Build Coastguard Worker    if os.name == 'nt':
281*cda5da8dSAndroid Build Coastguard Worker        return {
282*cda5da8dSAndroid Build Coastguard Worker            'prefix': 'nt',
283*cda5da8dSAndroid Build Coastguard Worker            'home': 'posix_home',
284*cda5da8dSAndroid Build Coastguard Worker            'user': 'nt_user',
285*cda5da8dSAndroid Build Coastguard Worker        }
286*cda5da8dSAndroid Build Coastguard Worker    if sys.platform == 'darwin' and sys._framework:
287*cda5da8dSAndroid Build Coastguard Worker        return {
288*cda5da8dSAndroid Build Coastguard Worker            'prefix': 'posix_prefix',
289*cda5da8dSAndroid Build Coastguard Worker            'home': 'posix_home',
290*cda5da8dSAndroid Build Coastguard Worker            'user': 'osx_framework_user',
291*cda5da8dSAndroid Build Coastguard Worker        }
292*cda5da8dSAndroid Build Coastguard Worker    return {
293*cda5da8dSAndroid Build Coastguard Worker        'prefix': 'posix_prefix',
294*cda5da8dSAndroid Build Coastguard Worker        'home': 'posix_home',
295*cda5da8dSAndroid Build Coastguard Worker        'user': 'posix_user',
296*cda5da8dSAndroid Build Coastguard Worker    }
297*cda5da8dSAndroid Build Coastguard Worker
298*cda5da8dSAndroid Build Coastguard Worker
299*cda5da8dSAndroid Build Coastguard Workerdef get_preferred_scheme(key):
300*cda5da8dSAndroid Build Coastguard Worker    if key == 'prefix' and sys.prefix != sys.base_prefix:
301*cda5da8dSAndroid Build Coastguard Worker        return 'venv'
302*cda5da8dSAndroid Build Coastguard Worker    scheme = _get_preferred_schemes()[key]
303*cda5da8dSAndroid Build Coastguard Worker    if scheme not in _INSTALL_SCHEMES:
304*cda5da8dSAndroid Build Coastguard Worker        raise ValueError(
305*cda5da8dSAndroid Build Coastguard Worker            f"{key!r} returned {scheme!r}, which is not a valid scheme "
306*cda5da8dSAndroid Build Coastguard Worker            f"on this platform"
307*cda5da8dSAndroid Build Coastguard Worker        )
308*cda5da8dSAndroid Build Coastguard Worker    return scheme
309*cda5da8dSAndroid Build Coastguard Worker
310*cda5da8dSAndroid Build Coastguard Worker
311*cda5da8dSAndroid Build Coastguard Workerdef get_default_scheme():
312*cda5da8dSAndroid Build Coastguard Worker    return get_preferred_scheme('prefix')
313*cda5da8dSAndroid Build Coastguard Worker
314*cda5da8dSAndroid Build Coastguard Worker
315*cda5da8dSAndroid Build Coastguard Workerdef _parse_makefile(filename, vars=None, keep_unresolved=True):
316*cda5da8dSAndroid Build Coastguard Worker    """Parse a Makefile-style file.
317*cda5da8dSAndroid Build Coastguard Worker
318*cda5da8dSAndroid Build Coastguard Worker    A dictionary containing name/value pairs is returned.  If an
319*cda5da8dSAndroid Build Coastguard Worker    optional dictionary is passed in as the second argument, it is
320*cda5da8dSAndroid Build Coastguard Worker    used instead of a new dictionary.
321*cda5da8dSAndroid Build Coastguard Worker    """
322*cda5da8dSAndroid Build Coastguard Worker    import re
323*cda5da8dSAndroid Build Coastguard Worker
324*cda5da8dSAndroid Build Coastguard Worker    if vars is None:
325*cda5da8dSAndroid Build Coastguard Worker        vars = {}
326*cda5da8dSAndroid Build Coastguard Worker    done = {}
327*cda5da8dSAndroid Build Coastguard Worker    notdone = {}
328*cda5da8dSAndroid Build Coastguard Worker
329*cda5da8dSAndroid Build Coastguard Worker    with open(filename, encoding=sys.getfilesystemencoding(),
330*cda5da8dSAndroid Build Coastguard Worker              errors="surrogateescape") as f:
331*cda5da8dSAndroid Build Coastguard Worker        lines = f.readlines()
332*cda5da8dSAndroid Build Coastguard Worker
333*cda5da8dSAndroid Build Coastguard Worker    for line in lines:
334*cda5da8dSAndroid Build Coastguard Worker        if line.startswith('#') or line.strip() == '':
335*cda5da8dSAndroid Build Coastguard Worker            continue
336*cda5da8dSAndroid Build Coastguard Worker        m = re.match(_variable_rx, line)
337*cda5da8dSAndroid Build Coastguard Worker        if m:
338*cda5da8dSAndroid Build Coastguard Worker            n, v = m.group(1, 2)
339*cda5da8dSAndroid Build Coastguard Worker            v = v.strip()
340*cda5da8dSAndroid Build Coastguard Worker            # `$$' is a literal `$' in make
341*cda5da8dSAndroid Build Coastguard Worker            tmpv = v.replace('$$', '')
342*cda5da8dSAndroid Build Coastguard Worker
343*cda5da8dSAndroid Build Coastguard Worker            if "$" in tmpv:
344*cda5da8dSAndroid Build Coastguard Worker                notdone[n] = v
345*cda5da8dSAndroid Build Coastguard Worker            else:
346*cda5da8dSAndroid Build Coastguard Worker                try:
347*cda5da8dSAndroid Build Coastguard Worker                    if n in _ALWAYS_STR:
348*cda5da8dSAndroid Build Coastguard Worker                        raise ValueError
349*cda5da8dSAndroid Build Coastguard Worker
350*cda5da8dSAndroid Build Coastguard Worker                    v = int(v)
351*cda5da8dSAndroid Build Coastguard Worker                except ValueError:
352*cda5da8dSAndroid Build Coastguard Worker                    # insert literal `$'
353*cda5da8dSAndroid Build Coastguard Worker                    done[n] = v.replace('$$', '$')
354*cda5da8dSAndroid Build Coastguard Worker                else:
355*cda5da8dSAndroid Build Coastguard Worker                    done[n] = v
356*cda5da8dSAndroid Build Coastguard Worker
357*cda5da8dSAndroid Build Coastguard Worker    # do variable interpolation here
358*cda5da8dSAndroid Build Coastguard Worker    variables = list(notdone.keys())
359*cda5da8dSAndroid Build Coastguard Worker
360*cda5da8dSAndroid Build Coastguard Worker    # Variables with a 'PY_' prefix in the makefile. These need to
361*cda5da8dSAndroid Build Coastguard Worker    # be made available without that prefix through sysconfig.
362*cda5da8dSAndroid Build Coastguard Worker    # Special care is needed to ensure that variable expansion works, even
363*cda5da8dSAndroid Build Coastguard Worker    # if the expansion uses the name without a prefix.
364*cda5da8dSAndroid Build Coastguard Worker    renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
365*cda5da8dSAndroid Build Coastguard Worker
366*cda5da8dSAndroid Build Coastguard Worker    while len(variables) > 0:
367*cda5da8dSAndroid Build Coastguard Worker        for name in tuple(variables):
368*cda5da8dSAndroid Build Coastguard Worker            value = notdone[name]
369*cda5da8dSAndroid Build Coastguard Worker            m1 = re.search(_findvar1_rx, value)
370*cda5da8dSAndroid Build Coastguard Worker            m2 = re.search(_findvar2_rx, value)
371*cda5da8dSAndroid Build Coastguard Worker            if m1 and m2:
372*cda5da8dSAndroid Build Coastguard Worker                m = m1 if m1.start() < m2.start() else m2
373*cda5da8dSAndroid Build Coastguard Worker            else:
374*cda5da8dSAndroid Build Coastguard Worker                m = m1 if m1 else m2
375*cda5da8dSAndroid Build Coastguard Worker            if m is not None:
376*cda5da8dSAndroid Build Coastguard Worker                n = m.group(1)
377*cda5da8dSAndroid Build Coastguard Worker                found = True
378*cda5da8dSAndroid Build Coastguard Worker                if n in done:
379*cda5da8dSAndroid Build Coastguard Worker                    item = str(done[n])
380*cda5da8dSAndroid Build Coastguard Worker                elif n in notdone:
381*cda5da8dSAndroid Build Coastguard Worker                    # get it on a subsequent round
382*cda5da8dSAndroid Build Coastguard Worker                    found = False
383*cda5da8dSAndroid Build Coastguard Worker                elif n in os.environ:
384*cda5da8dSAndroid Build Coastguard Worker                    # do it like make: fall back to environment
385*cda5da8dSAndroid Build Coastguard Worker                    item = os.environ[n]
386*cda5da8dSAndroid Build Coastguard Worker
387*cda5da8dSAndroid Build Coastguard Worker                elif n in renamed_variables:
388*cda5da8dSAndroid Build Coastguard Worker                    if (name.startswith('PY_') and
389*cda5da8dSAndroid Build Coastguard Worker                        name[3:] in renamed_variables):
390*cda5da8dSAndroid Build Coastguard Worker                        item = ""
391*cda5da8dSAndroid Build Coastguard Worker
392*cda5da8dSAndroid Build Coastguard Worker                    elif 'PY_' + n in notdone:
393*cda5da8dSAndroid Build Coastguard Worker                        found = False
394*cda5da8dSAndroid Build Coastguard Worker
395*cda5da8dSAndroid Build Coastguard Worker                    else:
396*cda5da8dSAndroid Build Coastguard Worker                        item = str(done['PY_' + n])
397*cda5da8dSAndroid Build Coastguard Worker
398*cda5da8dSAndroid Build Coastguard Worker                else:
399*cda5da8dSAndroid Build Coastguard Worker                    done[n] = item = ""
400*cda5da8dSAndroid Build Coastguard Worker
401*cda5da8dSAndroid Build Coastguard Worker                if found:
402*cda5da8dSAndroid Build Coastguard Worker                    after = value[m.end():]
403*cda5da8dSAndroid Build Coastguard Worker                    value = value[:m.start()] + item + after
404*cda5da8dSAndroid Build Coastguard Worker                    if "$" in after:
405*cda5da8dSAndroid Build Coastguard Worker                        notdone[name] = value
406*cda5da8dSAndroid Build Coastguard Worker                    else:
407*cda5da8dSAndroid Build Coastguard Worker                        try:
408*cda5da8dSAndroid Build Coastguard Worker                            if name in _ALWAYS_STR:
409*cda5da8dSAndroid Build Coastguard Worker                                raise ValueError
410*cda5da8dSAndroid Build Coastguard Worker                            value = int(value)
411*cda5da8dSAndroid Build Coastguard Worker                        except ValueError:
412*cda5da8dSAndroid Build Coastguard Worker                            done[name] = value.strip()
413*cda5da8dSAndroid Build Coastguard Worker                        else:
414*cda5da8dSAndroid Build Coastguard Worker                            done[name] = value
415*cda5da8dSAndroid Build Coastguard Worker                        variables.remove(name)
416*cda5da8dSAndroid Build Coastguard Worker
417*cda5da8dSAndroid Build Coastguard Worker                        if name.startswith('PY_') \
418*cda5da8dSAndroid Build Coastguard Worker                        and name[3:] in renamed_variables:
419*cda5da8dSAndroid Build Coastguard Worker
420*cda5da8dSAndroid Build Coastguard Worker                            name = name[3:]
421*cda5da8dSAndroid Build Coastguard Worker                            if name not in done:
422*cda5da8dSAndroid Build Coastguard Worker                                done[name] = value
423*cda5da8dSAndroid Build Coastguard Worker
424*cda5da8dSAndroid Build Coastguard Worker            else:
425*cda5da8dSAndroid Build Coastguard Worker                # Adds unresolved variables to the done dict.
426*cda5da8dSAndroid Build Coastguard Worker                # This is disabled when called from distutils.sysconfig
427*cda5da8dSAndroid Build Coastguard Worker                if keep_unresolved:
428*cda5da8dSAndroid Build Coastguard Worker                    done[name] = value
429*cda5da8dSAndroid Build Coastguard Worker                # bogus variable reference (e.g. "prefix=$/opt/python");
430*cda5da8dSAndroid Build Coastguard Worker                # just drop it since we can't deal
431*cda5da8dSAndroid Build Coastguard Worker                variables.remove(name)
432*cda5da8dSAndroid Build Coastguard Worker
433*cda5da8dSAndroid Build Coastguard Worker    # strip spurious spaces
434*cda5da8dSAndroid Build Coastguard Worker    for k, v in done.items():
435*cda5da8dSAndroid Build Coastguard Worker        if isinstance(v, str):
436*cda5da8dSAndroid Build Coastguard Worker            done[k] = v.strip()
437*cda5da8dSAndroid Build Coastguard Worker
438*cda5da8dSAndroid Build Coastguard Worker    # save the results in the global dictionary
439*cda5da8dSAndroid Build Coastguard Worker    vars.update(done)
440*cda5da8dSAndroid Build Coastguard Worker    return vars
441*cda5da8dSAndroid Build Coastguard Worker
442*cda5da8dSAndroid Build Coastguard Worker
443*cda5da8dSAndroid Build Coastguard Workerdef get_makefile_filename():
444*cda5da8dSAndroid Build Coastguard Worker    """Return the path of the Makefile."""
445*cda5da8dSAndroid Build Coastguard Worker    if _PYTHON_BUILD:
446*cda5da8dSAndroid Build Coastguard Worker        return os.path.join(_PROJECT_BASE, "Makefile")
447*cda5da8dSAndroid Build Coastguard Worker    if hasattr(sys, 'abiflags'):
448*cda5da8dSAndroid Build Coastguard Worker        config_dir_name = f'config-{_PY_VERSION_SHORT}{sys.abiflags}'
449*cda5da8dSAndroid Build Coastguard Worker    else:
450*cda5da8dSAndroid Build Coastguard Worker        config_dir_name = 'config'
451*cda5da8dSAndroid Build Coastguard Worker    if hasattr(sys.implementation, '_multiarch'):
452*cda5da8dSAndroid Build Coastguard Worker        config_dir_name += f'-{sys.implementation._multiarch}'
453*cda5da8dSAndroid Build Coastguard Worker    return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
454*cda5da8dSAndroid Build Coastguard Worker
455*cda5da8dSAndroid Build Coastguard Worker
456*cda5da8dSAndroid Build Coastguard Workerdef _get_sysconfigdata_name():
457*cda5da8dSAndroid Build Coastguard Worker    multiarch = getattr(sys.implementation, '_multiarch', '')
458*cda5da8dSAndroid Build Coastguard Worker    return os.environ.get(
459*cda5da8dSAndroid Build Coastguard Worker        '_PYTHON_SYSCONFIGDATA_NAME',
460*cda5da8dSAndroid Build Coastguard Worker        f'_sysconfigdata_{sys.abiflags}_{sys.platform}_{multiarch}',
461*cda5da8dSAndroid Build Coastguard Worker    )
462*cda5da8dSAndroid Build Coastguard Worker
463*cda5da8dSAndroid Build Coastguard Worker
464*cda5da8dSAndroid Build Coastguard Workerdef _generate_posix_vars():
465*cda5da8dSAndroid Build Coastguard Worker    """Generate the Python module containing build-time variables."""
466*cda5da8dSAndroid Build Coastguard Worker    import pprint
467*cda5da8dSAndroid Build Coastguard Worker    vars = {}
468*cda5da8dSAndroid Build Coastguard Worker    # load the installed Makefile:
469*cda5da8dSAndroid Build Coastguard Worker    makefile = get_makefile_filename()
470*cda5da8dSAndroid Build Coastguard Worker    try:
471*cda5da8dSAndroid Build Coastguard Worker        _parse_makefile(makefile, vars)
472*cda5da8dSAndroid Build Coastguard Worker    except OSError as e:
473*cda5da8dSAndroid Build Coastguard Worker        msg = f"invalid Python installation: unable to open {makefile}"
474*cda5da8dSAndroid Build Coastguard Worker        if hasattr(e, "strerror"):
475*cda5da8dSAndroid Build Coastguard Worker            msg = f"{msg} ({e.strerror})"
476*cda5da8dSAndroid Build Coastguard Worker        raise OSError(msg)
477*cda5da8dSAndroid Build Coastguard Worker    # load the installed pyconfig.h:
478*cda5da8dSAndroid Build Coastguard Worker    config_h = get_config_h_filename()
479*cda5da8dSAndroid Build Coastguard Worker    try:
480*cda5da8dSAndroid Build Coastguard Worker        with open(config_h, encoding="utf-8") as f:
481*cda5da8dSAndroid Build Coastguard Worker            parse_config_h(f, vars)
482*cda5da8dSAndroid Build Coastguard Worker    except OSError as e:
483*cda5da8dSAndroid Build Coastguard Worker        msg = f"invalid Python installation: unable to open {config_h}"
484*cda5da8dSAndroid Build Coastguard Worker        if hasattr(e, "strerror"):
485*cda5da8dSAndroid Build Coastguard Worker            msg = f"{msg} ({e.strerror})"
486*cda5da8dSAndroid Build Coastguard Worker        raise OSError(msg)
487*cda5da8dSAndroid Build Coastguard Worker    # On AIX, there are wrong paths to the linker scripts in the Makefile
488*cda5da8dSAndroid Build Coastguard Worker    # -- these paths are relative to the Python source, but when installed
489*cda5da8dSAndroid Build Coastguard Worker    # the scripts are in another directory.
490*cda5da8dSAndroid Build Coastguard Worker    if _PYTHON_BUILD:
491*cda5da8dSAndroid Build Coastguard Worker        vars['BLDSHARED'] = vars['LDSHARED']
492*cda5da8dSAndroid Build Coastguard Worker
493*cda5da8dSAndroid Build Coastguard Worker    # There's a chicken-and-egg situation on OS X with regards to the
494*cda5da8dSAndroid Build Coastguard Worker    # _sysconfigdata module after the changes introduced by #15298:
495*cda5da8dSAndroid Build Coastguard Worker    # get_config_vars() is called by get_platform() as part of the
496*cda5da8dSAndroid Build Coastguard Worker    # `make pybuilddir.txt` target -- which is a precursor to the
497*cda5da8dSAndroid Build Coastguard Worker    # _sysconfigdata.py module being constructed.  Unfortunately,
498*cda5da8dSAndroid Build Coastguard Worker    # get_config_vars() eventually calls _init_posix(), which attempts
499*cda5da8dSAndroid Build Coastguard Worker    # to import _sysconfigdata, which we won't have built yet.  In order
500*cda5da8dSAndroid Build Coastguard Worker    # for _init_posix() to work, if we're on Darwin, just mock up the
501*cda5da8dSAndroid Build Coastguard Worker    # _sysconfigdata module manually and populate it with the build vars.
502*cda5da8dSAndroid Build Coastguard Worker    # This is more than sufficient for ensuring the subsequent call to
503*cda5da8dSAndroid Build Coastguard Worker    # get_platform() succeeds.
504*cda5da8dSAndroid Build Coastguard Worker    name = _get_sysconfigdata_name()
505*cda5da8dSAndroid Build Coastguard Worker    if 'darwin' in sys.platform:
506*cda5da8dSAndroid Build Coastguard Worker        import types
507*cda5da8dSAndroid Build Coastguard Worker        module = types.ModuleType(name)
508*cda5da8dSAndroid Build Coastguard Worker        module.build_time_vars = vars
509*cda5da8dSAndroid Build Coastguard Worker        sys.modules[name] = module
510*cda5da8dSAndroid Build Coastguard Worker
511*cda5da8dSAndroid Build Coastguard Worker    pybuilddir = f'build/lib.{get_platform()}-{_PY_VERSION_SHORT}'
512*cda5da8dSAndroid Build Coastguard Worker    if hasattr(sys, "gettotalrefcount"):
513*cda5da8dSAndroid Build Coastguard Worker        pybuilddir += '-pydebug'
514*cda5da8dSAndroid Build Coastguard Worker    os.makedirs(pybuilddir, exist_ok=True)
515*cda5da8dSAndroid Build Coastguard Worker    destfile = os.path.join(pybuilddir, name + '.py')
516*cda5da8dSAndroid Build Coastguard Worker
517*cda5da8dSAndroid Build Coastguard Worker    with open(destfile, 'w', encoding='utf8') as f:
518*cda5da8dSAndroid Build Coastguard Worker        f.write('# system configuration generated and used by'
519*cda5da8dSAndroid Build Coastguard Worker                ' the sysconfig module\n')
520*cda5da8dSAndroid Build Coastguard Worker        f.write('build_time_vars = ')
521*cda5da8dSAndroid Build Coastguard Worker        pprint.pprint(vars, stream=f)
522*cda5da8dSAndroid Build Coastguard Worker
523*cda5da8dSAndroid Build Coastguard Worker    # Create file used for sys.path fixup -- see Modules/getpath.c
524*cda5da8dSAndroid Build Coastguard Worker    with open('pybuilddir.txt', 'w', encoding='utf8') as f:
525*cda5da8dSAndroid Build Coastguard Worker        f.write(pybuilddir)
526*cda5da8dSAndroid Build Coastguard Worker
527*cda5da8dSAndroid Build Coastguard Workerdef _init_posix(vars):
528*cda5da8dSAndroid Build Coastguard Worker    """Initialize the module as appropriate for POSIX systems."""
529*cda5da8dSAndroid Build Coastguard Worker    # _sysconfigdata is generated at build time, see _generate_posix_vars()
530*cda5da8dSAndroid Build Coastguard Worker    name = _get_sysconfigdata_name()
531*cda5da8dSAndroid Build Coastguard Worker    _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0)
532*cda5da8dSAndroid Build Coastguard Worker    build_time_vars = _temp.build_time_vars
533*cda5da8dSAndroid Build Coastguard Worker    vars.update(build_time_vars)
534*cda5da8dSAndroid Build Coastguard Worker
535*cda5da8dSAndroid Build Coastguard Workerdef _init_non_posix(vars):
536*cda5da8dSAndroid Build Coastguard Worker    """Initialize the module as appropriate for NT"""
537*cda5da8dSAndroid Build Coastguard Worker    # set basic install directories
538*cda5da8dSAndroid Build Coastguard Worker    import _imp
539*cda5da8dSAndroid Build Coastguard Worker    vars['LIBDEST'] = get_path('stdlib')
540*cda5da8dSAndroid Build Coastguard Worker    vars['BINLIBDEST'] = get_path('platstdlib')
541*cda5da8dSAndroid Build Coastguard Worker    vars['INCLUDEPY'] = get_path('include')
542*cda5da8dSAndroid Build Coastguard Worker    vars['EXT_SUFFIX'] = _imp.extension_suffixes()[0]
543*cda5da8dSAndroid Build Coastguard Worker    vars['EXE'] = '.exe'
544*cda5da8dSAndroid Build Coastguard Worker    vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
545*cda5da8dSAndroid Build Coastguard Worker    vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
546*cda5da8dSAndroid Build Coastguard Worker    vars['TZPATH'] = ''
547*cda5da8dSAndroid Build Coastguard Worker
548*cda5da8dSAndroid Build Coastguard Worker#
549*cda5da8dSAndroid Build Coastguard Worker# public APIs
550*cda5da8dSAndroid Build Coastguard Worker#
551*cda5da8dSAndroid Build Coastguard Worker
552*cda5da8dSAndroid Build Coastguard Worker
553*cda5da8dSAndroid Build Coastguard Workerdef parse_config_h(fp, vars=None):
554*cda5da8dSAndroid Build Coastguard Worker    """Parse a config.h-style file.
555*cda5da8dSAndroid Build Coastguard Worker
556*cda5da8dSAndroid Build Coastguard Worker    A dictionary containing name/value pairs is returned.  If an
557*cda5da8dSAndroid Build Coastguard Worker    optional dictionary is passed in as the second argument, it is
558*cda5da8dSAndroid Build Coastguard Worker    used instead of a new dictionary.
559*cda5da8dSAndroid Build Coastguard Worker    """
560*cda5da8dSAndroid Build Coastguard Worker    if vars is None:
561*cda5da8dSAndroid Build Coastguard Worker        vars = {}
562*cda5da8dSAndroid Build Coastguard Worker    import re
563*cda5da8dSAndroid Build Coastguard Worker    define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
564*cda5da8dSAndroid Build Coastguard Worker    undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
565*cda5da8dSAndroid Build Coastguard Worker
566*cda5da8dSAndroid Build Coastguard Worker    while True:
567*cda5da8dSAndroid Build Coastguard Worker        line = fp.readline()
568*cda5da8dSAndroid Build Coastguard Worker        if not line:
569*cda5da8dSAndroid Build Coastguard Worker            break
570*cda5da8dSAndroid Build Coastguard Worker        m = define_rx.match(line)
571*cda5da8dSAndroid Build Coastguard Worker        if m:
572*cda5da8dSAndroid Build Coastguard Worker            n, v = m.group(1, 2)
573*cda5da8dSAndroid Build Coastguard Worker            try:
574*cda5da8dSAndroid Build Coastguard Worker                if n in _ALWAYS_STR:
575*cda5da8dSAndroid Build Coastguard Worker                    raise ValueError
576*cda5da8dSAndroid Build Coastguard Worker                v = int(v)
577*cda5da8dSAndroid Build Coastguard Worker            except ValueError:
578*cda5da8dSAndroid Build Coastguard Worker                pass
579*cda5da8dSAndroid Build Coastguard Worker            vars[n] = v
580*cda5da8dSAndroid Build Coastguard Worker        else:
581*cda5da8dSAndroid Build Coastguard Worker            m = undef_rx.match(line)
582*cda5da8dSAndroid Build Coastguard Worker            if m:
583*cda5da8dSAndroid Build Coastguard Worker                vars[m.group(1)] = 0
584*cda5da8dSAndroid Build Coastguard Worker    return vars
585*cda5da8dSAndroid Build Coastguard Worker
586*cda5da8dSAndroid Build Coastguard Worker
587*cda5da8dSAndroid Build Coastguard Workerdef get_config_h_filename():
588*cda5da8dSAndroid Build Coastguard Worker    """Return the path of pyconfig.h."""
589*cda5da8dSAndroid Build Coastguard Worker    if _PYTHON_BUILD:
590*cda5da8dSAndroid Build Coastguard Worker        if os.name == "nt":
591*cda5da8dSAndroid Build Coastguard Worker            inc_dir = os.path.join(_PROJECT_BASE, "PC")
592*cda5da8dSAndroid Build Coastguard Worker        else:
593*cda5da8dSAndroid Build Coastguard Worker            inc_dir = _PROJECT_BASE
594*cda5da8dSAndroid Build Coastguard Worker    else:
595*cda5da8dSAndroid Build Coastguard Worker        inc_dir = get_path('platinclude')
596*cda5da8dSAndroid Build Coastguard Worker    return os.path.join(inc_dir, 'pyconfig.h')
597*cda5da8dSAndroid Build Coastguard Worker
598*cda5da8dSAndroid Build Coastguard Worker
599*cda5da8dSAndroid Build Coastguard Workerdef get_scheme_names():
600*cda5da8dSAndroid Build Coastguard Worker    """Return a tuple containing the schemes names."""
601*cda5da8dSAndroid Build Coastguard Worker    return tuple(sorted(_INSTALL_SCHEMES))
602*cda5da8dSAndroid Build Coastguard Worker
603*cda5da8dSAndroid Build Coastguard Worker
604*cda5da8dSAndroid Build Coastguard Workerdef get_path_names():
605*cda5da8dSAndroid Build Coastguard Worker    """Return a tuple containing the paths names."""
606*cda5da8dSAndroid Build Coastguard Worker    return _SCHEME_KEYS
607*cda5da8dSAndroid Build Coastguard Worker
608*cda5da8dSAndroid Build Coastguard Worker
609*cda5da8dSAndroid Build Coastguard Workerdef get_paths(scheme=get_default_scheme(), vars=None, expand=True):
610*cda5da8dSAndroid Build Coastguard Worker    """Return a mapping containing an install scheme.
611*cda5da8dSAndroid Build Coastguard Worker
612*cda5da8dSAndroid Build Coastguard Worker    ``scheme`` is the install scheme name. If not provided, it will
613*cda5da8dSAndroid Build Coastguard Worker    return the default scheme for the current platform.
614*cda5da8dSAndroid Build Coastguard Worker    """
615*cda5da8dSAndroid Build Coastguard Worker    if expand:
616*cda5da8dSAndroid Build Coastguard Worker        return _expand_vars(scheme, vars)
617*cda5da8dSAndroid Build Coastguard Worker    else:
618*cda5da8dSAndroid Build Coastguard Worker        return _INSTALL_SCHEMES[scheme]
619*cda5da8dSAndroid Build Coastguard Worker
620*cda5da8dSAndroid Build Coastguard Worker
621*cda5da8dSAndroid Build Coastguard Workerdef get_path(name, scheme=get_default_scheme(), vars=None, expand=True):
622*cda5da8dSAndroid Build Coastguard Worker    """Return a path corresponding to the scheme.
623*cda5da8dSAndroid Build Coastguard Worker
624*cda5da8dSAndroid Build Coastguard Worker    ``scheme`` is the install scheme name.
625*cda5da8dSAndroid Build Coastguard Worker    """
626*cda5da8dSAndroid Build Coastguard Worker    return get_paths(scheme, vars, expand)[name]
627*cda5da8dSAndroid Build Coastguard Worker
628*cda5da8dSAndroid Build Coastguard Worker
629*cda5da8dSAndroid Build Coastguard Workerdef get_config_vars(*args):
630*cda5da8dSAndroid Build Coastguard Worker    """With no arguments, return a dictionary of all configuration
631*cda5da8dSAndroid Build Coastguard Worker    variables relevant for the current platform.
632*cda5da8dSAndroid Build Coastguard Worker
633*cda5da8dSAndroid Build Coastguard Worker    On Unix, this means every variable defined in Python's installed Makefile;
634*cda5da8dSAndroid Build Coastguard Worker    On Windows it's a much smaller set.
635*cda5da8dSAndroid Build Coastguard Worker
636*cda5da8dSAndroid Build Coastguard Worker    With arguments, return a list of values that result from looking up
637*cda5da8dSAndroid Build Coastguard Worker    each argument in the configuration variable dictionary.
638*cda5da8dSAndroid Build Coastguard Worker    """
639*cda5da8dSAndroid Build Coastguard Worker    global _CONFIG_VARS
640*cda5da8dSAndroid Build Coastguard Worker    if _CONFIG_VARS is None:
641*cda5da8dSAndroid Build Coastguard Worker        _CONFIG_VARS = {}
642*cda5da8dSAndroid Build Coastguard Worker        # Normalized versions of prefix and exec_prefix are handy to have;
643*cda5da8dSAndroid Build Coastguard Worker        # in fact, these are the standard versions used most places in the
644*cda5da8dSAndroid Build Coastguard Worker        # Distutils.
645*cda5da8dSAndroid Build Coastguard Worker        _CONFIG_VARS['prefix'] = _PREFIX
646*cda5da8dSAndroid Build Coastguard Worker        _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
647*cda5da8dSAndroid Build Coastguard Worker        _CONFIG_VARS['py_version'] = _PY_VERSION
648*cda5da8dSAndroid Build Coastguard Worker        _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
649*cda5da8dSAndroid Build Coastguard Worker        _CONFIG_VARS['py_version_nodot'] = _PY_VERSION_SHORT_NO_DOT
650*cda5da8dSAndroid Build Coastguard Worker        _CONFIG_VARS['installed_base'] = _BASE_PREFIX
651*cda5da8dSAndroid Build Coastguard Worker        _CONFIG_VARS['base'] = _PREFIX
652*cda5da8dSAndroid Build Coastguard Worker        _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX
653*cda5da8dSAndroid Build Coastguard Worker        _CONFIG_VARS['platbase'] = _EXEC_PREFIX
654*cda5da8dSAndroid Build Coastguard Worker        _CONFIG_VARS['projectbase'] = _PROJECT_BASE
655*cda5da8dSAndroid Build Coastguard Worker        _CONFIG_VARS['platlibdir'] = sys.platlibdir
656*cda5da8dSAndroid Build Coastguard Worker        try:
657*cda5da8dSAndroid Build Coastguard Worker            _CONFIG_VARS['abiflags'] = sys.abiflags
658*cda5da8dSAndroid Build Coastguard Worker        except AttributeError:
659*cda5da8dSAndroid Build Coastguard Worker            # sys.abiflags may not be defined on all platforms.
660*cda5da8dSAndroid Build Coastguard Worker            _CONFIG_VARS['abiflags'] = ''
661*cda5da8dSAndroid Build Coastguard Worker        try:
662*cda5da8dSAndroid Build Coastguard Worker            _CONFIG_VARS['py_version_nodot_plat'] = sys.winver.replace('.', '')
663*cda5da8dSAndroid Build Coastguard Worker        except AttributeError:
664*cda5da8dSAndroid Build Coastguard Worker            _CONFIG_VARS['py_version_nodot_plat'] = ''
665*cda5da8dSAndroid Build Coastguard Worker
666*cda5da8dSAndroid Build Coastguard Worker        if os.name == 'nt':
667*cda5da8dSAndroid Build Coastguard Worker            _init_non_posix(_CONFIG_VARS)
668*cda5da8dSAndroid Build Coastguard Worker            _CONFIG_VARS['VPATH'] = sys._vpath
669*cda5da8dSAndroid Build Coastguard Worker        if os.name == 'posix':
670*cda5da8dSAndroid Build Coastguard Worker            _init_posix(_CONFIG_VARS)
671*cda5da8dSAndroid Build Coastguard Worker        if _HAS_USER_BASE:
672*cda5da8dSAndroid Build Coastguard Worker            # Setting 'userbase' is done below the call to the
673*cda5da8dSAndroid Build Coastguard Worker            # init function to enable using 'get_config_var' in
674*cda5da8dSAndroid Build Coastguard Worker            # the init-function.
675*cda5da8dSAndroid Build Coastguard Worker            _CONFIG_VARS['userbase'] = _getuserbase()
676*cda5da8dSAndroid Build Coastguard Worker
677*cda5da8dSAndroid Build Coastguard Worker        # Always convert srcdir to an absolute path
678*cda5da8dSAndroid Build Coastguard Worker        srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE)
679*cda5da8dSAndroid Build Coastguard Worker        if os.name == 'posix':
680*cda5da8dSAndroid Build Coastguard Worker            if _PYTHON_BUILD:
681*cda5da8dSAndroid Build Coastguard Worker                # If srcdir is a relative path (typically '.' or '..')
682*cda5da8dSAndroid Build Coastguard Worker                # then it should be interpreted relative to the directory
683*cda5da8dSAndroid Build Coastguard Worker                # containing Makefile.
684*cda5da8dSAndroid Build Coastguard Worker                base = os.path.dirname(get_makefile_filename())
685*cda5da8dSAndroid Build Coastguard Worker                srcdir = os.path.join(base, srcdir)
686*cda5da8dSAndroid Build Coastguard Worker            else:
687*cda5da8dSAndroid Build Coastguard Worker                # srcdir is not meaningful since the installation is
688*cda5da8dSAndroid Build Coastguard Worker                # spread about the filesystem.  We choose the
689*cda5da8dSAndroid Build Coastguard Worker                # directory containing the Makefile since we know it
690*cda5da8dSAndroid Build Coastguard Worker                # exists.
691*cda5da8dSAndroid Build Coastguard Worker                srcdir = os.path.dirname(get_makefile_filename())
692*cda5da8dSAndroid Build Coastguard Worker        _CONFIG_VARS['srcdir'] = _safe_realpath(srcdir)
693*cda5da8dSAndroid Build Coastguard Worker
694*cda5da8dSAndroid Build Coastguard Worker        # OS X platforms require special customization to handle
695*cda5da8dSAndroid Build Coastguard Worker        # multi-architecture, multi-os-version installers
696*cda5da8dSAndroid Build Coastguard Worker        if sys.platform == 'darwin':
697*cda5da8dSAndroid Build Coastguard Worker            import _osx_support
698*cda5da8dSAndroid Build Coastguard Worker            _osx_support.customize_config_vars(_CONFIG_VARS)
699*cda5da8dSAndroid Build Coastguard Worker
700*cda5da8dSAndroid Build Coastguard Worker    if args:
701*cda5da8dSAndroid Build Coastguard Worker        vals = []
702*cda5da8dSAndroid Build Coastguard Worker        for name in args:
703*cda5da8dSAndroid Build Coastguard Worker            vals.append(_CONFIG_VARS.get(name))
704*cda5da8dSAndroid Build Coastguard Worker        return vals
705*cda5da8dSAndroid Build Coastguard Worker    else:
706*cda5da8dSAndroid Build Coastguard Worker        return _CONFIG_VARS
707*cda5da8dSAndroid Build Coastguard Worker
708*cda5da8dSAndroid Build Coastguard Worker
709*cda5da8dSAndroid Build Coastguard Workerdef get_config_var(name):
710*cda5da8dSAndroid Build Coastguard Worker    """Return the value of a single variable using the dictionary returned by
711*cda5da8dSAndroid Build Coastguard Worker    'get_config_vars()'.
712*cda5da8dSAndroid Build Coastguard Worker
713*cda5da8dSAndroid Build Coastguard Worker    Equivalent to get_config_vars().get(name)
714*cda5da8dSAndroid Build Coastguard Worker    """
715*cda5da8dSAndroid Build Coastguard Worker    return get_config_vars().get(name)
716*cda5da8dSAndroid Build Coastguard Worker
717*cda5da8dSAndroid Build Coastguard Worker
718*cda5da8dSAndroid Build Coastguard Workerdef get_platform():
719*cda5da8dSAndroid Build Coastguard Worker    """Return a string that identifies the current platform.
720*cda5da8dSAndroid Build Coastguard Worker
721*cda5da8dSAndroid Build Coastguard Worker    This is used mainly to distinguish platform-specific build directories and
722*cda5da8dSAndroid Build Coastguard Worker    platform-specific built distributions.  Typically includes the OS name and
723*cda5da8dSAndroid Build Coastguard Worker    version and the architecture (as supplied by 'os.uname()'), although the
724*cda5da8dSAndroid Build Coastguard Worker    exact information included depends on the OS; on Linux, the kernel version
725*cda5da8dSAndroid Build Coastguard Worker    isn't particularly important.
726*cda5da8dSAndroid Build Coastguard Worker
727*cda5da8dSAndroid Build Coastguard Worker    Examples of returned values:
728*cda5da8dSAndroid Build Coastguard Worker       linux-i586
729*cda5da8dSAndroid Build Coastguard Worker       linux-alpha (?)
730*cda5da8dSAndroid Build Coastguard Worker       solaris-2.6-sun4u
731*cda5da8dSAndroid Build Coastguard Worker
732*cda5da8dSAndroid Build Coastguard Worker    Windows will return one of:
733*cda5da8dSAndroid Build Coastguard Worker       win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
734*cda5da8dSAndroid Build Coastguard Worker       win32 (all others - specifically, sys.platform is returned)
735*cda5da8dSAndroid Build Coastguard Worker
736*cda5da8dSAndroid Build Coastguard Worker    For other non-POSIX platforms, currently just returns 'sys.platform'.
737*cda5da8dSAndroid Build Coastguard Worker
738*cda5da8dSAndroid Build Coastguard Worker    """
739*cda5da8dSAndroid Build Coastguard Worker    if os.name == 'nt':
740*cda5da8dSAndroid Build Coastguard Worker        if 'amd64' in sys.version.lower():
741*cda5da8dSAndroid Build Coastguard Worker            return 'win-amd64'
742*cda5da8dSAndroid Build Coastguard Worker        if '(arm)' in sys.version.lower():
743*cda5da8dSAndroid Build Coastguard Worker            return 'win-arm32'
744*cda5da8dSAndroid Build Coastguard Worker        if '(arm64)' in sys.version.lower():
745*cda5da8dSAndroid Build Coastguard Worker            return 'win-arm64'
746*cda5da8dSAndroid Build Coastguard Worker        return sys.platform
747*cda5da8dSAndroid Build Coastguard Worker
748*cda5da8dSAndroid Build Coastguard Worker    if os.name != "posix" or not hasattr(os, 'uname'):
749*cda5da8dSAndroid Build Coastguard Worker        # XXX what about the architecture? NT is Intel or Alpha
750*cda5da8dSAndroid Build Coastguard Worker        return sys.platform
751*cda5da8dSAndroid Build Coastguard Worker
752*cda5da8dSAndroid Build Coastguard Worker    # Set for cross builds explicitly
753*cda5da8dSAndroid Build Coastguard Worker    if "_PYTHON_HOST_PLATFORM" in os.environ:
754*cda5da8dSAndroid Build Coastguard Worker        return os.environ["_PYTHON_HOST_PLATFORM"]
755*cda5da8dSAndroid Build Coastguard Worker
756*cda5da8dSAndroid Build Coastguard Worker    # Try to distinguish various flavours of Unix
757*cda5da8dSAndroid Build Coastguard Worker    osname, host, release, version, machine = os.uname()
758*cda5da8dSAndroid Build Coastguard Worker
759*cda5da8dSAndroid Build Coastguard Worker    # Convert the OS name to lowercase, remove '/' characters, and translate
760*cda5da8dSAndroid Build Coastguard Worker    # spaces (for "Power Macintosh")
761*cda5da8dSAndroid Build Coastguard Worker    osname = osname.lower().replace('/', '')
762*cda5da8dSAndroid Build Coastguard Worker    machine = machine.replace(' ', '_')
763*cda5da8dSAndroid Build Coastguard Worker    machine = machine.replace('/', '-')
764*cda5da8dSAndroid Build Coastguard Worker
765*cda5da8dSAndroid Build Coastguard Worker    if osname[:5] == "linux":
766*cda5da8dSAndroid Build Coastguard Worker        # At least on Linux/Intel, 'machine' is the processor --
767*cda5da8dSAndroid Build Coastguard Worker        # i386, etc.
768*cda5da8dSAndroid Build Coastguard Worker        # XXX what about Alpha, SPARC, etc?
769*cda5da8dSAndroid Build Coastguard Worker        return  f"{osname}-{machine}"
770*cda5da8dSAndroid Build Coastguard Worker    elif osname[:5] == "sunos":
771*cda5da8dSAndroid Build Coastguard Worker        if release[0] >= "5":           # SunOS 5 == Solaris 2
772*cda5da8dSAndroid Build Coastguard Worker            osname = "solaris"
773*cda5da8dSAndroid Build Coastguard Worker            release = f"{int(release[0]) - 3}.{release[2:]}"
774*cda5da8dSAndroid Build Coastguard Worker            # We can't use "platform.architecture()[0]" because a
775*cda5da8dSAndroid Build Coastguard Worker            # bootstrap problem. We use a dict to get an error
776*cda5da8dSAndroid Build Coastguard Worker            # if some suspicious happens.
777*cda5da8dSAndroid Build Coastguard Worker            bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
778*cda5da8dSAndroid Build Coastguard Worker            machine += f".{bitness[sys.maxsize]}"
779*cda5da8dSAndroid Build Coastguard Worker        # fall through to standard osname-release-machine representation
780*cda5da8dSAndroid Build Coastguard Worker    elif osname[:3] == "aix":
781*cda5da8dSAndroid Build Coastguard Worker        from _aix_support import aix_platform
782*cda5da8dSAndroid Build Coastguard Worker        return aix_platform()
783*cda5da8dSAndroid Build Coastguard Worker    elif osname[:6] == "cygwin":
784*cda5da8dSAndroid Build Coastguard Worker        osname = "cygwin"
785*cda5da8dSAndroid Build Coastguard Worker        import re
786*cda5da8dSAndroid Build Coastguard Worker        rel_re = re.compile(r'[\d.]+')
787*cda5da8dSAndroid Build Coastguard Worker        m = rel_re.match(release)
788*cda5da8dSAndroid Build Coastguard Worker        if m:
789*cda5da8dSAndroid Build Coastguard Worker            release = m.group()
790*cda5da8dSAndroid Build Coastguard Worker    elif osname[:6] == "darwin":
791*cda5da8dSAndroid Build Coastguard Worker        import _osx_support
792*cda5da8dSAndroid Build Coastguard Worker        osname, release, machine = _osx_support.get_platform_osx(
793*cda5da8dSAndroid Build Coastguard Worker                                            get_config_vars(),
794*cda5da8dSAndroid Build Coastguard Worker                                            osname, release, machine)
795*cda5da8dSAndroid Build Coastguard Worker
796*cda5da8dSAndroid Build Coastguard Worker    return f"{osname}-{release}-{machine}"
797*cda5da8dSAndroid Build Coastguard Worker
798*cda5da8dSAndroid Build Coastguard Worker
799*cda5da8dSAndroid Build Coastguard Workerdef get_python_version():
800*cda5da8dSAndroid Build Coastguard Worker    return _PY_VERSION_SHORT
801*cda5da8dSAndroid Build Coastguard Worker
802*cda5da8dSAndroid Build Coastguard Worker
803*cda5da8dSAndroid Build Coastguard Workerdef expand_makefile_vars(s, vars):
804*cda5da8dSAndroid Build Coastguard Worker    """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in
805*cda5da8dSAndroid Build Coastguard Worker    'string' according to 'vars' (a dictionary mapping variable names to
806*cda5da8dSAndroid Build Coastguard Worker    values).  Variables not present in 'vars' are silently expanded to the
807*cda5da8dSAndroid Build Coastguard Worker    empty string.  The variable values in 'vars' should not contain further
808*cda5da8dSAndroid Build Coastguard Worker    variable expansions; if 'vars' is the output of 'parse_makefile()',
809*cda5da8dSAndroid Build Coastguard Worker    you're fine.  Returns a variable-expanded version of 's'.
810*cda5da8dSAndroid Build Coastguard Worker    """
811*cda5da8dSAndroid Build Coastguard Worker    import re
812*cda5da8dSAndroid Build Coastguard Worker
813*cda5da8dSAndroid Build Coastguard Worker    # This algorithm does multiple expansion, so if vars['foo'] contains
814*cda5da8dSAndroid Build Coastguard Worker    # "${bar}", it will expand ${foo} to ${bar}, and then expand
815*cda5da8dSAndroid Build Coastguard Worker    # ${bar}... and so forth.  This is fine as long as 'vars' comes from
816*cda5da8dSAndroid Build Coastguard Worker    # 'parse_makefile()', which takes care of such expansions eagerly,
817*cda5da8dSAndroid Build Coastguard Worker    # according to make's variable expansion semantics.
818*cda5da8dSAndroid Build Coastguard Worker
819*cda5da8dSAndroid Build Coastguard Worker    while True:
820*cda5da8dSAndroid Build Coastguard Worker        m = re.search(_findvar1_rx, s) or re.search(_findvar2_rx, s)
821*cda5da8dSAndroid Build Coastguard Worker        if m:
822*cda5da8dSAndroid Build Coastguard Worker            (beg, end) = m.span()
823*cda5da8dSAndroid Build Coastguard Worker            s = s[0:beg] + vars.get(m.group(1)) + s[end:]
824*cda5da8dSAndroid Build Coastguard Worker        else:
825*cda5da8dSAndroid Build Coastguard Worker            break
826*cda5da8dSAndroid Build Coastguard Worker    return s
827*cda5da8dSAndroid Build Coastguard Worker
828*cda5da8dSAndroid Build Coastguard Worker
829*cda5da8dSAndroid Build Coastguard Workerdef _print_dict(title, data):
830*cda5da8dSAndroid Build Coastguard Worker    for index, (key, value) in enumerate(sorted(data.items())):
831*cda5da8dSAndroid Build Coastguard Worker        if index == 0:
832*cda5da8dSAndroid Build Coastguard Worker            print(f'{title}: ')
833*cda5da8dSAndroid Build Coastguard Worker        print(f'\t{key} = "{value}"')
834*cda5da8dSAndroid Build Coastguard Worker
835*cda5da8dSAndroid Build Coastguard Worker
836*cda5da8dSAndroid Build Coastguard Workerdef _main():
837*cda5da8dSAndroid Build Coastguard Worker    """Display all information sysconfig detains."""
838*cda5da8dSAndroid Build Coastguard Worker    if '--generate-posix-vars' in sys.argv:
839*cda5da8dSAndroid Build Coastguard Worker        _generate_posix_vars()
840*cda5da8dSAndroid Build Coastguard Worker        return
841*cda5da8dSAndroid Build Coastguard Worker    print(f'Platform: "{get_platform()}"')
842*cda5da8dSAndroid Build Coastguard Worker    print(f'Python version: "{get_python_version()}"')
843*cda5da8dSAndroid Build Coastguard Worker    print(f'Current installation scheme: "{get_default_scheme()}"')
844*cda5da8dSAndroid Build Coastguard Worker    print()
845*cda5da8dSAndroid Build Coastguard Worker    _print_dict('Paths', get_paths())
846*cda5da8dSAndroid Build Coastguard Worker    print()
847*cda5da8dSAndroid Build Coastguard Worker    _print_dict('Variables', get_config_vars())
848*cda5da8dSAndroid Build Coastguard Worker
849*cda5da8dSAndroid Build Coastguard Worker
850*cda5da8dSAndroid Build Coastguard Workerif __name__ == '__main__':
851*cda5da8dSAndroid Build Coastguard Worker    _main()
852