blob: 0e0decd42716ed79ae819293d7aa40ffd8dafcab [file] [log] [blame]
Tarek Ziade1231a4e2011-05-19 13:07:25 +02001"""Access to Python's configuration information."""
Tarek Ziadéedacea32010-01-29 11:41:03 +00002
Tarek Ziadéedacea32010-01-29 11:41:03 +00003import os
Tarek Ziade1231a4e2011-05-19 13:07:25 +02004import sys
Florent Xiclunaa4707382010-03-11 00:05:17 +00005from os.path import pardir, realpath
Tarek Ziadéedacea32010-01-29 11:41:03 +00006
Barry Warsawebbef6f2010-09-20 15:29:53 +00007__all__ = [
8 'get_config_h_filename',
9 'get_config_var',
10 'get_config_vars',
11 'get_makefile_filename',
12 'get_path',
13 'get_path_names',
14 'get_paths',
15 'get_platform',
16 'get_python_version',
17 'get_scheme_names',
18 'parse_config_h',
Tarek Ziade1231a4e2011-05-19 13:07:25 +020019]
Tarek Ziadé16ed6cb2010-05-25 09:47:06 +000020
Ronald Oussoren49926cf2021-02-01 04:29:44 +010021# Keys for get_config_var() that are never converted to Python integers.
22_ALWAYS_STR = {
23 'MACOSX_DEPLOYMENT_TARGET',
24}
25
Éric Araujoec177c12012-06-24 03:27:43 -040026_INSTALL_SCHEMES = {
27 'posix_prefix': {
Victor Stinner8510f432020-03-10 09:53:09 +010028 'stdlib': '{installed_base}/{platlibdir}/python{py_version_short}',
29 'platstdlib': '{platbase}/{platlibdir}/python{py_version_short}',
Éric Araujoec177c12012-06-24 03:27:43 -040030 'purelib': '{base}/lib/python{py_version_short}/site-packages',
Victor Stinner8510f432020-03-10 09:53:09 +010031 'platlib': '{platbase}/{platlibdir}/python{py_version_short}/site-packages',
Éric Araujoec177c12012-06-24 03:27:43 -040032 'include':
33 '{installed_base}/include/python{py_version_short}{abiflags}',
34 'platinclude':
35 '{installed_platbase}/include/python{py_version_short}{abiflags}',
36 'scripts': '{base}/bin',
37 'data': '{base}',
38 },
39 'posix_home': {
40 'stdlib': '{installed_base}/lib/python',
41 'platstdlib': '{base}/lib/python',
42 'purelib': '{base}/lib/python',
43 'platlib': '{base}/lib/python',
44 'include': '{installed_base}/include/python',
45 'platinclude': '{installed_base}/include/python',
46 'scripts': '{base}/bin',
47 'data': '{base}',
48 },
49 'nt': {
50 'stdlib': '{installed_base}/Lib',
51 'platstdlib': '{base}/Lib',
52 'purelib': '{base}/Lib/site-packages',
53 'platlib': '{base}/Lib/site-packages',
54 'include': '{installed_base}/Include',
55 'platinclude': '{installed_base}/Include',
56 'scripts': '{base}/Scripts',
57 'data': '{base}',
58 },
pxinwrab74c012020-12-21 06:27:42 +080059 }
60
61
62# NOTE: site.py has copy of this function.
63# Sync it when modify this function.
64def _getuserbase():
65 env_base = os.environ.get("PYTHONUSERBASE", None)
66 if env_base:
67 return env_base
68
69 # VxWorks has no home directories
70 if sys.platform == "vxworks":
71 return None
72
73 def joinuser(*args):
74 return os.path.expanduser(os.path.join(*args))
75
76 if os.name == "nt":
77 base = os.environ.get("APPDATA") or "~"
78 return joinuser(base, "Python")
79
80 if sys.platform == "darwin" and sys._framework:
81 return joinuser("~", "Library", sys._framework,
82 "%d.%d" % sys.version_info[:2])
83
84 return joinuser("~", ".local")
85
86_HAS_USER_BASE = (_getuserbase() is not None)
87
88if _HAS_USER_BASE:
89 _INSTALL_SCHEMES |= {
90 # NOTE: When modifying "purelib" scheme, update site._get_path() too.
91 'nt_user': {
92 'stdlib': '{userbase}/Python{py_version_nodot_plat}',
93 'platstdlib': '{userbase}/Python{py_version_nodot_plat}',
94 'purelib': '{userbase}/Python{py_version_nodot_plat}/site-packages',
95 'platlib': '{userbase}/Python{py_version_nodot_plat}/site-packages',
96 'include': '{userbase}/Python{py_version_nodot_plat}/Include',
97 'scripts': '{userbase}/Python{py_version_nodot_plat}/Scripts',
98 'data': '{userbase}',
99 },
100 'posix_user': {
101 'stdlib': '{userbase}/{platlibdir}/python{py_version_short}',
102 'platstdlib': '{userbase}/{platlibdir}/python{py_version_short}',
103 'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
104 'platlib': '{userbase}/{platlibdir}/python{py_version_short}/site-packages',
105 'include': '{userbase}/include/python{py_version_short}',
106 'scripts': '{userbase}/bin',
107 'data': '{userbase}',
108 },
109 'osx_framework_user': {
110 'stdlib': '{userbase}/lib/python',
111 'platstdlib': '{userbase}/lib/python',
112 'purelib': '{userbase}/lib/python/site-packages',
113 'platlib': '{userbase}/lib/python/site-packages',
114 'include': '{userbase}/include',
115 'scripts': '{userbase}/bin',
116 'data': '{userbase}',
117 },
Éric Araujoec177c12012-06-24 03:27:43 -0400118 }
Tarek Ziadéedacea32010-01-29 11:41:03 +0000119
Éric Araujoec177c12012-06-24 03:27:43 -0400120_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
121 'scripts', 'data')
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200122
Tarek Ziadéedacea32010-01-29 11:41:03 +0000123_PY_VERSION = sys.version.split()[0]
Serhiy Storchaka885bdc42016-02-11 13:10:36 +0200124_PY_VERSION_SHORT = '%d.%d' % sys.version_info[:2]
125_PY_VERSION_SHORT_NO_DOT = '%d%d' % sys.version_info[:2]
Tarek Ziadéedacea32010-01-29 11:41:03 +0000126_PREFIX = os.path.normpath(sys.prefix)
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100127_BASE_PREFIX = os.path.normpath(sys.base_prefix)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000128_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100129_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000130_CONFIG_VARS = None
131_USER_BASE = None
Victor Stinnerb103a932010-10-12 22:23:23 +0000132
Lumír 'Frenzy' Balhar90d02e52021-04-23 14:02:41 +0200133# Regexes needed for parsing Makefile (and similar syntaxes,
134# like old-style Setup files).
135_variable_rx = r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)"
136_findvar1_rx = r"\$\(([A-Za-z][A-Za-z0-9_]*)\)"
137_findvar2_rx = r"\${([A-Za-z][A-Za-z0-9_]*)}"
138
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200139
Victor Stinnerb103a932010-10-12 22:23:23 +0000140def _safe_realpath(path):
141 try:
142 return realpath(path)
143 except OSError:
144 return path
145
Victor Stinner171ba052010-03-12 14:20:59 +0000146if sys.executable:
Victor Stinnerb103a932010-10-12 22:23:23 +0000147 _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
Victor Stinner171ba052010-03-12 14:20:59 +0000148else:
149 # sys.executable can be empty if argv[0] has been changed and Python is
150 # unable to retrieve the real program name
Victor Stinnerb103a932010-10-12 22:23:23 +0000151 _PROJECT_BASE = _safe_realpath(os.getcwd())
Tarek Ziadéedacea32010-01-29 11:41:03 +0000152
Steve Dower65e4cb12014-11-22 12:54:57 -0800153if (os.name == 'nt' and
154 _PROJECT_BASE.lower().endswith(('\\pcbuild\\win32', '\\pcbuild\\amd64'))):
Victor Stinnerb103a932010-10-12 22:23:23 +0000155 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000156
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200157# set for cross builds
doko@ubuntu.com7e6c2e22012-06-30 22:35:00 +0200158if "_PYTHON_PROJECT_BASE" in os.environ:
159 _PROJECT_BASE = _safe_realpath(os.environ["_PYTHON_PROJECT_BASE"])
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200160
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100161def _is_python_source_dir(d):
Antoine Pitrou961d54c2018-07-16 19:03:03 +0200162 for fn in ("Setup", "Setup.local"):
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100163 if os.path.isfile(os.path.join(d, "Modules", fn)):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000164 return True
165 return False
166
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100167_sys_home = getattr(sys, '_home', None)
Steve Dower85e102a2019-02-04 17:15:13 -0800168
169if os.name == 'nt':
170 def _fix_pcbuild(d):
171 if d and os.path.normcase(d).startswith(
172 os.path.normcase(os.path.join(_PREFIX, "PCbuild"))):
173 return _PREFIX
174 return d
175 _PROJECT_BASE = _fix_pcbuild(_PROJECT_BASE)
176 _sys_home = _fix_pcbuild(_sys_home)
177
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100178def is_python_build(check_home=False):
179 if check_home and _sys_home:
180 return _is_python_source_dir(_sys_home)
181 return _is_python_source_dir(_PROJECT_BASE)
182
183_PYTHON_BUILD = is_python_build(True)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000184
Éric Araujoec177c12012-06-24 03:27:43 -0400185def _subst_vars(s, local_vars):
186 try:
187 return s.format(**local_vars)
Steve Dowerdd180012020-09-05 00:45:54 +0100188 except KeyError as var:
Éric Araujoec177c12012-06-24 03:27:43 -0400189 try:
190 return s.format(**os.environ)
Steve Dowerdd180012020-09-05 00:45:54 +0100191 except KeyError:
Serhiy Storchaka5affd232017-04-05 09:37:24 +0300192 raise AttributeError('{%s}' % var) from None
Tarek Ziadéedacea32010-01-29 11:41:03 +0000193
194def _extend_dict(target_dict, other_dict):
195 target_keys = target_dict.keys()
196 for key, value in other_dict.items():
197 if key in target_keys:
198 continue
199 target_dict[key] = value
200
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200201
Tarek Ziadéedacea32010-01-29 11:41:03 +0000202def _expand_vars(scheme, vars):
203 res = {}
204 if vars is None:
205 vars = {}
206 _extend_dict(vars, get_config_vars())
207
Éric Araujoec177c12012-06-24 03:27:43 -0400208 for key, value in _INSTALL_SCHEMES[scheme].items():
Tarek Ziadéedacea32010-01-29 11:41:03 +0000209 if os.name in ('posix', 'nt'):
210 value = os.path.expanduser(value)
211 res[key] = os.path.normpath(_subst_vars(value, vars))
212 return res
213
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200214
Tarek Ziadéedacea32010-01-29 11:41:03 +0000215def _get_default_scheme():
216 if os.name == 'posix':
217 # the default scheme for posix is posix_prefix
218 return 'posix_prefix'
219 return os.name
220
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200221
Tarek Ziadéedacea32010-01-29 11:41:03 +0000222
223
Lumír 'Frenzy' Balhar90d02e52021-04-23 14:02:41 +0200224def _parse_makefile(filename, vars=None, keep_unresolved=True):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000225 """Parse a Makefile-style file.
226
227 A dictionary containing name/value pairs is returned. If an
228 optional dictionary is passed in as the second argument, it is
229 used instead of a new dictionary.
230 """
Christian Heimes8c9cd5a2013-10-12 00:24:55 +0200231 import re
Tarek Ziadéedacea32010-01-29 11:41:03 +0000232
233 if vars is None:
234 vars = {}
235 done = {}
236 notdone = {}
237
Inada Naoki3d4af4a2021-04-06 10:01:11 +0900238 with open(filename, encoding=sys.getfilesystemencoding(),
239 errors="surrogateescape") as f:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000240 lines = f.readlines()
241
242 for line in lines:
243 if line.startswith('#') or line.strip() == '':
244 continue
Lumír 'Frenzy' Balhar90d02e52021-04-23 14:02:41 +0200245 m = re.match(_variable_rx, line)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000246 if m:
247 n, v = m.group(1, 2)
248 v = v.strip()
249 # `$$' is a literal `$' in make
250 tmpv = v.replace('$$', '')
251
252 if "$" in tmpv:
253 notdone[n] = v
254 else:
255 try:
Ronald Oussoren49926cf2021-02-01 04:29:44 +0100256 if n in _ALWAYS_STR:
257 raise ValueError
258
Tarek Ziadéedacea32010-01-29 11:41:03 +0000259 v = int(v)
260 except ValueError:
261 # insert literal `$'
262 done[n] = v.replace('$$', '$')
263 else:
264 done[n] = v
265
266 # do variable interpolation here
267 variables = list(notdone.keys())
268
Ronald Oussorend21886c2010-07-20 16:07:10 +0000269 # Variables with a 'PY_' prefix in the makefile. These need to
270 # be made available without that prefix through sysconfig.
271 # Special care is needed to ensure that variable expansion works, even
272 # if the expansion uses the name without a prefix.
273 renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
274
Tarek Ziadéedacea32010-01-29 11:41:03 +0000275 while len(variables) > 0:
276 for name in tuple(variables):
277 value = notdone[name]
Lumír 'Frenzy' Balhar90d02e52021-04-23 14:02:41 +0200278 m1 = re.search(_findvar1_rx, value)
279 m2 = re.search(_findvar2_rx, value)
doko@ubuntu.comb2b12172016-01-11 21:41:40 +0100280 if m1 and m2:
281 m = m1 if m1.start() < m2.start() else m2
282 else:
283 m = m1 if m1 else m2
Tarek Ziadéedacea32010-01-29 11:41:03 +0000284 if m is not None:
285 n = m.group(1)
286 found = True
287 if n in done:
288 item = str(done[n])
289 elif n in notdone:
290 # get it on a subsequent round
291 found = False
292 elif n in os.environ:
293 # do it like make: fall back to environment
294 item = os.environ[n]
Ronald Oussorend21886c2010-07-20 16:07:10 +0000295
296 elif n in renamed_variables:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200297 if (name.startswith('PY_') and
298 name[3:] in renamed_variables):
Ronald Oussorend21886c2010-07-20 16:07:10 +0000299 item = ""
300
301 elif 'PY_' + n in notdone:
302 found = False
303
304 else:
305 item = str(done['PY_' + n])
306
Tarek Ziadéedacea32010-01-29 11:41:03 +0000307 else:
308 done[n] = item = ""
Ronald Oussorend21886c2010-07-20 16:07:10 +0000309
Tarek Ziadéedacea32010-01-29 11:41:03 +0000310 if found:
311 after = value[m.end():]
312 value = value[:m.start()] + item + after
313 if "$" in after:
314 notdone[name] = value
315 else:
316 try:
Ronald Oussoren49926cf2021-02-01 04:29:44 +0100317 if name in _ALWAYS_STR:
318 raise ValueError
Tarek Ziadéedacea32010-01-29 11:41:03 +0000319 value = int(value)
320 except ValueError:
321 done[name] = value.strip()
322 else:
323 done[name] = value
324 variables.remove(name)
Ronald Oussorend21886c2010-07-20 16:07:10 +0000325
326 if name.startswith('PY_') \
Victor Stinner1273b7c2011-05-24 23:37:07 +0200327 and name[3:] in renamed_variables:
Ronald Oussorend21886c2010-07-20 16:07:10 +0000328
329 name = name[3:]
330 if name not in done:
331 done[name] = value
332
Tarek Ziadéedacea32010-01-29 11:41:03 +0000333 else:
Lumír 'Frenzy' Balhar90d02e52021-04-23 14:02:41 +0200334 # Adds unresolved variables to the done dict.
335 # This is disabled when called from distutils.sysconfig
336 if keep_unresolved:
337 done[name] = value
Victor Stinner1273b7c2011-05-24 23:37:07 +0200338 # bogus variable reference (e.g. "prefix=$/opt/python");
339 # just drop it since we can't deal
Tarek Ziadéedacea32010-01-29 11:41:03 +0000340 variables.remove(name)
341
Antoine Pitroudbec7802010-10-10 09:37:12 +0000342 # strip spurious spaces
343 for k, v in done.items():
344 if isinstance(v, str):
345 done[k] = v.strip()
346
Tarek Ziadéedacea32010-01-29 11:41:03 +0000347 # save the results in the global dictionary
348 vars.update(done)
349 return vars
350
Tarek Ziadéedacea32010-01-29 11:41:03 +0000351
Barry Warsawebbef6f2010-09-20 15:29:53 +0000352def get_makefile_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000353 """Return the path of the Makefile."""
Tarek Ziadéedacea32010-01-29 11:41:03 +0000354 if _PYTHON_BUILD:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100355 return os.path.join(_sys_home or _PROJECT_BASE, "Makefile")
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200356 if hasattr(sys, 'abiflags'):
357 config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags)
358 else:
359 config_dir_name = 'config'
doko@ubuntu.com55532312016-06-14 08:55:19 +0200360 if hasattr(sys.implementation, '_multiarch'):
361 config_dir_name += '-%s' % sys.implementation._multiarch
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200362 return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000363
Zachary Warec4b53af2016-09-09 17:59:49 -0700364
Xavier de Gaye92dec542016-09-11 22:22:24 +0200365def _get_sysconfigdata_name():
366 return os.environ.get('_PYTHON_SYSCONFIGDATA_NAME',
367 '_sysconfigdata_{abi}_{platform}_{multiarch}'.format(
368 abi=sys.abiflags,
369 platform=sys.platform,
370 multiarch=getattr(sys.implementation, '_multiarch', ''),
371 ))
Zachary Warec4b53af2016-09-09 17:59:49 -0700372
373
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200374def _generate_posix_vars():
375 """Generate the Python module containing build-time variables."""
376 import pprint
377 vars = {}
Tarek Ziadéedacea32010-01-29 11:41:03 +0000378 # load the installed Makefile:
Barry Warsawebbef6f2010-09-20 15:29:53 +0000379 makefile = get_makefile_filename()
Tarek Ziadéedacea32010-01-29 11:41:03 +0000380 try:
381 _parse_makefile(makefile, vars)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200382 except OSError as e:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000383 msg = "invalid Python installation: unable to open %s" % makefile
384 if hasattr(e, "strerror"):
385 msg = msg + " (%s)" % e.strerror
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200386 raise OSError(msg)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000387 # load the installed pyconfig.h:
388 config_h = get_config_h_filename()
389 try:
Inada Naoki3d4af4a2021-04-06 10:01:11 +0900390 with open(config_h, encoding="utf-8") as f:
Antoine Pitroub86680e2010-10-14 21:15:17 +0000391 parse_config_h(f, vars)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200392 except OSError as e:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000393 msg = "invalid Python installation: unable to open %s" % config_h
394 if hasattr(e, "strerror"):
395 msg = msg + " (%s)" % e.strerror
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200396 raise OSError(msg)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000397 # On AIX, there are wrong paths to the linker scripts in the Makefile
398 # -- these paths are relative to the Python source, but when installed
399 # the scripts are in another directory.
400 if _PYTHON_BUILD:
Antoine Pitrou0abb2182013-10-19 22:05:05 +0200401 vars['BLDSHARED'] = vars['LDSHARED']
Victor Stinner65651ea2011-10-20 00:41:21 +0200402
Trent Nelsonee528cc2012-10-17 04:23:50 -0400403 # There's a chicken-and-egg situation on OS X with regards to the
404 # _sysconfigdata module after the changes introduced by #15298:
405 # get_config_vars() is called by get_platform() as part of the
406 # `make pybuilddir.txt` target -- which is a precursor to the
407 # _sysconfigdata.py module being constructed. Unfortunately,
408 # get_config_vars() eventually calls _init_posix(), which attempts
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400409 # to import _sysconfigdata, which we won't have built yet. In order
410 # for _init_posix() to work, if we're on Darwin, just mock up the
411 # _sysconfigdata module manually and populate it with the build vars.
412 # This is more than sufficient for ensuring the subsequent call to
413 # get_platform() succeeds.
Xavier de Gaye92dec542016-09-11 22:22:24 +0200414 name = _get_sysconfigdata_name()
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400415 if 'darwin' in sys.platform:
Brett Cannonf15a59f2013-06-15 14:32:11 -0400416 import types
417 module = types.ModuleType(name)
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400418 module.build_time_vars = vars
419 sys.modules[name] = module
Tarek Ziadéedacea32010-01-29 11:41:03 +0000420
Serhiy Storchaka885bdc42016-02-11 13:10:36 +0200421 pybuilddir = 'build/lib.%s-%s' % (get_platform(), _PY_VERSION_SHORT)
Trent Nelsonee528cc2012-10-17 04:23:50 -0400422 if hasattr(sys, "gettotalrefcount"):
423 pybuilddir += '-pydebug'
424 os.makedirs(pybuilddir, exist_ok=True)
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400425 destfile = os.path.join(pybuilddir, name + '.py')
Trent Nelsonee528cc2012-10-17 04:23:50 -0400426
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400427 with open(destfile, 'w', encoding='utf8') as f:
428 f.write('# system configuration generated and used by'
429 ' the sysconfig module\n')
430 f.write('build_time_vars = ')
431 pprint.pprint(vars, stream=f)
Trent Nelsonee528cc2012-10-17 04:23:50 -0400432
Trent Nelsonc101bf32012-10-16 08:13:12 -0400433 # Create file used for sys.path fixup -- see Modules/getpath.c
Victor Stinner52ad33a2019-09-25 02:10:35 +0200434 with open('pybuilddir.txt', 'w', encoding='utf8') as f:
Trent Nelsonc101bf32012-10-16 08:13:12 -0400435 f.write(pybuilddir)
436
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200437def _init_posix(vars):
438 """Initialize the module as appropriate for POSIX systems."""
439 # _sysconfigdata is generated at build time, see _generate_posix_vars()
Zachary Warec4b53af2016-09-09 17:59:49 -0700440 name = _get_sysconfigdata_name()
doko@ubuntu.com55532312016-06-14 08:55:19 +0200441 _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0)
442 build_time_vars = _temp.build_time_vars
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200443 vars.update(build_time_vars)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200444
Tarek Ziadéedacea32010-01-29 11:41:03 +0000445def _init_non_posix(vars):
446 """Initialize the module as appropriate for NT"""
447 # set basic install directories
Matti Picusc0afb7f2020-12-07 19:33:20 +0200448 import _imp
Tarek Ziadéedacea32010-01-29 11:41:03 +0000449 vars['LIBDEST'] = get_path('stdlib')
450 vars['BINLIBDEST'] = get_path('platstdlib')
451 vars['INCLUDEPY'] = get_path('include')
Matti Picusc0afb7f2020-12-07 19:33:20 +0200452 vars['EXT_SUFFIX'] = _imp.extension_suffixes()[0]
Tarek Ziadéedacea32010-01-29 11:41:03 +0000453 vars['EXE'] = '.exe'
454 vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
Victor Stinnerb103a932010-10-12 22:23:23 +0000455 vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
Steve Dowerdd180012020-09-05 00:45:54 +0100456 vars['TZPATH'] = ''
Tarek Ziadéedacea32010-01-29 11:41:03 +0000457
458#
459# public APIs
460#
461
Tarek Ziadébd797682010-02-02 23:16:13 +0000462
463def parse_config_h(fp, vars=None):
464 """Parse a config.h-style file.
465
466 A dictionary containing name/value pairs is returned. If an
467 optional dictionary is passed in as the second argument, it is
468 used instead of a new dictionary.
469 """
Tarek Ziadébd797682010-02-02 23:16:13 +0000470 if vars is None:
471 vars = {}
Christian Heimes8c9cd5a2013-10-12 00:24:55 +0200472 import re
Tarek Ziadébd797682010-02-02 23:16:13 +0000473 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
474 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
475
476 while True:
477 line = fp.readline()
478 if not line:
479 break
480 m = define_rx.match(line)
481 if m:
482 n, v = m.group(1, 2)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200483 try:
Ronald Oussoren49926cf2021-02-01 04:29:44 +0100484 if n in _ALWAYS_STR:
485 raise ValueError
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200486 v = int(v)
487 except ValueError:
488 pass
Tarek Ziadébd797682010-02-02 23:16:13 +0000489 vars[n] = v
490 else:
491 m = undef_rx.match(line)
492 if m:
493 vars[m.group(1)] = 0
494 return vars
495
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200496
Tarek Ziadébd797682010-02-02 23:16:13 +0000497def get_config_h_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000498 """Return the path of pyconfig.h."""
Tarek Ziadébd797682010-02-02 23:16:13 +0000499 if _PYTHON_BUILD:
500 if os.name == "nt":
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100501 inc_dir = os.path.join(_sys_home or _PROJECT_BASE, "PC")
Tarek Ziadébd797682010-02-02 23:16:13 +0000502 else:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100503 inc_dir = _sys_home or _PROJECT_BASE
Tarek Ziadébd797682010-02-02 23:16:13 +0000504 else:
505 inc_dir = get_path('platinclude')
506 return os.path.join(inc_dir, 'pyconfig.h')
507
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200508
Tarek Ziadéedacea32010-01-29 11:41:03 +0000509def get_scheme_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000510 """Return a tuple containing the schemes names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400511 return tuple(sorted(_INSTALL_SCHEMES))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200512
Tarek Ziadéedacea32010-01-29 11:41:03 +0000513
514def get_path_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000515 """Return a tuple containing the paths names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400516 return _SCHEME_KEYS
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200517
Tarek Ziadéedacea32010-01-29 11:41:03 +0000518
519def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000520 """Return a mapping containing an install scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000521
522 ``scheme`` is the install scheme name. If not provided, it will
523 return the default scheme for the current platform.
524 """
525 if expand:
526 return _expand_vars(scheme, vars)
527 else:
Éric Araujoec177c12012-06-24 03:27:43 -0400528 return _INSTALL_SCHEMES[scheme]
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200529
Tarek Ziadéedacea32010-01-29 11:41:03 +0000530
531def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000532 """Return a path corresponding to the scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000533
534 ``scheme`` is the install scheme name.
535 """
536 return get_paths(scheme, vars, expand)[name]
537
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200538
Tarek Ziadéedacea32010-01-29 11:41:03 +0000539def get_config_vars(*args):
540 """With no arguments, return a dictionary of all configuration
541 variables relevant for the current platform.
542
543 On Unix, this means every variable defined in Python's installed Makefile;
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700544 On Windows it's a much smaller set.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000545
546 With arguments, return a list of values that result from looking up
547 each argument in the configuration variable dictionary.
548 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000549 global _CONFIG_VARS
550 if _CONFIG_VARS is None:
551 _CONFIG_VARS = {}
552 # Normalized versions of prefix and exec_prefix are handy to have;
553 # in fact, these are the standard versions used most places in the
Éric Araujo859aad62012-06-24 00:07:41 -0400554 # Distutils.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000555 _CONFIG_VARS['prefix'] = _PREFIX
556 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
557 _CONFIG_VARS['py_version'] = _PY_VERSION
558 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
Serhiy Storchaka885bdc42016-02-11 13:10:36 +0200559 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION_SHORT_NO_DOT
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100560 _CONFIG_VARS['installed_base'] = _BASE_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000561 _CONFIG_VARS['base'] = _PREFIX
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100562 _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000563 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000564 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
Victor Stinner8510f432020-03-10 09:53:09 +0100565 _CONFIG_VARS['platlibdir'] = sys.platlibdir
Barry Warsawd5eaa5f2010-11-25 01:34:47 +0000566 try:
567 _CONFIG_VARS['abiflags'] = sys.abiflags
568 except AttributeError:
569 # sys.abiflags may not be defined on all platforms.
570 _CONFIG_VARS['abiflags'] = ''
Steve Dowerdd180012020-09-05 00:45:54 +0100571 try:
572 _CONFIG_VARS['py_version_nodot_plat'] = sys.winver.replace('.', '')
573 except AttributeError:
574 _CONFIG_VARS['py_version_nodot_plat'] = ''
Tarek Ziadéedacea32010-01-29 11:41:03 +0000575
Jesus Cea4791a242012-10-05 03:15:39 +0200576 if os.name == 'nt':
Tarek Ziadéedacea32010-01-29 11:41:03 +0000577 _init_non_posix(_CONFIG_VARS)
578 if os.name == 'posix':
579 _init_posix(_CONFIG_VARS)
Barry Warsaw87b96372013-11-22 11:08:05 -0500580 # For backward compatibility, see issue19555
581 SO = _CONFIG_VARS.get('EXT_SUFFIX')
582 if SO is not None:
583 _CONFIG_VARS['SO'] = SO
pxinwrab74c012020-12-21 06:27:42 +0800584 if _HAS_USER_BASE:
585 # Setting 'userbase' is done below the call to the
586 # init function to enable using 'get_config_var' in
587 # the init-function.
588 _CONFIG_VARS['userbase'] = _getuserbase()
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000589
Richard Oudkerk46874ad2012-07-27 12:06:55 +0100590 # Always convert srcdir to an absolute path
591 srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE)
592 if os.name == 'posix':
593 if _PYTHON_BUILD:
594 # If srcdir is a relative path (typically '.' or '..')
595 # then it should be interpreted relative to the directory
596 # containing Makefile.
597 base = os.path.dirname(get_makefile_filename())
598 srcdir = os.path.join(base, srcdir)
599 else:
600 # srcdir is not meaningful since the installation is
601 # spread about the filesystem. We choose the
602 # directory containing the Makefile since we know it
603 # exists.
604 srcdir = os.path.dirname(get_makefile_filename())
605 _CONFIG_VARS['srcdir'] = _safe_realpath(srcdir)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000606
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700607 # OS X platforms require special customization to handle
608 # multi-architecture, multi-os-version installers
Tarek Ziadéedacea32010-01-29 11:41:03 +0000609 if sys.platform == 'darwin':
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700610 import _osx_support
611 _osx_support.customize_config_vars(_CONFIG_VARS)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000612
613 if args:
614 vals = []
615 for name in args:
616 vals.append(_CONFIG_VARS.get(name))
617 return vals
618 else:
619 return _CONFIG_VARS
620
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200621
Tarek Ziadéedacea32010-01-29 11:41:03 +0000622def get_config_var(name):
623 """Return the value of a single variable using the dictionary returned by
624 'get_config_vars()'.
625
626 Equivalent to get_config_vars().get(name)
627 """
Barry Warsaw197a7702013-11-21 18:57:14 -0500628 if name == 'SO':
629 import warnings
Serhiy Storchakaeaec3592013-11-26 17:08:24 +0200630 warnings.warn('SO is deprecated, use EXT_SUFFIX', DeprecationWarning, 2)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000631 return get_config_vars().get(name)
632
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200633
Tarek Ziadéedacea32010-01-29 11:41:03 +0000634def get_platform():
635 """Return a string that identifies the current platform.
636
637 This is used mainly to distinguish platform-specific build directories and
Benjamin Peterson06930632017-09-04 16:36:05 -0700638 platform-specific built distributions. Typically includes the OS name and
639 version and the architecture (as supplied by 'os.uname()'), although the
640 exact information included depends on the OS; on Linux, the kernel version
641 isn't particularly important.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000642
643 Examples of returned values:
644 linux-i586
645 linux-alpha (?)
646 solaris-2.6-sun4u
Tarek Ziadéedacea32010-01-29 11:41:03 +0000647
648 Windows will return one of:
649 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000650 win32 (all others - specifically, sys.platform is returned)
651
652 For other non-POSIX platforms, currently just returns 'sys.platform'.
Benjamin Peterson06930632017-09-04 16:36:05 -0700653
Tarek Ziadéedacea32010-01-29 11:41:03 +0000654 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000655 if os.name == 'nt':
Zachary Ware49ce74e2017-09-06 15:45:25 -0700656 if 'amd64' in sys.version.lower():
Tarek Ziadéedacea32010-01-29 11:41:03 +0000657 return 'win-amd64'
Paul Monson62dfd7d2019-04-25 11:36:45 -0700658 if '(arm)' in sys.version.lower():
659 return 'win-arm32'
Paul Monsondaf62622019-06-12 10:16:49 -0700660 if '(arm64)' in sys.version.lower():
661 return 'win-arm64'
Tarek Ziadéedacea32010-01-29 11:41:03 +0000662 return sys.platform
663
664 if os.name != "posix" or not hasattr(os, 'uname'):
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700665 # XXX what about the architecture? NT is Intel or Alpha
Tarek Ziadéedacea32010-01-29 11:41:03 +0000666 return sys.platform
667
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200668 # Set for cross builds explicitly
669 if "_PYTHON_HOST_PLATFORM" in os.environ:
670 return os.environ["_PYTHON_HOST_PLATFORM"]
671
Tarek Ziadéedacea32010-01-29 11:41:03 +0000672 # Try to distinguish various flavours of Unix
673 osname, host, release, version, machine = os.uname()
674
Benjamin Peterson288d1da2017-09-28 22:44:27 -0700675 # Convert the OS name to lowercase, remove '/' characters, and translate
676 # spaces (for "Power Macintosh")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000677 osname = osname.lower().replace('/', '')
678 machine = machine.replace(' ', '_')
679 machine = machine.replace('/', '-')
680
681 if osname[:5] == "linux":
682 # At least on Linux/Intel, 'machine' is the processor --
683 # i386, etc.
684 # XXX what about Alpha, SPARC, etc?
685 return "%s-%s" % (osname, machine)
686 elif osname[:5] == "sunos":
687 if release[0] >= "5": # SunOS 5 == Solaris 2
688 osname = "solaris"
689 release = "%d.%s" % (int(release[0]) - 3, release[2:])
Jesus Cea1aa1cf32012-01-18 04:49:26 +0100690 # We can't use "platform.architecture()[0]" because a
691 # bootstrap problem. We use a dict to get an error
692 # if some suspicious happens.
693 bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
Jesus Cea031605a2012-01-18 05:04:49 +0100694 machine += ".%s" % bitness[sys.maxsize]
Tarek Ziadéedacea32010-01-29 11:41:03 +0000695 # fall through to standard osname-release-machine representation
Tarek Ziadéedacea32010-01-29 11:41:03 +0000696 elif osname[:3] == "aix":
Michael Felt39afa2d2019-12-15 15:17:53 +0100697 from _aix_support import aix_platform
698 return aix_platform()
Tarek Ziadéedacea32010-01-29 11:41:03 +0000699 elif osname[:6] == "cygwin":
700 osname = "cygwin"
Christian Heimes8c9cd5a2013-10-12 00:24:55 +0200701 import re
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200702 rel_re = re.compile(r'[\d.]+')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000703 m = rel_re.match(release)
704 if m:
705 release = m.group()
706 elif osname[:6] == "darwin":
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700707 import _osx_support
708 osname, release, machine = _osx_support.get_platform_osx(
709 get_config_vars(),
710 osname, release, machine)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000711
712 return "%s-%s-%s" % (osname, release, machine)
713
714
715def get_python_version():
716 return _PY_VERSION_SHORT
Tarek Ziadéa7514992010-05-25 09:44:36 +0000717
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200718
Lumír 'Frenzy' Balhar90d02e52021-04-23 14:02:41 +0200719def expand_makefile_vars(s, vars):
720 """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in
721 'string' according to 'vars' (a dictionary mapping variable names to
722 values). Variables not present in 'vars' are silently expanded to the
723 empty string. The variable values in 'vars' should not contain further
724 variable expansions; if 'vars' is the output of 'parse_makefile()',
725 you're fine. Returns a variable-expanded version of 's'.
726 """
727 import re
728
729 # This algorithm does multiple expansion, so if vars['foo'] contains
730 # "${bar}", it will expand ${foo} to ${bar}, and then expand
731 # ${bar}... and so forth. This is fine as long as 'vars' comes from
732 # 'parse_makefile()', which takes care of such expansions eagerly,
733 # according to make's variable expansion semantics.
734
735 while True:
736 m = re.search(_findvar1_rx, s) or re.search(_findvar2_rx, s)
737 if m:
738 (beg, end) = m.span()
739 s = s[0:beg] + vars.get(m.group(1)) + s[end:]
740 else:
741 break
742 return s
743
744
Tarek Ziadéa7514992010-05-25 09:44:36 +0000745def _print_dict(title, data):
746 for index, (key, value) in enumerate(sorted(data.items())):
747 if index == 0:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200748 print('%s: ' % (title))
749 print('\t%s = "%s"' % (key, value))
750
Tarek Ziadéa7514992010-05-25 09:44:36 +0000751
752def _main():
Éric Araujo300623d2010-11-22 01:19:20 +0000753 """Display all information sysconfig detains."""
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200754 if '--generate-posix-vars' in sys.argv:
755 _generate_posix_vars()
756 return
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200757 print('Platform: "%s"' % get_platform())
758 print('Python version: "%s"' % get_python_version())
759 print('Current installation scheme: "%s"' % _get_default_scheme())
Éric Araujo559b5f12011-05-25 18:21:43 +0200760 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000761 _print_dict('Paths', get_paths())
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200762 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000763 _print_dict('Variables', get_config_vars())
764
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200765
Tarek Ziadéa7514992010-05-25 09:44:36 +0000766if __name__ == '__main__':
767 _main()